• Cmake学习


    cmake大致

    image.png

    cmake_minimum_required(VERSION 3.0)
    
    project(test)
    #通过set自定义变量,通过${}取出
    #set(SRC add.cpp main.cpp muti.cpp sub.cpp)
    #cmake搜索文件 宏定义PROJECT_SOURCE_DIR
    aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
    #file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
    #GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
    #GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。
    
    #指定最后生成程序输出的路径
    set(EXECUTABLE_OUTPUT_PATH ./bin)
    #指定c++使用的标准
    set(CAMKE_CXX_STANDARD 11)
    #生成可执行程序exe
    add_executable(app ${SRC})
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    #指定头文件路径
    cmake_minimum_required(VERSION 3.0)
    
    project(test)
    #通过set自定义变量,通过${}取出
    #aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
    file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
    #指定最后生成程序输出的路径
    set(EXECUTABLE_OUTPUT_PATH ./bin)
    #引入头文件
    include_directories(${PROJECT_SOURCE_DIR}/include)
    #指定c++使用的标准
    set(CAMKE_CXX_STANDARD 11)
    add_executable(app ${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    通过Cmake制作库文件

    制作静态库

    cmake_minimum_required(VERSION 3.0)
    project(CALC)
    include_directories(${PROJECT_SOURCE_DIR}/include)
    file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
    add_library(calc STATIC ${SRC_LIST})
    #add_library(库名称 STATIC 源文件1 [源文件2] ...) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    动态库dll是有可执行权限的

    制作动态库

    include_directories(${PROJECT_SOURCE_DIR}/include) #包含头文件
    set(LIBRARY_OUTPUT_PATH ../lib)
    add_library(calc SHARED ${SRC})
    
    • 1
    • 2
    • 3

    链接静态库

    如果要新建一个项目使用库文件,需要将原来的头文件和库文件一同拷贝过来

    #使用静态链接库
    cmake_minimum_required(VERSION 3.0)
    
    project(test)
    #通过set自定义变量,通过${}取出
    file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    include_directories(${PROJECT_SOURCE_DIR}/include)
    #链接静态库
    link_libraries(calc)
    #指定静态库的位置
    link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
    add_executable(app ${SRC})
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    当我们在使用静态库的时候,在生成可执行文件exe的时候相应的静态库文件会打包到exe那个文件夹里面

    链接动态库

    target_link_libraries(
         
         ... 
        [ ...]...)
    
    • 1
    • 2
    • 3
    • 4

    target:指定要加载动态库的文件的名字
    动态库具有链接的能力,假如说动态库a链接b再链接c,但是传递是由前提条件的,必须是public
    该文件可能是一个源文件
    该文件可能是一个动态库文件
    该文件可能是一个可执行文件
    PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC

    如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。

    动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。

    target_link_libraries(A B C)
    target_link_libraries(D A)
    
    • 1
    • 2
    • PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用。
    • PRIVATE:在private后面的库仅被link到前面的target中,并且终结掉,第三方不能感知你调了啥库
    • INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号。

    使用动态链接库

    #使用动态链接库
    cmake_minimum_required(VERSION 3.0)
    project(test)
    
    
    FILE(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    
    include_directories(${PROJECT_SOURCE_DIR}/include)
    # 指定动态库存放的位置
    link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
    add_executable(app ${SRC})
    # 使用动态链接库
    target_link_libraries(app calc)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    动态库的链接和静态库是完全不同的:

    静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就被加载到内存中了。
    动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存
    因此,在cmake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后:

    cmake_minimum_required(VERSION 3.0)
    project(TEST)
    file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    # 添加并指定最终生成的可执行程序名
    add_executable(app ${SRC_LIST})
    # 指定可执行程序要链接的动态库名字
    target_link_libraries(app pthread)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在target_link_libraries(app pthread)中:

    app: 对应的是最终生成的可执行程序的名字
    pthread:这是可执行程序要加载的动态库,这个库是系统提供的线程库,全名为libpthread.so,在指定的时候一般会掐头(lib)去尾(.so)。
    假设在测试文件main.cpp中既使用了自己制作的动态库libcalc.so又使用了系统提供的线程库,此时CMakeLists.txt文件可以这样写:

    cmake_minimum_required(VERSION 3.0)
    project(TEST)
    file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    include_directories(${PROJECT_SOURCE_DIR}/include)
    add_executable(app ${SRC_LIST})
    target_link_libraries(app pthread calc)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    cmake日志

    #使用动态链接库
    cmake_minimum_required(VERSION 3.0)
    project(test)
    
    
    FILE(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    
    include_directories(${PROJECT_SOURCE_DIR}/include)
    # 日志
    message("first logs")
    # 指定动态库存放的位置
    link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
    message(STATUS "second logs")
    add_executable(app ${SRC})
    # 使用动态链接库
    target_link_libraries(app calc)
    message(FATAL_ERROR "third fatal error")
    message(STATUS "fourth logs")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image.png

    #使用动态链接库
    cmake_minimum_required(VERSION 3.0)
    project(test)
    
    
    FILE(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    
    include_directories(${PROJECT_SOURCE_DIR}/include)
    # 日志
    message("first logs")
    # 指定动态库存放的位置
    link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
    message(STATUS "second logs")
    add_executable(app ${SRC})
    # 使用动态链接库
    target_link_libraries(app calc)
    #打印变量值
    message("var is :"${SRC})
    message(FATAL_ERROR "third fatal error")
    message(STATUS "fourth logs")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    image.png

    字符串操作

    cmake_minimum_required(VERSION 3.5)
    project(test)
    set(value1 "value1")
    set(value2 "value2")
    message(${value1})
    #字符串拼接
    set(value3 ${value1} "+" ${value2})
    message("value3:" ${value3})
    
    #使用list追加字符串
    list(APPEND value3 " zhui jia zi fu chuan")
    message(${value3})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    
    #移除src中main.cpp的名字
    cmake_minimum_required(VERSION 3.5)
    project(test)
    #获取src目录下所有源文件的绝对路径
    file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
    message("======================")
    message(${SRC})
    list(REMOVE_ITEM SRC ${PROJECT_SOURCE_DIR}/src/main.cpp)
    message("删除之后的字符串")
    message(${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    =====================
    D:/C++workspace/c++程序/cmake_str/src/add.cppD:/C++workspace/c++程序/cmake_str/src/main.cppD:/C++workspace/c++程序/cmake_str/src/muti.cppD:/C++workspace/c++程序/cmake_str/src/sub.cpp
    删除之后的字符串
    D:/C++workspace/c++程序/cmake_str/src/add.cppD:/C++workspace/c++程序/cmake_str/src/muti.cppD:/C++workspace/c++程序/cmake_str/src/sub.cpp

    list的其他命令:
    获取list长度

    list(LENGTH  )
    
    • 1
    • LENGTH:子命令LENGTH用于读取列表长度
    • :当前操作的列表
    • :新创建的变量,用于存储列表的长度。

    读取列表中指定索引的的元素,可以指定多个索引:

    list(GET   [ ...] )
    
    • 1
    • :当前操作的列表
    • :列表元素的索引
      • 从0开始编号,索引0的元素为列表中的第一个元素;
      • 索引也可以是负数,-1表示列表的最后一个元素,-2表示列表倒数第二个元素,以此类推
      • 当索引(不管是正还是负)超过列表的长度,运行会报错
    • :新创建的变量,存储指定索引元素的返回结果,也是一个列表。

    将列表中的元素用连接符(字符串)连接起来组成一个字符串

    list (JOIN   )
    
    • 1
    • :当前操作的列表
    • :指定的连接符(字符串)
    • :新创建的变量,存储返回的字符串

    查找列表是否存在指定的元素,若果未找到,返回-1

    list(FIND   )
    
    • 1
    • :当前操作的列表
    • :需要再列表中搜索的元素
    • :新创建的变量

    等等。。。

    cmake中自定义宏

    #include 
    #define NUMBER  3
    
    int main()
    {
        int a = 10;
        //cmake中没有添加debug相关配置所以在debug模式下运行,并不会运行ifdef debug里面的打印内容
        #ifdef DEBUG
        printf("我是一个程序猿, 我不会爬树...\n");
        #endif
        for(int i=0; i<NUMBER; ++i)
            {
                printf("hello, GCC!!!\n");
            }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    image.png

    cmake_minimum_required(VERSION 3.5)
    project(Test)
    file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
    add_definitions(-DDEBUG)
    add_executable(app ${SRC})
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image.png

    嵌套的cmake

    文件夹目录
    image.png
    根目录下的cmakelist

    cmake_minimum_required(VERSION 3.5)
    project(test)
    #定义变量
    #静态库生成路径
    set(LIBPATH ${PROJECT_SOURCE_DIR}/lib)
    #可执行程序存放地址
    set(EXECPATH ${PROJECT_SOURCE_DIR}/bin)
    #头文件路径
    set(HEADPATH ${PROJECT_SOURCE_DIR}/include)
    #库文件的名字
    set(CALCLIB calc)
    set(SORTLIB sort)
    #可执行程序的名字
    set(APPNAME1 app1)
    set(APPNAME2 app2)
    
    
    #给当前节点添加子目录
    add_subdirectory(calc)
    add_subdirectory(sort)
    add_subdirectory(test1)
    add_subdirectory(test2)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    calc文件夹下的cmakelist 子节点中的变量无法在父节点中用,父节点的变量可以在子节点用

    cmake_minimum_required(VERSION 3.5)
    project(calc)
    #搜索当前路径下的所有cpp文件 搜索源文件
    aux_source_directory(./ SRC)
    # 搜索头文件 include文件夹下 父节点已经定义了include文件夹路径变量HEADPATH
    include_directories(${HEADPATH})
    #指定静态库生成的路径
    set(LIBRARY_OUTPUT_PATH ${LIBPATH})
    #把源文件变成静态库
    add_library(${CALCLIB} STATIC ${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    sort目录下的文件cmakelist

    cmake_minimum_required(VERSION 3.5)
    project(sort)
    #搜索当前路径下的所有cpp文件 搜索源文件
    aux_source_directory(./ SRC)
    # 搜索头文件 include文件夹下 父节点已经定义了include文件夹路径变量HEADPATH
    include_directories(${HEADPATH})
    #指定静态库生成的路径
    set(LIBRARY_OUTPUT_PATH ${LIBPATH})
    #把源文件变成静态库
    add_library(${SORTLIB} STATIC ${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    test1目录下的cmakelist执行calc的主程序

    cmake_minimum_required(VERSION 3.5)
    project(test1)
    
    aux_source_directory(./ SRC)
    
    include_directories(${HEADPATH})
    link_directories(${LIBPATH})
    link_libraries(${CALCLIB})
    #生成可执行文件的目录
    set(EXECUTABLE_OTPUT_PATH ${EXECPATH})
    add_executable(${APPNAME1} ${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在静态库中链接静态库

    主要做的是在排序的静态库sort.lib中引用calc.lib需要做以下修改
    冒泡排序cpp中调用calc静态库的链接 删掉test2

    #include
    #include "sort.h"
    #include "calc.h"
    
    using namespace std;
    
    
    void bubble_sort(int mylist[],int listsize){
        
        int number1 = add(mylist[0],mylist[1]);
        cout<<"在选择排序中调用calc的加法操作"<<number1<<endl;
        for(int i=0;i<listsize;i++){
    
            for(int j=i;j<listsize;j++){
    
                if(mylist[i]<mylist[j])
                {
                    int temp = mylist[i];
                    mylist[i]=mylist[j];
                    mylist[j]=temp;
    
                }
            }
    
        }
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    calc目录下的cmakelist保持不变
    sort目录下的cmakelist

    cmake_minimum_required(VERSION 3.5)
    project(sort)
    #搜索当前路径下的所有cpp文件 搜索源文件
    aux_source_directory(./ SRC)
    # 搜索头文件 include文件夹下 父节点已经定义了include文件夹路径变量HEADPATH
    include_directories(${HEADPATH})
    #指定静态库生成的路径
    set(LIBRARY_OUTPUT_PATH ${LIBPATH})
    # 指定自定义静态库的存放路径
    link_directories(${LIBPATH})
    # 链接calc静态库
    link_libraries(${CALCLIB})
    #把源文件变成静态库
    add_library(${SORTLIB} STATIC ${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    test/main.cpp下的cmakelist

    cmake_minimum_required(VERSION 3.5)
    project(test2)
    
    aux_source_directory(./ SRC)
    
    include_directories(${HEADPATH})
    link_directories(${LIBPATH})
    link_libraries(${SORTLIB})
    #生成可执行文件的目录
    set(EXECUTABLE_OTPUT_PATH ${EXECPATH})
    add_executable(${APPNAME2} ${SRC})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    sort.lib已经引用的calc.lib所以,test下就不需要再引用calc.lib了
    image.png

  • 相关阅读:
    教你初学者如何快速学会 Python
    pta团队天题题-阅览室(c++)
    数据分析之Logistic回归分析(二元逻辑回归、多元有序逻辑回归、多元无序逻辑回归)
    OpenCV7-copyTo截取ROI
    antd4 Table实现翻页勾选
    开源的工业软件-面向生产控制环节
    汉诺塔与二进制、满二叉树的千丝万缕
    Qt OpenGL相机系统
    超短高手赚大钱的必备3个问题
    MQ - 39 Serverless : 基于MQ和Serverless设计事件驱动架构
  • 原文地址:https://blog.csdn.net/ProgreamA/article/details/134482796