使用CMake将文件从源目录复制到二进制目录

mon*_*ata 78 cmake

我正在尝试在CLion上创建一个简单的项目.它使用CMake(我是新来的)生成Makefile来构建项目(或某种类型)

我需要的是每次运行我的代码时将一些非项目文件(某种资源文件)传输到二进制目录.

该文件包含测试数据,应用程序将其打开以读取它们.我尝试了几种方法:

  • 通过 file(COPY ...

    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
            DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input.txt
    
    Run Code Online (Sandbox Code Playgroud)

    看起来很好,但它只工作一次,而不是下次运行后重新复制文件.

  • 通过 add_custom_command

    • OUTPUT

      add_custom_command(
              OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/input.txt
              COMMAND ${CMAKE_COMMAND} -E copy
                      ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
                      ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
      
      Run Code Online (Sandbox Code Playgroud)
    • TARGET

      add_custom_target(foo)
      add_custom_command(
              TARGET foo
              COMMAND ${CMAKE_COMMAND} copy
                      ${CMAKE_CURRENT_BINARY_DIR}/test/input.txt
                      ${CMAKE_SOURCE_DIR})
      
      Run Code Online (Sandbox Code Playgroud)

    但没有人工作.

我究竟做错了什么?

tam*_*nez 106

您可以考虑将configure_fileCOPYONLY选项一起使用:

configure_file(<input> <output> COPYONLY)
Run Code Online (Sandbox Code Playgroud)

file(COPY ...)它在输入和输出之间创建文件级依赖关系不同,即:

如果输入文件被修改,构建系统将重新运行CMake以重新配置文件并再次生成构建系统.

  • 请注意,`configure_file`不适用于子目录,即使您使用GLOB创建文件列表也是如此. (6认同)
  • 另请注意,这不是输入和输出之间的“文件级依赖关系”:它是输入和 *cmake 配置步骤* 之间的依赖关系。因此,与常规构建依赖项(更改源文件仅重建相应的目标文件)不同,这会导致整个 cmake 重新配置,这可能会产生其他副作用。 (3认同)

小智 48

这两个选项都有效,并针对您的构建的两个不同步骤:

  1. file(COPY ...在配置步骤中复制文件,仅在此步骤中复制.在未更改cmake配置的情况下重建项目时,将不会执行此命令.
  2. add_custom_command 如果要在每个构建步骤中复制文件,则首选.

您的任务的正确版本将是:

add_custom_command(
        TARGET foo POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_SOURCE_DIR}/test/input.txt
                ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
Run Code Online (Sandbox Code Playgroud)

你可以选择PRE_BUILD,PRE_LINK,POST_BUILD 最好是你阅读的文档add_custom_command

可以在此处找到有关如何使用第一个版本的示例:使用CMake add_custom_command为另一个目标生成源

  • 如果`test/input.txt` 文件与当前的`CMakeLists.txt` 文件相关,则@SyaifulNizamYahya 使用`CMAKE_CURRENT_SOURCE_DIR`。如果它相对于根`CMakeLists.txt`,则使用`CMAKE_SOURCE_DIR`。 (2认同)
  • 注意:要递归复制目录而不是文件,请使用 `${CMAKE_COMMAND} -E copy_directory` (2认同)

ar3*_*r31 13

建议的configure_file可能是最简单的解决方案。但是,如果您从构建目录中手动删除该文件,它将不会重新运行复制命令。为了也处理这种情况,以下方法对我有用:

add_custom_target(copy-test-makefile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/input.txt
                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
                                                    ${CMAKE_CURRENT_BINARY_DIR}/input.txt
                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.txt)
Run Code Online (Sandbox Code Playgroud)


Ger*_*ano 12

您尝试的第一个选项无效,原因有两个.

首先,您忘记关闭括号.

其次,DESTINATION应该是目录,而不是文件名.假设您关闭了括号,该文件将最终位于名为的文件夹中input.txt.

要使其工作,只需将其更改为

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
     DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
Run Code Online (Sandbox Code Playgroud)


Ami*_*agh 7

如果要将文件夹从 currant 目录复制到二进制(构建文件夹)文件夹

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/yourFolder/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yourFolder/)
Run Code Online (Sandbox Code Playgroud)

那么语法是:

file(COPY pathSource DESTINATION pathDistination)
Run Code Online (Sandbox Code Playgroud)


Fel*_* Xu 5

我建议TARGET_FILE_DIR您是否希望将文件复制到与 .exe 文件相同的文件夹中。

$ 主文件目录(.exe、.so.1.2、.a)。

add_custom_command(
  TARGET ${PROJECT_NAME} POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy 
    ${CMAKE_CURRENT_SOURCE_DIR}/input.txt 
    $<TARGET_FILE_DIR:${PROJECT_NAME}>)
Run Code Online (Sandbox Code Playgroud)

在 VS 中,无论是调试还是发布,此 cmake 脚本都会将 input.txt 复制到与最终 exe 相同的文件中。


小智 5

这是我用来复制一些资源文件的内容:复制文件是一个忽略错误的空目标

 add_custom_target(copy-files ALL
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_BINARY_DIR}/SOURCEDIRECTORY
    ${CMAKE_BINARY_DIR}/DESTINATIONDIRECTORY
    )
Run Code Online (Sandbox Code Playgroud)

  • 我还会添加 `add_dependency(MainTarget copy-files)` 以使其在构建 MainTarget 时自动运行 (2认同)