• 一文读懂CMake


    这篇文章是站在VS角度描述CMake语法的。具体语法对应关系,参照下表。

    CMake函数对应VS相关设置

    VS相关设置CMake函数
    指定包含头文件目录target_include_directories
    指定链接库目录target_link_directories
    指定链接库target_link_libraries
    指定C++标准set(CMAKE_CXX_STANDARD 11)
    指定编译器版本cmake -G “Visual Studio 12 2013”
    指定平台集cmake -G “Visual Studio 12 2013 Win64”
    指定编译类型set(CMAKE_BUILD_TYPE “Debug”)等价于g++ -g
    指定预编译宏add_definitions(-Dxxx -Dyyy ) 必须-D开头
    指定解决方案名称project(xxxx)
    文件分类source_group(“folder_name” file_list)

    CMake常见内置变量

    CMake内置变量说明(路径都是全路径)
    PROJECT_NAMECMakeList.txt里设置的project_name
    PROJECT_SOURCE_DIR根CMakeLists.txt所在的路径
    PROJECT_BINARY_DIR工程的构建目录(build目录)
    CMAKE_CURRENT_SOURCE_DIR当前’CMakeLists.txt’ 所在的路径
    CMAKE_CURRENT_BINARY_DIR当前正在处理的’构建目录’
    CMAKE_CURRENT_LIST_DIR当前处理的’cmake文件’所在的目录
    CMAKE_CURRENT_LIST_FILE当前处理的’CMakeLists.txt或cmake’文件的全路径
    CMAKE_CURRENT_LIST_LINE当前处理的’CMakeLists.txt或cmake’文件的’行号’
    CMAKE_PROJECT_NAME整个项目’配置的project_name
    CMAKE_LIBRARY_OUTPUT_DIRECTORY库的存放目录(需要用户设置)
    CMAKE_RUNTIME_OUTPUT_DIRECTORY可执行文件的存放目录(需要用户设置,必须在设置可执行文件之前设置)

    CMake Hellow word

    project
    project/main.cpp
    project/CMakeLists.txt
    
    project/build
    
    • 1
    • 2
    • 3
    • 4
    • 5

    project/CMakeLists.txt

    #设置CMake版本要求
    cmake_minimum_required(VERSION 3.10)
    
    #设置工程名称
    project(hellow)
    
    #设置C++11标准
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED true)
    
    #添加可执行文件
    add_executable(hellow main.cpp)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    执行CMake指令

    #当前目录build
    
    #-G指定编译器Vs2013以及平台工具集类型X64
    cmake -G "Visual Studio 12 2013 Win64" ../
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    指定Debug模式(-g)

    set(CMAKE_BUILD_TYPE "Debug")
    
    • 1

    生成mymath库add_library

    project/mymath
    project/mymath/mymath.h
    project/mymath/mymath.cpp
    project/mymath/CMakeLists.txt
    
    • 1
    • 2
    • 3
    • 4

    project/CMakeLists.txt

    #增加一个子目录到编译工程中,子目录应该包含CMakeLists.txt
    add_subdirectory(mymath)
    
    #增加头文件包含目录
    target_include_directories(hellow PUBLIC 
                            "${PROJECT_SOURCE_DIR}/mymath"
                            )
    
    #链接lib
    target_link_libraries(hellow PUBLIC mymath)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    project/mymath/CMakeLists.txt

    #添加lib默认是静态库,如果指定SHARED则为动态库
    add_library(mymath SHARED mymath.cpp)
    
    • 1
    • 2

    此时就会生成mymath库了,下面是完整的project/CMakeLists.txt

    #设置CMake版本要求
    cmake_minimum_required(VERSION 3.10)
    
    #设置工程名称
    project(hellow)
    
    #设置C++11标准
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED true)
    
    #增加一个子目录到编译工程中,子目录应该包含CMakeLists.txt
    add_subdirectory(mymath)
    
    #添加可执行文件
    add_executable(hellow main.cpp)
    
    #增加头文件包含目录
    target_include_directories(hellow PUBLIC 
                            "${PROJECT_SOURCE_DIR}/mymath"
                            )
    #链接lib
    target_link_libraries(hellow PUBLIC mymath)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    链接第三方库

    下面以链接 d://test//test.lib为例,test.lib的头文件在d://test//include//

    #附加test.lib
    target_link_libraries(hellow PUBLIC mymath test)
    #指定lib库位置
    target_link_directories(hellow PUBLIC "d:/test")
    #指定lib头文件位置
    target_include_directories(hellow PUBLIC 
                            "d:/test/include"
                            "${PROJECT_SOURCE_DIR}/mymath"
                            )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    下面是完整的project/CMakeLists.txt

    #设置CMake版本要求
    cmake_minimum_required(VERSION 3.10)
    
    #设置工程名称
    project(hellow)
    
    #设置C++11标准
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED true)
    
    #增加一个子目录到编译工程中,子目录应该包含CMakeLists.txt
    add_subdirectory(mymath)
    
    #添加可执行文件
    add_executable(hellow main.cpp)
    
    #增加头文件包含目录
    target_include_directories(hellow PUBLIC 
    						"d:/test/include"
                            "${PROJECT_SOURCE_DIR}/mymath"
                            )
    #链接lib
    target_link_libraries(hellow PUBLIC mymath test)
    
    
    #指定链接库的目录
    target_link_directories(hellow PUBLIC "d:/test")
    
    • 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

    在这里插入图片描述

    增加预定义宏add_definitions

    例如:必须定义USE_OPEN_SSL才能开启openssl

    #增加预定义宏,必须-D开头
    add_definitions(-DUSE_OPEN_SLL)
    
    • 1
    • 2

    多文包含件处理

    如果目标里面包含多个文件,如果手动指定则会很麻烦。可以通过aux_source_directory扫描并获取当前目录文件。

    #增加sub函数
    project/sub.cpp
    project/sub.h
    
    • 1
    • 2
    • 3
    #扫描当前目录文件,并且保存在变量all_file中
    #或者使用file(GLOB all_file ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    aux_source_directory("${CMAKE_CURRENT_SOURCE_DIR}" all_file)
    add_executable(hellow ${all_file})
    
    • 1
    • 2
    • 3
    • 4

    配置项目版本号和信息

    #设置项目名称和版本
    project(Tutorial VERSION 1.0)
    
    #配置头文件传递版本号给源代码
    #配置宏定义,配置默认值为ON,如果想关闭 cmake -DUSE_MYMATH=OFF
    #option 除了ON之外其他的都默认为OFF
    option(USE_MYMATH "user mymath.lib" ON)
    
    #传递字符串给配置文件
    set(var_Key "hellow word")
    #传递INT给配置文件
    set(INT_Key 1)
    
    #输入文件 输出文件
    configure_file(hellow_ver.h.in hellow_ver.h)
    
    #由于配置好的文件hellow_ver.h将被写入二进制目录
    #所以我们必须将该目录添加到 include 文件的搜索路径中
    target_include_directories(hellow PUBLIC 
    						"d:/test/include"
                            "${PROJECT_SOURCE_DIR}/mymath"
                            "${PROJECT_BINARY_DIR}"
                            )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    hellow_ver.h.in

    //配置的项目版本号
    #define hellow_VERSION_MAJOR @hellow_VERSION_MAJOR@
    #define hellow_VERSION_MINOR @hellow_VERSION_MINOR@
    
    //宏定义
    #cmakedefine USE_MYMATH
    //注意:${}之间的名称要与cmakedefine后的变量名一样
    //变量名称和cmakeLists.txt设置的变量名称相同
    #cmakedefine var_Key "@var_Key@”
    #cmakedefine INT_Key @INT_Key@
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行之后生成的hellow_ver.h
    在这里插入图片描述
    如果想取消USE_MYMATH 可以使用 -DUSE_MYMATH=OFF

    cmake -G "Visual Studio 12 2013 Win64" ../ -DUSE_MYMATH=OFF
    
    • 1

    生成动态库or静态库

    #确定mymath.lib是否使用静态库
    option(MYMATH_STATIC "user mymath static lib" ON)
    
    if(MYMATH_STATIC)
    add_library(mymath STATIC mymath.cpp)
    else()
    add_library(mymath SHARED mymath.cpp)
    endif()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    cmake -G "Visual Studio 12 2013 Win64" ../ -DUSE_MYMATH=OFF
    
    • 1

    指定二进制文件或者库文件生成位置

    #一定要在设置target之前设置,否则无效
    #二进制文件位置
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
    #库文件位置
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    设置Target的生成目标名称

    #修改输出文件的名称,默认和target同名
    set_target_properties(hellow PROPERTIES OUTPUT_NAME main)
    
    • 1
    • 2

    执行生成后事件

    #在VS中我们经常会执行生成后事件,例如生成后复制文件
    add_custom_command(TARGET hellow POST_BUILD
      COMMAND ${CMAKE_COMMAND} -E copy_if_different
      ${PROJECT_BINARY_DIR}/bin/mymath.dll ${PROJECT_SOURCE_DIR}/bin/mymath.dll)
    
    • 1
    • 2
    • 3
    • 4

    指定项目依赖项(指定项目生成顺序)

    #例如当前项目hellow依赖mymath.lib
    add_dependencies(hellow mymath)
    
    • 1
    • 2

    文件分类source_group

    通过上述生成的工程文件没有分类,并且没有包含头文件。下面我们将按照目录结构进行分类(不使用lib)。

    在这里插入图片描述
    注意涉及函数filesource_group

    #获取当前目录下所有的头文件并进行分类
    #GLOB-只索引当前目录,不包括子目录
    #GLOB_RECURSE-索引当前目录以及包括子目录 
    file(GLOB project_header_files ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
    
    #进行头文件,只能是相同类型的文件,否则会失败
    source_group("Header Files" ${project_header_files})
    
    #获取mymath目录下的头文件和源文件并且进行分类
    #获取mymath目录下所有的文件这里并没有使用aux_source_directory("${CMAKE_CURRENT_SOURCE_DIR}/mymath" maths_file)
    file(GLOB math_header_files ${CMAKE_CURRENT_SOURCE_DIR}/mymath/*.h)
    file(GLOB math_src_files ${CMAKE_CURRENT_SOURCE_DIR}/mymath/*.cpp)
    
    #source_group有两种写法
    #自己定义folder,名称
    #source_group("mymath" FILES ${math_header_files} ${math_src_files})
    #根据目录结构截取生成目录名称 files的绝对路径去掉${CMAKE_CURRENT_SOURCE_DIR},即拼成目录名称
    source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${math_src_files} ${math_header_files})
    
    #最后一步也是最重要的一步,一定要添加到target里面,否则也不会展示
    add_executable(hellow ${all_file} ${project_header_files} ${math_header_files} ${math_src_files})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    cmake -G "Visual Studio 12 2013 Win64" ../ -DUSE_MYMATH=OFF
    
    • 1

    此时可以看到文件已经分类,层级分明了。
    在这里插入图片描述

    编译工程项目(--build

    当cmake指令运行之后,如果想编译文件,在windows下我们可以使用对应的VS打开编译,在linux下我们可以使用make编译。但是我们可以统一使用CMake自己来编译cmake --build 目录(cmake输出位置)

    #如果在windows平台
    #release版本
    cmake --build . --config Release
    #debug版本
    cmake --build . --config Debug
    
    #如果在linux平台
    #release版本
    cmake ../ -DCMAKE_BUILD_TYPE=Release
    cmake --build .
    #Debug版本
    cmake ../ -DCMAKE_BUILD_TYPE=Debug
    cmake --build .
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    本文参考:CMake 教程,至于CMake的安装和测试将在下一章讲解。

    函数简单说明

    对于CMake,可能存在两种函数:xxxxx和target_xxxx。下面以link_librariestarget_link_libraries来做讲解。
    link_libraries:针对全局的,即:CMake的所有模块都会添加该库。
    target_link_libraries:针对指定目标的,只有指定目标包含该库。
    例如CMake包含连个目标AB,此时如果通过link_libraries(ws2_32 test)包含ws2_32.libtest.lib那么AB都将包含这两个库。但是如果通过target_link_libraries(A PUBLIC ws2_32 test)那么此时仅仅目标A包含这两个库。

  • 相关阅读:
    《数字化与碳中和(园区篇)》报告正式发布,助力加快推进国家“双碳”战略实施
    SaaSBase:什么是涂色scrm?
    mysql5.6---windows和linux安装教程和忘记密码怎么办
    软件无线电处理平台解决方案:330-基于FMC接口的Kintex-7 XC7K325T PCIeX4 3U PXIe接口卡
    LVGL---基础对象的样式(styles)
    Debezium-Embedded 实时监控MySQL数据变更
    华为云云耀云服务器L实例评测|centos7.9 配置python虚拟环境 运行django
    GBase 8c V3.0.0数据类型——文本检索函数
    如何挑选自媒体平台进行创作?这3个关键需要把握
    国内哪个工具可以平替chatgpt?国内有哪些比较好用的大模型gpt?
  • 原文地址:https://blog.csdn.net/CAir2/article/details/125995922