cmake语法

1. 基本语法


命令行

  1. cmake -B build
    进行 build 目录的创建与 Makefile 等构建文件的生成,-B 选项后面需要提供一个目录路径,这个路径就是用来存放生成的构建系统文件和其他构建过程中产生的中间文件的目录。在上述命令中,build 就是构建目录的名称,build 表明生成的构建系统文件都存放在 ${PROJECT_SOURCE_DIR}/build 目录下。
    • 可加参数 -DCMAKE_BUILD_TYPE=RELEASE 自由调节编译的模式。
    • 可加参数 -G Ninja 改变构建时候用的程序,Ninja是在有了cmake之后才出现的,在编写时更好的适配了cmake工具,因此性能表现上一般会更好。
  2. cmake --build build
    在build目录下并行构建。
    • 可加参数 --parallel N-jN 进行N线程并行构建

执行

  1. 简单说明一下上面两条 cmake 的命令以及 cmake 工具的逻辑。cmake 是在 make 工具之后出现的,为 make 提供跨平台与跨语言支持的一种工具。cmake 提供了一种简化跨平台构建的方式。传统使用 make 时需要手工编写 Makefile 并执行进行系统构建,Makefile 中可能包含平台的一些配置信息等导致 Makefile 的跨平台支持比较差,并且 Makefile 的多语言支持也比较差。而 cmake 的思路是通过编写 CMakeLists.txt,解释执行 CMakeLists.txt 用来生成 Makefile,最终再执行 Makefile 进行系统构建,用更高层的抽象来支持跨平台与跨语言的特性。在这个思路上 cmake 后来又发展出了对于 Ninja,Visual Studio,Xcode 等构建系统的支持,从而达成了目标。
  2. cmake -B build 是 cmake 的执行命令,具体功能就是执行我们编写的 CMakeLists.txt 文件。刚才提到 cmake 是一门解释型语言,因此 cmake 的解释器会以根目录的 CMakeLists.txt 作为入口进行解释执行。如果在 CMakeLists.txt 文件中使用了 add_subdirectory() 命令,指定了其他子目录,那么 cmake 会进入这些子目录的 CMakeLists.txt 中递归执行。最终 cmake 生成指定构建系统所需的构建文件并存放在 build 目录。
  3. cmake --build build 是通过 cmake 调用相应的构建工具构建项目的过程,这个过程与 cmake 工具无关。

project

  1. 参数加上项目的名字,比如 project(hello)
  2. 这个有什么用呢,其实没什么用,但是又有那么一点用。
  3. 比如 MSVC 会使用这个项目名在 build 里面生成 hello.sln 文件以作他用,也算是一点用。
  4. 同时这个命令会初始化一些可以访问的变量,例如 PROJECT_NAME,会输出 hello。类似的还有
    1. hello_SOURCE_DIR
    2. hello_BINARY_DIR
    3. PROJECT_SOURCE_DIR
    4. PROJECT_BINARY_DIR
    5. CMAKE_CURRENT_SOURCE_DIR
    6. CMAKE_CURRENT_BINARY_DIR
    7. 等~
  5. 还有一个很重要的参数 LANGUAGES 字段,默认情况下为 C 和 CXX,使用这个参数则可以明确的指定项目需要的语言(可以多于一种)。例如如果指定了语言为 CXX,那么添加一个C语言的文件就会报错。

add_subdirectory

  1. cmake 中的调用语句,填写一个文件夹路径 cmake 的解释器会跳转到文件夹目录下寻找对应的 CMakeLists.txt 文件解释执行。如果没有对应的 CMakeLists.txt 则会报错 does not contain a CMakeLists.txt file. 并中断 cmake 执行,请谨慎使用。
    在这里插入图片描述

add_executable

  1. 第一个参数是可执行文件的名称,指明生成的可执行文件
  2. 之后的参数写可执行文件所依赖的 cpp 文件,这部分可以暂时不加后面的依赖文件,后续通过 target_sources 命令补加。
  3. 依赖文件可以用双引号 "" 包裹,一种可选的表达方式,但如果文件名中有空格就必须用双引号包裹,防止被解释器错误识别。

target_sources

  1. 补充上一条命令,为可执行文件添加依赖的 cpp 文件。第一个参数写可执行文件,第二个参数写 PUBLIC 表示依赖的权限,之后的参数写依赖的文件cpp文件。

set

  1. 比较重要的一条命令,定义 cmake 中的变量。第一个参数写变量的名称,后续参数写变量所指代的内容。
  2. cmake 所定义的变量在后续的使用时要通过 ${变量名} 语法进行访问。

file

  1. 也是一条定义变量的命令,在形式上为 set 的书写做了一些简化
  2. 第一个参数可以写 GLOB 表示当前目录的搜索,也可以写 GLOB_RECURSE 表示当前目录与其子目录递归的搜索。
  3. 第二个参数写变量名。
  4. 第三个参数可写可不写,CONFIGURE_DEPENDS 表示后续的文件产生增加等变化时 cmake 会重新进行一次构建,如果不写这个参数那么添加一个新的 cpp 可能就不能被及时的放进变量中,导致编译失败。
  5. 之后的参数形如 *.cpp *.h 等,表示通配的内容,当前目录下所有类似形式的文件名都会被放入变量之中以供取用。

add_library

  1. 生成库文件,第一个参数是库文件的名称,第二个参数可以用 STATIC 或者 SHARED,分别代表动态库和静态库,之后的参数写库所依赖的 cpp 文件即可。
  2. 还有一种很厉害的库叫对象库,参数用 OBJECT 表示。对象库厉害就厉害在他不生成一个库,而是直接把库内容植入使用库的可执行文件中,浑然天成。那有人就会问了,不生成库直接植入在可执行文件中,那我为什么还要打一个库,岂不是多此一举,直接把 cpp 依赖加入可执行文件不就行了。诶,这你就有所不知了,我自己打成一个库不就可以使用和可执行文件不同的编译选项。
  3. 在 linux 下生成的静态库以 .a 结尾,动态库以 .so 结尾。
  4. 在 windows 下静态库以 .lib 结尾,动态库以 .dll 结尾。

message

  1. 打印指令,里面加字符串可以在 cmake 的时候输出信息,字符串中可以使用 ${变量名} 语法来打印之前定义的变量。
  2. 这个命令可以加修饰符来表示不同信息的打印
    1. 可以什么都不加,直接写一个字符串,这个情况就表示我知道你很急,但是你先别急,字符串会直接打印在屏幕上不加任何修饰。
    2. 可以加 STATUS 再写字符串,这个情况是正常的信息输出,一般会在前面给加两个杠 --
    3. 可以加 WARNING,这个情况表示值得注意了,可能与预期不符,一般会改变成黄色并和下面留出一段距离。
    4. 可以加 FATAL_ERROR,这个情况就非常的危及,发生了红色错误并且直接停止 cmake,比如用 find_package 寻找一个库找不到的时候就会发这个信息。
    5. 可以加 SEND_ERROR,也是发红色错误信息,但是并不停止 cmake,应该是还没有危及到生命。

target_link_libraries

  1. 创建了可执行文件和库文件之后,如果想用可执行文件就需要这个命令。他的第一个参数是希望添加的目标可执行文件,第二个参数是 PUBLIC 表示链接权限,之后的参数写想要链接的库文件。

target_include_directories

  1. 添加我们某一个目录为目标文件的include搜索目录。
  2. 第一个参数写目标文件,可以是一个可执行文件也可以是一个库文件。
  3. 第二个参数写 PUBLIC 或者 PRIVATE,表示添加的权限,如果是公有的那么在其他可执行文件链接的时候也会传播include的搜索目录,私有的则不会。
  4. 之后的参数需要能够表示一个目录的路径,例如写一个库文件就表示库文件所在的目录路径,写一个 . 就表示目标文件所在的目录路径。

find_package

  1. 通过 find_package 这个命令查找预安装的库,原理是通过执行预安装的 XXXConfig.cmake 文件,通过这个文件引入一些依赖或定义一些变量,然后我们的项目中就可以使用这个库了。
  2. 例如 find_package(TBB REQUIRED) 这个命令就会执行 TBBConfig.cmake 引入 TBB 这个库。
  3. REQUIRED 表示在找不到所需的包时发出错误信息并停止构建,如果省略了 REQUIRED 则当 cmake 没有找到 TBB 时会继续构建,这可能导致编译错误或运行时错误。
  4. find_package(TBB) 会把一个变量 TBB_FOUND 根据有没有找到设置为 treu 或 false。如果不加 REQUIRED 选项也是可以的,这时就需要用户通过手动判断 TBB_FOUND 来保证安全,例如在未找到库时可以发出一段警告,或者通过 TBB_FOUND 的值来定义一个 WITH_TBB 的宏在源文件内,通过这个宏分别实现带 TBB 库和不带 TBB 库的两套版本。

2. 标准模板

在这里插入图片描述


3. 项目模块化管理

推荐结构

在这里插入图片描述

  • 注意,推荐在include下进行一层项目名的嵌套,其作用类似于命名空间,隔绝项目头文件与标准库头文件或项目头文件之间的冲突。

1. 例如

在这里插入图片描述

2. 配置CMakeList.txt

在这里插入图片描述

3. 子项目的CMakeList.txt

在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值