【Cmake 增加编译参数 】cmake增加编译参数和预处理指令的几种方法

简介: 【Cmake 增加编译参数 】cmake增加编译参数和预处理指令的几种方法

简述几种方法

CMake是一个跨平台的构建系统,它允许开发者编写一种简单的文件来描述所有平台的构建过程。在CMake中,你可以通过以下方式增加编译参数和预处理指令:

  1. 添加编译参数:
  • 使用add_compile_options命令。这个命令将添加到所有的目标上。例如:
add_compile_options(-Wall)
  • 使用target_compile_options命令。这个命令只会添加到指定的目标上。例如:
target_compile_options(target PRIVATE -Wall)
  • set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...")是另一种常见的添加编译参数的方法。这种方法直接修改了CMake的全局变量,所以它会影响到所有的目标。
    例如,如果你想添加-Wall编译选项,你可以这样写:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
  • 这行代码的意思是,将-Wall添加到CMAKE_CXX_FLAGS变量中。CMAKE_CXX_FLAGS变量包含了C++编译器的编译选项。
    同样的,对于C编译器,你可以使用CMAKE_C_FLAGS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
  • 这种方法的一个缺点是,它会影响到所有的目标,而不仅仅是一个特定的目标。如果你只想为一个特定的目标添加编译选项,你应该使用target_compile_options命令。
  1. 添加预处理指令:
  • 使用add_definitions命令。这个命令将添加到所有的目标上。例如:
add_definitions(-DDEBUG)
  • 使用target_compile_definitions命令。这个命令只会添加到指定的目标上。例如:
target_compile_definitions(target PRIVATE DEBUG)
  1. 在上述两个例子中,DEBUG是一个预处理指令,它会在编译时被定义。

注意,PRIVATEPUBLICINTERFACE这些关键字的含义:

  • PRIVATE:只有目标自己会使用这些编译参数。
  • PUBLIC:目标自己和其他依赖这个目标的目标都会使用这些编译参数。
  • INTERFACE:只有其他依赖这个目标的目标会使用这些编译参数。

以上就是在CMake中增加编译参数和预处理指令的所有方法。

add_definitions 解析

根据CMake官方文档,add_definitions命令用于向源文件的编译中添加-D定义标志。这个命令可以用来添加任何标志,但它主要是用来添加预处理器定义的。

例如,add_definitions(-DFOO -DBAR ...)会将定义添加到当前目录中的目标的编译器命令行,无论这个命令是在添加目标之前还是之后调用的,以及在此命令调用后添加的子目录中的目标。

然而,这个命令已经被以下的替代方法取代:

  • 使用add_compile_definitions()来添加预处理器定义。
  • 使用include_directories()来添加包含目录。
  • 使用add_compile_options()来添加其他选项。

以-D或/D开头的标志,看起来像预处理器定义的,会自动添加到当前目录的COMPILE_DEFINITIONS目录属性中。具有非平凡值的定义可能会保留在标志集中,而不是被转换,这是出于向后兼容性的考虑。

因此,你的说法是正确的,add_definitions命令可以用于添加编译器标志,但这并不是它的主要用途,而且在某些情况下可能会导致问题。对于编译器标志,如-Wall和-g,更推荐使用add_compile_options()命令。

add_compile_options 解析

add_compile_options命令用于向源文件的编译中添加选项。这些选项会被添加到COMPILE_OPTIONS目录属性中,这些选项在编译当前目录及其子目录中的目标时会被使用。需要注意的是,这些选项在链接时不会被使用,链接时的选项需要使用add_link_options()命令来添加。

add_compile_options命令的参数可以使用生成器表达式,最终用于目标的选项集是通过从当前目标和其依赖项的使用要求中累积选项来构造的,选项集会进行去重以避免重复。

例如,你可以在特定的编译器条件下使用这个命令:

if (MSVC)
 # warning level 4
 add_compile_options(/W4)
else()
 # additional warnings
 add_compile_options(-Wall -Wextra -Wpedantic)
endif()

如果你想要为特定的目标添加编译选项,你应该使用target_compile_options命令。例如,如果你有一个目标叫做my_target,你可以这样为它添加编译选项:

target_compile_options(my_target PRIVATE -Wall -Wextra -Wpedantic)

在这个例子中,-Wall -Wextra -Wpedantic这些编译选项只会被添加到my_target这个目标,而不会影响到其他的目标。

不同用法 的 区别

CMAKE_<LANG>_FLAGS是用于所有配置时构建语言的全局标志。这些标志将被传递给编译器的所有调用,包括驱动编译和驱动链接的调用。

对于每种语言,如果这个变量没有被定义,它会使用环境变量和CMake的工具链内置默认值进行初始化并存储在缓存中。例如,CMAKE_CXX_FLAGS会被CXXFLAGS环境变量初始化。

这个值是一个命令行字符串片段,因此,多个选项应该由空格分隔,带有空格的选项应该被引用。

这个变量中的标志将在每个配置的CMAKE_<LANG>_FLAGS_<CONFIG>变量中的标志之前被传递。在驱动编译的调用中,这两个变量中的标志都会在add_compile_options()target_compile_options()等命令添加的标志之前被传递。在驱动链接的调用中,它们会在add_link_options()target_link_options()等命令添加的标志之前被传递。

因此,add_compile_optionsset(CMAKE_CXX_FLAGS ...)都可以用来添加编译选项,但是它们的使用场景和影响范围是不同的。add_compile_options更加灵活,可以在特定条件下添加选项,而set(CMAKE_CXX_FLAGS ...)则是全局设置,会影响所有的目标。这两个命令可以同时使用,它们的效果是累积的,不会互相覆盖。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

目录
相关文章
|
自然语言处理 安全 C++
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
11055 4
|
存储 安全 算法
Linux命令sha256sum详解
`sha256sum`是Linux中用于计算文件SHA-256哈希的命令,确保数据完整性。它基于安全哈希算法,产生不可逆的64字符哈希值,用于验证文件未被篡改。主要参数包括`-b`(二进制模式)、`-c`(检查校验和)、`-t`(文本模式)。应用示例包括计算单个文件哈希、校验文件哈希及批量处理多个文件。最佳实践包括定期验证文件、保存校验和文件和结合其他安全工具使用。
|
Android开发
基于android-11.0.0_r39,系统应用的手动签名方法和过程
本文介绍了基于Android 11.0.0_r39版本进行系统应用手动签名的方法和解决签名过程中遇到的错误,包括处理`no conscrypt_openjdk_jni-linux-x86_64`和`RegisterNatives failed`的问题。
1084 2
|
Unix
深入理解 CMake 的 `cmake --build` 命令
深入理解 CMake 的 `cmake --build` 命令
3490 1
|
存储 安全 算法
【C/C++ std::memory_order 枚举】掌握 C++ 内存模型:深入理解 std::memory_order 的原理与应用
【C/C++ std::memory_order 枚举】掌握 C++ 内存模型:深入理解 std::memory_order 的原理与应用
1754 0
解决办法:无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。
解决办法:无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。
2424 0
|
存储 NoSQL Linux
《探索 Linux 命令:systemd-coredumpctl》
**《systemd-coredumpctl概览》** `systemd-coredumpctl`, Linux中管理&分析core dump的利器。集中管控systemd生成的转储,详述crash细节。用`--list`查看所有转储,`--info &lt;ID&gt;`深入单一转储。需注意权限、存储管理,配gdb深化分析。精通此命令,加速问题诊断。#LinuxTips #CoreDumpAnalysis
|
Java Android开发
android 设置系统时间的流程
android 设置系统时间的方法
1236 2
|
异构计算 内存技术
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
972 0