我有一个CMake项目,该项目使用外部工具为特定平台构建特殊的库。运行此工具会使用“配置文件”生成几个文件,这些文件会在最终程序生成时注入到编译器和链接器选项中:
这些文件中的任何一个更改时,都必须完全重建主程序,因为它们是程序的固有部分,并且涉及诸如编译器标志和系统包含之类的东西。
到目前为止,我有类似的建议,appears是推荐的方法:
# run the external build tool to generate platform libs
# and compiler/linker option files
add_custom_command(
OUTPUT ${LINKER_CMD_FILE} ${COMPILER_OPTS_FILE} ${PLATFORM_OBJECT_LIB}
COMMAND "${EXTERNAL_BUILD_TOOL}"
ARGS --config ${CFG_FILE}
DEPENDS ${CFG_FILE}
COMMENT "Invoking external build tool for ${CFG_FILE}"
)
add_custom_target(platform_libs
DEPENDS ${LINKER_CMD_FILE} ${COMPILER_OPTS_FILE} ${PLATFORM_OBJECT_LIB}
)
....
add_executable(main_prog
main.c
)
# whenever any of these change, rebuild
add_dependencies(main_prog platform_libs)
# add the platform compiler opts from the generated file
target_compile_options(main_prog PRIVATE
@${COMPILER_OPTS_FILE}
)
这也是in this question完成的工作。
当我更改配置文件时,platform_libs
目标将运行并根据需要生成库和其他文件。但是,尽管运行make main_prog
确实会正确触发platform_libs
的生成,但是它似乎没有“注意到”任何更改,因此得出结论,实际上不需要重新构建主程序。 / p>
我总是可以运行make clean
,但是让CMake完全不了解基本系统库的更改并不是很好。
如果main_prog
已运行,如何强制platform_libs
进行重建?
答案 0 :(得分:0)
[此答案的中心方法来自问题评论中@KamilCuk的答案]。
诀窍是使用以下一种:
LINK_DEPENDS
属性(在示例中为main_prog
)-这意味着,如果此属性中的文件发生更改,将执行重新链接。OBJECT_DEPENDS
的每个来源上设置main_prog
。对于我来说,由于${COMPILER_OPTS_FILE}
影响每个文件的编译,因此我需要OBJECT_DEPENDS
方法。如果这样做,您实际上并不需要LINK_DEPENDS
,因为您将重新编译源代码并重新链接,但是为了清楚起见,我都这样做了。从理论上讲,您可以设计一种情况,其中链接程序命令文件发生更改,但编译器不选择更改,在这种情况下,您可能会错过重新链接。
就我而言,我不仅需要main_prog
还要使用所有其他main_prog
的库来执行此操作,所以我将链接器命令文件存储在了文件中,并且编译器选择文件作为目标属性放在了platform_libs
目标:
set_property(TARGET platform_libs
PROPERTY MY_LINKER_CMD_FILE ${LINKER_CMD_FILE}
)
set_property(TARGET platform_libs
PROPERTY MY_COMPILER_OPTS_FILE ${COMPILER_OPTS_FILE}
)
这意味着以后很容易将它们拉出,而不必知道确切的文件名(甚至可以访问变量本身):
# Retrieve the previously-stored options
# To do this, we only need the target name and the (fixed) property name
get_target_property(MY_LINKER_CMD platform_libs MY_LINKER_CMD_FILE)
get_target_property(MY_COMPILER_OPTS platform_libs MY_COMPILER_OPTS_FILE)
set_target_properties(main_prog PROPERTIES
LINK_DEPENDS ${MY_LINKER_CMD}
)
# Also set as the linker cmd on the linker command line
# This depends on the linker, for GCC it's -Wl,T<file>
target_link_libraries(main_prog PRIVATE
-Wl,-T${MY_LINKER_CMD}
)
# these are the sources that depend on the opts file
get_target_property(MAIN_SRCS main_prog SOURCES)
# set the dependency of source files on platform_libs
set_property(SOURCE ${MAIN_SRCS}
PROPERTY OBJECT_DEPENDS ${MY_COMPILER_OPTS}
)
# Set as a compiler opt file
# For GCC: @<opt_file>
target_compile_options(${TARGET_TO_COMPILE} PRIVATE
@${MY_COMPILER_OPTS}
)
# make sure the platform_libs is a dep
# or the compiler opts and linker files won't be generated
add_dependencies(main_prog platform_libs)
值得注意的是,在此Cmake代码中,项目名称main_prog
和platform_libs
可以是变量,然后可以将整个内容变成一个仅需要这两个项目名称的函数。这样可以轻松地重用代码,以根据platform_libs
库来编译库。