【问题标题】:CMake: Regenerate source file if target gets rebuiltCMake:如果重新构建目标,则重新生成源文件
【发布时间】:2020-08-30 18:34:52
【问题描述】:

我正在尝试将构建日期嵌入到源文件中,以便每次构建特定目标时都会刷新嵌入日期,而不会在每次构建整个项目时重新生成。

即我有一个头文件builddate.h,它是由具有一组#defines 的命令生成的。然后从其他源文件中包含此头文件。

我的第一次尝试是这样的:

add_custom_target(builddate COMMAND <command that generates header file>)
add_library(mylibrary ...)
add_dependencies(mylibrary builddate)

这样会正确生成头文件,但是每次都会生成头文件,不管mylibrary目标是否需要重建。

尝试使用自定义命令,即

add_custom_command(OUTPUT builddate.h COMMAND <command that generates header file>)
add_library(mylibrary ... builddate.h)

正确生成一次标头,但如果重新构建mylibrary 目标,则不会重新生成标头,因为builddate.h 已经是最新的。

这感觉应该是相当普遍的,但我无法弄清楚自定义命令和目标的什么咒语会给我想要的效果。我想要的是每次构建mylibrary 目标时调用该命令,如果没有任何更改或构建不相关的目标(例如使用mylibrary 的可执行文件),则不会进行虚假重建。

使用PRE_BUILD 自定义命令听起来是个好主意,但文档指出这会在PRE_LINK 命令之前被调用,而不是Visual Studio,即 源之后编译。这似乎使它不适合此目的,因为在编译源代码时需要标头。

【问题讨论】:

    标签: cmake cmake-custom-command add-custom-target


    【解决方案1】:

    https://cmake.org/pipermail/cmake/2010-October/040247.html 找到一个旧线程,建议调用 CMake 的 --build 作为 PRE_LINK 命令作为目标:

    # This is the library that I want to build
    add_library(mylibrary ...)
    
    # Set up a library that contains the code depending on the build date
    # Use an OBJECT library because we don't need it to be a full static lib
    # we just want to build some source that would "normally" have been part of mylibrary
    add_library(builddate OBJECT EXCLUDE_FROM_ALL codethatusesbuilddate.cpp)
    
    # Add a PRE_LINK command for mylibrary so that prior to linking we
    # 1. Generate the builddate.h header
    # 2. Call CMake to build the builddate library we just set up
    add_custom_command(
        TARGET mylibrary PRE_LINK
        COMMAND <command that generates builddate.h>
        COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target builddate
    )
    
    # We also need to link with the library
    # NOTE: uses the generator expression to link with the output files rather than the target
    # to avoid CMake setting up a dependency from builddate to mylibrary which I think
    # would cause builddate to be built prior to building mylibrary, but at that point we
    # haven't generated the header yet. Which we could fix, but then we'd just build it twice
    target_link_libraries(mylibrary PRIVATE $<TARGET_OBJECTS:builddate>)
    
    
    

    这感觉有点尴尬,但似乎有效。

    脚注:使用 CMake 可以轻松生成标头,即首先使用 configure_file 或类似方法来创建执行生成的 CMake 脚本,然后调用 ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/generated_cmake_file.cmake 作为生成标头的命令。

    【讨论】:

      【解决方案2】:

      前段时间,我写了一个cmake makro。它添加了自定义命令,通过执行 Cversion.cmake 在当前构建目录中生成 version.cpp。 只有在依赖关系发生变化时才会执行文件的生成。 使用 cmake-generator-expressions 将依赖项设置为目标的依赖项减去它自己的(文件)。

      可以通过添加libs依赖来改进它,同时生成一个新的版本文件。

      macro(add_versioning T)
      add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
              COMMAND ${CMAKE_COMMAND} "-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
              -P "${PROJECT_SOURCE_DIR}/Version/CVersion.cmake"
              MAIN_DEPENDENCY "${PROJECT_SOURCE_DIR}/Version/version.cpp.in"
              DEPENDS "$<FILTER:$<TARGET_OBJECTS:${T}>,EXCLUDE,version.cpp.+$>")
      
      target_include_directories(${T} PUBLIC "${PROJECT_SOURCE_DIR}/Version")
      target_sources(${T} PUBLIC "${PROJECT_SOURCE_DIR}/Version/version.h" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
      
      endmacro()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-03
        • 1970-01-01
        • 1970-01-01
        • 2010-10-23
        相关资源
        最近更新 更多