【问题标题】:How can I have the dependencies on an external project target be automatically rebuilt when the external project changes?当外部项目更改时,如何自动重建对外部项目目标的依赖关系?
【发布时间】:2021-02-24 03:24:52
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 据我了解,只有使用add_executableadd_library 创建的目标才能拥有“主要目标的输出”文件。所有其他目标(包括ExternalProject_Add 创建的目标)都没有此类文件,因此您需要明确使用add_custom_command 的DEPENDS 参数依赖于代码生成器。请注意,add_custom_command 不会创建/声明 target:此命令仅声明 file 的依赖项。在 CMake 中,“文件”和“目标”是不同的东西。
  • 根据您的最后一句话添加了说明。但是,我不认为第一句话的建议对我有用。如果文件(ExternalProject_Add() 的输出)比依赖对象更新,CMake 必须以某种方式触发构建依赖目标。

标签: cmake dependencies cross-compiling


【解决方案1】:

我需要IMPORT 一个基于代码生成器可执行文件的目标。在我的顶级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)

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

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

不做任何更改,后续构建会执行以下操作:

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

如果我触摸任何codegen 源并构建,那么:

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

我相信,如果我从codegenCMakeLists.txt 设置EXPORTed 目标,那么我就不必对可执行路径进行硬编码。未来的任务……

【讨论】:

  • 不应该add_dependencies(codegen codegen2Executable)这个行是add_dependencies(codegen codegenExecutable)吗?
  • 正确:应该。将编辑修复。 (谢谢。)
猜你喜欢
  • 2016-04-19
  • 2023-04-10
  • 2013-05-10
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-09
相关资源
最近更新 更多