我正在开发一个源代码存储库,该存储库通过运行 python 脚本输出 header 和实现来生成一些 C++ 代码。此代码随后被编译并链接到我的库和可执行文件。我知道只有当两个条件之一为真时,生成的代码才会改变:
我想使用 cmake 来管理构建过程。目前,我正在使用 execute_process
来启动生成器。但是,每次我运行 cmake 时都会运行它并且它会触及文件,导致我生成的代码被重新编译并增加了我的总编译时间。
我还想确保生成的代码始终在我的库之前运行。换句话说,我希望库依赖于生成器来运行。
在 cmake 中处理这种情况的正确方法是什么?我已经看到了这个先前的答案:“Get CMake to execute a target in project before building a library”。但这依赖于预先知道的代码生成器的输出。我的代码生成器将生成可变数量的文件。
最佳答案
使用 ADD_CUSTOM_COMMAND
来触发您的生成器。它允许您定义输入和输出依赖关系,并且仅当输出比输入更早时才会运行。
ADD_CUSTOM_COMMAND( OUTPUT generatedfile1 generatedfile2
COMMAND python generateSources.py xmlfile1 xmlfile2
DEPENDS xmlfile1 xmlfile2 generateSources.py
COMMENT "Generating source code from XML" )
确保生成的文件不会在多个可能并行编译的独立目标中使用,否则您可能(将)在构建过程中遇到冲突。为确保这一点,以下应该可以解决问题:
ADD_CUSTOM_TARGET( RunGenerator DEPENDS generatedfile1 generatedfile2
COMMENT "Checking if re-generation is required" )
然后让你的其他目标依赖于这个:
ADD_DEPENDENCIES( MyTarget RunGenerator )
注意: RunGenerator
目标将始终被视为过期,因此始终运行。但是,由于在这种情况下它什么都不做(除了打印注释和检查依赖项),这并不重要。如果需要,自定义命令将负责重新生成。
评论后更新:
如果不知道文件名,可以使用
ADD_CUSTOM_COMMAND( OUTPUT generated.timestamp
COMMAND python generateSources.py xmlfile1 xmlfile2
COMMAND ${CMAKE_COMMAND} -E touch generated.timestamp
DEPENDS xmlfile1 xmlfile2 generateSources.py
COMMENT "Generating source code from XML" )
但是:使用 GLOB 需要您显式运行 CMake 来更新您的文件列表。 将此集成到自定义命令中可能会打乱您的构建过程(如果多个项目正在并行构建并且一个项目重新启动 CMake 配置)。 IIRC,当您知道 python 脚本或 XML 文件已更改时,您可以手动运行 CMake,但您的问题是,当其他任何事情需要重新运行 CMake 时,这些文件会被触及。
如果 python 脚本运行时间不长,你可以让它在每次 CMake 运行时运行(就像你现在做的那样),但要确保未触及未更改的文件,你可以尝试以下方法(未经测试) :
# generated sources files into a temporary directory (adjust your current execute_process)
EXECUTE_PROCESS( COMMAND python ../generateSources.py ../xmlfile1 ../xmlfile2
WORKING_DIRECTORY tmp )
# get the filenames
FILE( GLOB GENERATED_TEMP_FILES tmp/* )
# copy to the "expected" directory, but only if content CHANGED
FOREACH( F ${GENERATED_TEMP_FILES} )
GET_FILENAME_COMPONENT( "${F}" FN NAME)
CONFIGURE_FILE( "${F}" "./generated/${FN}" COPY_ONLY )
ENDFOREACH()
# use your current globbing command
FILE( GLOB GENERATED_SOURCES ./generated/* )
https://stackoverflow.com/questions/26193068/