target_compile_definitions 用于多个 CMake 目标?
target_compile_definitions for multiple CMake targets?
我 been told 直接在 CMake 中设置 CFLAGS
之类的事情是不好的做法,相反,我应该使用 target_compile_definitions()
命令。
好的,但是 - 如果我想对多个(独立的)目标使用 similar/identical 定义怎么办?我不想一遍又一遍地重复自己。
我看到三种可能的方式:
首选使用target_compile_definitions(... INTERFACE/PUBLIC ...)
which would self-propagate the compiler definitions to targets depending on it via target_link_libraries()
命令。
使用 set_property(TARGET target1 target2 ... APPEND PROPERTY COMPILE_DEFINITIONS ...)
为多个目标设置相同的定义。
您仍可以在此目录范围内使用 add_definitions()
and remove_definitions()
to modify COMPILE_DEFINITIONS
directory property (which would pre-set all COMPILE_DEFINITIONS
目标属性的 "old commands"。
参考资料
- Is Cmake set variable recursive?
tl;dr:您可以循环迭代目标。
如果您有一堆具有某些 common/similar 功能的目标,您可能希望在一个循环中简单地操作它们!请记住 - CMake 与 GNU Make 不同,它是一种 full-fledged 脚本语言(嗯,有点)。所以你可以写:
set(my_targets
foo
bar
baz)
foreach(TARGET ${my_targets})
add_executable(${TARGET} "${TARGET}.cu")
target_compile_options(${TARGET} PRIVATE "--some_option=some_value")
target_link_libraries(${TARGET} PRIVATE some_lib)
# and so on
set_target_properties(
${TARGET}
PROPERTIES
C_STANDARD 99
C_STANDARD_REQUIRED YES
C_EXTENSIONS NO )
endforeach(TARGET)
您还可以初始化一个空的目标列表,然后向其添加 here-and-there,最后才将您的常用选项和设置集中应用到所有目标。
注意:在此示例中,我添加了 PRIVATE
编译选项,但如果您需要其中一些选项传播到目标 使用 您的目标,您可以将它们 PUBLIC
).
另一个简洁的解决方案是使用所有必需的属性和编译器定义定义一个接口库目标(一个不生成任何二进制文件的假目标),然后 link 其他现有目标反对它
示例:
add_library(myfakelib INTERFACE)
target_compile_definitions(myfakelib INTERFACE MY_NEEDED_DEFINITION)
add_executable(actualtarget1 main1.cpp)
add_executable(actualtarget2 main2.cpp)
set_property(
TARGET actualtarget1 actualtarget2
APPEND PROPERTY LINK_LIBRARIES myfakelib
)
参考资料:
https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries
我 been told 直接在 CMake 中设置 CFLAGS
之类的事情是不好的做法,相反,我应该使用 target_compile_definitions()
命令。
好的,但是 - 如果我想对多个(独立的)目标使用 similar/identical 定义怎么办?我不想一遍又一遍地重复自己。
我看到三种可能的方式:
首选使用
target_compile_definitions(... INTERFACE/PUBLIC ...)
which would self-propagate the compiler definitions to targets depending on it viatarget_link_libraries()
命令。使用
set_property(TARGET target1 target2 ... APPEND PROPERTY COMPILE_DEFINITIONS ...)
为多个目标设置相同的定义。您仍可以在此目录范围内使用
add_definitions()
andremove_definitions()
to modifyCOMPILE_DEFINITIONS
directory property (which would pre-set allCOMPILE_DEFINITIONS
目标属性的 "old commands"。
参考资料
- Is Cmake set variable recursive?
tl;dr:您可以循环迭代目标。
如果您有一堆具有某些 common/similar 功能的目标,您可能希望在一个循环中简单地操作它们!请记住 - CMake 与 GNU Make 不同,它是一种 full-fledged 脚本语言(嗯,有点)。所以你可以写:
set(my_targets
foo
bar
baz)
foreach(TARGET ${my_targets})
add_executable(${TARGET} "${TARGET}.cu")
target_compile_options(${TARGET} PRIVATE "--some_option=some_value")
target_link_libraries(${TARGET} PRIVATE some_lib)
# and so on
set_target_properties(
${TARGET}
PROPERTIES
C_STANDARD 99
C_STANDARD_REQUIRED YES
C_EXTENSIONS NO )
endforeach(TARGET)
您还可以初始化一个空的目标列表,然后向其添加 here-and-there,最后才将您的常用选项和设置集中应用到所有目标。
注意:在此示例中,我添加了 PRIVATE
编译选项,但如果您需要其中一些选项传播到目标 使用 您的目标,您可以将它们 PUBLIC
).
另一个简洁的解决方案是使用所有必需的属性和编译器定义定义一个接口库目标(一个不生成任何二进制文件的假目标),然后 link 其他现有目标反对它
示例:
add_library(myfakelib INTERFACE)
target_compile_definitions(myfakelib INTERFACE MY_NEEDED_DEFINITION)
add_executable(actualtarget1 main1.cpp)
add_executable(actualtarget2 main2.cpp)
set_property(
TARGET actualtarget1 actualtarget2
APPEND PROPERTY LINK_LIBRARIES myfakelib
)
参考资料:
https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries