• cmake 常用指令入门指南



    本博客记录:在使用cmake进行构建工程时,写CMakeLists.txt 文件时,常使用到的命令与变量, 不断补充更新中。

    相关链接

    官方地址: https://cmake.org/cmake/help/
    git上很好实践教程: https://github.com/ttroy50/cmake-examples

    CMKAE中脚本相关的命令

    cmake_minimum_required 命令

    语法与参数介绍

    语法: cmake_minimum_required(VERSION min[...policy_max] [FATAL_ERROR])

    • min 指定了编译当前的cmake需要的最old的版本号,如果cmake版本号小于指定的版本号时,运行cmake 就报错。

      举例:当前有cmake版本号为3.10.2, 运行如下的CMakeLists.txt 文件时, 就会报错:

      cmake_minimum_required(VERSION 3.12)
      

      运行cmake命令,报错如下:提示运行版本小于要求的最小版本。

      CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
      CMake 3.10.3 or higher is required.  You are running version 3.10.2
      
      
      -- Configuring incomplete, errors occurred!
      
    • ... 表示min或max版本号之间的连接符。

    • policy_max 参数与cmake的policy setting相关,当指定了【policy_max】参数(要大于等于min版本号)时, 所有【小于等于 policy_max版本 或者 小于等于当前运行版本(谁小取谁)】中的已经的policy都设置为NEW.

      policy 可以理解为版本之间的变更,例如语法新增加、约束变严等, policy使用CMPXXXX格式的编号,例如:CMP0000表示cmake文件中必须指定要求的最低版本号,CMP0002表示....等。
      在新的版本中,如果要指定policy的新的规定, 语法为: cmake_policy(SET CMPXXXX NEW), 有时候为了新版本兼容之前写的CMakeLists.txt文件, 则可以使用原来的policy, 语法为:cmake_policy(SET CMPXXXX OLD).
      可以使用cmake_policy(VERSION min[...max])指定policy的要求min与max版本号:
      - 当不指定max版本号时,cmake会把min版本以及之前的版本引入的所有policy设置为NEW, 大于min版本号引入的policy默认不设置。
      - 当指定max版本号时, cmake会把 【max版本或者当前运行的版本号(谁小取谁)】以及之前的版本号引入的的所有polixy设置为NEW, 超过的版本引入的policy默认不设置。
      当使用cmake_minimum_required(VERSION)命令时,会隐式地调用cmake_policy(VERSION)命令用于设置policy相关的版本要求。

    举例: 下面的cmake命令:

    cmake_mini_mum_required(VERSION 3.12...3.15)
    
    # 上面命令会隐示地调用下面这条命令
    cmake_policy(VERSION 3.12...3.15)
    
    • FATAL_ERROR
      该选项在2.6涉及2.6版本以下有用, 当指定该选项时,如果当前支行的版本号小于要求的版本号,就会报错;如果不指定该选项时,只会报warning. 2.6版本之后,都是报错了,所以用不着该选项了。

    引入的变量

    • CMAKE_MINIMUM_REQUIRED_VERSION : 设置该变量的值为 min.

    file 命令

    file 命令专门用于访问文件系统对文件与路径进行操作的。

    读相关

    写相关

    文件系统相关

    file(GLOB variable 通配符表达式)

    语法与参数

    使用语法为: file(GLOB <variable> [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...])
    含义: GLOB, 就是globbing的缩写, 该命令查找所有在当前目录(CMakeLists.txt所在目录,即CMAKE_CURRENT_SOURCE_DIR变量)下所有满足匹配通配符表达式的文件,并保存到给定的变量中。

    • GLOB: 是关键字。
    • variable: 保存文件名的变量
    • LIST_DIRECTORIES true| false : 表示是否要保存文件的路径,默认保存。 (试了一下,置为false为什么不管用呢?)
    • RELATIVE path: 给定该参数时,保存的路径中是相对于给定path的路径名。
    • globbing-expressions: 通配符表达式。

    使用举例

    file(GLOB source_list "src/*.cpp")
    

    注意事项

    不建议使用该命令搜索源文件名,原因是:如果CMakeLists.txt文件没有变化,但是你增加了源文件, 此时给的结果不一样正确。(我试了一下,ubuntu下可以给出正确结果)

    路径转换相关

    set命令

    设置普通的命令

    使用语法:set(<variable> <value>... [PARENT_SCOPE]), 设置一个变量的值。 如果不给定值,就表示取消该变量的设置。

    • PARENT_SCOPE: 表示在上层作用域内设置变量的值。

    使用举例

    set(SOURCE_LIST 1.c 2.c 3.c)
    

    设置cache 变量

    使用语法与参数含义

    语法:set(<variable> <value>... CACHE <type> <docstring> [FORCE]), 该命令会设置的cache变量会被保存到CMakeCache.txt 文档中, 可以打开看看的。

    • CACHE 是关键字。
    • type 表示变量的类型, 包含: BOOL、FILEPATH、PATH、STRING、INTERNAL。
    • docstring: 类型注释,表明该参数的含义。
    • FORCE: 默认情况下,如果该cache 变量已经设置过了,再次执行该变量就不会被写入,如果使用了FORCE关键字的话,只要命令被执行,就会对变量进行写入的。

    使用举例

    set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
    

    set_property 命令

    使用语法与参数含义

    该命令用于设置一个对象的属性信息, 它的使用语法如下所示:

    set_property(<GLOBAL                      |
                  DIRECTORY [<dir>]           |
                  TARGET    [<target1> ...]   |
                  SOURCE    [<src1> ...]
                            [DIRECTORY <dirs> ...] |
                            [TARGET_DIRECTORY <targets> ...]
                  INSTALL   [<file1> ...]     |
                  TEST      [<test1> ...]     |
                  CACHE     [<entry1> ...]    >
                 [APPEND] [APPEND_STRING]
                 PROPERTY <name> [<value1> ...])
    
    • [对象类型] [对象名称]: 指定了对象的类型以及要设置的对象名称, 包含: GLOBAL, DIRECTORY, TARGET, SOURCE 等。例如TARGET hello_main.
    • PROPERTY 属性名: 指定了要设置的属性名以及属性值。

    使用举例

    cmake_minimum_required(VERSION 3.10.2)
    project(hello_main)
    add_executable(hello_main main.cpp)
    set_property(TARGET hello_main PROPERTY CXX_STANDARD 11)
    

    include 命令

    ** 语法与参数说明**

    该命令用于导入文件或模块中的CMAKE代码, 类似于c语言中的include 功能。 使用语法为:

    include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>]
                          [NO_POLICY_SCOPE])
    
    • file | module: 指定的包含CMKE指定的文件 或者 模块名。模块名其实就是安装cmake时已经提供的***.cmake文件(例如/usr/share/cmake-3.10/Modules/目录下好多模块)
    • OPTIONAL: 如果指定了该选项,当cmake查找不到指定文件时,不会报错, 因为它是可选的嘛。
    • RESULT_VARIABLE var: 用于保存查找到的文件路径(查找成功时) 或者保存失败结果NOTFOUND(失败时)

    举例说明

    cmake_minimum_required(VERSION 2.8)
    project (hello_cpp11)
    
    #这里导入CheckCXXCompilerFlag模块, 并运行该模块内的CHECK_CXX_COMPILER_FLAG命令。
    include(CheckCXXCompilerFlag)
    CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
    CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
    

    message 命令

    该命令是用于记录log消息的,使用语法为:message([<mode>] "message text" ...)。 其中,mode 关键字用于表示要记录的log的类型,常用的有:

    • FATAL_ERROR: cmake errer, 遇到该错误,cmake 直接停止处理。
    • WARNING: 警告信息, 但是cmake会继续执行下去的。
    • STATUS: 用于记录一些cmake 运行过程中的有用的信息。

    例如:

    message(STATUS "hello, world.")
    set(NAME xiaoming)
    messaeg(STATUS "hello, ${NAME}")
    

    CMAKE中project相关命令

    project 命令

    语法与参数

    使用语法为:project(项目名字, [VERSION 版本号] [DESCRIPTION 描述字符串] ), 例如:

    project(myproject, VERSION 1.0.0 DESCRIPTION "my first project" )
    
    • 项目名字, 即指定一个项目名字
    • VERSION, 指定项目的版本号, 可选字段, 一般不用不着它,不学习,不介绍
    • DESCRIPTION, 项目的描述, 可选字段,一般也不需要用它,不学习,不介绍
    • 还有其它的可选参数,例如HOMEPAGE_URL, LANGUAGES, 用不着,不介绍

    隐式引入的变量

    • PROJECT_NAME: 它的值为 最近调用的project()命令设置的项目名, 例如你的子目录中调用了project()命令,那么该变量名在子目录中的值就是新设置的项目名。
    • CMAKE_PROJECT_NAME: 它的值为 最top 层的 project 设置的项目名
    • PROJECT_SOURCE_DIR: 最近 调用project() 命令定义的项目所在的源文件的绝对路径。
      例如:在根目录中定义的CMakeLists.txt文件中调用了project()命令, 在该作用域内, 该变量的值就是定义该CMakeLists.txt的绝对路径。
      如果在子目录中定义的CMakeLists.txt文件中也调用了project()命令, 在子目录中CMakeLists.txt的作用域内,该变量的值就是子目录的绝对路径。
    • PROJECT_BINARY_DIR: 最近调用project()命令定义的项目的binary的绝对路径。 与调用cmake命令的位置有关, 通常会在build 目录下调用cmake, 所以该binary目录都在build 目录内。
    • <PROJECT-NAME>_SOURCE_DIR: 首先不推荐使用它,如果你修改的项目名字,该变量名也需要适配。 它的值与PROJECT_SOURCE_DIR变量的值相同。
    • <PROJECT-NAME>_BINARY_DIR: 不推荐使用, 与PROJECT_BINARY_DIR的值相同。

    add _executable 命令

    普通的可执行文件

    语法与参数说明

    使用语法为:add_executable(name [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] [source2] ...). 例如:

    cmake_minimum_required(VERSION 3.12)
    add_executable(myMain 1.c 2.c)
    
    • name : 即可执行文件的名字。windows平台下实际产生的可执行文件名为name.exe, linux平台下产生的可执行文件名就是name.

    • WIN32关键字: 用不着,不学习,跳过。

    • MACOSX_BUNDLE: 用不着,不学习,跳过。

    • source1: 源文件列表, 多个源文件使用空格分开,说明如下:

      1. 从3.1版本开始, 可以使用“generator expressions"语法表示($<...>)依赖的源文件列表。
      2. 在该命令中可以暂时不写依赖的源文件列表, 后续由target_sources() 再添加源文件列表。
    • EXCLUDE_FROM_ALL:当指定该参数时,要构建的target 就会被排除在all target 列表之外, 这样当执行makemake all时, 该target 不会被编译。

    相关变量

    • CMAKE_RUNTIME_OUTPUT_DIRECTORY: 该变量指定了生成的可执行文件的保存路径.

    import可执行文件

    用到的时候补。

    alias可执行文件

    使用语法:add_library(<name> ALIAS <target>), 为给定的target添加一个别名name. 例如:

    add_library(other_name ALIAS mylib)
    

    add_library 命令

    Normal Libraries

    语法与参数说明

    使用语法:add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [<source>...]) , 该命令用于添加一个库文件的target, 包含静态库、动态库等。

    • name: target的名字。
    • [STATIC | SHARED | MODULE]: STATIC 表示静态库,SHARED 表示动态库,MODULE表示模块库,可以在运行时使用 dlopen 之类的命令动态加载的插件。
    • EXCLUDE_FROM_ALL: 与add_executable命令中的参数相同,当指定该参数时,要构建的target 就会被排除在all target 列表之外。
    • source: 源文件列表。

    例如举例

    add_library(hello_library STATIC src/Hello.cpp)
    

    相关变量

    • ARCHIVE_OUTPUT_DIRECTORY: 修改静态库的输出路径。
    • LIBRARY_OUTPUT_DIRECTORY: 修改动态库的输出路径。
    • ARCHIVE_OUTPUT_NAME: 修改静态库的输出路径。
    • LIBRARY_OUTPUT_NAME: 修改动态库的输出路径。

    target_include_directories 命令

    语法与参数说明

    语法:target_include_directories(<target> [SYSTEM] [AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

    当编译给定target时,该命令用于指令要包含的路径名。 当使用 gcc 编译器编译目标时,就会使用-I选项指定该命令添加的路径, 使用-I directory/include.

    • target: 要编译的目标文件
    • SYSTEM: 感觉用不到,跳过。
    • AFTER 或 BEFORE: 控制把需要添加的路径append 还是 prepend 到已有的路径列表中。
    • INTERFACE/PUBLIC/PRIVATE: 这几个关键字很有用。
      • 从内部实现上讲: 当使用PRIVATEPUBLIC 指定路径名时, 会把路径名添加到target的INCLUDE_DIRECTORIES属性中; 当使用PUBLICINTERFACE指定路径名时, 会把路径名添加到target的INTERFACE_INCLUDE_DIRECTORIES的属性中。
      • 从外部表现上讲:使用PRIVATE关键字时,添加的路径只会在编译当前target时使用到。 当使用INTERFACE关键字时,添加的路径只会在编译任何链接到当前target的目标文件时使用到。 使用PUBLIC关键字时,会包含以两种使用。 因此,通常情况下,如果target是可执行文件,建议使用PRIVATE, 如果target是动态或静态库, 建议使用PUBLIC,比较方便。

    命令举例

    target_include_directories(mylib PUBLIC include/1.h PUBLIC ${PROJECT_SOURCE_DIR}/include)
    target_include_directories(mytarget PRIVATE ${PROJECT_SOURCE_DIR}/include)
    
    

    语法及参数含义

    使用语法: target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>...[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
    该命令的用于指定一个target的链接阶段的依赖库。 它还可以 propagate any include directories with PUBLIC or INTERFACE scope from the linked library target.

    PRIVATE|PUBLIC|INTERFACE的作用

    暂时不太明白。

    使用举例

    target_link_libraries( hello_binary PRIVATE hello_library)
    

    install 命令

    Installing Target

    语法与参数

    该命令用于安装指定的target到指定目录内。 全量的使用语法为:

    install(TARGETS targets ... [EXPORT <export-name>]
            [RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
            [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
              PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
             [DESTINATION <dir>]
             [PERMISSIONS permissions...]
             [CONFIGURATIONS [Debug|Release|...]]
             [COMPONENT <component>]
             [NAMELINK_COMPONENT <component>]
             [OPTIONAL] [EXCLUDE_FROM_ALL]
             [NAMELINK_ONLY|NAMELINK_SKIP]
            ] [...]
            [INCLUDES DESTINATION [<dir> ...]]
            )
    
    • TARGET targets: 指明了要安装的target.
    • ARCHIVE|LIBRARY|RUNTIME等: 指明了target的类型。
    • DESTINATION dir: 指明了要安装到的路径。当使用相对路径时,是相对于变量CMAKE_INSTALL_PREFIX的, 该变量默认为/usr/local/, 也可以在CMakeLists.txt文件中指定,也可以在运行CMAKE命令时指定,例如:cmake .. -DCMAKE_INSTALL_PREFIX=/install/location

    使用举例

    install(TARGETS mylib LIBRARY DESTINATION lib)
    install(TARGETS mybin RUNTIME DESTINATION bin)
    

    Installing Directories

    该命令用于安装指定的目录(包含目录内的文件)到指定目录。

    使用语法与参数说明

    install(DIRECTORY dirs...
            TYPE <type> | DESTINATION <dir>
            [FILE_PERMISSIONS permissions...]
            [DIRECTORY_PERMISSIONS permissions...]
            [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
            [CONFIGURATIONS [Debug|Release|...]]
            [COMPONENT <component>] [EXCLUDE_FROM_ALL]
            [FILES_MATCHING]
            [[PATTERN <pattern> | REGEX <regex>]
             [EXCLUDE] [PERMISSIONS permissions...]] [...])
    
    • DIRECTORY dirs: 要安装的头文件的目录路径,默认为相对于当前的路径。 注意:如果路径以/结尾时, 会把路径里面的内容复制到给定路径,如果没有以/结尾,则也会复制该层目录的。
    • DESTINATION: 要安装到的目录路径。

    使用举例

    install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)
    

    Installing Files

    使用语法与参数介绍

    该命令用于安装指定的文件到指定目录:

    install(<FILES|PROGRAMS> files...
            TYPE <type> | DESTINATION <dir>
            [PERMISSIONS permissions...]
            [CONFIGURATIONS [Debug|Release|...]]
            [COMPONENT <component>]
            [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])
    
    • FILES files: 指定要安装的文件。
    • DESTINATION dir: 指定要安装的路径。

    使用举例

    install(FILES cmake.config DESTINATION etc)
    

    target_compile_definitions

    使用语法与参数定义

    该命令用于指定指定编译给定的target时,要定义的宏名称:

    target_compile_definitions(<target>
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    
    • target: 要指定编译的target。
    • INTERFACE/PUBLIC/PRIVATE: 与之前介绍的类似, 从内部实现是讲: 当使用INTERFACEPUBLIC时,会把宏定义指定赋值给INTERFACE_COMPILE_DEFINITIONS变量, 当使用PUBLICPRIVATE时,会把宏定义内容赋值给COMPILE_DEFINITIONS变量。从外部表现上讲, 当使用INTERFACEPUBLIC时,表示编译任何链接到该target(当target是一个库时)的目标文件时,都增加了该宏定义。当使用PUBLICPRIVATE时,表示编译当前target时,才使用该宏定义。
    • items1: 表示要定义的宏名字。

    其它方法:1. 修改变量CMAKE_CXX_FLAGS(c++) 或者CMAKE_C_FLAGS(C代码),也可以实现该效果,但是建议使用target_compile_definitions命令。
    2. 在执行cmake 命令时,也可以通过参数指定,例如:cmake .. -DCMAKE_CXX_FLAGS="-DCHINA", 它就会定义一个CHINA的宏定义。

    使用举例

    main函数定义如下:

    #include <iostream>
    int main() {
    #ifdef CHINA
    	std::cout << "I Love CHINA" << std::endl;
    #endif
    	return 0;
    }
    
    cmake_minimum_required(VERSION 3.10.2)
    add_executable(myTarget main.c)
    target_compile_definations(myTarget PRIVATE CHINA)
    

    add_subdirectory 命令

    该命令用于增加一个构建的子目录。 注意执行的数据流: cmake 命令会执行完子目录中的CmakeLists.txt文件之后,再执行后面的命令。

    使用语法与参数说明

    使用语法为: add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

    • source_dir: 要添加的子目录, 建议使用相对路径啊(相对于当前位置)。
    • binary_dir: 用于保存输出文件位置。 一般都不写。
    • EXCLUDE_FROM_ALL: 该参数很熟悉了,就是编译的时候(make 或 make all),默认不被编译。如果想要编译它,显示自己执行。

    举例

    cmake_minimum_required(VERSION 3.10.2)
    project(example)
    add_subdirectory(subdir1)
    add_subdirectory(subdir2)
    

    set_target_properties 命令

    该命令用于设置给定target的一些属性值,类似于类对象的成员变量的值。 它们会影响到该target如何被构建的。

    使用语法与参数说明

    使用语法为:

    set_target_properties(target1 target2 ...
                          PROPERTIES prop1 value1
                          prop2 value2 ...)
    
    • target1... : 要设置的target的名字。
    • PROPERTIES: 后面跟要设置的属性的名字以及它们的值。

    使用举例

    cmake_minimum_required(VERSION 3.10.2)
    project(hello_main)
    add_executable(hello_main main.cpp)
    set_target_properties(hello_main PROPERTIES CXX_STANDARD 11)
    

    target_compile_features 命令

    该命令用于 Specifies compiler features required when compiling a given target.

    使用语法与参数说明

    使用语法为:target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...]).

    • target: 要编译的目标文件的名称。
    • PRIVATE | PUBLIC | INTERFACE : 这个关键字已经介绍过N次了,它指明了什么场景下生效该设置。
    • feature: 就是支持的一些feature了,例如:cxx_std_98cxx_std_11cxx_rvalue_references等。

    使用举例

    cmake_minimum_required(VERSION 3.10.2)
    project(hello_main)
    add_executable(hello_main main.cpp)
    target_compile_features(hello_main PRIVATE cxx_std_11)
    

    cmake中的常用变量

    CMAKE_SOURCE_DIR

    表示:源码的根目录,也就是最top层 CMakeLists.txt文件存在的目录。

    CMAKE_BINARY_DIR

    表示:为编译的binary的根目录,也就是运行CMake时的目录,一般就是build目录。

    CMAKE_CURRENT_SOURCE_DIR

    表示:当前正在运行的CMakeLists.txt文件的目录

    CMAKE_CURRENT_BINARY_DIR

    表示:当前正处于的编译目录,例如如果正在运行src目录下的CMakeLists.txt, 该变量通常为build/src目录。

    CMAKE_CXX_FLAGS 和 CMAKE_C_FLAGS

    表示:当使用g++(或gcc)编译文件时,用于设置compiler flags, 也就是宏定义。

    CMAKE_CXX_STANDARD

    表示:该变量用于编译target时,使用的c++标准,支持98, 11, 14, 17, 20, 23. 该变量的作用原理是:用于初始化target的CXX_STANDARD属性。

    C++编译器相关的宏命令

    check_cxx_compiler_flag 命令

    该宏定义在CheckCXXCompilerFlag.cmake模块中, 可以打开该文件看它的实现的。 它的功能是用于检测c++编译器是否支持给定的编译选项,并把检测结果写的给定变量中。

    使用语法为:check_cxx_compiler_flag(<flag> <var>),

    • flag: 要检测的c++编译选项
    • var: 保存检测结果的cache 变量。

    使用举例

  • 相关阅读:
    PMP:9.项目资源管理
    @JsonIgnore忽略JSON字段
    xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
    android加载不到.so文件
    报错Failed to install the following SDK components: platforms;android-29 Android SDK Platform 29
    Mac 终端启动运行Redis
    Mac 命令行执行Sublime
    Bean转为Json指定字段名,防止被修改大小写
    Rest接口入参忽略大小写 使用jackson注解
    mongo批量导入
  • 原文地址:https://www.cnblogs.com/yinheyi/p/14968494.html
Copyright © 2020-2023  润新知