CMake:每次制作后都可以运行CONFIGURE_FILE吗?

时间:2014-02-09 09:04:06

标签: makefile cmake

我的CMake文件中有以下脚本:

CONFIGURE_FILE(
    ${CMAKE_CURRENT_SOURCE_DIR}/version.hpp.cmake
    ${CMAKE_CURRENT_SOURCE_DIR}/version.hpp
)

但它只在执行cmake后运行,而不是make。是否可以在每次制作后创建version.hpp文件?

以下是version.hpp.cmake的内容:

#ifndef _VERSION_HPP_
#define _VERSION_HPP_

#define MAJOR_VERSION "${MAJOR}"
#define MINOR_VERSION "${MINOR}"
#define PATCH_VERSION "${PATCH}"
#define RELEASE_VERSION "${RELEASE}"

#endif //_VERSION_HPP_

MAJOR文件中定义了MINORPATCHRELEASECMakeLists.txt变量。

P.S。 This post显然与我的问题有关,但我无法理解它。

3 个答案:

答案 0 :(得分:4)

问题是configure_file应该在配置时运行,即运行cmake而不是编译时,即运行make时。没有简单的方法。

问题是configure_file写的信息依赖于CMake构建环境中的变量。如果不再次运行CMake,则无法检测到这些变量的更改。如果您将该信息镜像到其他位置,则可以使用自定义命令将其解压缩并为您执行代码生成,如Peter's answer所示。

你答案中post from the CMake mailing list that you linked中建议的方法基于两阶段CMake运行:外部CMake项目(仅运行一次)添加了一个自定义构建步骤,用于构建内部CMake项目(然后在执行make的每个configure_file运行。基本思想与Peter的答案相同,只是使用CMake脚本代替Python脚本来生成文件。

我的个人建议:对于一个简单的问题作为版本标题,我不会打扰这么复杂的方法。只需将文件生成到您的BINARY_DIR(而不是您目前的项目目录!您希望保留从同一来源执行多个源外构建的能力)并假设它将用于编译。如果用户有足够的勇气来搞乱那里生成的文件,他们可以自己重新运行CMake。

答案 1 :(得分:3)

所以我不小心偶然发现了这个,我知道这可能为时已晚,但调用configure可能与我使用mercurial版本完全相同。

这个技巧需要很多不同的工具,我没有时间制定一个好的答案atm,但提出问题,我会在有空的时候填写。

工具1:调用exec_program来提取修订信息(这对mercurial来说真的很容易)

exec_program(hg ${PROJECT_SOURCE_DIR} ARGS "id" "-i" OUTPUT_VARIABLE OUTPUT_VARIABLE ${PROJECT_NAME}_HG_HASH_CODE)

我可能正在做一些比你在乎的事情更复杂的事情,但基本的一点是hg你将用你正在使用的任何版本控制替换,${PROJECT_SOURCE_DIR}你将设置到你想要的任何执行目录,并填写自定义args。

我将所有版本提取放入一个宏(ReadProjectRevisionStatus())。

下一步是创建一个完全不同的CMake文件,该文件调用ReadProjectRevisionStatus()然后调用CONFIGURE_FILE。此文件将假定您进入时设置了所有正确的值。在我的例子中,我将此文件的位置存储到$ {CONFIG_FILE_LOC}。

最后一步是添加一个将调用此脚本的自定义目标。例如:

ADD_CUSTOM_TARGET(${PROJECT_NAME}_HG_VERSION_CONFIG
    COMMAND ${CMAKE_COMMAND}
    ARGS -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
    -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}
    -DPROJECT_NAME=${PROJECT_NAME}
    -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}
    "-D${PROJECT_NAME}_HG_CONFIG_FILE_IN=\"${${PROJECT_NAME}_HG_CONFIG_FILE_IN}\""
    "-D${PROJECT_NAME}_HG_CONFIG_FILE_OUT=\"${${PROJECT_NAME}_HG_CONFIG_FILE_OUT}\""
    ${ARGN}
    -P ${CONFIG_FILE_LOC})

这样做的一个好处是,仍然可以在cmake构建系统之外调用自定义目标调用,我已经在几个项目中进行了调用,这类调用类似于:

cmake -D PROJECT_SOURCE_DIR=$sourcedir -DPROJECT_BINARY_DIR=$sourcedir -DPROJECT_NAME=uControl -DCMAKE_MODULE_PATH=$sourcedir -DuControl_HG_CONFIG_FILE_IN=$sourcedir/tsi_software_version.h.in -DuControl_HG_CONFIG_FILE_OUT=$sourcedir/tsi_software_version.h -P $sourcedir/ConfigureHGVersion.cmake

答案 2 :(得分:1)

一种可能性是从Python生成version.hpp并使用ADD_CUSTOM_TARGET

... find python ...
ADD_CUSTOM_TARGET(gen_version ALL ${PYTHON_EXECUTABLE} gen_version.py)
SET_SOURCE_FILES_PROPERTIES(version.hpp PROPERTIES GENERATED 1)
... link gen_version to your library/executable ...