CMake中set_property设置COMPILE_FLAGS时分号替代空格问题解决
解决CMake中SOURCE属性COMPILE_FLAGS选项分号分隔问题
问题场景
为文件夹内部分C文件设置特殊编译选项,尝试用set_property的两种方式配置(列表定义、直接写入),但生成的Make命令中编译选项被分号分隔,导致编译异常:
原始CMake代码
cmake_minimum_required(VERSION 3.16) file(GLOB_RECURSE all_sources "./*.c" "./*.S") set(CURRENT_LIB_NAME my_c_library) enable_language(ASM) set(c_flags -msse4.1 # some other flags ) set(c_sandybridge_flags -O2 -march=sandybridge -mtune=sandybridge ) file(GLOB SANDYBRIDGE_SRC_FILES "*_slow.c" "*_dispatcher.c" "arion.c" ) set_property(SOURCE ${SANDYBRIDGE_SRC_FILES} PROPERTY COMPILE_FLAGS ${c_sandybridge_flags}) file(GLOB HASWELL_SRC_FILES "./*_ab2.c" ) set_property(SOURCE ${HASWELL_SRC_FILES} PROPERTY COMPILE_FLAGS -O2 -mavx2 ) add_compile_options( "$<$<COMPILE_LANGUAGE:C>:${c_flags}>" ) add_library(${CURRENT_LIB_NAME} STATIC ${all_sources} ) target_include_directories(${CURRENT_LIB_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/mylibrary/include)
生成的错误编译命令示例
/usr/bin/clang -Isomeinclude -msse4.1 -O2;-march=sandybridge;-mtune=sandybridge -MD -MT CMakeFiles/c_file.c.o -MF CMakeFiles/c_file.c.o.d -o CMakeFiles/c_file.c.o -c lib/c_file.c
问题原因
CMake的COMPILE_FLAGS属性接收的是单个字符串,而非列表。当直接传入列表变量(如${c_sandybridge_flags})时,CMake会将列表元素用分号拼接成字符串;直接写多个参数(如-O2 -mavx2)时,会被识别为多个列表元素,最终同样被分号连接。
解决方法
1. 列表定义的编译选项:转为空格分隔字符串
使用CMake的$<JOIN:...>生成器表达式,将列表元素用空格连接后传入:
set_property(SOURCE ${SANDYBRIDGE_SRC_FILES} PROPERTY COMPILE_FLAGS "$<JOIN:${c_sandybridge_flags}, >")
或者提前用string(JOIN)处理列表:
string(JOIN " " c_sandybridge_flags_str ${c_sandybridge_flags}) set_property(SOURCE ${SANDYBRIDGE_SRC_FILES} PROPERTY COMPILE_FLAGS ${c_sandybridge_flags_str})
2. 直接写入的编译选项:包裹为单个字符串
将多个编译选项放在双引号内,作为单个字符串传递:
set_property(SOURCE ${HASWELL_SRC_FILES} PROPERTY COMPILE_FLAGS "-O2 -mavx2")
修改后的完整CMake代码
cmake_minimum_required(VERSION 3.16) file(GLOB_RECURSE all_sources "./*.c" "./*.S") set(CURRENT_LIB_NAME my_c_library) enable_language(ASM) set(c_flags -msse4.1 # some other flags ) set(c_sandybridge_flags -O2 -march=sandybridge -mtune=sandybridge ) file(GLOB SANDYBRIDGE_SRC_FILES "*_slow.c" "*_dispatcher.c" "arion.c" ) # 使用JOIN将列表转为空格分隔字符串 set_property(SOURCE ${SANDYBRIDGE_SRC_FILES} PROPERTY COMPILE_FLAGS "$<JOIN:${c_sandybridge_flags}, >") file(GLOB HASWELL_SRC_FILES "./*_ab2.c" ) # 直接将选项包裹为单个字符串 set_property(SOURCE ${HASWELL_SRC_FILES} PROPERTY COMPILE_FLAGS "-O2 -mavx2") add_compile_options( "$<$<COMPILE_LANGUAGE:C>:${c_flags}>" ) add_library(${CURRENT_LIB_NAME} STATIC ${all_sources} ) target_include_directories(${CURRENT_LIB_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/mylibrary/include)
内容的提问来源于stack exchange,提问作者Tomáš Zato
相关产品推荐
相关产品推荐

