CMake:如何让execute_process等待子目录完成?

4

我的部分源代码是由一个工具生成的,该工具也是在我们的主项目下构建的,使用了add_subdirectory。我们使用execute_process命令来执行这个工具。很明显,如果在达到execute_process语句之前没有构建好该工具,它将会失败。

我使用GLOB(file(GLOB...))来查找已生成的源文件。我这样做是因为无法预先知道有多少文件被生成,也不知道它们的名称。

我应该如何强制CMake在执行进程之前等待子项目编译完毕?我需要像execute_processDEPENDS属性一样的东西,但这个选项不可用。

# This subproject will source generator the tool
add_subdirectory(generator)


# I need something like: wait_for(generator)
execute_process(COMMAND generator ${CMAKE_SOURCE_DIR}/src)

file(GLOB GeneratedSources ${CMAKE_SOURCE_DIR}/src/*.cpp)
add_executable(mainprject.exe ${ProcessorSourceFiles}

1
使用add_custom_command代替execute_process - arrowd
@arrowd 这样做不行。因为我需要在运行 file(GLOB ...) 命令之前执行该过程。add_custom_command 不允许我这样做。 - rph
你可以执行 file(GLOB ...) 并将其结果传递给 add_custom_command - arrowd
如果在执行进程之前运行 file(GLOB....),则目录 src 将为空。我需要在搜索文件 (file(GLOB...)) 之前运行 execute_process - rph
2个回答

2

命令execute_process会在配置阶段立即执行其COMMAND。因此,它不能在使用add_executable命令创建可执行文件之后再进行排列:该可执行文件将仅在构建阶段构建。

您还需要在配置阶段构建子项目。例如:

execute_process(COMMAND ${CMAKE_COMMAND}
    -S ${CMAKE_SOURCE_DIR}/generator
    -B ${CMAKE_BINARY_DIR}/generator
    -G ${CMAKE_GENERATOR}
    )

execute_process(COMMAND ${CMAKE_COMMAND}
    --build ${CMAKE_BINARY_DIR}/generator
    )

第一条命令调用cmake来配置'generator'项目,该项目位于${CMAKE_SOURCE_DIR}/generator目录下。使用-G选项为子项目使用与主项目相同的CMake生成器。

第二条命令构建该项目,以便生成generator可执行文件。

创建generator可执行文件后,您可以将其用于您的项目:

execute_process(COMMAND ${CMAKE_BINARY_DIR}/generator/<...>/generator ${CMAKE_SOURCE_DIR}/src)

在这里,你需要将绝对路径传递给 COMMAND 的第一个参数:generator 可执行文件。CMake 不再具有 generator 可执行文件目标,因此它不会自动替换其路径。


1
您需要使用目标依赖来对此进行建模。工具“generator”应该是一个cmake目标。在这种情况下,使用add_custom_target而不是execute_process,就像这样:
add_custom_target(generate_sources ALL COMMAND generator ${CMAKE_SOURCE_DIR}/src))

然后使用add_dependencies为“generator”添加目标依赖关系:

add_dependencies(generate_sources generator)

这将确保目标“generate_sources”在目标“generator”编译后才会在构建期间运行工具。
以下内容是错误的,请查看注释获取更多信息:
使用add_dependencies将从“mainproject.exe”到“generate_sources”的依赖项添加。现在我从未测试过这一点,因此需要谨慎:使用CMake 3.12以上的版本,根据file上的条目,您应该能够将文件命令更改为:
file(GLOB GeneratedSources CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/*.cpp)

我理解为如果目录发生变化,这将重新对文件进行全局搜索并构建。

1
我理解为如果目录发生变化,这将在构建期间重新对文件进行全局搜索。它将在构建的最开始进行重新检查,即在任何目标被构建之前。因此,在生成器可执行文件构建后,CONFIGURE_DEPENDS选项无法帮助重新运行GLOB。该选项旨在捕获用户创建的新源文件。 - Tsyvarev
谢谢你澄清了这个问题。我会进行编辑。这严重复杂化了事情...不过我们该如何在构建期间进行全局匹配呢?我的下一个最佳猜测是运行一个cmake脚本作为自定义目标,执行cmake -P,让它执行全局匹配并将找到的文件写入文本文件。然后将可执行目标依赖于该文本文件,并以某种方式读取文件名... - d-karl
我的下一个最佳猜测是运行一个cmake脚本作为自定义目标,执行cmake -P,让它执行全局匹配并将找到的文件写入文本文件。这样的做法可能有效,但只适用于“两步走”的情况:第一次构建将生成源文件,但创建可执行文件将失败;第二次构建将全局匹配正确的源文件,因此可执行文件将无错误地创建。顺便说一句,在第二次构建中进行全局匹配实际上可以使用CONFIGURE_DEPENDS选项来实现。 - Tsyvarev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接