Cmake

Cmake变量

Cmake的基本类型只有两种,分别是字符串字符串列表,使用set命令来设置变量

set(var abc) # abc是字符串,var是值为“abc”的字符串变量
set(var a b c) # var是包含a b c三个元素的字符串列表
set(var a;b;c) # 同上
set(var “a b c”) # var是值为“a b c”的字符串变量

Cmake命令不区分大小写,变量区分大小写

变量取值方法如下:

set(var abc)  # abc是字符串,var是变量
message(${var}) # 使用${变量}的形式来取值,并打印

条件语句

(1)if条件语句

if(condition1)
expression1
elseif(condition2)
expression2
endif()

(2)循环语句

foreach(item IN LISTS list_var)
message(${item})
endforeach()

常用命令

(1)版本号要求

指定Cmake最低版本号

cmake_minimum_required(VERSION xx.xx)

(2)指定项目信息

project(PRO_NAME)

(3)设置构建目标Target

  • 创建可执行文件
add_executable()  # 用于创建一个可执行的Target
  • 创建静态库/动态库
add_library(target STATIC/SHARED a.cpp b.cpp)

源文件过多的情况下,可以通过调用aux_source_directory([目录] [变量名])来批量添加

aux_source_directory(./src Clist)
add_library(target STATIC ${Clist})
  • 子目录联编

父级CMakeList.txt通过调用add_subdirectory()来实现包含、调用存在CMakeList.txt的子目录或者子工程

add_subdirectory([目录])
  • 指定链接选项
  1. 仅用于可执行文件或者动态库目标(必须先创建target):
add_executable(mymathApp mymathApp.cc)
target_link_options(mymathApp <INTERFACE|PUBLIC|PRIVATE> -wl,-shared,-z,noexecstack)

PUBLIC、PRIVATE和INTERFACE是目标属性的修饰符

  1. 指定目标的属性
set_target_properties
  1. 设置链接属性变量LINK_FLAGS
set(LINK_FLAGS "-rdynamic -W1,-z,noexecstack -W1,-z,relro -W1,-z,now")
  • 添加源编译选项

1)向源文件编译添加选项,相关选项将添加到COMPILE_OPTIONS目录属性。从当前目录和下一级目录编译target时,将使用这些选项。

add_compile_options(<option> ...)
e.g.
add_compile_options(-DSAMPLE_ADD_VALUE=10)
add_compile_options(-Wall -Wextra -pedantic -Werror)

2)向target添加编译选项

add_executable(main samples/sample_add.cpp)
target_compile_options(main
PRIVATE $<$<CXX_COMPILER_ID:AppleClang,IBMClang,Clang,GNU,LCC>:-DMY_PRIVATE_DEFINE>
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU,LCC>:-DMY_PUBLIC_DEFINE>
PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,GNU,LCC,Clang,AppleClang,IBMClang>:-
DMY_MUTLI_COMP_PUBLIC_DEFINE>
INTERFACE $<$<CXX_COMPILER_ID:GNU,LCC>:-DMY_INTERFACE_DEFINE>
INTERFACE $<$<CXX_COMPILER_ID:GNU,LCC,Clang,AppleClang,IBMClang>:-
DMY_MULTI_COMP_INTERFACE_DEFINE>
)
  • 给顶级目标添加依赖项

使顶级<目标>依赖于其他顶级目标,以确保子一级的目标在<目标>之前构建 ,顶级目标是由add_executable()、 add_library()或add_custom_target()命令创建的

ADD_EXECUTABLE(main main.cpp)
ADD_DEPENDENCIES(main a.so b.so) ## main有一些符号的定义在a.so或者b.so中,提示编译器先生产依赖库,再去生成main
TARGET_LINK_LIBRARIES(main a.so b.so c.so d.so)
  • 查找某级目录下的所有源文件,并保存文件列表到变量
aux_source_directory([目录] [变量名])
e.g.
aux_source_directory(../ DIR_SRC)
  • 添加子目录进行构建
add_subdirectory(../src)
  • 添加头文件搜索目录,如果是相对路径,则是基于当前源文件的路径
include_directories
  • 添加链接器寻找库文件的目录
link_directories

注意:该命令只适用于在它被调用后创建target的场景, 如果必须提供库搜索路径,则最好尽可能使用 target_link_directories命令

  • 将库文件链接目录添加到target里,指定连接器在链接给定target的时候应该在设置的目录下搜索库文件
target_link_directories(<target> [INTERFACE/PUBLIC/PRIVATE] DIR)

注意:命名中的target必须先由add_excecutable或者add_library等命令创建

  • 将库链接到稍后添加的所有目标里
link_libraries("/opt/libeng.so" "/opt/bin/libmx.so")

注意:该命令只适用于在它被调用后创建target的场景

  • 指定将要链接到给定target的库
target_link_libraries(<target> [INTERFACE/PUBLIC/INTERFACE] item1 ...)
target_link_libraries(myProject libcomm.so) # 这些库名写法都可以
target_link_libraries(myProject comm)
target_link_libraries(myProject -lcomm)

PUBLIC 在public后面的库会被Link到你的target中,并且里面的符号也会被导出,提供给第三方使用。

PRIVATE在private后面的库仅被link到你的target中,并且终结掉,第三方不能感知你调了啥库 INTERFACE 在 interface后面引入的库不会被链接到你的target中,只会导出符号。

作用域

没有指定作用域的情况

父目录的CMakeList.txt变量作用域会扩展至子目录,但是子目录不能扩展到父亲目录。例如, sub_module_a1/CMakeLists.txt可以访问到module_a和root下的CMakeLists.txt中定义的变量,反之 module_a/CMakeLists.txt访问不到sub_module_a1/CMakeLists.txt中定义的变量。

root
|--CMakeLists.txt
|--module_a
| |--CMakeLists.txt
| |--sub_module_a1
| |--CMakeLists.txt
|
|--module_b
|--CMakeLists.txt

如果子目录变量需要被上一级父目录访问

set(var xxx PARENT_SCOPE)

如果子目录变量作用域需要扩大到全局CMakeList.txt

set(var xxx CACHE INTERNAL "")

常见的内部变量

变量名 描述
CMAKE_C_COMPILER/CMAKE_CXX_COMPILER C/C++编译器
CMAKE_C_FLAGS/CMAKE_CXX_FLAGS C/C++编译选项
CMAKE_BINARY_DIR/PROJECT_BINARY_DIR 执行cmake命令的dir,即cmake生成件所在dir
CMAKE_SOURCE_DIR/PROJECT_SOURCE_DIR 工程顶层目录
CMAKE_CURRENT_SOURCE_DIR 当前CMakeLists.txt所在dir
CMAKE_INSTALL_PREFIX 执行make install的发布件安装dir
CMAKE_TOOLCHAIN_FILE 指定交叉编译环境的配置文件,在cmake命令中指定
CMAKE_CXX_STANDARD 指定C++的版本号: 11、17等

cmake基础知识的更多相关文章

  1. ros基础知识总结

    参考于:ros官网教程 实验楼:ros机器人操作系统自主学习实验 基础知识 1 一个catkin程序包由什么组成? 一个程序包要想称为catkin程序包必须符合以下要求: 该程序包必须包含catkin ...

  2. MySQL 基础知识梳理

    MySQL 的安装方式有多种,但是对于不同场景,会有最适合该场景的 MySQL 安装方式,下面就介绍一下 MySQL 常见的安装方法,包括 rpm 安装,yum 安装,通用二进制安装以及源码编译安装, ...

  3. MySQL基础知识:Character Set和Collation

    A character set is a set of symbols and encodings. A collation is a set of rules for comparing chara ...

  4. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  5. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

  6. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  7. selenium自动化基础知识

    什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...

  8. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  9. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  10. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

随机推荐

  1. 多版本Java 配置记录

    来自 https://blog.csdn.net/zdl177/article/details/105246997 起因是为了启动MC 目录结构 Java总目录下放置多个jdk目录(jdk16.0.2 ...

  2. vue watch监听路由变化

    vue watch监听路由变化 // 监听 this.$route.path // watch监听非DOM元素的改变 watch:{ '$route.path':function(to,from){ ...

  3. 数据、信息、知识、智慧:AI时代我们该如何思考?

    时代的浪潮滚滚向前,AI技术的演进正悄然改变着我们认知世界和创造价值的方式.从数据.信息到知识.智慧,从大数据到大模型,从单一智能体到多智能体协作,这是一场深刻的认知革命,也是生产力解放的新纪元. A ...

  4. Content-Encoding:br 是一种什么编码格式?

    一.前言 在之前测试HTTP应答的压缩过程中无意间发现在Google浏览器下出现了 Content-Encoding:br 这种的编码格式,当时我就纳闷了,前面不是一直在研究GZip压缩吗?br压缩又 ...

  5. [源码系列:手写spring] IOC第十一节:Aware接口

    内容介绍 Aware简洁 在Spring框架中,Aware接口是一个非常有用的工具,用于实现Bean与Spring容器及其他资源之间的集成.Aware接口是一个标记接口,其中定义了各种Aware子接口 ...

  6. api使用流程、Scanner键盘录入字符串

    1.api介绍 2.api使用流程 API帮助文档的使用流程 在索引位置搜索自己要查看的类 看包 目的: 是不是java.lang包(核心包), 不需要编写导包代码(import) - 不是java. ...

  7. Fast Prefix Sum Implementation Using Subgroups in GLSL Compute Shaders

    利用 Vulkan 1.1 的 subgroup 特性加速 ComputeShader 的前缀和计算,参考: Vulkan Subgroup Tutorial - Khronos Blog - The ...

  8. 『Plotly实战指南』--雷达图绘制与应用

    在数据分析和可视化领域,雷达图是一种适用于多维数据的可视化.综合评估和决策支持的工具. 雷达图通过将数据点沿多个轴分布,并通过多边形面积或线条连接来展示数据的多维度特征,能够直观地呈现数据在各个维度上 ...

  9. eolinker环境变量配置:用例执行前给把某参数设置为全局参数的方法

    特别注意:需要使用全局变量或者预处理前务必阅读本链接https://www.cnblogs.com/becks/p/13713278.html 1.场景分析 注册会员流程共计有添加数据,校验数据,提交 ...

  10. 理解.NET Core中的配置Configuration

    什么是配置 .NET中的配置,本质上就是key-value键值对,并且key和value都是字符串类型. 在.NET中提供了多种配置提供程序来对不同的配置进行读取.写入.重载等操作,这里我们以为.NE ...