cmake_usgae
cmake 变量
预定义变量
cmake 命令行使用预定义变量
cmake -D变量名=值 的形式
常用的预定义变量
CMAKE_BUILD_TYPE
取值为Release、Debug 和 RelWithDebInfo 其中 RelWithDebInfo 是在Rlease 的基础上加上 -gCMAKE_INSTALL_PREFIX=install 安装目录的前缀
CMAKE_SKIP_RPATH=ON/OFF 补充说明一下rpath:https://www.cnblogs.com/rickyk/p/3875084.html 就是把运行时的链接依赖写到rpath 中,如果编译和运行时的目录结构一致且系统环境一致,则 rpath 是比较有用的,因为不需要设置LD_LIBRARY_PATH;rpath 的优先级在LD_LIBRARY_PATH之前,因此如果编译和运行时的系统环境不一致,即便设置了LD_LIBRARY_PATH,也可能链接到错误的库上。 除了rpath 和 LD_LIBRARY_PATH,还有 runpath,设置了runpath 后会导致rpath 失效,但是runpath 的优先级排在LD_LIBRARAY_PATH 之后
环境变量
- CPM_SOURCE_CACHE
设置cmp 拉取依赖的保存路径
unset CPM_SOURCE_CACHE
set CPM_SOURCE_CACHE=/home/hans/_deps/
自定义变量
外部定义
变量类型有两种,bool类型和string
类型,在外部定义时,即通过命令行cmake -DXXX -DYYY
的形式传递变量时,其并不区分变量类型,可在CMakeList.txt
和 .cmake文件进行使用,帮助进行条件编译和宏定义传递。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 判断 XXX 变量是否定义
if (DEFINED XXX)
message(STATUS "XXX is defined, val=${XXX}.")
endif()
if (NOT (DEFINED XXX))
message(FATAL_ERROR "XXX is not defined.")
endif()
# 判断 YYY 变量是否定义,一般 YYY 为字符串时判断是否DEFINED
if (DEFINED YYY)
add_definitions(-DXXX=100) # cpp带值宏定义
endif()
# 判断 YYY 变量是否为OFF,一般 YYY 为布尔类型时判断是否为 ON/OFF
if (YYY) # if (NOT YYY)
add_definitions(-DUSE_XXX) # cpp不带值宏定义
endif()
内部定义
bool 类型通过 OPTION 命令进行定义 1
2
3
4# 语法:
OPTION(var_name "var comments" 初始值: OFF/ON)
# 示例:
OPTION(USE_GPU "whether to use gpu" OFF)
string 类型通过 SET 命令进行定义 1
2
3
4
5
6
7
SET(var_name "var_value")
SET(BUILD_PLATFORM "x86" CACHE STRING "select build cpu type")
# 设置CXX_FLAGS, 如果options 太多, 可以分行写, \后面注意什么也不要加
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
-fno-omit-frame-pointer -fsanitize=undefined \
-fsanitize=leak -fsanitize=address -fsanitize-recover=address -lasan")
命令不区分大小写,变量区分大小写
gcc编译阶段打印宏定义的内容 https://www.cnblogs.com/suiyek/p/14164160.html
缓冲变量
语法如下: set(
1 |
|
CMake中的缓存变量都会保存在CMakeCache.txt文件中, 也就是作为整个工程的全局变量
message 打印信息
message(STATUS "")
编译选项
-isystem 和 -I 的区别
搜索顺序: -I > -isystem -> 系统默认路径 -isystem 会忽略警告
include_directories(SYSTEM xxx)
SYSTEM 选项的用途是告诉编译器,这些目录中的头文件应被视为“系统”头文件,即这些头文件不应被视为候选的警告来源。换句话说,如果编译器在这些系统头文件中发现了某些警告(如未使用的变量、类型不匹配等),则不会将这些警告报告给用户。
设置nvcc 编译器C++版本和编译选项
set(CMAKE_CUDA_STANDARD "14") set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wall -Werror=return-type")
链接
默认链接的是静态库还是动态库
CMake在查找库时默认会优先找动态库(如.so文件或.dll文件),如果找不到或者特别指定了静态库,它会链接到静态库(如.a或.lib文件)。你可以通过find_library
等命令及其相关参数来控制链接到静态库或动态库,或者添加定义来指定链接库的类型。
add_library 默认生成的静态库还是动态库
cmake
中 add_library
命令默认生成的是静态库还是动态库取决于项目设置和 CMake 版本。在 CMake
3.0 及以上版本中,如果未指定库类型,它将根据变量
BUILD_SHARED_LIBS
的设置来决定,默认情况下,此变量不设定时add_library
生成的是静态库。如果BUILD_SHARED_LIBS
被设置为
ON,那么add_library
不带库类型的情况下将生成动态库。
可以这样设置来决定默认的库类型:
1 |
|
或者,在add_library
时直接指定库的类型:
1 |
|
在不指定STATIC
或SHARED
,并且没有设置BUILD_SHARED_LIBS
变量时,add_library()
会创建静态库。
属性
二进制依赖库能否传递宏定义
target_compile_definitions
: 这是传递宏定义的推荐方式。使用它时,可以设置私有(PRIVATE)宏,它们只会影响当前目标;接口(INTERFACE)宏,它们会影响链接了当前库的其他目标,但不会影响当前目标;或者是公共(PUBLIC)宏,它们既影响当前目标又影响链接了当前库的其他目标。add_definitions
:这个指令会给当前目录下所有目标添加宏定义,但是它不会传递给依赖的目标。且它的作用范围是全局的,会影响到后续所有的目标。
自定义make 目标
add_custom_target 可以定义一个 target,然后通过
make target_name
命令进行目标的构建,该目标也可以是命令,比如下面这样 1
add_custom_target(copy_file sh copy_file.sh)
问题记录
版本问题
- 3.24 版本 报 download_extract_timestamp warning
- 3.21 版本报 find_package
Could not find philog using the following names: -- Configuring incomplete, errors occurred!
https://github.com/nluhmann/BlastFrost/issues/8 说可以用 3.14 解决
依赖库找不到问题
- find_package(xxxx REQUIRED) 当 xxx 找不到的时候,采用
cmake -Dxxx_DIR=path/to/cmake
的方式 path/to/cmake 是 xxConfig.cmake 或 xxx-config.cmake 的目录。不要用CMAKE_PREFIX_PATH,查找目录因平台而异,也会受其他变量的影响,最直接的就是直接使用 xxx_DIR,下面就是要查找的.cmake文件
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!