CMake - 仅在文件不存在时复制文件

时间:2018-02-03 02:17:21

标签: visual-studio cmake

我想将带有cmake的postbuild文件复制到build目录,但前提是它们还不存在。

我知道有一个" copy_if_different"切换为" add_custom_command",但我找不到类似" copy_if_doesnt_exist"。

目前我对此感到困惑:

$<TARGET_FILE_DIR:${PROJECT_NAME_STR}>/data/configurations

我不知道如何获取目标文件路径

{{1}}

为了把它放到if语句

1 个答案:

答案 0 :(得分:2)

对于不直接支持的情况,file(GENERATE ...)命令非常有用(因为它确实评估generator expressions)。

因此,在您的情况下,我已成功测试了以下代码示例:

cmake_minimum_required(VERSION 2.8.12)

if (POLICY CMP0070)
    cmake_policy(SET CMP0070 NEW)
endif()

project(CopyFileIfNotExists)

file(
    GENERATE 
        OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/CopyConfigurationData$<CONFIG>.cmake"
        CONTENT 
            "if (NOT EXISTS \"$<TARGET_FILE_DIR:${PROJECT_NAME}>/data/configurations\")
                execute_process(
                     COMMAND \"${CMAKE_COMMAND}\" -E copy_directory
                         \"${PROJECT_SOURCE_DIR}/data/configurations\"
                         \"$<TARGET_FILE_DIR:${PROJECT_NAME}>/data/configurations\"
                )
            endif()"
)

file(WRITE "main.cpp" "int main() { return 0; }")

add_executable(${PROJECT_NAME} "main.cpp")

add_custom_command(
    TARGET ${PROJECT_NAME} 
    POST_BUILD 
    COMMAND "${CMAKE_COMMAND}" -P "CopyConfigurationData$<CONFIG>.cmake"
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)

<强>替代

或者,如果可以运行每个CMake(重新)配置,只需添加以下内容而不是后构建步骤:

file(
    GLOB 
        CONFIGURATION_DATA 
        RELATIVE "${PROJECT_SOURCE_DIR}"
        "${PROJECT_SOURCE_DIR}/data/configurations/*"
 )

foreach(data IN LISTS CONFIGURATION_DATA)
    file(
        GENERATE 
            OUTPUT "$<TARGET_FILE_DIR:${PROJECT_NAME}>/${data}"
            INPUT  "${PROJECT_SOURCE_DIR}/${data}"
    )
endforeach()

替代方案:优化版

利用file(COPY ...)基于最短脚本的版本,我可以想到这也可以优化现有项目

  

“复制会保留输入文件时间戳,并在目标中存在具有相同时间戳的文件时对其进行优化。”

看起来像这样:

file(
    GENERATE 
        OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/CopyConfigurationData$<CONFIG>.cmake"
        CONTENT "file(
                    COPY \"${PROJECT_SOURCE_DIR}/data/configurations\"
                    DESTINATION \"$<TARGET_FILE_DIR:${PROJECT_NAME}>/data\"
                 )"
)