cmake_usgae

cmake 变量

预定义变量

cmake 命令行使用预定义变量

cmake -D变量名=值 的形式

常用的预定义变量

  1. CMAKE_BUILD_TYPE
    取值为Release、Debug 和 RelWithDebInfo 其中 RelWithDebInfo 是在Rlease 的基础上加上 -g

  2. CMAKE_INSTALL_PREFIX=install 安装目录的前缀

  3. 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 之后

环境变量

  1. 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( ... CACHE [FORCE]) variable:变量名称 value:变量值列表 CACHE:cache变量的标志 type:变量类型,取决于变量的值。类型分为:BOOL、FILEPATH、PATH、STRING、INTERNAL docstring:必须是字符串,作为变量概要说明 FORCE:强制选项,强制修改变量值,第一次定义后,后面的修改需要使用 FORCE 选项

1
2
# 示例
set(MY_GLOBAL_VAR_STRING "abc" CACHE STRING "定义一个STRING缓存变量" FORCE)

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 默认生成的静态库还是动态库

cmakeadd_library 命令默认生成的是静态库还是动态库取决于项目设置和 CMake 版本。在 CMake 3.0 及以上版本中,如果未指定库类型,它将根据变量 BUILD_SHARED_LIBS 的设置来决定,默认情况下,此变量不设定时add_library生成的是静态库。如果BUILD_SHARED_LIBS被设置为 ON,那么add_library不带库类型的情况下将生成动态库。

可以这样设置来决定默认的库类型:

1
set(BUILD_SHARED_LIBS ON) # 默认生成动态库

或者,在add_library时直接指定库的类型:

1
2
add_library(mylibrary STATIC mysource.cpp) # 生成静态库
add_library(mylibrary SHARED mysource.cpp) # 生成动态库

在不指定STATICSHARED,并且没有设置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)
然后在终端中可以通过执行 make copy_file 命令来执行 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 协议 ,转载请注明出处!