0

我正在尝试为 C++ 项目生成一个 CMake 目标,使用add_custom_target它将CMakeLists.txt驻留目录的内容复制到其中${CMAKE_BINARY_DIR}但不包括给定的文件列表

虽然这看起来很容易,但我在这里遇到了问题。到目前为止我的尝试:

1)生成所有文件/目录的列表,删除要排除的项目并使用 CMake 复制命令:

file(GLOB files_to_copy LIST_DIRECTORIES TRUE *)
list(REMOVE_ITEM files_to_copy
  ${CMAKE_CURRENT_SOURCE_DIR}/file_to_exclude.txt
  ${CMAKE_CURRENT_SOURCE_DIR}/dir_to_exclude
  # ...
)
add_custom_target(my-target
  COMMAND ${CMAKE_COMMAND} -E copy ${files_to_copy} ${CMAKE_BINARY_DIR}
)

问题:

  • 以这种方式删除项目适用于字符串比较级别,这可能会在使用符号链接时导致问题,例如
  • 命令行copy工具显然支持复制目录,但它似乎在我的机器上不起作用,因此目录不会被复制。

2)使用file命令复制文件,不包括部分文件

file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/" DESTINATION ${CMAKE_BINARY_DIR}
  PATTERN "file_to_exclude.txt" EXCLUDE
  PATTERN "dir_to_exclude" EXCLUDE
)

问题:

  • 这正是我想要的,除了命令没有绑定到目标,因此总是被执行。但我只需要将复制操作作为目标。

是否有可能将file(COPY ...)命令绑定到目标?或者任何其他直接的解决方案来实现我想要的?

请注意,我只想使用 CMake 内置工具,而不是执行任何特定于操作系统的 shell 命令(在跨平台项目上工作)。

4

1 回答 1

1

CMake脚本命令仅在CMake 上下文中工作并立即执行。

但是COMMANDin add_custom_command(or add_custom_target) 是在构建工具(例如 Makefile)的上下文中执行的,而不是在 CMake 上下文中执行的。

但是,您可以将 CMake 脚本命令放入单独的 CMake 脚本中,然后从COMMAND. 此解决方案具有与其自身相同的平台无关属性CMakeLists.txt

您可以参数化单独的脚本:

  1. 使用configure_fileCMake 命令。
  2. 通过-D在调用脚本时将参数传递给 CMake。

第一种方法非常简单:编写脚本就像编写脚本CMakeLists.txt本身一样。但它会为每个参数化集生成附加文件。

第二种方法对于多用途(或多用途)脚本很有用,因为它不会为每次使用创建额外的脚本副本。但这需要对参数进行一些设计。

使用“配置文件”

copy_sources.cmake.in(好像命令写在CMakeLists.txt):

file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/" DESTINATION ${CMAKE_BINARY_DIR}
  PATTERN "file_to_exclude.txt" EXCLUDE
  PATTERN "dir_to_exclude" EXCLUDE

)

CMakeLists.txt

# Instantiate the parameterized script in the binary directory.
configure_file(copy_sources.cmake.in copy_sources.cmake)

add_custom_target(my-target
  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/copy_sources.cmake

)

使用“-D”参数

copy_sources.cmake

# Expect the script to be called from the source directory.
# This saves one parameter.
# 
# DEST_DIR denotes the directory for copy to.
file(COPY "${CMAKE_SOURCE_DIR}/" DESTINATION ${DEST_DIR}
  PATTERN "file_to_exclude.txt" EXCLUDE
  PATTERN "dir_to_exclude" EXCLUDE
)

CMakeLists.txt

add_custom_target(my-target
  COMMAND ${CMAKE_COMMAND}
    -DDEST_DIR=${CMAKE_BINARY_DIR} # all '-D' options should preceed '-P' one
    -P ${CMAKE_CURRENT_SOURCE_DIR}/copy_sources.cmake
  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} # The script assumes proper current directory

)

于 2020-04-21T11:27:43.330 回答