【问题标题】:Build a program at CMake configure time在 CMake 配置时构建程序
【发布时间】:2017-01-26 14:53:32
【问题描述】:

有没有办法让 CMake 在配置时(即运行 cmake . 时)构建和运行 C++ 程序,但前提是它尚未构建?

例如,假设我有一个程序(用 C++ 编写)为我的主程序生成版本信息,我想在主程序的CMakeLists.txt 中使用该版本信息。

我相信您可以通过让主CMakeLists.txt 作为子进程执行 cmake 来做到这一点,但这似乎不是很干净。有没有更好的“官方”方式?

编辑This 基本上是同一个问题,似乎没有真正的好方法。

【问题讨论】:

  • 对我来说听起来很可疑。是 x-y 问题吗?为了提取版本信息,我希望您不必编译和执行文件。
  • 好吧,我本可以做很多粗略的 CMake 东西,但编写 C++ 程序并将其与 libgit2 链接起来更容易。当我希望版本信息进入标题时,它实际上非常有用,因为我可以使用add_custom_command 并且这取决于我的版本提取程序。但如果我想在 CMake 变量中使用它,它就行不通了。
  • 这是一个选项,但之后有一些字符串处理,这在 CMake 中有点痛苦。它可能略高于顶部,但看起来更干净(如果我能解决这个问题)。

标签: cmake


【解决方案1】:

我同意 cmets 的观点,在这种情况下,解决您的潜在问题可能比直接回答您的问题更容易。以下是我从 git 获取分支/版本信息并将其放入我的程序的方法:

我在支持 Windows 和几个 linux 变体的代码库上使用此方法。

创建一个 CMake 宏以从 git 中提取信息:

# Get the current Git commit hash
macro(git_information BRANCH_VAR COMMIT_VAR COMMIT_VAR_SHORT)

    # Get the branch name
    execute_process(
    COMMAND git rev-parse --abbrev-ref HEAD
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    OUTPUT_VARIABLE ${BRANCH_VAR}
    OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    MESSAGE(STATUS "GIT: Current branch -> ${${BRANCH_VAR}}")

    # Retrigger configuration process each time config file changes
    get_filename_component(_cfg_name "${CMAKE_SOURCE_DIR}/.git/refs/heads/${BRANCH}" NAME)
    configure_file("${CMAKE_SOURCE_DIR}/.git/refs/heads/${BRANCH}" "${_cfg_name}.tmp")
    set_source_files_properties(${_cfg_name}.tmp PROPERTIES GENERATED true)

    # Get the head commit
    execute_process(
    COMMAND git rev-parse HEAD
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    OUTPUT_VARIABLE ${COMMIT_VAR}
    OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    MESSAGE(STATUS "GIT: Current commit -> ${${COMMIT_VAR}}")

    # Get the short version of the head commit
    execute_process(
    COMMAND git rev-parse --short HEAD
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    OUTPUT_VARIABLE ${COMMIT_VAR_SHORT}
    OUTPUT_STRIP_TRAILING_WHITESPACE
    )

endmacro()

然后在您的顶级CMakeLists.txt 中像这样调用宏:

find_package(Git)
if(GIT_FOUND)
    git_information(BRANCH GIT_COMMIT GIT_COMMIT_SHORT)
ELSE()
    # as a fallback, use the directory name as the branch name
    GET_FILENAME_COMPONENT(BRANCH ${CMAKE_CURRENT_SOURCE_DIR} NAME)
ENDIF()

要真正将信息输入程序,我使用configure_file(如果您不熟悉,请参阅documentation):

configure_file(include/version.h.in version.h @ONLY NEWLINE_STYLE LF)

该文件看起来像这样:

#include <string>

namespace myProg
{
    static const std::string BRANCH("@BRANCH@");
    static const std::string GIT_COMMIT("@GIT_COMMIT@");
    static const std::string GIT_COMMIT_SHORT("@GIT_COMMIT_SHORT@");
}

您可以想象,通过使用适当的 git 命令添加额外的 execute_process 块,该宏也可用于从 git 中提取标记或描述性信息。

【讨论】:

  • 我喜欢这个答案,也许这个问题必须调整,而不是把它作为重复关闭。
  • @usr1234567 这也是我想知道的,但我认为我们首先需要来自 OP 的一些反馈,即编辑问题以适应答案不会破坏他的初衷,事实上帮助了他。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多