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. git 命令手册【不定时更新】

    本地分支 --> 远程服务器 git add xxx git commit -m "xxx" git push origin xxx 远程服务器 --> 本地分支 gi ...

  2. mysql存储过程之循环遍历查询结果集

    mysql存储过程之循环遍历查询结果集 -- 创建存储过程之前需判断该存储过程是否已存在,若存在则删除 DROP PROCEDURE IF EXISTS init_reportUrl; -- 创建存储 ...

  3. etcd 快速入门

    一.认识etcd 1.1 etcd 概念 从哪里说起呢?官网第一个页面,有那么一句话: "A distributed, reliable key-value store for the mo ...

  4. Ansible运行临时命令

    一.基本语法格式: 格式:ansible 受控主机IP/主机组 [选项] 参数 选项 -k 手动输入SSH协议的代码 -l 指定主机清单文件 -m 指定要使用的模块名 -a 设置传递给模块的参数 -M ...

  5. Joker 智能开发平台再放大招,新作将彻底重塑开发模式

    -- 突破传统枷锁,引领开发模式全面革新 自前端可视化智能平台重磅发布后,其在行业内的影响力便如涟漪般迅速扩散.凭借着创新的设计理念和过硬的性能表现,这个平台为无数开发者和企业提供了高效且便捷的开发解 ...

  6. nginx + lua脚本

    Nginx配合Lua 案例 今天实现一个非常简单的例子. 云服务器上部署的了一个很通用的应用程序(它没有保护策略),其端口是a,但是我想使用他,就要通过公网ip:端口去访问它.暴露在外面很不安全. 那 ...

  7. Docker Swarm多节点环境的搭建(二): Docker的集群调配

    Docker的集群调配在上篇文章中介绍了如何如何在多个CentOS中安装Docker应用.本文章为大家介绍如何实现对已安装的这一堆机器实现集群化.Docker Swarm运行Spring Cloud应 ...

  8. 【Java】修饰符

    修饰符(Modifier):是用于限定类型以及类型成员的声明的一种符号. 其用来定义类.方法或者变量,通常放在语句的最前端. 例子: public class Person { default Str ...

  9. AIops

    How does AIOps work?With AIOps, your organization takes a more proactive approach to resolve IT oper ...

  10. 【ESP32】两种模拟 USB 鼠标的方法

    上一篇水文中,老周给大伙伴们扯了关于 idf 中添加自定义 Arduino 组件的方案.这次咱们做一下 USB 鼠标玩玩. 很遗憾的是,老周无能,在 Arduino-esp32 组件依赖 TinyUS ...