【问题标题】:CMake copy if original file changed如果原始文件更改,则 CMake 复制
【发布时间】:2017-05-19 05:04:38
【问题描述】:

在 CMake 中,我有一个包含预定义 Gettext 目录的文件夹,在构建时我将其复制到一个文件夹中,然后对其进行修改。但问题是每次我运行目标时,它都会将预定义文件复制到本地副本(可能已修改)。如果文件与之前的状态不同,有没有办法复制,否则不要管它?

我还想这样做的一种方法是在 CMake 生成时复制它们,但我觉得这样做有点厌倦,因为人们可能会删除文件夹并将事情搞砸。另外我不知道如何在生成时执行命令,只在构建时执行。

【问题讨论】:

    标签: cmake


    【解决方案1】:

    我相信您应该能够使用依赖于文件的自定义命令。比如:

    add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/output.file
        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/input.file ${CMAKE_CURRENT_BINARY_DIR}/output.file
        MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/input.file)
    

    如果不这样做,请告诉我。提供您当前使用的 CMake 代码可能会有所帮助。

    你也可以试试 "${CMAKE_COMMAND} -E copy_if_different";考虑到命令的依赖关系,我不清楚这是否会有所不同,但我肯定会遗漏一些东西,或者如果你不使用“make”输出可能会有所不同。


    如果您想尝试在“生成时间”(运行 cmake 时)进行复制,可以使用此命令(我认为我的语法是正确的,但我没有测试它):

    file(COPY
        ${CMAKE_CURRENT_SOURCE_DIR}/input.file
        DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
    

    使用 INSTALL 而不是 COPY 的行为略有不同。

    如果您需要在生成时运行任意进程,请尝试execute_process 命令。

    当然,详情见the CMake documentation

    【讨论】:

    • 除了使用“cp”,你可以简单地使用“${CMAKE_COMMAND} -E copy”——运行“cmake -E”而不需要任何其他参数来查看可用的cmake -E cross列表-platform 可以运行的类似工具的命令。甚至还有“copy_if_different”...使用这样的自定义命令是完美的解决方案,我也会给出答案。
    • 哦,是的,我之前至少使用过一次,但完全忘记了它。谢谢指点。
    • copy_if_different 没有做我需要的事情(只有在原始文件自上次复制后发生更改时才复制),但我不只是复制文件,我正在做一个 MSGMERGE,我只想要如果原始文件更改,请执行此操作。也许这是不可能的,所以似乎生成时间是要走的路,但我不知道如何在生成时间运行命令。
    • 再次,也许您可​​以发布您实际使用的 CMake 脚本的相关部分,以及它到底在做什么。但无论如何,要在生成时运行任意命令,看起来你会使用“execute_process”命令。
    【解决方案2】:

    另一种选择是将configure_fileCOPYONLY 参数一起使用。

    configure_file(input_file output_file COPYONLY)
    

    这不会执行任何变量替换,并且会在您运行 make 时复制“input_file”。但它会触发 cmake 运行,由于时间消耗,这可能是不可取的。

    【讨论】:

      【解决方案3】:

      好的,我不久前设法解决了这个问题,但忘记了这个答案。对不起所有跳过这个但没有答案的人!

      # ----- Copy and merge across the po files that come with the source.
      
      message("Copying and updating stock translations...")
      
      file(GLOB poFiles "${stockDir}/*.po")
      
      foreach(file ${poFiles})
        # Get the language name, like en_US or zh_CN from the name of the po file, so
        # 'en_US.po' or 'zh_CN.po' become 'en_US' or 'zh_CN.po'
        get_filename_component(langName ${file} NAME_WE)
      
        set(newFile "${langDir}/${langName}.po")
      
        if(NOT EXISTS ${newFile})
          execute_process(COMMAND ${MSGMERGE_EXECUTABLE}
            "--output-file" ${newFile} ${file} ${potFile}
            OUTPUT_QUIET ERROR_VARIABLE error RESULT_VARIABLE ret)
      
          if(ret) # Have to do this hack as msgmerge prints to stderr.
            message(SEND_ERROR "${error}")
          endif()
      
          message(" '${langName}' copied.")
        elseif(${file} IS_NEWER_THAN ${newFile})
           execute_process(COMMAND ${MSGMERGE_EXECUTABLE}
             "--update" ${newFile} ${file}
             OUTPUT_QUIET ERROR_VARIABLE error RESULT_VARIABLE ret)
      
           if(ret) # Have to do this hack as msgmerge prints to stderr.
             message(SEND_ERROR "${error}")
           endif()
      
           message(" '${langName}' merged.")
        endif()
      endforeach()
      

      stockDir 是包含不打算由用户编辑的存储 po 文件的目录(除非提交到 repo)。 langDir 位于“lang”下的构建目录中。它会根据文件的年龄进行复制或更新。

      【讨论】:

        猜你喜欢
        • 2021-01-18
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-29
        • 1970-01-01
        • 2021-10-19
        • 2022-10-24
        • 1970-01-01
        相关资源
        最近更新 更多