当外部项目发生变化时,如何自动重建对外部项目目标的依赖?

How can I have the dependencies on an external project target be automatically rebuilt when the external project changes?

我正在开发一个交叉编译项目,其中包含生成 Makefile 的顶级 CMakeLists.txt 文件。一些交叉编译的源代码是由基于主机的代码生成工具生成的;由于该工具需要不同的工具链,顶级 CMakeLists.txt 使用 ExternalProject_Add() 调用代码生成器子目录的 CMakeLists.txtBUILD_ALWAYS 设置为 TRUE。代码生成目标依赖于代码生成器目标,所以在初始构建时构建代码生成器,然后生成代码,然后将整个 shebang 编译成最终结果。

如果我更改代码生成器的源代码,那么代码生成器可执行文件将在下一个 make 上正确重建。问题:依赖的代码生成目标将不会被重建。 ExternalProject_Add() 目标似乎无法指示 when/if 应重建目标的任何依赖项。

例如,如果代码生成器目标是使用 Add_Custom_Command() 配置的,那么我会使用 OUTPUT 关键字来指定生成的可执行文件,并且任何相关目标都可以配置为自动在更新代码生成器可执行文件的时间戳时重建。

(为清楚起见进行编辑:在为 Add_Custom_Command() 指定一个 OUTPUT 文件后,我将使用 Add_Custom_Target() 创建一个方便的目标,其 DEPENDS 关键字引用了 Add_Custom_Command()OUTPUT 文件。然后我会让代码生成目标依赖于这个方便的目标。但是,据我所知,这对我不起作用。)

有没有办法配置基于 ExternalProject_Add() 的目标,以便在主目标的输出更改时自动重建依赖目标?

我需要 IMPORT 一个基于代码生成器可执行文件的目标。在我的 top-level CMakeLists.txt:

# Run next-gen code generation
# Use ExternalProject_Add() because we are building this for the host
# We DO NOT want cross-compile toolchain applied here
set(CODEGEN_EXECUTABLE ${CMAKE_CURRENT_LIST_DIR}/codegen/_build/codegen)
ExternalProject_Add(codegenExecutable
  SOURCE_DIR        ${CMAKE_CURRENT_LIST_DIR}/codegen
  # The two "--unset" options tell it to use the host defaults rather than the configured ones.
  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env --unset=CC --unset=CXX ${CMAKE_COMMAND} -H. -B_build
  INSTALL_COMMAND   ""
  BUILD_IN_SOURCE   TRUE
  EXCLUDE_FROM_ALL  TRUE
  BUILD_ALWAYS      TRUE
)

# Imported target, so that any change in the code generator will result in rerunning the
# code generation.
add_executable(codegen IMPORTED)
set_property(
    TARGET codegen
    PROPERTY
        IMPORTED_LOCATION "${CODEGEN_EXECUTABLE}"
)
add_dependencies(codegen codegenExecutable)

任何代码生成目标都设置为依赖于代码生成。第一次搭建:

  1. 构建 codegenExecutable 外部项目,创建 ${CODEGEN_EXECUTABLE} 可执行文件
  2. codegen 目标的时间戳由可执行文件的时间戳设置
  3. 所有依赖于codegen的代码生成任务都被重建

在没有更改的情况下,后续构建执行以下操作:

  1. 已构建 codegenExecutable 外部项目,但由于 none 其源代码已更改,因此不会重建可执行文件且不会更改其时间戳
  2. codegen 目标的时间戳没有改变
  3. 依赖于 codegen 的代码生成任务未重建

如果我触及任何 codegen 源并构建,则:

  1. 构建了 codegenExecutable 外部项目,创建了一个新的 ${CODEGEN_EXECUTABLE} 可执行文件并更新了时间戳
  2. codegen 目标的时间戳由可执行文件的时间戳更新
  3. 依赖codegen的代码生成任务重新构建

我相信,如果我从 codegenCMakeLists.txt 设置一个 EXPORTed 目标,那么我就不必 hard-code 可执行路径。未来的任务...