带有代码生成器的CMake + Ninja需要两个构建周期

问题描述

我有一个代码生成器(第三方Java可执行文件),该代码生成器使用xml输入(不同的第三方API定义)来生成我需要在项目中使用的C ++头文件。我不知道生成的头文件名会是什么。我只需要查看生成器在其输出目录中生成内容。实际上,它是50多个文件,并且在更新xml时添加/删除/修改文件名。

我继承了这样的代码,该代码创建了一个目标generated_lib,项目的其他部分可以用来添加所需的包含目录:

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/subdir_with_generated
  COMMENT "Generating C++ headers"
  PRE_BUILD
  DEPENDS api_deFinition.xml
  COMMAND java
    ARGS -Doptions.to.the.java.thing=123
    ARGS -jar ${JAVA_GENERATOR} ${CMAKE_SOURCE_DIR}/subdir/api_deFinition.xml
  )

add_custom_target(generated_stubs DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/subdir_with_generated)
add_library(generated_lib INTERFACE)
add_dependencies(generated_lib generated_stubs)
target_include_directories(generated_lib SYstem INTERFACE ${CMAKE_CURRENT_BINARY_DIR})

如果我使用Make作为CMake的-G选项,则结果系统将无法正常运行。最初的干净构建很好。典型的增量构建很好。但是,如果我touch subdir/api_deFinition.xml,那么每个随后的增量构建将重新生成标头,然后重新编译所有依赖于这些标头的内容,即使我不再触摸xml文件也是如此。很快就变得烦人了。

如果我将忍者用作我的-G(我的偏爱),则结果系统将以不同的方式运行不正常。初始构建很好。典型的增量构建很好。但是,如果我touch subdir/api_deFinition.xml,则下一个增量构建将重新生成文件,但将重新编译依赖于它们的文件。如果在此之后重新运行构建命令(ninja),那么所有依赖于标头的文件都将重新编译,然后一切都将恢复正常。

这些行为都不是“正确的”。我要么一遍又一遍地编译东西,要么必须非常小心地运行两次ninja,才能真正完成构建。

有没有办法让CMake在这里“做正确的事”?

我更喜欢使用忍者。我正在使用CMake 3.12.1,但可以升级

额外研究

基于this answer,我一直试图使用“时间戳记”文件标记生成文件的最后更改时间。

add_custom_command(
  OUTPUT generated.timestamp
  COMMENT "Generating C++ headers"
  DEPENDS ${JAVA_GENERATOR} api_deFinition.xml
  COMMAND java
    ARGS -Doptions.to.the.java.thing=123
    ARGS -jar ${JAVA_GENERATOR} ${CMAKE_SOURCE_DIR}/subdir/api_deFinition.xml
  COMMAND touch generated.timestamp
  )
                                                                                                      
add_custom_target(generated_stubs DEPENDS generated.timestamp)
add_library(generated_lib INTERFACE)
add_dependencies(generated_lib generated_stubs)
target_include_directories(generated_lib SYstem INTERFACE ${CMAKE_CURRENT_BINARY_DIR})

使用Make可以正常工作。始终不会重新生成和重新编译它。但是使用忍者,仍然存在需要两次ninja调用才能到达正确状态的问题。如果有人能够解决这个难题,我真的更愿意坚持忍者……

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)