• 入门CMake看这篇文章就对了


    什么是CMake,为什么要用CMake

    • CMake是一个跨平台的构建工具,可以用简单的语句来描述所有平台的安装(编译过程)。能够输出各种各样的makefile或者project文件。CMake并不直接构建出最终的软件,而是产生其他工具的脚本(如makefile),然后再依据这个工具的构建方式使用。
    • CMake是一个比make更高级的编译配置工具,它可以根据不同的平台、不同的编译器,生成相应的makefile或vcproj项目,从而达到跨平台的目的。Android Studio利用CMake生成的是ninja。ninja是一个小型的关注速度的构建系统。我们不需要关心ninja的脚本,知道怎么配置CMake就可以了。
    • 使用CMake的话我们就可以更快更方便的进行编译链接程序,要不然我们就得”傻傻的“gcc balabala …一长串的东西才可以构建我们要的可执行文件,如果我们使用CMake的话我们就只需要cmake然后make就可以构建出我们想要的可执行文件。

    初级阶段——写个HelloWorld用cmake进行编译

    main.cpp

    #include
    int main()
    {
        std::cout<<"hello world"<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在和main.cpp同级目录下创建并编辑CMakeLists.txt(这个名字一定别写错了!一定别写错了!一定别写错了!这是规范不能乱写)
    CMakeLists.txt

    PROJECT(HELLO)
    SET (SRCLIST main.cpp)
    MESSAGE(STATUS "THIS IS BINARY_DIR" ${HELLO_BINARY_DIR})
    MESSAGE(STATUS "THIS IS SOURCE_DIR" ${HELLO_SOURCE_DIR})
    
    ADD_EXECUTABLE(hello ${SRCLIST})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我这采用的是外部构建,会把生成的临时文件放在build(先创建build文件夹,build文件夹需要和咱们写的CMakeLists.txt同级目录)目录下,为了不会对源文件有任何影响,强烈建议使用外部构建方式,如果是外部构建记得是cmake ..而不是cmake .哦
    在这里插入图片描述

    PROJECT命令

    可以用来指定工程的名字和支持的语言,默认支持所有语言

    PROJECT (HELLO) 指定了工程的名字,并且支持所有语言—建议

    PROJECT (HELLO CXX) 指定了工程的名字,并且支持语言是C++

    PROJECT (HELLO C CXX) 指定了工程的名字,并且支持语言是C和C++

    隐式定义了两个CMAKE的变量

    _BINARY_DIR,本例中是 HELLO_BINARY_DIR

    _SOURCE_DIR,本例中是 HELLO_SOURCE_DIR

    问题:如果改了工程名,这两个变量名也会改变

    解决:又定义两个预定义变量:PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR,这两个变量和HELLO_BINARY_DIR,HELLO_SOURCE_DIR是一致的。所以改了工程名也没有关系

    SET命令

    用来显式指定变量

    SET(SRC_LIST main.cpp) SRC_LIST变量就包含了main.cpp

    也可以 SET(SRC_LIST main.cpp t1.cpp t2.cpp)

    MESSAGE命令

    向终端输出用户自定义的信息

    主要包含三种信息:

    • SEND_ERROR,产生错误,生成过程被跳过。
    • SATUS,输出前缀为—的信息。
    • FATAL_ERROR,立即终止所有 cmake 过程.

    ADD_EXECUTABLE命令

    生成可执行文件
    ADD_EXECUTABLE(hello ${SRC_LIST}) 生成的可执行文件名是hello,源文件读取变量SRC_LIST中的内容

    中级阶段——让HelloWorld变得更像一个工程

    1、为工程添加一个子目录 src,用来放置工程源代码,使用外部构建,最后将可执行文件放到bin目录下(这个不好用语言表达,看下面的操作你就知道怎么回事了)
    层次结构:
    在这里插入图片描述
    最外层的CMakeLists.txt用于给项目命名,指示源代码放在哪里(到时候就会调用内层的CMakeLists.txt),并可以指定中间二进制和目标二进制存放的位置。
    外层CMakeLists.txt

    PROJECT(HELLO)
    
    #关联到src下的CMakeLists.txt,生成的二进制文件放到bin目录下
    ADD_SUBDIRECTORY(src bin)
    
    • 1
    • 2
    • 3
    • 4

    内层CMakeLists.txt

    SET(SRC_LIST main.cpp)
    
    MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
    
    MESSAGE(STATUS "This is SOURCE dir "${PROJECT_SOURCE_DIR})
    
    ADD_EXECUTABLE(hello ${SRC_LIST})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    我们现在回到最外层的build文件夹中cmake
    在这里插入图片描述
    现在我们再make,那么可执行文件就会到上面的bin目录下
    在这里插入图片描述
    2、安装

    • 使用INSTALL来实现安装
    • 可以安装二进制、动态库、静态库以及文件、目录、脚本…
    • CMAKE_INSTALL_PREFIX默认为/usr/local/

    层次结构(大家在看完上面的基础后,以下面的这个结构创建其他文件)
    在这里插入图片描述
    外层CMakeLists.txt

    PROJECT(HELLO)
    # 关联到src下的CMakeLists.txt,生成的二进制文件放到bin目录下
    ADD_SUBDIRECTORY(src bin)
    
    # 安装的是文件 要安装什么文件 安装的路径
    INSTALL(FILES COPYRIGHT README DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/doc/cmake/)
    
    # 安装脚本,实际安装在usr/local/bin(如果我们就写个bin这样的相对路径的话)
    INSTALL(PROGRAMS runhello.sh DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/bin/)
    
    # 安装文档
    INSTALL(DIRECTORY doc/ DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/share/doc/cmake)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    INSTALL的DETINATION后面可以用绝对路径也可以用相对路径,但是如果使用相对路径的话,则安装的路径为CMAKE_INSTALL_PREFIX/你设置的相对路径,当然CMAKE_INSTALL_PREFIX也是可以改变的,改变的方式有:
    ①在cmake的时候直接设置cmake -DCMAKE_INSTALL_PREFIX=<你想要安装的路径>
    ②在CMakeLists.txt内部进行设置SET(CMAKE_INSTALL_PREFIX )

    进入到build下cmake
    在这里插入图片描述
    make install,将我们想要安装的东西安装到指定路径,同时也会
    在这里插入图片描述

    高级阶段——共享库以及使用外部文件

    静态库和动态库的区别

    • 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”
    • 静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行
    • 动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行。

    1、共享库的构建
    创建一个新的目录CMake01,在里面创建相关文件
    在这里插入图片描述
    外层的CMakeLists.txt

    PROJECT(HELLO)
    ADD_SUBDIRECTORY(lib bin)
    
    • 1
    • 2

    内层的CMakeLists.txt

    SET(LIBHELLO_SRC hello.cpp)
    # hello为生成的lib的名字,SHARED表示会生成一个共享库(静态库则是STATIC),${LIBHELLO_SRC}为源文件
    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
    
    • 1
    • 2
    • 3

    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

    • hello为生成的lib的名字,但是最终生成的库会变成libhello.so
    • SHARED为动态库,STATIC为静态库
    • ${LIBHELLO_SRC}为你用于生成库的源文件

    hello.cpp

    #include "hello.h"
    #include 
    
    void HelloFunc(){
        std::cout<<"Hello Word"<<std::endl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    hello.h

    #ifndef HELLO_TEST_H
    #define HELLO_TEST_H
    
    void HelloFunc();
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    进入到build以后cmake,然后最终生成libhello.so
    在这里插入图片描述


    2、同时构建动态库和静态库并进行安装
    这里可不能说直接ADD_LIBRARY两次就可以(如果是输出的名字不一样那倒是也可以,下面讲的情况是输出的名字相同的静态库和动态库)一下代码是在CMake01目录下
    外层CMakeLists.txt不变,内层CMakeLists.txt有如下变化

    SET(LIBHELLO_SRC hello.cpp)
    
    ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
    
    # 对hello_static的重名为hello
    SET_TARGET_PROPERTIES(hello_static PROPERTIES  OUTPUT_NAME "hello")
    # cmake 在构建一个新的target 时,会尝试清理掉其他使用"这个名字的库",因为,在构建 libhello.so 时, 就会清理掉 libhello.a,这样下面就又可以用hello这个名字了
    SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
    # ---------------------------------------------------------------------
    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
    
    SET_TARGET_PROPERTIES(hello PROPERTIES  OUTPUT_NAME "hello")
    SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
    # 文件放到该目录下
    INSTALL(FILES hello.h DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/include/hello)
    
    # 二进制,静态库,动态库安装都用TARGETS
    # ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME 特指可执行目标二进制。
    INSTALL(TARGETS hello hello_static LIBRARY DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib ARCHIVE DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME “hello”)把hello_static重命名为hello

    SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)将资源进行清理,这样下面就又可以使用hello这个名字了

    INSTALL(TARGETS hello hello_static LIBRARY DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib ARCHIVE DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib)

    • TARGETS:二进制、库想要安装都是用TARGETS
    • hello和hello_static为要安装的库
    • LIBRARY DESTINATION后面跟的是动态库要安装到哪里去
    • ARCHIVE DESTINATION后面跟的是静态库要安装到哪里去

    回到build下cmake并make install

    在这里插入图片描述


    3、使用外部共享库和头文件

    新创建一个目录CMake02,新目录的此次结构如下:
    在这里插入图片描述
    外层CMakeLists.txt

    PROJECT(HELLO)
    ADD_SUBDIRECTORY(src bin)
    
    • 1
    • 2

    main.cpp

    #include 
    
    int main(){
    	HelloFunc();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    最关键的内层CMakeLists.txt

    INCLUDE_DIRECTORIES(/home/sqh/qiniuLearning/demo/testMkdir/include/hello)
    ADD_EXECUTABLE(hello main.cpp)
    TARGET_LINK_LIBRARIES(hello /home/sqh/qiniuLearning/demo/testMkdir/lib/libhello.so)
    
    • 1
    • 2
    • 3
    • INCLUDE_DIRECTORIES(/home/sqh/qiniuLearning/demo/testMkdir/include/hello,INCLUDE_DIRECTORIES用于包含头文件,hello文件夹下存的是咱们前面INSTALL到include/hello下的hello.h,就是👇
      在这里插入图片描述
    • TARGET_LINK_LIBRARIES(hello /home/sqh/qiniuLearning/demo/testMkdir/lib/libhello.so),TARGET_LINK_LIBRARIES用于链接库(这里hello一定要与上面ADD_EXECUTABLE所生成的可执行文件名相同),这里的libhello.so就是咱们前面通过.cpp文件生成的库文件,那个cpp文件就是👇
      在这里插入图片描述

    最终呈现的结果:
    在这里插入图片描述


    感谢大家看完这篇文章,如果这篇文章对您有些许帮助,我会感到万分荣幸😊😊,当然,如果哪里有不足的地方也欢迎大家指出
    大家可以点开这个链接看看,这个up将cmake讲的挺好的,我这里的总结也有非常多是来自这里的

  • 相关阅读:
    【Java第33期】:在普通的Maven项目中存储Bean对象并获取和使用
    【日记】gulp之删除文件
    【转载】RocketMQ和RabbitMQ的特性及区别
    《大话设计模式》精髓理解——Chapter 16 - 20 状态、适配器、备忘录、组合、迭代器
    【数据库】Sql Server数据迁移,处理自增字段赋值
    【YOLO改进】换遍主流单阶段检测器主干网络(基于MMYOLO)
    第一章:各种款式的算法复杂度例子+计算小技巧
    JavaEE:网络编程
    python——单例模式
    python中items()函数
  • 原文地址:https://blog.csdn.net/Jacksqh/article/details/127406891