• cmake学习笔记2


    生成表达式

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

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

    最基础的表达式如下:

    $
    
    • 1

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出:

    1 = FOO , 0 =
    
    • 1

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

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

    输出

    1 = isAppleClang 
    
    • 1

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

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

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

    安装组件

    在我们安装文件的编译的时候,我们会有将其放入指定位置的需求。而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  [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
    )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

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

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

    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
    
    • 1
    • 2
    • 3
    • 4
    #myTestModule2.cmake
    set(hello "hello world")
    
    • 1
    • 2
    #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})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出:

    hello world
    
    • 1

    系统也给我们提供了很多有用模块比如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 
        int main() {
            std::cout << \"Hello, world!\" << std::endl;
            return 0;
        }
    " MY_SOURCE_COMPILES)
    
    if (MY_SOURCE_COMPILES)
        message("源文件编译成功!")
    else()
        message("源文件编译失败。")
    endif()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    前端研习录(12)——动画效果讲解及示例说明
    2023秋冬系列丨追求本真的自然纯粹之美
    Docker consul的容器服务更新与发现
    第四个专栏,Kubernetes云原生实战,它来了~
    参数化的 4 种方式用法总结
    CI2454集成2.4G收发SOC【遥控;灯具;玩具】技术开发资料
    独立站运营和facebook投放怎么做
    矩阵相乘
    GIS工具maptalks开发手册(四)01——渲染地图信息框之添加绘制工具、获取点的坐标数据信息框进行展示
    短视频矩阵系统/pc、小程序版独立原发源码开发搭建上线
  • 原文地址:https://blog.csdn.net/qfanmingyiq/article/details/137383364