FAIRYFAR-INTERNAL
 
  FAIRYFAR-INTERNAL  |  SITEMAP  |  ABOUT-ME  |  HOME  
您的足迹: Modern CMake文档
Modern CMake文档

Modern CMake文档

安装

  • Windows安装
  • macOS安装
    • 网址:https://cmake.org/download/,下载CMake,并正常安装
    • 安装完成之后,使用以下指令创建/usr/local/bin下的CMake的软连接
      • sudo \"/Applications/CMake.app/Contents/bin/cmake-gui" --install
      • 注意:执行此命令的时候确保CMake处于关闭状态
    • 重新打开Terminal,即可正常使用 CMake 的各种指令了,也可以在应用程序列表中使用带 GUI 的 CMake 工具。
  • Linux安装
    • 网址:https://cmake.org/download/,下载对应版本的CMake(32位或者64位)
    • 将下载的安装包上传到Linux服务器,比如:/root
    • 输入以下命令进行解压
      • tar -zxvf cmake-3.13.0-rc1-Linux-x86_64.tar.gz
      • 注意:后面是官网下载的对应版本的名字
    • 把解压后的目录改名为:cmake
      • mv cmake-3.10.0-rc4-Linux-x86_64 cmake
    • 设置环境变量
      • 使用指令"vi .bash_profile"来设置环境变量,找到PATH=\$PATH:\$.…这一行,后面添加CMake安装目录里面的bin目录的地址
      • 如果是在/root目录安装的CMake,那添加的目录就是:/root/cmake/bin
    • 安装完毕,环境变量设置成功之后,命令行输入:cmake --version检测是否安装成功
      • 输出:cmake version 3.13,表示安装成功

使用CMake生成项目

  • 使用Windows或者Linux生成项目
    • 进入项目目录(CMakeLists.txt所在目录),新建一个build文件夹,因为CMake会产生很多自己的中间文件。
    • 执行 :cmake ../ 就会在build目录产生项目文件,windows下面默认产生vs的项目。
    • 如果要产生其他编译器的makefile,就需要使用-G指定编译器
      • cmake -G \"MinGW Makefiles\" ../
    • 可以使用cmake --help 来查看使用的编译器的名字
    • 生成项目工程文件或者makefile之后,就可以使用对应的编译器来编译项目
  • 使用macOS生成项目
    • mac下基本操作和windows、Linux相同,不过cmake命令使用的是:cmake .. (没有右斜杠)
  • 注意:(默认已经配置好环境变量)

CMake命令行选项的设置

  • 指定构建系统生成器:-G
    • 使用:-G 命令可以指定编译器,当前平台支持的编译器名称可以通过帮助手册查看:cmake --help,
      例如:cmake -G \"Visual Studio 15 2017\" ../ 使用vs2017构建工程
      • CMakeCache.txt文件
        • 当cmake第一次运行一个空的构建的时候,他就会创建一个CMakeCache.txt文件,文件里面存放了一些可以用来制定工程的设置,比如:变量、选项等
        • 对于同一个变量,如果Cache文件里面有设置,那么CMakeLists文件里就会优先使用Cache文件里面的同名变量。
        • CMakeLists里面通过设置了一个Cache里面没有的变量,那就将这个变量的值写入到Cache里面
        • 例子:
          • SET(var 1024)
            //变量var的值被设置成1024,如果变量var在Cache中已经存在,该命令不会覆盖cache里面的值
            - SET(var 1024..CACHE..)
            
              > //如果var在Cache中存在,就优先使用Cache里面的值,如果不存在,就将该值写入Cache里面​
            
            - SET(var..CACHE..FORCE)
            
              > //无论Cache里面是否存在,都始终使用该值

            -

            添加变量到Cache文件中:-D

        • 注意:-D后面不能有空格,例如:cmake -DCMAKEBUILDTYPE:STRING=Debug
      • 从Cache文件中删除变量:-U
        • 此选项和-D功能相反,从Cache文件中删除变量,支持使用*和?通配符
      • CMake命令行模式:-E
        • CMake提供了很多和平台无关的命令,在任何平台都可以使用:chdir, copy, copyifdifferent等
        • 可以使用:cmake -E help进行查询
      • 打印运行的每一行CMake
        • 命令行选项中:--trace,将打印运行的每一行CMake,例如windows下执行: cmake --trace ..
        • 命令:--trace-source=\"filename\"就会打印出有关filename的执行
      • 设置编译参数
        • add_definitions(-DENABLED),当在CMake里面添加该定义的时候,如果代码里面定义了#ifdef ENABLED [#endif相关的片段]{.underline},此时代码里面这一块代码就会生效
        • add_definitions( "-Wall -ansi –pedantic –g") - 该命令现已经被取代,使用: addcompiledefinitions(WITH_OPENCV2) - 设置默认值命令:option - option命令可以帮助我们设置一个自定义的宏,如下: - option(MY-MESSAGE \"this is my message\" ON) - 第一个参数就是我们要设置的默认值的名字 - 第二个参数是对值的解释,类似于注释 - 第三个值是这个默认值的值,如果没有声明,CMake默认的是OFF - 使用:设置好之后我们在命令行去使用的时候,也可以去给他设定值:cmake -DMY-MESSAGE=on ../ - 注意:使用的时候我们应该在值的前面加"D" - 这条命令可将MY-MESSAGE的值设置为on,通过这个值我们可以去触发相关的判断 # CMake基础知识简介 - 最低版本 - 每一个CMake.txt的第一行都会写:cmakeminimumrequired(VERSION 3.1),该命令指定了CMake的最低版本是3.1 - 命令名称cmakeminimumrequired不区分大小写 - 设置版本范围: cmake_minimum_required(VERSION 3.1\...3.12) 该命令表示支持3.1至3.12之间的版本 - 判断CMake版本: if(\${CMAKE_VERSION} VERSION_LESS 3.12) cmake_policy(VERSION \${CMAKE_MAJOR_VERSION}.\${CMAKE_MINOR_VERSION}) endif() - 该命令表示:如果CMake版本小于3.12,则if块将为true,然后将设置为当前CMake版本;如果CMake版本高于3.12,if块为假​,cmakeminimumrequired将被正确执行 - 注意:如果需要支持非命令行Windows版本则需在上面的if判断加上else分支,如下: cmake_minimum_required(VERSION 3.1) if(${CMAKE_VERSION} VERSION_LESS 3.12) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() cmake_policy(VERSION 3.12) endif() - 设置生成项目名称 - 使用的命令:project(MyProject) - 表示我们生成的工程名字叫做:MyProject - 命令还可以标识项目支持的语言,写法:project(MyProject[C] [C++]),不过通常将后面的参数省掉,因为默认支持所有语言 - 使用该指令之后系统会自动创建两个变量:\<projectname>_BINARYDIR:二进制文件保存路径、\<projectname>_SOURCEDIR:源代码路径 - 执行:project(MyProject),就是定义了一个项目的名称为:MyProject,对应的就会生成两个变量:_BINARYDIR和SOURCEDIR,但是cmake中其实已经有两个预定义的变量:PROJECTBINARYDIR和PROJECTSOURCR_DIR - 关于两个变量是否相同,涉及到是内部构建还是外部构建 - 内部构建\ > cmake ./\ > make​ - 外部构建\ > mkdir build\ > cd ./build\ > cmake ../\ > make​​​ - 内部构建和外部构建的不同在于:cmake 的工作目录不同。内部构建会将cmake生成的中间文件和可执行文件放在和项目同一目录;外部构建的话,中间文件和可执行文件会放在build目录。 - PROJECTSOURCEDIR和SOURCEDIR无论内部构建还是外部构建,指向的内容都是一样的,都指向工程的根目录 - PROJECTBINARYDIR和BINARYDIR指向的相同内容,内部构建的时候指向CMakeLists.txt文件的目录,外部构建的,指向target编译的目录 - 生成可执行文件 - 语法:add_executable(exename srcname)\ > exename:生成的可执行文件的名字\ > srcname:以来的源文件​​ - 该命令指定生成exe的名字以及指出需要依赖的源文件的文件名 - 获取文件路径中的所有源文件 - 命令:auxsourcrdirectory(\<dir> \<variable>) - 例子:auxsourcrdirectory(. DIRSRCS),将当前目录下的源文件名字存放到变量DIRSRCS里面 ,如果源文件比较多,直接用DIR_SRCS变量即可 - 生成可执行文件:addexecutable(Demo \${DIRSRCS}),将生成的可执行文件命名为:Demo.exe - 生成lib库 - 命令:addlibrary(libname [SHARED\|STATIC\|MODULE] [EXCLUDEFROM_ALL] source1 source2 ... sourceN)\ > libname:生成的库文件的名字\ > ​[SHARED\|STATIC\|MODULE]:生成库文件的类型(动态库\|静态库\|模块)\ > [EXCLUDEFROMALL]:有这个参数表示该库不会被默认构建​\ > source2 ... sourceN:生成库依赖的源文件,如果源文件比较多,可以使用​auxsourcrdirectory命令获取路径下所有源文件,具体章节参见:CMake基础知识简介->生成可执行文件->获取路径中所有源文件 - 例子:add_library(ALib SHARE alib.cpp) - 添加头文件目录 - 命令1:targetincludedirectories(\<target> [SYSTEM] [BEFORE] \<INTERFACE\|PUBLIC\|PRIVATE> [items1...] [\<INTERFACE\|PUBLIC\|PRIVATE> [items2...] ...])\ > 当我们添加子项目之后还需要设置一个include路径,例子:\ > eg:targetincludedirectories(RigelEditor PUBLIC ./include/rgeditor),表示给RigelEditor 这个子项目添加一个库文件的路径 - 命令2:include_directories([AFTER\|BEFORE] [SYSTEM] dir1 [dir2 …])\ > 参数解析:\ > ​[AFTER\|BEFORE]:指定了要添加路径是添加到原有列表之前还是之后\ > [SYSTEM]​:若指定了system参数,则把被包含的路径当做系统包含路径来处理\ > dir1 [dir2 …]​把这些路径添加到CMakeLists及其子目录的CMakeLists的头文件包含项目中\ > 相当于g++选项中的-l的参数的作用\ > ​​举例:\ > include_directories(\"/opt/MATLAB/R2012a/extern/include\") - 两条指令的作用都是讲将include的目录添加到目标区别在于includedirectories是CMake编译所有目标的目录进行添加,targetinclude_directories是将CMake编译的指定的特定目标的包含目录进行添加 - 添加需要链接的库文件路径 - 命令1:targetlinklibraries(\<target> [item1 [item2 [...]]] [[debug\|optimized\|general] \<item>] ...) - 作用:为给定的目标设置链接时使用的库(设置要链接的库文件的名称) - eg:targetlinklibraries(MyProject a b.a [c.so]{.underline})   将若干库文件链接到hello中,targetlinklibraries里的库文件的顺序符合gcc/g++链接顺序规则,即:被依赖的库放在依赖他的库的后面,如果顺序有错,链接将会报错
          • 关键字:debug对应于调试配置
          • 关键字:optimized对应于所有其他的配置类型
          • 关键字:general对应于所有的配置(该属性是默认值)
        • 命令2:link_libraries
          • 作用:给当前工程链接需要的库文件(全路径)
          • eg:link_libraries((\"/opt/MATLAB/R2012a/bin/glnxa64/[libeng.so]{.underline}\")必须添加带名字的全路径 - 区别:linklibraries和targetlinklibraries命令的区别:targetlinklibraries可以给工程或者库文件设置其需要链接的库文件,而且不需要填写全路径,但是linklibraries只能给工程添加依赖的库,而且必须添加全路径 - 添加需要链接的库文件目录 - 命令:link_directories(添加需要链接的库文件目录) - 语法:link_directories(directory1 directory2 ...) - 例子:link_directories(\"/opt/MATLAB/R2012a/bin/glnxa64\") - 指令的区别:指令的前缀带target,表示针对某一个目标进行设置,必须指明设置的目标;includedirectories是在编译时用,指明.h文件的路径;linkdirectoeies是在链接时用的,指明链接库的路径;targetlinklibraries是指明链接库的名字,也就是具体谁链接到哪个库。link_libraries不常用,因为必须指明带文件名全路径 - 控制目标属性 - 以上的几条命令的区分都是:是否带target前缀,在CMake里面,一个target有自己的属性集,如果我们没有显示的设置这些target的属性的话,CMake默认是由相关的全局属性来填充target的属性,我们如果需要单独的设置target的属性,需要使用命令:settargetproperties() - 命令格式\ > 格式:\ > ​settargetproperties(target1 target2 ...\ > PROPERTIES\ > 属性名称1 值\ > 属性名称2 值\ > ...\ > ) - 控制编译选项的属性是:COMPILE_FLAGS - 控制链接选项的属性是:LINK_FLAGS - 控制输出路径的属性:EXECUTABLEOUTPUTPATH(exe的输出路径)、LIBRARYOUTPUTPATH(库文件的输出路径) - 举例:\ > 命令:\ > ​settargetproperties(exe\ > PROPERTIES\ > LINKFLAGS -static\ > LINKFLAGS_RELEASE -s\ > ) - 这条指令会使得exe这个目标在所有的情况下都采用-static选项,而且在release build的时候 -static -s 选项。但是这个属性仅仅在exe这个target上面有效 - 变量和缓存 - 局部变量 - CMakeLists.txt相当于一个函数,第一个执行的CMakeLists.txt相当于主函数,正常设置的变量不能跨越CMakeLists.txt文件,相当于局部变量只在当前函数域里面作用一样, - 设置变量:set(MY_VARIABLE \"value\") - 变量的名称通常大写 - 访问变量:\${MY_VARIABLE} - 缓存变量 - 缓存变量就是cache变量,相当于全局变量,都是在第一个执行的CMakeLists.txt里面被设置的,不过在子项目的CMakeLists.txt文件里面也是可以修改这个变量的,此时会影响父目录的CMakeLists.txt,这些变量用来配置整个工程,配置好之后对整个工程使用。 - 设置缓存变量:set(MYCACHEVALUE \"cache_value\" CACHE INTERNAL \"THIS IS MY CACHE VALUE\")\ > THIS IS MY CACHE VALUE,这个字符串相当于对变量的描述说明,不能省略,但可以自己随便定义
        • 环境变量
          • 设置环境变量:set(ENV{variable_name} value)
          • 获取环境变量:\$ENV{variable_name}
        • 内置变量
          • CMake里面包含大量的内置变量,和自定义的变量相同,常用的有以下:
          • CMAKE_C_COMPILER:指定C编译器
          • CMAKECXXCOMPILER:指定C++编译器
          • EXECUTABLEOUTPUTPATH:指定可执行文件的存放路径
          • LIBRARYOUTPUTPATH:指定库文件的放置路径
          • CMAKECURRENTSOURCE_DIR:当前处理的CMakeLists.txt所在的路径
          • CMAKEBUILDTYPE:控制构建的时候是Debug还是Release\
            命令:set(CMAKE_BUILD_TYPE Debug)
            - CMAKE_SOURCR_DIR:无论外部构建还是内部构建,都指的是工程的顶层目录(参考project命令执行之后,生成的_SOURCR_DIR以及CMake预定义的变量PROJECT_SOURCE_DIR)
            
            - CMAKE_BINARY_DIR:内部构建指的是工程顶层目录,外部构建指的是工程发生编译的目录(参考project命令执行之后,生成的_BINARY_DIR以及CMake预定义的变量PROJECT_BINARY_DIR)
            
            - CMAKE_CURRENT_LIST_LINE:输出这个内置变量所在的行
            1. 缓存
            1. 缓存就是之前提到的CMakeCache文件,参见:CMake命令行选项的设置->CMakeCache.txt文件

            -

            CMake基本控制语法

        • If
          • 基本语法\
            if (expression)\
                >     COMMAND1(ARGS \...)\
                >     COMMAND2(ARGS \...)\
                >     \...\
                > else (expression)\
                >     COMMAND1(ARGS \...)\
                >     COMMAND2(ARGS \...)\
                >     \...\
                > endif (expression)\
                > 注意:ENDIF要和IF对应​
            1. if (expression),expression不为:空,0,N,NO,OFF,FALSE,NOTFOUND或\< var >_NOTFOUND,为真
            1. IF (not exp),与上面相反
            1. if (var1 AND var2),var1且var2都为真,条件成立
            1. if (var1 OR var2),var1或var2其中某一个为真,条件成立
            1. if (COMMAND cmd), 如果cmd确实是命令并可调用,为真;
            1. if (EXISTS dir) 如果目录存在,为真
            1. if (EXISTS file) 如果文件存在,为真
            1. if (file1 ISNEWERTHAN file2),当file1比file2新,或file1/file2中有一个不存在时为真,文件名需使用全路径
            1. if (IS_DIRECTORY dir) 当dir是目录时,为真
            1. if (DEFINED var) 如果变量被定义,为真
            1. if (string MATCHES regex) 当给定变量或字符串能匹配正则表达式regex时,为真\
                  > 例:\
                  > IF (\"hello\" MATCHES \"ell\") \
                  > MESSAGE(\"true\") \
                  > ENDIF (\"hello\" MATCHES \"ell\")
            1. 数字表达式
            1. if (var LESS number),var小于number为真
            1. if (var GREATER number),var大于number为真
            1. if (var EQUAL number),var等于number为真
            1. 字母表顺序比较
            1. IF (var1 STRLESS var2),var1字母顺序小于var2为真
            1. IF (var1 STRGREATER var2),var1字母顺序大于var2为真
            1. IF (var1 STREQUAL var2),var1和var2字母顺序相等为真
            1. While
            1. 语法结构\
                > WHILE(condition)\
                > COMMAND1(ARGS \...)\
                > COMMAND2(ARGS \...)\
                > \...\
                > ENDWHILE(condition)
            1. 真假条件的判断参考if
            1. Foreach
            1. FOREACH有三种使用形式的语法,且每个FOREACH都需要一个ENDFOREACH()与之匹配。
            1. 列表循环
            1. 语法\
                  > FOREACH(loop_var arg1 arg2 \...)\
                  > COMMAND1(ARGS \...)\
                  > COMMAND2(ARGS \...)\
                  > \...\
                  > ENDFOREACH(loop_var)​
            1. 例子\
                  > eg:\
                  > ​AUX_SOURCE_DIRECTORY(. SRC_LIST)\
                  > FOREACH(F \${SRC_LIST})\
                  > MESSAGE(\${F})\
                  > ENDFOREACH(F)
            1. 例子中,先将当前路径的源文件名放到变量SRC_LIST里面,然后遍历输出文件名
            1. 范围循环
            1. 语法\
                  > FOREACH(loop_var RANGE total)\
                  > COMMAND1(ARGS \...)\
                  > COMMAND2(ARGS \...)\
                  > \...\
                  > ENDFOREACH(loop_var)
            1. 例子\
                  > eg:\
                  > ​FOREACH(VAR RANGE 100)\
                  > MESSAGE(\${VAR})\
                  > ENDFOREACH(VAR)\
                  > ​​
            1. 例子中默认起点为0,步进为1,作用就是输出:0\~100
            1. 范围步进循环
            1. 语法\
                  > FOREACH(loop_var RANGE start stop \[step\])\
                  > COMMAND1(ARGS \...)\
                  > COMMAND2(ARGS \...)\
                  > \...\
                  > ENDFOREACH(loop_var)
            1. 例子\
                  > eg:\
                  > FOREACH(A RANGE 0 100 10)\
                  > MESSAGE(\${A})\
                  > ENDFOREACH(A)​
            1. 例子中,起点是0,终点是100,步进是10,输出:0,10,20,30,40,50,60,70,80,90,100

            -

            构建规范以及构建属性 - 用于指定构建规则以及程序使用要求的指令:targetincludedirectories(), targetcompiledefinitions(), targetcompileoptions() - 指令格式 - targetincludedirectories(\<target> [SYSTEM] [BEFORE]\<INTERFACE\|PUBLIC\|PRIVATE> [items1...] [\<INTERFACE\|PUBLIC\|PRIVATE> [items2...] ...])\ > Include的头文件的查找目录,也就是Gcc的[-Idir...]选项 - targetcompiledefinitions(\<target> \<INTERFACE\|PUBLIC\|PRIVATE> [items1...][\<INTERFACE\|PUBLIC\|PRIVATE> [items2...] ...])\ > 通过命令行定义的宏变量 - targetcompileoptions(\<target> [BEFORE] \<INTERFACE\|PUBLIC\|PRIVATE> [items1...] [\<INTERFACE\|PUBLIC\|PRIVATE> [items2...] ...]\ > gcc其他的一些编译选项指定,比如-fPIC\ > ​​ - -fPIC选项说明\ > 说明:-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),\ >   则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意\ >   位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。 - -ldir选项说明\ > 说明:在你是用 [#include]{.underline} \"file\" 的时候, gcc/g++ 会先在当前目录查找你所制定的头文件, 如果没有找到, 他会到缺省的头文件目录找, 如果使用 -I 制定了目录,他会先在你所制定的目录查找, 然后再按常规的顺序去找。 - 以上的额三个命令会生成INCLUDEDIRECTORIES, COMPILEDEFINITIONS, COMPILEOPTIONS变量的值,。或者 INTERFACEINCLUDEDIRECTORIES,INTERFACECOMPILEDEFINITIONS, INTERFACECOMPILE_OPTIONS的值. - 这三个命令都有三种可选模式: PRIVATE, PUBLIC。 INTERFACE. PRIVATE模式仅填充不是接口的目标属性; INTERFACE模式仅填充接口目标的属性.PUBLIC模式填充这两种的目标属性。 - - 宏和函数 - CMake里面可以定义自己的函数(function)和宏(macro) - 区别1:范围。函数是有范围的,而宏没有。如果希望函数设置的变量在函数的外部也可以看见,就需要使用PARENT_SCOPE来修饰,但是函数对于变量的控制会比较好,不会有变量泄露 - 例子 - 宏(macro)\ > eg:\ > ​macro( [arg1 [arg2 [arg3 ...]]])\ >      COMMAND1(ARGS ...)\ >      COMMAND2(ARGS ...)\ >      ...\ > endmacro() - 函数(function)\ > eg:\ > ​function( [arg1 [arg2 [arg3 ...]]])\ >      COMMAND1(ARGS ...)\ >      COMMAND2(ARGS ...)\ >      ...\ > endfunction() - 函数和宏的区别还在于,函数很难将计算结果传出来,使用宏就可以将一些值简单的传出来 - 例子\ > eg:\ > macro(macroTest)\ >      set(test1 \"aaa\")\ > endmacro()\ > ​\ > function(funTest)\ >      set(test2 \"bbb\")\ > endfunction()\ > ​\ > macroTest()\ > message(\"\${test1}\")\ > ​\ > funTest()\ > message(\"\${test2}\")\ > ​ - 运行上面这个代码,就会显示"aaa",因为函数里面的test1是局部的,出了这个函数就出了他的作用域 - 和其他文件的交互 - 在代码中使用CMake中定义的变量 - 命令:configure_file - 作用:让普通文件也能使用CMake中的变量。 - 语法\ > configurefile(\<input> \<output>\ > [COPYONLY] [ESCAPEQUOTES] [[\@ONLY]{.underline}]\ > [NEWLINE_STYLE [UNIX\|DOS\|WIN32\|LF\|CRLF] ])​\ > 解释:拷贝一个 \<input>(输入文件) 文件到 \<output> (输出文件),并且替换输入文件中被 \@VAR@ 或者 \${VAR} 引用的变量值。每一个变量将被替换成当前的变量值​ - 参数解析 - COPYONLY:只拷贝文件,不进行任何的变量替换。这个选项在指定了 NEWLINE_STYLE 选项时不能使用(无效)。 - ESCAPE_QUOTES:躲过任何的反斜杠(C风格)转义。\ > 注:躲避转义,比如你有个变量在CMake中是这样的 set(FOOSTRING \"\\\"foo\\\"\") 那么在没有 ESCAPEQUOTES 选项的状态下,通过变量替换将变为 \"\"foo\"\",如果指定了 ESCAPE_QUOTES 选项,变量将不变。 - [\@ONLY]{.underline}:限制变量替换,让其只替换被 \@VAR@ 引用的变量(那么 \${VAR} 格式的变量将不会被替换)。这在配置 \${VAR} 语法的脚本时是非常有用的。 - NEWLINE_STYLE \<style>:指定输出文件中的新行格式。UNIX 和 LF 的新行是 \\n ,DOS 和 WIN32 和 CRLF 的新行格式是 \\r\\n 。 这个选项在指定了 COPYONLY 选项时不能使用(无效)。 - 在CMake对文件的操作 - file命令 - file(WRITE filename \"message to write\"... ) - 解释:WRITE选项会写一条消息到名为filename中,如果文件存在,则会覆盖原文件,如果文件不存在,他将创建该文件 - file(APPEND filename \"message to write\"... ) - 解释:APPEND选项和WRITE选项一样,只是APPEND会写到文件的末尾 - file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX]) - 解释:READ选项会将读取的文件内容存放到变量variable ,读取numBytes个字节,从offset位置开始,如果指定了[HEX]参数,二进制代码就会转换为十六进制的转换方式 - file(STRINGS filename variable [LIMITCOUNT num] [LIMITINPUT numBytes] [LIMITOUTPUT numBytes] [LENGTHMINIMUM numBytes] [LENGTHMAXIMUM numBytes] [NEWLINECONSUME] [REGEX regex] [NOHEXCONVERSION]) - 解释:STRINGS标志,将会从一个文件中将ASCII字符串的list解析出来,然后储存在variable 变量中,文件中的二进制数据将会被忽略,回车换行符会被忽略(可以设置NOHEXCONVERSION选项来禁止这个功能)。LIMITCOUNT:设定了返回字符串的最大数量;LIMITINPUT:设置了从输入文件中读取的最大字节数;LIMITOUTPUT:设置了在输出变量中允许存储的最大字节数;LENGTHMINIMUM:设置了返回字符串的最小长度,小于该长度的字符串将会被忽略;LENGTHMAXIMUM设置了返回字符串的最大长度,大于该长度的字符串将会被忽略;NEWLINECONSUME:该标志允许新行被包含到字符串中,而不是终止他们;REGEX:指定了返回的字符串必须满足的正则表达式 - 典型的使用方式:file(STRINGS myfile.txt myfile) - 该命令在变量myfile中储存了一个list,该list每一项是myfile.txt中的一行文本 - file(GLOB variable [RELATIVE path] [globbing expressions]...) - 解释:GLOB:该选项将会为所有匹配表达式的文件生成一个文件list,并将该list存放在variable 里面,文件名的查询表达式和正则表达式类似, - 查询表达式的例子:①*.cpp -匹配所有后缀是.cpp的文件②*.vb? -匹配文件后缀是.vba——.vbz的文件③f[3-5].txt :匹配f3.txt,f4.txt,f5.txt文件 - file(GLOBRECURSE variable [RELATIVE path] [FOLLOWSYMLINKS] [globbing expressions]...) - 解释:GLOB_RECURSE会生成一个类似于通常GLOB选项的list,不过该选项可以递归查找文件中的匹配项 - 比如:/dir/*.py -就会匹配所有在/dir文件下面的python文件, - file(RENAME \<oldname> \<newname>) - 解释:RENAME选项对同一个文件系统下的一个文件或目录重命名 - file(REMOVE [file1 ...]) - 解释:REMOVE选项将会删除指定的文件,包括在子路径下的文件 - file(REMOVE_RECURSE [file1 ...]) - 解释:REMOVE_RECURSE选项会删除给定的文件以及目录,包括非空目录 - file(MAKE_DIRECTORY [directory1 directory2 ...]) - 解释:MAKE_DIRECTORY选项将会创建指定的目录,如果它们的父目录不存在时,同样也会创建 - file(RELATIVE_PATH variable directory file) - 解释:RELATIVE_PATH选项会确定从direcroty参数到指定文件的相对路径,然后存到变量variable中 - file(TOCMAKEPATH path result) - 解释:TOCMAKEPATH选项会把path转换为一个以unix的 / 开头的cmake风格的路径 - file(TONATIVEPATH path result) - 解释:TONATIVEPATH选项与TOCMAKEPATH选项很相似,但是它会把cmake风格的路径转换为本地路径风格 - file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log] [EXPECTEDMD5 sum] [SHOWPROGRESS]) - 解释:DOWNLOAD将给定的url下载到指定的文件中,如果指定了LOG log,下载的日志将会被输出到log中,如果指定了STATUS status选项下载操作的状态就会被输出到status里面,该状态的返回值是一个长度为2的list,list第一个元素是操作的返回值,是一个数字 ,第二个返回值是错误的字符串,错误信息如果是0,就表示没有错误;如果指定了TIMEOUT time选项,time秒之后,操作就会推出。如果指定了EXPECTEDMD5 sum选项,下载操作会认证下载的文件的实际MD5和是否与期望值相匹配,如果不匹配,操作将返回一个错误;如果指定了SHOWPROGRESS,进度信息会被打印出来,直到操作完成 - source_group命令 - 使用该命令可以将文件在VS中进行分组显示 - sourcegroup(\"Header Files\" FILES \${HEADERFILES}) - 以上命令是将变量HEADER_FILES里面的文件,在VS显示的时候都显示在"Header Files"选项下面 - 如何构建项目 - 工程文件结构 - lib文件夹 - libA.c - libB.c - CMakeLists.txt - include文件夹 - includeA.h - inclueeB.h - CMakeLists.txt - main.c - CMakeLists.txt - 第一层CMakeLists\ > 内容如下:\ > ​[#项目名称]{.underline}\ > project(main)\ > \ > [#需要的cmake最低版本]{.underline}\ > cmakeminiumrequired(VERSION 2.8)\ > \ > [#将当前目录下的源文件名都赋给DIRSRC目录]{.underline}\ > auxsourcedirectories(. DIRSRC)\ > \ > [#添加include目录]{.underline}\ > includedirectories(include)\ > \ > [#生成可执行文件]{.underline}\ > addexecutable(main \${DIRSRC})​​​​​​​​​​​​​​\ > \ > [#添加子目录]{.underline}\ > addsubdirectories(lib)\ > \ > [#将生成的文件与动态库相连]{.underline}\ > targetlinklibraries(main test)​​​​​​\ > [#test是lib目录里面生成的]{.underline}​ - lib目录下的CMakeLists\ > 内容如下:\ > [#将当前的源文件名字都添加到DIRLIB变量下]{.underline}​\ > ​auxsourcedirector(. DIRLIB)\ > \ > ​​[#生成库文件命名为test]{.underline}\ > addlibraries(test \${DIRLIB})​​ - include目录的CMakeLists可以为空,因为我们已经将include目录包含在第一层的文件里面 - 运行其他程序 - 在配置时运行命令 - 指令:execute_process\ > 参数:\ > executeprocess(COMMAND \<cmd1> [args1...]]\ > [COMMAND \<cmd2> [args2...] [...]]\ > [WORKINGDIRECTORY \<directory>]\ > [TIMEOUT \<seconds>]\ > [RESULTVARIABLE \<variable>]\ > [OUTPUTVARIABLE \<variable>]\ > [ERRORVARIABLE \<variable>]\ > [INPUTFILE \<file>]\ > [OUTPUTFILE \<file>]\ > [ERRORFILE \<file>]\ > [OUTPUTQUIET]\ > [ERRORQUIET]\ > [OUTPUTSTRIPTRAILINGWHITESPACE]\ > [ERRORSTRIPTRAILINGWHITESPACE])​ - 作用:这条指令可以执行系统命令,将输出保存到cmake变量或文件中去,运行一个或多个给定的命令序列,每一个进程的标准输出通过管道流向下一个进程的标准输入。 - 参数解析 - COMMAND:子进程的命令行,CMake使用操作系统的API直接执行子进程,所有的参数逐字传输,没有中间脚本参与,像">"的输出重定向也会被直接的传输到子进程里面,当做普通的参数进行处理。 - WORKING_DIRECTORY:指定的工作目录将会设置为子进程的工作目录 - TIMEOUT:子进程如果在指定的秒数之内没有结束就会被中断 - RESULT_VARIABLE:变量被设置为包含子进程的运算结果,也就是命令执行的最后结果将会保存在这个变量之中,返回码将是来自最后一个子进程的整数或者一个错误描述字符串 - OUTPUTVARIABLE、ERRORVARIABLE:输出变量和错误变量

            • INPUTFILE、OUTPUTFILE、ERROR_FILE:输入文件、输出文件、错误文件 - OUTPUTQUIET、ERRORQUIET:输出忽略、错误忽略,标准输出和标准错误的结果将被默认忽略 - 例子\ > eg:\ > ​set(MAKECMD \"/src/bin/make.bat\")\ > MESSAGE(\"COMMAND: \${MAKECMD}\")\ > executeprocess(COMMAND \"\${MAKECMD}\"\ > RESULTVARIABLE CMDERROR\ > OUTPUTFILE CMDOUTPUT)\ > MESSAGE( STATUS \"CMDERROR:\" \${CMDERROR})\ > MESSAGE( STATUS \"CMDOUTPUT:\" \${CMDOUTPUT})\ > 输出:\ > ​​COMMAND:/src/bin/make.bat\ > CMDERROR:No such file or directory\ > CMDOUTPUT:\ > (因为这个路径下面没有这个文件)​\ > ​ - 在构建的时运行命令\ > [https://www.jianshu.com/p/0fc0e1613587]{.underline} - 例子(调用python脚本生成头文件):\ > findpackage(PythonInterp REQUIRED)\ > addcustomcommand(OUTPUT \"\${CMAKECURRENTBINARYDIR}/include/Generated.hpp\"\ > COMMAND \"\${PYTHONEXECUTABLE}\" \"\${CMAKECURRENTSOURCEDIR}/scripts/GenerateHeader.py\" --argument\ > DEPENDS sometarget)\ > addcustomtarget(generateheader ALL\ > DEPENDS \"\${CMAKECURRENTBINARYDIR}/include/Generated.hpp\")\ > install(FILES \${CMAKECURRENTBINARYDIR}/include/Generated.hpp DESTINATION include) - find_package:查找链接库\ > 如果编译的过程使用了外部的库,事先并不知道其头文件和链接库的位置,得在编译命令中加上包含外部库的查找路径,CMake中使用find_package方法 - find_package()命令查找***.cmake的顺序 - 介绍这个命令之前,首先得介绍一个变量:CMAKEMODULEPATH - 工程比较大的时候,我们会创建自己的cmake模块,我们需要告诉cmake这个模块在哪里,CMake就是通过CMAKEMODULEPATH这个变量来获取模块路径的 - 我们使用set来设置模块的路径:set(CMAKEMODULEPATH \${PROJECTSOURCEDIR}/cmake) - 如果上面的没有找到,就会在../.cmake/packages或者../uesr/local/share/中的包目录中查找:\<库名字大写>Config.cmake或者\<库名字小写>-config.cmake。这种查找模式称作Config模式。 - 如果找到这个包,则可以通过在工程的顶层目录中的CMakeLists.txt中添加:includedirectories(\<Name>_INCLUDEDIRS)来包含库的头文件,使用命令:targetlinklibraries(源文件 \<NAME>_LIBRARIES)将源文件以及库文件链接起来 - 无论哪一种方式,只要找到***.cmake文件,***.cmake里面都会定义下面这些变量\ > \<NAME>_FOUND\ > \<NAME>_INCLUDE_DIRS or \<NAME>_INCLUDES\ > \<NAME>_LIBRARIES or \<NAME>_LIBRARIES or \<NAME>_LIBS\ > \<NAME>_DEFINITIONS\ > 注:\<NAME>就是库名​ - CMake中使用:cmake --help-module-list命令来查看当前CMake中有哪些支持的模块 - findpackage(\<Name>)命令首先会在模块路径,也就是刚才我们介绍的CMAKEMODULEPATH变量里面存放的路径中查找Find\<Name>.cmake。查找路径依次为:变量\${CMAKEMODULE_PATH}中的所有目录,这种查找模式被称为Module模式。 - find_package - 命令参数 - FINDPACKAGE( \<name> [version] [EXACT] [QUIET] [NOMODULE] [ [ REQUIRED \| COMPONENTS ] [ componets... ] ] ) - version:需要一个版本号,给出这个参数而没有给出EXACT,那个就是找到和给出的这个版本号相互兼容就符合条件 - EXACT:要求版本号必须和version给出的精确匹配。 - QUIET:会禁掉查找的包没有被发现的警告信息。对应于Find\<Name>.cmake模块里面的的NAMEFINDQUIETLY变量。 - NO_MODULE:给出该指令之后,cmake将直接跳过Module模式的查找,直接使用Config模式查找。查找模式详见下方 - REQUIRED:该选项表示如果没有找到需要的包就会停止并且报错 - COMPONENTS:在REQUIRED选项之后,或者如果没有指定REQUIRED选项但是指定了COMPONENTS选项,在COMPONENTS后面就可以列出一些与包相关部分组件的清单 - 搜索原理 - Cmake可以支持很多外部内部的库,通过命令可以查看当前cmake支持的模块有哪些: cmake --help-module-list 。或者直接查看模块路径。Windosw的路径在cmak的安装目录:..\\share\\cmake-3.13\\Modules - cmake本身是不提供任何搜索库的便捷方法,所有搜索库并给变量赋值的操作必须由cmake代码完成 - find_psckage的搜索模式: - Module模式:搜索CMAKEMODULEPATH指定路径下的FindXXX.cmake文件(XXX就是我们要搜索的库的名字),这个CMAKEMODULEPATH变量是cmake预先定义,但是没有值,我们一旦给这个变量赋值之后,cmake就会最高优先级的在这个变量里面去查找,没有找到就在自己的安装库里面去找有没有FindXXX.cmake模块,找到之后,执行该文件从而找到XXX库,其中具体查找库并给XXXINCLUDEDIR和XXX_LIBRARIES这两个变量赋值的操作有FindXXX.cmake模块完成 - Config模式:如果Module模式没有找到,则启用Config模式查找,搜索XXXDIR路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库,其中查找库以及给XXXINCLUDEDIR和XXXLIBRARY赋值的操作都是由XXXConfig.cmake模块完成 - cmake默认采取的时Module模式,如果Module模式没有找到,才会使用Config模式查找, - ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - version选项和EXACT -
              - ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - COMPONENTS选项,有些库不是一个整体比如Qt,其中还包含QtOpenGL和QtXml组件,当我们需要使用库的组件的时候,就使用COMPONENTS这个选项 - find_package(Qt COMPONENTS QtOpenGL QtXml REQUIRED) - ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 找到之后给一些预定义的变量赋值 - 无论哪一种查找模式,只要找到包之后,就会给以下变量赋值:\<NAME>_FOUND,\<NAME>_INCLUDE_DIRS或者\<NAME>_INCLUDES,\<NAME>_LIBRARIES,\<NAME>_DEFINITIONS。这些变量都在Find\<NAME>.cmake文件中。 - 我们可以在CMakeLists.txt中使用\<NAME>_FOUND变量来检测摆包是否被找到, - ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - find_package的本质是执行一个.cmake文件,相当于cmake的内置的脚本,这个脚本将设置我们之前提到的相关的变量,相当于根据传进来的参数来使用一个查找模块,每一个常用的库在cmake里面就有一个对应的查找模块。 - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - find模块的编写流程: - 首先使用:findpath和findlibrary查找模块的头文件以及库文件,然后将结果放到\<NAME>_INCLUDE_DIR和\<NAME>_LIBRARY里面 - find_path(): - find_path(\<VAR> name1 [path1 path2 ...]) - 该命令搜索包含某个文件的路径,用于给定名字的文件所在路径, - 一条名为:\<VAR>的变量的Cache将会被创建。 - 如果在某个文件下面发现了该文件,路径就会被储存到变量里面,除非变量被清除,否则搜搜将不会进行。 - 如果没有发现该文件,\<VAR>里面储存的就是\<VAR>-NOTFOUND - find_library(): - find_library(\<VAR> name1 [path1 path2 ...]) - 查找一个库文件 - 设置:\<NAME>_INCLUDEDIRS为\<NAME>_INCLUDEDIR\<dependency1>_INCLUDE_DIRS ... - 设置 \<name>_LIBRARIES 为 \<name>_LIBRARY \<dependency1>_LIBRARIES ... - 调用宏 findpackagehandlestandardargs() 设置 \<name>_FOUND 并打印或失败信息 - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - 我们以Cmake里面自带的bzip2库为例,Cmake的module目录里面有一个:FindBZip.cmake模块,我们使用find_package(BZip2),然后CMake就会给相关的变量赋值,我们就可以调用这个模块,就可以使用模块里面的变量,模块里面的变量有哪些,我们可以使用命令: cmake --help-module FindBZip2来查看,最后面的参数就是带上Find前缀之后的模块的名字。 - 假如一个程序需要使用BZip2库,编译器需要知道bzlib.h的位置,链接器需要知道bzip2库(动态链接:.so或者.dll) -
              - 添加库的指令:find_package(BZip2 REQUIRED) - CMake里面又很多内置的库,当我们使用findpackage查找包的时候CMake首先会去CMAKEMODULE_PATH这个变量存放的路径里面去寻找 - 注意:CMAKEMODULEPATH的路径设置需要在顶层的CMakeLists.txt里面去设置。 - findpackage之后,变量:BZIPINCLUDEDIRS以及BZIP2LIBRARIES就会被设置,然后我们使用includedirectories以及targetlink_libraries来使用即可 - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - 使用一个cmake里面没有带的库 - cmake的/share/cmake-X.XX/Modules里面带的都是一些常用的库,如果我们现在需要使用一个cmake里面没有提供给我们find模块的库,做法如下: - 首先模拟生成一个生成lib文件 - 创建工程,名为:ThirdLIB - 生成一个lib文件,名为:ThirdDLL.lib - lib文件里面只提供了一个求和的add函数,返回两个int值的和 - 在CMakeLists.txt里面设置CMAKEMODULEPATH,这里设置的是本地的路径,这个路径存放的find模块 -
              - 编写自己的find模块 - 注意:cmake使用find_package查找使用的库,当我们把库名字传进去之后,cmake会在按照指定的模式查找一个:Find\<NAME>.cmake的文件,常用的库,cmake都会提供对应的.cmake文件,但是现在我们使用的是自己编写的库,所以cmake是没有提供的,需要自己编写 - 编写大致流程已经给出,我们编写的文件名必须是:Find\<Name>.cmake,现在就是"FindThidrDLL.cmake" - FindThirDLL.cmake内容如下 -
              - 修改CMakeLists.txt文件,在里面使用find_package命令添加模块、 -
              - 完成之后,打开生成的工程,查看工程的依赖项,就会有ThirdLIB.lib的选项 -
              - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - 当我们在CMake里面使用一个库时候,如何在网上查找,比如现在需要查找:apr库,在goole里面搜索:find package apr cmake,就可以直接找到对应的CMake脚本。然后复制粘贴,创建.cmake文件,放在工程根目录下面的modules目录,没有则创建之 - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -
              - addcustomcommand:(1)为某一个工程添加一个自定义的命令\ > addcustomcommand(TARGET target\ > PREBUILD \| PRELINK\| POSTBUILD\ > COMMAND command1[ARGS] [args1...]\ > [COMMAND command2[ARGS] [args2...] ...]\ > [WORKINGDIRECTORYdir]\ > [COMMENT comment][VERBATIM])\ > 作者:drybeans\ > 链接:[https://www.jianshu.com/p/66df9650a9e2]{.underline}\ > 來源:简书\ > 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。 - 执行命令的时间由第二个参数决定\ > 1.PREBUILD - 命令将会在其他依赖项执行前执行\ > 2.PRELINK - 命令将会在其他依赖项执行完后执行\ > [3.POST]{.underline}_BUILD - 命令将会在目标构建完后执行。 - 例子1:\ > addcustomcommand (\ > TARGET \${PROJECTNAME}\ > POSTBUILD\ > COMMAND \${CMAKECOMMAND} -E sleep 5\ > )\ > [#目标就是TARGET后面跟的工程]{.underline},​当PROJECTNAME被生成的时候就会执行COMMAND后面的命令 - 例子2:\ > addcustomcommand(TARGET testelf\ > ​PREBUILD\ > COMMAND\ > move E:/cfg/start.o \${CMAKEBINARYDIR}/. &&\ > )\ > ​[#在test_el执行依赖之前]{.underline},将start.o文件复制到编译目录 - addcustomcommand:(2)添加自定义命令来产生一个输出\ >     addcustomcommand(OUTPUT output1 [output2 ...]\ >                         COMMAND command1[ARGS] [args1...]\ >                         [COMMAND command2 [ARGS] [args2...] ...]\ >                         [MAINDEPENDENCYdepend]\ >                         [DEPENDS[depends...]]\ >                         [IMPLICITDEPENDS\<lang1> depend1 ...]\ >                         [WORKING_DIRECTORYdir]\ >                         [COMMENT comment] [VERBATIM] [APPEND]) - 其中ARGS选项 是为了向后兼容,MAIN_DEPENDENCY选项是针对Visual Studio给出一个建议,这两选项可以忽略 - COMMAND:指定一些在构建阶段执行的命令。如果指定了多于一条的命令,他会按照顺序去执行。如果指定了一个可执行目标的名字(被add_executable()命令创建),他会自动被在构建阶段创建的可执行文件的路径替换, - DEPENDS:指定目标依赖的文件,如果依赖的文件是和CMakeLists.txt相同目录的文件,则命令就会在CMakeLists.txt文件的,目录执行。如果没有指定DEPENDS,则只要缺少OUTPUT,该命令就会执行。如果指定的位置和CMAkeLists.txt不是同一位置,会先去创建依赖关系,先去将依赖的目标或者命令先去编译。 - WORKING_DIRECTORY:使用给定的当前目录执行命令,如果是相对路径,则相对于当前源目录对应的目录结构进行解析 - 例子\ > [#首先生成creator的可执行文件]{.underline}\ > ​addexecutable(creator creator.cxx)\ > \ > [#获取EXELOC的LOCATION属性存放到creator里面]{.underline}​​\ > gettargetproperty(creator EXELOC LOCATION)\ > \ > ​[#生成created]{.underline}.c文件\ > addcustomcommand (\ > OUTPUT \${PROJECTBINARYDIR}/created.c\ > DEPENDS creator\ > COMMAND \${EXELOC}\ > ARGS \${PROJECTBINARYDIR}/created.c\ > )\ > \ > [#使用上一步生成的created]{.underline}.c文件来生成Foo可执行文件​​\ > addexecutable(Foo \${PROJECTBINARY_DIR}/created.c) - 注意:不要再多个相互独立的文件中使用该命令产生相同的文件,防止冲突。 - addcustomtarget:增加定制目标\ > addcustomtarget(Name [ALL] [command1 [args1...]]\ > [COMMAND command2 [args2...] ...]\ > [DEPENDS depend depend depend ... ]\ > [BYPRODUCTS [files...]]\ > [WORKINGDIRECTORY dir]\ > [COMMENT comment]\ > [VERBATIM] [USESTERMINAL]\ > [SOURCES src1 [src2...]]) - 命令 addcustomtarget 可以增加定制目标,常常用于编译文档、运行测试用例等。 - addcustomcommand和addcustomtarget的区别 - 命令命名里面的区别就在于:command和target,前者是自定义命令,后者是自定义目标 - 目标:一般来说目标是调用:addlibrary或者addexecutable生成的exe或者库,他们具有许多属性集,这些就是所谓目标,而使用addcustomtarget定义的叫做自定义目标,因此这些"目标"区别于正常的目标,他们不生成exe或者lib,但是仍然会具有一些正常目标相同的属性,构建他们的时候,只是调用了为他们设置的命令,如果自定义目标对于其他目标有依赖,那么就会优先生成依赖的那些目标 - 自定义命令:自定义命令不是一个"可构建"的对象,并且没有可以设置的属性,自定义命令是一个在构建依赖目标之前被调用的命令,自定义命令的依赖可以通过addcustomcommand(TARGET target …)形式显式设置,也可以通过addcustomcommand(OUTPUT output1 …)生成文件的形式隐式设置。显示执行的时候,每次构建目标,首先会执行自定义的命令,隐式执行的时候,如果自定义的命令依赖于其他文件,则在构建目标的时候先去执行生成其他文件。 - 如何添加C++项目中的常用选项 > 如:如何支持C++11、如何支持IDE等 - 如何激活C++11功能 > 语法:targetcompilefeatures(\<target> \<PRIVATE\|PUBLIC\|INTERFACE> \<feature> [...]) - targetcompilefeatures(\<projectname> PUBLIC cxxstd_11) - 参数target必须是由:addexecutable或者addlibrary生成的目标 - 另外一种支持C++标准的方法 > #设置C++标准级别 > ​set(CMAKECXXSTANDARD 11) > ​ > [#告诉CMake使用他]{.underline}​它 > set(CMAKECXXSTANDARDREQUIRED ON) > ​ > #(可选)​​确保-std=C++11 > set(CMAKECXX_EXTENSIONS OFF) - CMake的过程间优化 - 如果编译器不支持,就会将设置的过程间优化标记为错误,可以使用命令:checkiposupported()来查看 > [#检测编译器是否支持过程间优化]{.underline} > ​checkiposupported(RESULT result) > > [#如果不支持]{.underline},判断进不去​​ > if(result) > [#为工程foo设置]{.underline}​过程间优化 > settargetproperties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) > endif() - CMake的option简介 - option命令可以设置默认值 > option(address \"this is path for value\" ON) - 命令表示,当用户没有设置address的时候,默认值就是ON,当用户显示的设置address的时候,address里面就是用户设置的值 - 注意:加入有一些变量依赖了address,但是这些变量的使用在option语句之前,此时对于这些变量来说,address还是属于没有定义的。 - 在用户没有提供ON或者OFF的时候,默认是OFF。如果option有改变,一定要清理CMakeCache.txt文件和CMakeFiles文件夹 - CMake编译选项的管理 - 在工程的根目录,编写CMakeLists.txt,另外单独创建option.txt文件,专门管理编译选项 - 在CMakeLists.txt中加入: > include option.txt​ - 在option.txt中添加: > /*USEMYMATH 为编译开关,中间的字符串为描述信息,ON/OFF 为默认选项*/\ > option (USEMYMATH \ >         \"Use tutorial provided math implementation\" ON)  - 在编译之前,执行ccmake . 就会弹出cmake GUI,进行配置所有的编译开关,配置结束之后会生成一个CMakeCache.txt,配置后的编译选项会保存在这个文件中\ > [https://blog.csdn.net/haima1998/article/details/23352881]{.underline} - 怎么生成依赖于其他option的option > [#设置option]{.underline}:USECURL > ​option(USECURL \"use libcurl\" ON) > ​ > [#设置option]{.underline}:USEMATH​​ > option(USEMATH \"use libm\" ON) > ​ > [#设置一个option]{.underline}:​​DEPENTUSECURL,第二个参数是他的说明,ON后面的参数是一个表达式,当"USECURL"且"USEMATH"为真的时候,DEPENTUSECURL取ON,为假取OFF\ > cmakedependentoption(DEPENTUSECURL \"this is dependent on USECURL\" ON \"USECURL;NOT USE_MATH\" OFF) - 属性调试模块(CMakePrintHelpers) > CMAKEPRINTPROPERTIES([TARGETS target1 .. targetN]\ > [SOURCES source1 .. sourceN] > [DIRECTORIES dir1 .. dirN] > [TESTS test1 .. testN] > [CACHE_ENTRIES entry1 .. entryN] > PROPERTIES prop1 .. propN ) - 如果要检查foo目标的INTERFACEINCLUDEDIRS和LOCATION的值,则执行: > cmakeprintproperties ( TARGETS foo > PROPERTIES > INTERFACEINCLUDEDIRS > LOCATION ) -
              CMake3.8以上叫做Modern CMake


打赏作者以资鼓励:
移动端扫码阅读: