首页 > 其他分享 >CMake实用知识点之二

CMake实用知识点之二

时间:2024-07-19 21:18:20浏览次数:14  
标签:知识点 CMAKE CMake CXX LIST 之二 编译器 cmake

1 CMP0003

该策略与链接指令的相对路径解析有关,就是在链接共享库时如何解释相对路径。

背景介绍

  • OLD 行为: 在旧行为下,相对路径被直接传递给链接器。这可能会导致在构建和运行时出现未定义的行为,因为相对路径是相对于构建目录解释的,而不是相对于目标文件的目录。
  • NEW 行为: 在新行为下,CMake 将相对路径转换为绝对路径,确保链接器始终能够正确找到共享库。

使用方法

通过设置cmake_policy(SET CMP0003 NEW),告诉CMake使用新行为处理相对路径。这通常是更安全和可靠的选择,尤其是在复杂的项目中。

示例代码

add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable ../lib/mylib)

如果不设置 CMP0003 策略,CMake 可能会将 ../lib/mylib 作为相对路径传递给链接器。在一些情况下,这可能会导致链接失败或者运行时找不到库的问题。而通过设置 cmake_policy(SET CMP0003 NEW),CMake 会将 ../lib/mylib 转换为绝对路径,例如 /path/to/project/lib/mylib,这样可以确保链接器正确找到库文件。

# CMake会解析命令cmake_policy是否存在,若存在返回true,否则返回false
# 注意:这是命令函数
if(COMMAND cmake_policy)
  cmake_policy(SET CMP0003 NEW)
endif()

2 ccache

set(CMAKE_C_COMPILER "ccache") 在 CMake 脚本中将 C 编译器设置为 ccache。不过,通常这是不对的,因为 ccache 不是一个编译器,而是一个编译器缓存工具,需要编译器来加载这个缓存工具。ccache 是一个用于加速 C/C++ 编译的工具,通过缓存编译结果,当相同的代码再次编译时,可以直接从缓存中获取结果,而不需要实际调用编译器。

要正确地使用 ccache 与 CMake,需要设置 C 和 C++ 编译器来使用 ccache 包装实际的编译器,如 gcc 或 clang。下面是一个示例,展示了如何在 CMake 中正确地使用 ccache:

set(CMAKE_C_COMPILER_LAUNCHER ccache)
set(CMAKE_CXX_COMPILER_LAUNCHER ccache)

这个配置告诉 CMake 在调用实际的 C 和 C++ 编译器之前,使用 ccache。

cmake_minimum_required(VERSION 3.0)
project(MyProject)

# 使用 ccache 作为编译器缓存工具
set(CMAKE_C_COMPILER_LAUNCHER ccache)
set(CMAKE_CXX_COMPILER_LAUNCHER ccache)

add_executable(MyExecutable main.cpp)

通过这种方式,可以确保每次构建都会使用 ccache,从而加快重复构建的速度。

  1. 安装 ccache: sudo apt-get install ccache

  2. 配置环境变量(可选): 如果希望 ccache 始终生效,可以在你的 shell 配置文件中添加以下内容:

     export PATH="/usr/lib/ccache:$PATH"
    
  3. 运行 CMake 构建:

     mkdir build
     cd build
     cmake ..
     make
    

通过这种方式,ccache 会被自动使用,帮助加速编译过程.

3 string

在 CMake 中,string 命令用于处理和操作字符串。它提供了多种功能,可以用于字符串的操作,如查找子字符串、替换子字符串、转换大小写等。以下是一些常见的 string 命令及其用法:

常见用法

  • 字符串长度

    string(LENGTH "Hello, World!" len)
    message(STATUS "The length of the string is: ${len}")

  • 子字符串提取

    string(SUBSTRING "Hello, World!" 7 5 substr)
    message(STATUS "The substring is: ${substr}")

  • 查找子字符串

    string(FIND "Hello, World!" "World" pos)
    message(STATUS "The position of 'World' is: ${pos}")

  • 字符串替换

    将“Hello, World”字符串中的World替换成CMake

    string(REPLACE "World" "CMake" new_string "Hello, World!")
    message(STATUS "The new string is: ${new_string}")

  • 字符串比较

    string(COMPARE EQUAL "foo" "foo" result)
    if (result)
    message(STATUS "Strings are equal")
    else()
    message(STATUS "Strings are not equal")
    endif()

  • 转换大小写

    string(TOUPPER "Hello, World!" upper)
    message(STATUS "Uppercase: ${upper}")

    string(TOLOWER "Hello, World!" lower)
    message(STATUS "Lowercase: ${lower}")

  • 字符串拼接

    set(str1 "Hello")
    set(str2 "World")
    set(full_str "${str1}, ${str2}!")
    message(STATUS "The concatenated string is: ${full_str}")

实际示例

假设有一个项目,需要根据某些条件动态生成一些文件名。可以使用 string 命令来处理这些字符串。

cmake_minimum_required(VERSION 3.0)
project(MyProject)

# 提取文件名的基础部分
string(REGEX REPLACE "(.+)\\..*" "\\1" base_name "example.txt")
message(STATUS "Base name: ${base_name}")


SET( MARS_VERSION 2.7.1.240708_rc )
# 将每一个段连续的数字都读取出来,并放在变量MARS_VERSIONS中,且以数组的方式存放
STRING( REGEX MATCHALL "[0-9]+" MARS_VERSIONS ${MARS_VERSION} ) 
LIST( GET MARS_VERSIONS 0 MARS_VERSION_MAJOR) # 
LIST( GET MARS_VERSIONS 1 MARS_VERSION_MINOR)
LIST( GET MARS_VERSIONS 2 MARS_VERSION_PATCH)

# 将文件名转换为大写
string(TOUPPER "${base_name}" upper_base_name)
message(STATUS "Uppercase base name: ${upper_base_name}")

# 生成新的文件名
set(new_file "${upper_base_name}.log")
message(STATUS "New file name: ${new_file}")

在这个示例中,首先提取文件名的基础部分,然后将其转换为大写,最后生成一个新的文件名。

总结

CMake 中的 string 命令非常强大,适用于各种字符串操作和处理任务。这些功能在构建复杂项目时尤其有用,可以帮助你动态生成配置、处理文件路径和名称等。掌握这些命令将使你的 CMake 脚本更加灵活和强大。

4 list

在 CMake 中,list 命令用于操作 CMake 列表。CMake 列表是以分号分隔的一系列字符串,它们可以用来存储和管理多个值。list 命令提供了一组函数来操作这些列表,包括添加、删除、查找、替换和排序列表项等。以下是一些常见的 list 命令及其用法示例:

4.1 常见用法

  1. 创建和初始化列表

set(MY_LIST "item1;item2;item3")
或者通过追加的方式:

list(APPEND MY_LIST "item1" "item2" "item3")

  1. 添加元素: list(APPEND MY_LIST "item4" "item5")

  2. 插入元素:在指定位置插入元素:list(INSERT MY_LIST 1 "new_item"),在索引 1 位置插入 new_item。

  3. 删除元素:

    • 根据索引删除元素:list(REMOVE_AT MY_LIST 1),删除索引 1 位置的元素。
    • 根据值删除元素:list(REMOVE_ITEM MY_LIST "item3"),删除列表中所有等于 item3 的元素。
  4. 查找元素:list(FIND MY_LIST "item2" INDEX)
    查找 item2 在列表中的索引,并存储在变量 INDEX 中。如果未找到,INDEX 的值将为 -1。

  5. 获取列表长度:

    • list(LENGTH MY_LIST LENGTH), 获取列表的长度,并存储在变量 LENGTH 中。
    • list(GET MY_LIST 0 FIRST_ITEM), 获取索引 0 位置的元素,并存储在变量 FIRST_ITEM 中。
  6. 合并两个列表:list(APPEND LIST1 ${LIST2}) 将 LIST2 的元素追加到 LIST1 中。

  7. 分割字符串为列表: string(REPLACE ";" ";" MY_LIST "item1;item2;item3"), 这会将字符串 "item1;item2;item3" 转换为列表 MY_LIST。

  8. 连接列表为字符串: list(JOIN MY_LIST "," JOINED_STRING),这会将 MY_LIST 中的元素使用逗号连接成一个字符串,并存储在变量 JOINED_STRING 中。

  9. 获取列表元素: list(GET MARS_VERSION 0 MARS_VERSION_MAJOR), 将列表中的第一个元素取出来放到变量MARS_VERSION_MAJOR中

4.2 示例

以下是一个完整的示例,展示了如何在 CMake 中使用 list 命令来操作列表

	cmake_minimum_required(VERSION 3.0)
	project(ListExample)

	# 创建和初始化列表
	set(MY_LIST "item1;item2;item3")

	# 添加元素
	list(APPEND MY_LIST "item4" "item5")

	# 插入元素
	list(INSERT MY_LIST 1 "new_item")

	# 删除元素
	list(REMOVE_AT MY_LIST 2)
	list(REMOVE_ITEM MY_LIST "item5")

	# 查找元素
	list(FIND MY_LIST "item3" INDEX)
	message(STATUS "Index of item3: ${INDEX}")

	# 获取列表长度
	list(LENGTH MY_LIST LENGTH)
	message(STATUS "Length of MY_LIST: ${LENGTH}")

	# 获取列表元素
	list(GET MY_LIST 0 FIRST_ITEM)
	message(STATUS "First item: ${FIRST_ITEM}")

	# 合并两个列表
	set(OTHER_LIST "other1;other2")
	list(APPEND MY_LIST ${OTHER_LIST})

	# 连接列表为字符串
	list(JOIN MY_LIST "," JOINED_STRING)
	message(STATUS "Joined string: ${JOINED_STRING}")

4.3 总结

在 CMake 中,list 命令是处理和操作列表的强大工具。它可以用来创建、修改和查询列表,方便管理和处理多个值。在构建系统中,列表操作非常常见,因此掌握这些命令将有助于编写更加灵活和高效的 CMake 脚本。

5 include

在 CMake 中,include 命令的作用是引入和执行其他 CMake 脚本文件。这允许你将CMake配置拆分成多个文件,以提高可读性和可维护性。include 命令可以加载指定的CMake文件,并在当前作用域内执行其中的命令。

OPTIONAL: 如是没有该文件,也不会报警。更加灵活

include(<filename>)

<filename> 是要包含的 CMake 文件的路径。如果文件不存在,CMake 会发出警告。

  • 假如有如下目录结构:

      project/
      ├── CMakeLists.txt
      ├── src/
      │   └── CMakeLists.txt
      └── cmake/
      		├── CommonSettings.cmake
      		└── CompilerOptions.cmake
    
  • CMakeLists.txt如下:

      cmake_minimum_required(VERSION 3.10)
      project(MyProject)
    
      # 包含通用设置
      include(cmake/CommonSettings.cmake)
    
      # 包含编译器选项
      include(cmake/CompilerOptions.cmake)
    
      # 添加子目录
      add_subdirectory(src)
    
  • CommonSettings.cmake
    在 cmake/CommonSettings.cmake 中,你可以定义一些通用设置,例如:

      # 设置一些通用编译选项
      set(CMAKE_CXX_STANDARD 17)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      set(CMAKE_CXX_EXTENSIONS OFF)
    
  • CompilerOptions.cmake
    在 cmake/CompilerOptions.cmake 中,你可以定义一些与编译器相关的选项,例如:

      # 设置编译器选项
      if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
      elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
      		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
      endif()
    
  • 条件包含

    还可以使用条件语句来有选择地包含文件:

      if (EXISTS "${CMAKE_SOURCE_DIR}/cmake/OptionalSettings.cmake")
      		include(cmake/OptionalSettings.cmake)
      endif()
    
  • include_guard

    为了防止多次包含同一个文件(类似于 C/C++ 中的 include guard),你可以使用 include_guard 命令:

      include_guard(GLOBAL)
    
  • 总结

    include 命令在 CMake 中的主要作用是允许你将构建配置分散到多个文件中,从而提高配置的可维护性和可读性。通过将常见的设置和选项拆分到单独的文件中,你可以更轻松地管理和复用这些配置。

6 CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT

CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT是一个CMake的内部变量,‌它表示CMAKE_INSTALL_PREFIX被初始化为默认值。‌这个变量通常在第一次运行CMake时设置,‌当在新的构建树中运行CMake且CMAKE_INSTALL_PREFIX环境变量未设置时,‌CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT会被设置为true。

‌这个变量的主要作用是提供一个默认的prefix值,‌同时保留从命令行覆盖这个默认值的能力。‌这意味着,‌如果用户想要改变安装的前缀路径,‌就可以通过命令行选项来实现,‌而不需要手动修改CMakeLists.txt文件中的设置。‌这种机制使得CMake更加灵活和用户友好,‌允许用户在构建和安装过程中根据需要调整安装路径。

7 if(MSVC)

在CMake中,‌使用if(MSVC)是判断是否使用的是Microsoft Visual Studio的编译器。‌

当你在CMake脚本中使用if(MSVC)时,‌你正在检查当前编译器是否为Microsoft Visual Studio的编译器。‌如果条件为真,‌即当前使用的是Microsoft Visual Studio编译器,‌那么CMake会执行if(MSVC)块内的命令。‌这种检查通常用于根据编译器的不同调整构建配置,‌例如设置特定的编译标志或选择不同的源代码路径。‌

此外,‌CMake还提供了其他方法来检测编译器的具体类型和版本,‌例如通过检查CMAKE_CXX_COMPILER_ID变量的值来确定是否使用的是MSVC或其他类型的编译器。‌例如,‌如果使用的是Microsoft Visual Studio编译器,‌CMAKE_CXX_COMPILER_ID的值将为"MSVC"。‌而如果是使用Mingw编译器,‌其值将为"GNU"12。‌

总的来说,‌if(MSVC)在CMake中用于特定于Microsoft Visual Studio编译器的条件判断,‌允许开发者根据编译器的不同进行相应的配置调整。‌

8 set

set(<variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])

<type>的值可以是以下值之一

FILEPATH = File chooser dialog.
PATH     = Directory chooser dialog.
STRING   = Arbitrary string.
BOOL     = Boolean ON/OFF checkbox.
INTERNAL = No GUI entry (used for persistent variables).

9 CMAKE_BUILD_TYPE

它可以有以下四种情况Debug, Release,RelWithDebInfo, 或 MinSizeRel

在 CMake 中,CMAKE_BUILD_TYPE 变量用于指定构建类型,它决定了编译器和链接器的设置。这些设置通常包括优化级别、调试信息、以及其他相关的编译选项。以下是 CMake 中常见的四种构建类型及其区别:

  1. Debug
  • 特点:包含调试信息,禁用优化。
  • 编译器选项:
    • GCC/Clang:-g
    • MSVC:/Zi
  • 用途:用于开发和调试。包含详细的调试信息,方便使用调试器(如 gdb、lldb)进行代码调试。
  1. Release
  • 特点:启用优化,不包含调试信息。
  • 编译器选项:
    • GCC/Clang:-O3 或 -O2(具体取决于 CMake 版本和配置)
    • MSVC:/O2
  • 用途:用于发布。生成的二进制文件运行速度更快,文件尺寸更小,但不包含调试信息,调试难度较大。
  1. RelWithDebInfo (Release with Debug Information)
  • 特点:启用优化,包含调试信息。
  • 编译器选项:
    • GCC/Clang:-O2 -g
    • MSVC:/O2 /Zi
  • 用途:用于需要调试优化后的代码场合。提供了优化后的性能,同时保留了调试信息,便于调试优化后的代码。
  1. MinSizeRel (Minimum Size Release)
  • 特点:优化以减小生成的二进制文件大小,不包含调试信息。
  • 编译器选项:
    • GCC/Clang:-Os
    • MSVC:/O1
  • 用途:用于嵌入式系统或存储受限的环境。目标是生成尽可能小的二进制文件,同时尽量保留一定的性能。

示例:假设我有一个简单的 CMake 项目,以下是如何指定不同的构建类型:

# 生成 Debug 构建
cmake -DCMAKE_BUILD_TYPE=Debug ..

# 生成 Release 构建
cmake -DCMAKE_BUILD_TYPE=Release ..

# 生成 RelWithDebInfo 构建
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..

# 生成 MinSizeRel 构建
cmake -DCMAKE_BUILD_TYPE=MinSizeRel ..

总结

  • Debug:用于开发和调试,包含调试信息,禁用优化。
  • Release:用于发布,启用优化,不包含调试信息。
  • RelWithDebInfo:用于需要调试优化后的代码,启用优化,并包含调试信息。
  • MinSizeRel:用于存储受限的环境,启用优化以减小文件大小,不包含调试信息。

这些构建类型帮助开发人员根据不同的需求(如开发调试、发布优化、调试优化代码、减小文件大小)生成合适的二进制文件。

10 CMAKE_CXX_FLAGS

在 CMake 中,CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_<CONFIG> 用于设置编译器的标志,但它们的作用范围不同:

  • CMAKE_CXX_FLAGS:这是一个全局变量,包含所有构建类型通用的编译器标志。无论你选择什么构建类型(Debug、Release、RelWithDebInfo、MinSizeRel),这些标志都会应用。

  • CMAKE_CXX_FLAGS_<CONFIG>:这些是特定于某个构建类型的编译器标志。<CONFIG> 可以是 DEBUG、RELEASE、RELWITHDEBINFO、MINSIZEREL 等。只有在对应的构建类型被选中时,这些标志才会应用。

      cmake_minimum_required(VERSION 3.10)
      project(MyProject)
    
      # 设置全局的编译器标志
      set(CMAKE_CXX_FLAGS "-Wall -Wextra")
    
      # 设置特定构建类型的编译器标志
      set(CMAKE_CXX_FLAGS_DEBUG "-g")
      set(CMAKE_CXX_FLAGS_RELEASE "-O3")
      set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
      set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
    

解释

  • CMAKE_CXX_FLAGS-Wall -Wextra, 这些标志会在所有构建类型中应用。

  • -DBOOST_FUSION_INVOKE_MAX_ARITY=13

      SET ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -DBOOST_FUSION_INVOKE_MAX_ARITY=13 -DRCF_MAX_METHOD_COUNT=400" )
    

    -DBOOST_FUSION_INVOKE_MAX_ARITY=13 是一个编译器选项,用于设置 Boost.Fusion 库中的宏 BOOST_FUSION_INVOKE_MAX_ARITY 的值。

    详细解释 Boost.Fusion 是 Boost 库的一部分,提供了一组用于处理异构数据结构的模板库。Boost.Fusion 中的一些功能需要处理不同数量的参数,而这些参数的最大数量可以通过设置宏 BOOST_FUSION_INVOKE_MAX_ARITY 来控制。

    BOOST_FUSION_INVOKE_MAX_ARITY 定义:它是一个宏,用于指定 Boost.Fusion 库中函数调用(invoke)的最大参数数量。

    默认值:这个值在默认情况下可能设置为某个固定值(如 10),但可以根据需要进行调整。

    作用:增加这个值可以允许 Boost.Fusion 处理更多参数的函数调用,但这也会增加编译时间和内存使用量。

    用法示例: 假设我在编译一个使用 Boost.Fusion 的项目,并且需要处理多达 13 个参数的函数调用。我可以通过以下方式设置这个值:

    在命令行中设置:

      cmake -DBOOST_FUSION_INVOKE_MAX_ARITY=13 ..
    

    在 CMakeLists.txt 中设置

      add_definitions(-DBOOST_FUSION_INVOKE_MAX_ARITY=13) 
    

    在源代码中设置 我也可以在源代码中定义这个宏,但这种方式需要在包含任何 Boost.Fusion 头文件之前进行定义:

    cpp代码如下:

      #define BOOST_FUSION_INVOKE_MAX_ARITY 13 
      #include <boost/fusion/include/invoke.hpp> 
    

    具体示例 假设我有一个使用 Boost.Fusion 的函数,需要处理 13 个参数:

    cpp代码如下:

      #include <boost/fusion/include/invoke.hpp> 
      #include <boost/fusion/tuple.hpp> #include
    
      void my_function(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m) { 
      		std::cout << "Sum: " << (a + b + c + d + e + f + g + h + i + j + k + l + m) << std::endl; 
      }
    
      int main() { 
      	#define BOOST_FUSION_INVOKE_MAX_ARITY 13 
      	boost::fusion::tuple<int, int, int, int, int, int, int, int, int, int, int, int, int> args(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); 
      	boost::fusion::invoke(&my_function, args); 
      	return 0; 
      } 
    

    在这个例子中,我定义了一个接受 13 个参数的函数 my_function,并使用 Boost.Fusion 的 invoke 函数调用它。通过设置 BOOST_FUSION_INVOKE_MAX_ARITY 为 13,我们确保 Boost.Fusion 可以处理这个函数调用。

    总结

    -DBOOST_FUSION_INVOKE_MAX_ARITY=13 是一个编译选项,用于设置 Boost.Fusion 库中处理函数调用的最大参数数量。通过增加这个值,可以让 Boost.Fusion 处理更多参数的函数调用,但这也可能增加编译时间和内存使用量。这个设置在需要处理多参数函数调用的情况下非常有用。

11 定义预处理宏-D

CMakeLists.txt 文件中,设置 CMAKE_CXX_FLAGS-DRCF_MAX_METHOD_COUNT=400 的作用如下:

  • 定义预处理器宏
    -D 选项用于定义一个预处理器宏。在这种情况下,RCF_MAX_METHOD_COUNT 被定义为 400。这意味着在编译代码时,所有引用 RCF_MAX_METHOD_COUNT 的地方都会被替换为 400

  • 影响编译行为
    RCF_MAX_METHOD_COUNT 这个宏的具体作用取决于它在代码中的使用方式。通常,这样的宏定义用于控制代码中的某些配置参数。例如,它可能用于限制或设置某个特定功能的最大值或数量。在这个例子中,RCF_MAX_METHOD_COUNT 可能用于限制某个框架(可能是 Remote Call Framework, RCF)的最大方法数量为 400。

  • 代码可读性和可维护性
    通过在 CMakeLists.txt 中设置预处理器宏,可以使得配置参数更加集中和统一管理。这样,当需要更改这些参数时,只需修改一个地方,而不是在多个文件中手动查找和替换。

具体作用还需要参考项目的相关文档或者代码实现,来看RCF_MAX_METHOD_COUNT 在代码中具体如何使用。例如,它可能用于控制某个数组的大小、某些数据结构的容量、某个循环的次数等等。

12 测试框架CTest

在 CMake 中使用 include(CTest)enable_testing() 有助于为项目配置和启用测试功能。具体作用如下:

include(CTest)
  • 引入CTest模块: CTest 是 CMake 自带的测试框架模块,通过 include(CTest) 可以引入该模块。CTest 提供了运行和管理测试的功能。

  • 定义测试目标: 通过引入 CTest 模块,你可以使用 CTest 提供的命令(如 add_test())来定义测试目标。

  • 支持持续集成: 通过引入 CTest 模块,可以更容易地集成到持续集成系统中,如 Jenkins、GitHub Actions 等。

    enable_testing()

  • 启用测试: 该命令在项目中启用测试功能。它会生成必要的测试文件(如 CTestTestfile.cmake),并设置测试的基本配置。

  • 允许定义测试: 在调用 enable_testing() 之后,你可以使用 CMake 提供的 add_test() 命令来添加测试。这些测试可以是可执行文件、脚本或其他可以被执行的程序。

  • 支持运行测试: 启用测试后,你可以使用 ctest 命令来运行项目中的测试。例如,运行 ctest 命令可以执行所有定义的测试并报告结果。

下面是一个简化的示例 CMakeLists.txt,展示了如何使用 include(CTest) 和 enable_testing():

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 引入CTest模块
include(CTest)

# 启用测试
enable_testing()

# 添加可执行文件
add_executable(my_program main.cpp)

# 添加测试,NAME是MyTest,运行的可执行文件是my_program
add_test(NAME MyTest COMMAND my_program)

在这个示例中:

  • include(CTest): 引入了 CTest 模块,使得我可以使用 add_test() 命令。
  • enable_testing(): 启用了测试功能。
  • add_test(NAME MyTest COMMAND my_program): 定义了一个名为 MyTest 的测试,该测试会运行 my_program 可执行文件。
    通过这种方式,我可以轻松地在 CMake 项目中配置和管理测试,从而确保项目的质量和可靠性。

13 CMakeDependentOption函数

在 CMake 中,include(CMakeDependentOption) 的主要作用是引入 CMakeDependentOption 模块,以便在 CMakeLists.txt 中使用 CMakeDependentOption() 函数。这些函数可以创建相互依赖的选项(即配置选项),根据某些条件来决定是否启用某个选项。这样可以更加灵活地管理项目配置。

具体来说,CMakeDependentOption() 函数可以根据其他选项的值来自动设置当前选项的默认值,并可以在条件不满足时隐藏该选项。这样可以避免用户在配置项目时混淆或误设无效的选项。

13.1 使用 include(CMakeDependentOption) 的步骤:

  1. 引入模块:在 CMakeLists.txt 文件中引入 CMakeDependentOption 模块。

    include(CMakeDependentOption)

  2. 定义依赖选项:使用 CMakeDependentOption() 定义依赖关系

    CMakeDependentOption(
    OPTION_NAME # 选项名称
    "Description of the option" # 选项描述
    ON # 默认值
    "DEPENDENT_OPTION" # 依赖选项或条件
    "CONDITION" # 条件
    )

13.2 示例

假设有一个项目,它有一个主选项 ENABLE_FEATURE,以及一个依赖于它的子选项 ENABLE_SUBFEATURE。我可以如下配置:

cmake_minimum_required(VERSION 3.0)

project(ExampleProject)

include(CMakeDependentOption)

option(ENABLE_FEATURE "Enable the main feature" ON)

CMakeDependentOption(
		ENABLE_SUBFEATURE            # 子选项名称
		"Enable the sub-feature"     # 子选项描述
		ON                           # 默认值
		"ENABLE_FEATURE"             # 依赖选项
		"ENABLE_FEATURE"             # 条件,这个条件如何理解
)

if (ENABLE_FEATURE)
		message(STATUS "Main feature is enabled.")
		if (ENABLE_SUBFEATURE)
				message(STATUS "Sub-feature is enabled.")
		else()
				message(STATUS "Sub-feature is disabled.")
		endif()
else()
		message(STATUS "Main feature is disabled.")
endif()

在这个例子中,如果 ENABLE_FEATURE 被禁用(OFF),则ENABLE_SUBFEATURE也会被禁用,且用户在 CMake GUI 或命令行中看不到 ENABLE_SUBFEATURE 选项。这种依赖关系使得配置选项更加直观和便于管理。

14 CMAKE_ROOT

  • CMAKE_ROOT: /usr/share/cmake-3.5

15 自动检测C++编译器

INCLUDE (${CMAKE_ROOT}/Modules/CMakeDetermineCXXCompiler.cmake) 是 CMake 中用于确定 C++ 编译器的模块。这个命令在配置 CMake 项目时有助于自动检测和设置适当的 C++ 编译器,使得构建过程更加简化和自动化。

15.1 作用和功能

自动检测 C++ 编译器:CMakeDetermineCXXCompiler.cmake 模块会搜索系统中可用的 C++ 编译器,并选择一个适合的编译器。例如,它会检查 g++、clang++ 等常见的 C++ 编译器。

设置相关变量:该模块会设置一些关键的 CMake 变量,如 CMAKE_CXX_COMPILER,这些变量在后续的配置和构建过程中会被使用。

检查编译器有效性:它会验证找到的编译器是否可用,确保所选的编译器能够正确编译和链接 C++ 代码

  • 编译器GCC本身包含多个编译器,(如:gcc用于Cg++用于C++),负责将源代码转换为目标代码(中间的机器码)

15.2 使用场景

在一些自定义的 CMake 配置文件或项目中,可能需要显式包含这个模块来确保编译器的检测和设置。这在某些特殊的构建环境或复杂的项目中可能特别有用。

15.2.1 示例

以下是一个示例,说明如何在自定义的 CMake 脚本中使用 CMakeDetermineCXXCompiler.cmake 模块:

cmake_minimum_required(VERSION 3.0)

# 指定项目名称和语言
project(ExampleProject CXX)

# 显式包含 CMakeDetermineCXXCompiler 模块
INCLUDE(${CMAKE_ROOT}/Modules/CMakeDetermineCXXCompiler.cmake)

# 其他项目配置和设置
set(SOURCE_FILES main.cpp)
add_executable(ExampleExecutable ${SOURCE_FILES})

# 输出所选择的编译器
message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")

在这个示例中,INCLUDE(${CMAKE_ROOT}/Modules/CMakeDetermineCXXCompiler.cmake) 会自动检测系统上的 C++ 编译器,并设置相关变量。然后,我们可以使用这些变量进行进一步的配置和构建过程。

15.3 总结

INCLUDE(${CMAKE_ROOT}/Modules/CMakeDetermineCXXCompiler.cmake) 在 CMake 中主要用于自动检测和设置 C++ 编译器,确保项目能够在不同的构建环境中正确编译和链接。这对提高构建过程的自动化和可移植性非常有帮助。

16GCC

GCC(GNU Compiler Collection)不仅是编译器,也是链接器。GCC 充当了一个集成工具,调用了不同的程序来完成每个阶段的工作。

16.1 编译器和链接器

编译器:GCC 本身包含了多个编译器(如 gcc 用于 C,g++ 用于 C++),负责将源代码转换为目标代码(中间的机器代码)。

链接器:GCC 调用了链接器(通常是 ld),负责将多个目标文件和库文件链接在一起,生成可执行文件。

16.2 GCC 的角色

作为编译器驱动程序:GCC 根据命令行参数自动决定调用预处理器编译器汇编器链接器的顺序。我只需使用一个命令,它就会自动完成整个编译和链接过程。

作为链接器的接口:在链接阶段,GCC 充当接口,将目标文件和库文件传递给链接器(通常是 ld)以生成可执行文件

标签:知识点,CMAKE,CMake,CXX,LIST,之二,编译器,cmake
From: https://www.cnblogs.com/gwzz/p/18312391

相关文章

  • Python入门知识点 4--格式化输出与运算符
    1、格式化输出name='小赵'age=18#print('大家好,我是'+name+'我今年'+age+'岁了')#字符串和整型不能拼接print('大家好,我是'+name+'我今年'+str(age)+'岁了')#把整型转换成字符串输出,但比较麻烦print('大家好,我是',name,'我今年',age,&#......
  • C++中关于异常的知识点
    C++中关于异常的知识点异常基本概念异常处理的基本思想C++异常处理的实现异常基本语法栈解旋(unwinding)异常接口声明异常变量生命周期异常的多态使用C++标准异常库标准库介绍编写自己的异常类异常基本概念异常是一种程序控制机制,与函数机制独立和互补函数是一......
  • LangChain补充四:Agent知识点和案例补充
    https://www.alang.ai/langchain/101/lc07一:基本流程和概念(一)概念LangChainAgent的核心思想是,使用大语言模型选择一系列要执行的动作。在Chain中,一系列动作是硬编码在代码中的。在Agent中,大语言模型被用作推理引擎,以确定要采取的动作及其顺序。它包括3个组件:规划:将任......
  • 知识点
    scSC命令的格式:SC[Servername]commandServicename[Optionname=Optionvalues]Servername:指定服务所在的远程服务器的名称。名称必须采用通用命名约定(UNC)格式(“\myserver”)。如果是在本地运行SC.exe,请忽略此参数。command:如query,start,stop,create,config等Servicena......
  • Pybind11和CMake构建python扩展模块环境搭建
    使用pybind11的CMake模板来创建拓展环境搭建从Github上下载cmake_example的模板,切换分支,并升级pybind11子模块到最新版本拉取pybind11使用cmake构建工具的模板仓库gitclone--recursivehttps://github.com/mrchipset/cmake_example.git切换分支gitcheckout-bdev升级s......
  • 力扣第十题——正则表达式匹配(动态规划化的运用)(附思路讲解、完整代码及知识点精炼)
    题目介绍给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。'.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。 示例1:输入:s="aa",p="a"输出:false解......
  • python 基础知识点(一)
    1.Python可以将一条长语句分成多行显示的续行符号是 \2.缩进可以用tab键实现,也可以用多个空格实现3.在Python中,使用缩进对齐来标记语句块4.在Python中,使用缩进对齐来体现代码之间的逻辑关系。5.严格的缩进可以约束程序结构,可以多层缩进6.Python中......
  • 计算机组成复习——第八章存储器系统知识点总结
    ......
  • 计算机组成复习——第二章机器指令知识点总结
    ......
  • 计算机组成复习——第六章流水线知识点总结
    ......