cmake学习笔记2

生成表达式

有时候我们想根据一些上下文情况设置一些东西。在cmake我们可以通过if判断条件去完成 也可通过一个生成表达式的东西完成。
generator-expressions官方文档

cmake有很多生成表达式,这里做一个简述。

最基础的表达式如下:

$<condition:true_string>

condition只能传0或者1,如果为1那么返回true_string 否则返回空字符串。如果你的condition不是0或者1那么你需要结合其他其他生成表达式进行嵌套完成。

需要注意的是表达式并会在生成构建系统文件的求值,而是在构建目标的时候计算,所以我们这里创建一个自定义目标进行输出。

cmake_minimum_required(VERSION 3.26)
project(learnC)
set(CMAKE_CXX_STANDARD 17)
#[[
由于$<1:FOO>和$<0:FOO>不会再创建构建系统的时候求值完成,所以我们构造一个自定义目标去打印
对应命令 cmake -B build -S . ;(cd build && cmake --build . -t genexdebug)
]]
add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "1 = $<1:FOO> , 0 = $<0:FOO>")

输出:

1 = FOO , 0 =

我们再看一个复杂的例子,下面的例子会用另一个生成表达式$<STREQUAL:string1,string2> 。我们会在这个例子中进行嵌套完成输出

cmake_minimum_required(VERSION 3.26)
project(learnC)
set(CMAKE_CXX_STANDARD 17)
#[[
$<STREQUAL:string1,string2> 用于比较两个字符串是否相等如果相等返回1 否则0
$<$<STREQUAL:${CMAKE_CXX_COMPILER_ID},AppleClang>:isAppleClang> 可以理解为当前的编译器是否为AppleClang如果是那么输出isAppleClang
]]
add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "1 = $<$<STREQUAL:${CMAKE_CXX_COMPILER_ID},AppleClang>:isAppleClang> ")

输出

1 = isAppleClang 

对于复杂的嵌套表达式可以利用变量进行分解。如下:

cmake_minimum_required(VERSION 3.26)
project(learnC)
set(CMAKE_CXX_STANDARD 17)
#抽出嵌套表达式到变量中
set(isAppleClangVar $<STREQUAL:${CMAKE_CXX_COMPILER_ID},AppleClang>)
set(myvar "$<${isAppleClangVar}:isAppleClang>")
#[[
$<STREQUAL:string1,string2> 用于比较两个字符串是否相等如果相等返回1 否则0
$<$<STREQUAL:${CMAKE_CXX_COMPILER_ID},AppleClang>:isAppleClang> 可以理解为当前的编译器是否为AppleClang如果是那么输出isAppleClang
]]
add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "${myvar}")

其他表达式可参阅官方文档进行实践。

安装组件

在我们安装文件的编译的时候,我们会有将其放入指定位置的需求。而cmake中install变派上用场了。install文档

这个函数的签名有很多我们这里只举例其中几个做说明

cmake_minimum_required(VERSION 3.26)
project(learnC)
set(CMAKE_CXX_STANDARD 17)
#是一个名为mycalc静态库
add_subdirectory(mycalclib)
add_executable(main main.cpp)

# 语法 install(TARGET <target> [type] [DESTINATION <目录>])  其中如果不说明type的话cmake会自动探测类型放入对应的目录
# 安装目标main到/usr/local/bin/main
install(TARGETS main DESTINATION bin)
# 安装目标到/usr/local/bin/main  由于我们声明main是RUNTIME 类别可以不需要声明DESTINATION
install(TARGETS main RUNTIME)
# 等价install(TARGETS main RUNTIME  )
install(TARGETS main RUNTIME DESTINATION bin)
# 安装目标main到/usr/local/bin/main
install(TARGETS main)

# 由于mycalc是一个静态库会自动放入/usr/local/lib
install(TARGETS mycalc)
# 其他省略写法参考上面

# 由于头文件不是一个target只能使用其他语法导入饭庄
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
        DESTINATION include
)

你可以执行cmake --install .去完成完成

 cmake -B build -S . ;(cd build && cmake --build .&& cmake --install .)

include 模块化

有时候我们一个CMakeLists.txt结构复杂超出我们的预期,我们期望拆分为更小的文件。而include命令就是满足我们期望的。include可以导入一个特定的明确路径的文件,也可以只指定模块名从指定的模块路径下查找。
模块路径有两个:

  1. CMAKE_MODULE_PATH变量所定义的路径,默认为空
  2. CMAKE安装目录下的module下的。比如mac为opt/homebrew/Cellar/cmake/3.27.4/share/cmake/Modules

我们看一个案例,假设我们有一下文件:

.
├── CMakeLists.txt
└── myTestModule2.cmake
1 directory, 2 files
#myTestModule2.cmake
set(hello "hello world")
#CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 导入方式1 ,设置模块路径然后可以去掉后缀名去导入
#set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
#include(myTestModule2)
# 导入方式2 写明指定路径文件
include(./myTestModule2.cmake)
# 输出导入的文件中定义的变量
message(${hello})

输出:

hello world

系统也给我们提供了很多有用模块比如CheckCXXSourceCompiles中提供了check_cxx_source_compiles函数.
check_cxx_source_compiles函数提供了一个检查指定的代码是否能正确编译

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# CheckCXXSourceCompiles在CMAKE自带的目录下。opt/homebrew/Cellar/cmake/3.27.4/share/cmake/Modules 导入目录
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
    #include <iostream>
    int main() {
        std::cout << \"Hello, world!\" << std::endl;
        return 0;
    }
" MY_SOURCE_COMPILES)

if (MY_SOURCE_COMPILES)
    message("源文件编译成功!")
else()
    message("源文件编译失败。")
endif()

相关推荐

  1. cmake学习笔记2

    2024-04-06 23:34:03       40 阅读
  2. Cmake学习笔记3

    2024-04-06 23:34:03       41 阅读
  3. CMake 学习笔记(访问Python)

    2024-04-06 23:34:03       28 阅读
  4. CMAKE学习

    2024-04-06 23:34:03       59 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-06 23:34:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-06 23:34:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-06 23:34:03       82 阅读
  4. Python语言-面向对象

    2024-04-06 23:34:03       91 阅读

热门阅读

  1. 渗透测试、人肉搜索算不算犯罪?

    2024-04-06 23:34:03       36 阅读
  2. RabbitMQ死信队列

    2024-04-06 23:34:03       33 阅读
  3. react组件:strictmode

    2024-04-06 23:34:03       38 阅读
  4. 全错排列c++代码

    2024-04-06 23:34:03       34 阅读
  5. 2024.3.23力扣每日一题——统计桌面上的不同数字

    2024-04-06 23:34:03       38 阅读
  6. 《深度学习的数学基础》小结

    2024-04-06 23:34:03       41 阅读
  7. 信息化、数字化、智能化、数智化概念剖析

    2024-04-06 23:34:03       38 阅读
  8. 【C++从0到1-黑马程序员】STL常用算法

    2024-04-06 23:34:03       42 阅读
  9. 一些常见的nginx问题和答案

    2024-04-06 23:34:03       42 阅读
  10. 使用宝塔面板安装nginxVOD点播系统

    2024-04-06 23:34:03       40 阅读