首页 > 解决方案 > 什么 cmake 命令会将文件目录复制到构建后步骤中的目录

问题描述

我有一组与 GCC 的构建步骤或其他编译器的输出无关的资源文件。我需要将它们从我项目中的文件夹复制到 cmake 构建输出文件夹。目标是可执行文件,当从构建输出文件夹运行时,可以看到资源。

人们通常如何在 cmake 构建中复制和安装资源?此外,无论构建中的更改如何,我都希望它们被复制,并且我希望每次运行某些 cmake 命令时都执行它,例如 build. 请参阅下文了解我试图解决此问题的方法。

例如:

我有一堆要复制的着色器文件。所有 shaders/* 文件都应该复制到构建输出中名为“shaders”的目录中,因为这是程序的可执行文件所在的位置。

file(GLOB out shaders/*)
foreach (o ${out})
    message("${o} was copied to shaders")
    file(COPY ${o} DESTINATION shaders)
endforeach ()

这仅在某些时候有效,例如当我重新加载 CMake 项目时,例如:

/opt/clion-2021.2.3/bin/cmake/linux/bin/cmake \
  -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEPENDS_USE_COMPILER=FALSE \
  -G "CodeBlocks - Unix Makefiles" \
  /home/hack/glad

此外,它不执行“POST_BUILD”,因此shaders/a.vert文件的最新版本不会被复制到输出中的 shaders/ 目录。

我也尝试过使用它,但它让我有些头疼:

add_custom_command(TARGET my-executable POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy shaders/* shaders)

我认为上面有一些不正确的地方,因为如果构建的代码没有改变,它就不会在每个 POST_BUILD 中运行。我不在乎构建的代码是否不会更改,因为 shaders/* 中的文件可能已经更改并且应该被复制,无论 cmake 确定我的可执行文件是否有更改。

标签: cmake

解决方案


github上的这个要点非常有帮助,适用于我的问题的要点包括在下面。

add_custom_target(bar
        COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/shaders
        COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/shaders ${CMAKE_BINARY_DIR}/shaders
        COMMENT "copying ${CMAKE_SOURCE_DIR}/shaders to ${CMAKE_BINARY_DIR}/shaders"
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        )

上面的代码创建了一个bar可以与 Make bar 单独运行的 cmake 目标;然后,如果您添加另一个需要这些资源的目标(上面的着色器是其他可执行文件的资源),那么您可以使用add_dependencies以下方式将依赖项绑定在一起:

add_executable(a
        main.c
        opengl.c)
add_dependencies(a bar)

现在,每次a运行目标时,bar目标也会运行,这具有创建目录和复制文件的效果。

这对我来说已经足够好了,但要完成,您可以在其他依赖项完成运行后使用它在构建后步骤中创建文件:

add_custom_command(TARGET bar
    # Run after all other rules within the target have been executed
    POST_BUILD
    COMMAND echo "executing a POST_BUILD command"
    COMMENT "This command will be executed after building bar"
    VERBATIM
)

请注意,${CMAKE_COMMAND}在上面的示例中add_custom_command是一个指向 cmake 可执行文件的变量,您可以运行cmake -E以查看 cmake 附带的非常有用的命令列表。

YIKES后构建步骤仅在 bar 的目标构建后运行,而不是a目标。希望有人可以帮助我更好地回答这个问题。我仍然想知道如何在构建目标后复制文件,除非这完全没有必要并且没有人应该这样做。


推荐阅读