CMake之生成器表达式


我们承担ROS,FastDDS等通信中间件,C++,cmake等技术的项目开发和专业指导和培训,有10年+相关工作经验,质量有保证,如有需要请私信联系。

CMake分两个阶段生成项目的构建系统:配置阶段(解析CMakeLists.txt)和生成阶段(实际生成构建环境)。生成器表达式在第二阶段进行计算,可以使用仅在生成时才能知道的信息来调整构建系统。生成器表达式在交叉编译时很有用,一些可用的信息只有解析CMakeLists.txt之后或者在多配置项目后获取,构建系统生成的所有项目可以有不同的配置。
生成器表达式对于在访问或操作文件路径时很出色。
CMake提供了三种类型的生成器表达式:

  • 逻辑表达式,基本模式为 $<condition:outcome> 。condition为0表示false,1表示true
  • 信息表达式,基本模式为 $<information>$<information:input>
  • 输出表达式,模式为$<operation>$<operation:input> 这些表达式可能基于一些输入参数,生成一个输出,他们的输出可以直接在CMake命令中使用,也可以与其他生成表达式组合使用

生成器表达式是在生成构建系统时的表达式。生成器表达式在生成目标时使用,如 LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS等,或者target_link_libraries(), target_include_directories(), target_compile_definitions()等。有如下格式 $<...>
生成器表达式在测试时非常方便,因为不必显式硬编码可执行程序的位置和名称,方便不同平台的移植。
查看cmake有哪些生成器:cmake --help,其中generators显示如下
在这里插入图片描述
使用-G切换生成器,如使用Ninja:

mkdir -p build
cd build
cmake -G Ninja ..
cmake --build .

布尔生成器表达式

布尔生成器表达式值为0或者1,主要为以下:

逻辑表达式

  • $<BOOL:string>
  • $<AND:conditions>
  • $<OR:conditions>
  • $<NOT:condition>

字符串比较

  • $<STREQUAL:string1,string2>
  • $<EQUAL:value1,value2>
  • $<IN_LIST:string,list>
  • $<VERSION_LESS:v1,v2>
  • $<VERSION_GREATER:v1,v2>
  • $<VERSION_EQUAL:v1,v2>
  • $<VERSION_LESS_EQUAL:v1,v2>
  • $<VERSION_GREATER_EQUAL:v1,v2>

变量查询

  • $<TARGET_EXISTS:target>
  • $<CONFIG:cfgs> 如果config时cfgs中的一个词条,则为1,否则为0。不区分大小写
  • $<PLATFORM_ID:platform_ids> platform_ids是逗号分隔的列表,如果platform_id是platform_ids中的一个则为1
  • $<C_COMPILER_ID:compiler_ids>
  • $<CXX_COMPILER_ID:compiler_ids>
  • $<CUDA_COMPILER_ID:compiler_ids>
  • $<OBJC_COMPILER_ID:compiler_ids>
  • $<OBJCXX_COMPILER_ID:compiler_ids>
  • $<Fortran_COMPILER_ID:compiler_ids>
  • $<ISPC_COMPILER_ID:compiler_ids>
  • $<C_COMPILER_VERSION:version>
  • $<CXX_COMPILER_VERSION:version>
  • $<CUDA_COMPILER_VERSION:version>
  • $<OBJC_COMPILER_VERSION:version>
  • $<OBJCXX_COMPILER_VERSION:version>
  • $<Fortran_COMPILER_VERSION:version>
  • $<ISPC_COMPILER_VERSION:version>
  • $<TARGET_POLICY:policy>
  • $<COMPILE_FEATURES:features>
  • $<COMPILE_LANG_AND_ID:language,compiler_ids>
  • $<COMPILE_LANGUAGE:languages>
  • $<LINK_LANG_AND_ID:language,compiler_ids>
  • $<LINK_LANGUAGE:languages>
  • $<DEVICE_LINK:list>
  • $<HOST_LINK:list>

String-Valued生成器表达式

可以和其他的生成器表达式一起使用

转义字符

  • $<ANGLE-R>
  • $<COMMA>
  • $<SEMICOLON>

条件表达式

  • $<condition:true_string> 如果condition为1则字符串为true_string,否则为空
  • $<IF:condition,true_string,false_string> 如果condition为1则为true_string,否则为false_string

字符串转换

  • $<JOIN:list,string> 将list加入到string中
  • $<REMOVE_DUPLICATES:list>
  • $<FILTER:list,INCLUDE|EXCLUDE,regex> 根据regex从list中包含或删除
  • $<LOWER_CASE:string> 将string转换成小写
  • $<UPPER_CASE:string> 将string转换成大写
  • $<GENEX_EVAL:expr>
  • $<TARGET_GENEX_EVAL:tgt,expr>

变量查询

  • $<CONFIG> 配置名
  • $<PLATFORM_ID> 当前系统的cmake platform id
  • $<C_COMPILER_ID> C编译器ID
  • $<CXX_COMPILER_ID> C++编译器ID
  • $<CUDA_COMPILER_ID>
  • $<OBJC_COMPILER_ID>
  • $<OBJCXX_COMPILER_ID>
  • $<Fortran_COMPILER_ID>
  • $<ISPC_COMPILER_ID>
  • $<C_COMPILER_VERSION>
  • $<CXX_COMPILER_VERSION>

依赖目标查询

查询由add_executable()add_library()生成的目标。这个生成目标文件是个二进制文件

  • $<TARGET_NAME_IF_EXISTS:tgt> 如果目标存在则tgt为目标文件名,否则为空字符串
  • $<TARGET_FILE:tgt> 二进制文件tgt 的全路径名
  • $<TARGET_FILE_BASE_NAME:tgt>
  • $<TARGET_FILE_PREFIX:tgt>
  • $<TARGET_FILE_SUFFIX:tgt>
  • $<TARGET_FILE_NAME:tgt>:会返回目标(如库或可执行的bin文件)的文件名,不包含路径,例如有一个目标是libmyso.so,$<TARGET_FILE_NAME:myso>会得到libmyso.so
  • $<TARGET_FILE_DIR:tgt>
  • $<TARGET_LINKER_FILE:tgt>
  • $<TARGET_LINKER_FILE_BASE_NAME:tgt>
  • $<TARGET_LINKER_FILE_PREFIX:tgt>
  • $<TARGET_LINKER_FILE_SUFFIX:tgt>
  • $<TARGET_LINKER_FILE_NAME:tgt>
  • $<TARGET_LINKER_FILE_DIR:tgt>
  • $<TARGET_SONAME_FILE:tgt>
  • $<TARGET_SONAME_FILE_NAME:tgt>
  • $<TARGET_SONAME_FILE_DIR:tgt>
  • $<TARGET_PDB_FILE:tgt>
  • $<TARGET_PDB_FILE_BASE_NAME:tgt>
  • $<TARGET_PDB_FILE_NAME:tgt>
  • $<TARGET_PDB_FILE_DIR:tgt>
  • $<TARGET_BUNDLE_DIR:tgt>
  • $<TARGET_BUNDLE_CONTENT_DIR:tgt>
  • $<TARGET_PROPERTY:tgt,prop>
  • $<TARGET_PROPERTY:prop>
  • $<INSTALL_PREFIX>

输出关联表达式

  • $<TARGET_NAME:...>
  • $<LINK_ONLY:...>
  • $<INSTALL_INTERFACE:...> 用于安装阶段使用的路径
  • $<BUILD_INTERFACE:...> 用于构建阶段使用的路径,举例如下
target_include_directories(${PROJECT_NAME} PUBLIC
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
  "$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")

"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"只在构建阶段有效,包含的目录为指定目录
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"只在安装阶段有效
综上,这段代码的作用是,告知CMake在构建和安装阶段,应该使用哪些目录作为头文件查找目录,并将这些目录添加到目标项目的PUBLIC中,这意味着链接到该目标的其他目标也会继承这些包含目录。

  • $<MAKE_C_IDENTIFIER:...>
  • $<TARGET_OBJECTS:objLib>:在生成共享库/静态库或可执行文件时,用于引用另一个目标(就是这里的objLib文件)的对象文件。
    举例说明:假设你有两个目标,一个是库libA,它包含一些源文件,另一个是库libB,你想在其中复用libA的源文件编译生成的对象文件,但不想直接链接到libA。在这种情况下,你可以使用$<TARGET_OBJECTS:libA>生成器表达式来引用libA的对象文件。

这样,库libB就会包含libA的源文件编译生成的对象文件,而不需要重新编译libA的源文件,也不会链接到libA。这个特性在大型项目中,当一些目标需要共享源文件,但又不希望这些目标之间存在链接依赖时,非常有用。

add_library(objLib OBJECT ${OBJLIB_SOURCES})  # 生成要编译的对象文件
add_library(obj STATIC ${SOURCES} $<TARGET_OBJECTS:objLib>) # 目标文件引用对象文件
  • $<SHELL_PATH:...>
  • $<OUTPUT_CONFIG:...>
  • $<COMMAND_CONFIG:...>

调试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值