尝试使用CMake和set_source_files_properties触发最小重建

时间:2016-09-16 07:01:58

标签: cmake

我已将问题分离到一个非常小的双源项目:https://github.com/ennorehling/versioning/tree/v0.1

我要做的是在version.c中没有硬编码的版本号,而是从外部变量将版本号提供给我的构建过程。请参阅我的构建过程的s / build:如果定义了$ VERSION,我希望它是程序打印的版本号。我通过执行命令VERSION = 1.2 s / build形成shell来实现这一点(或者,如果未定义VERSION,则使用git中最新的标记)。

这个问题是我每次构建都运行cmake .. -DVERSION=$VERSION,并重新创建Makefile,这会导致完全重建。我想只重建version.o,因为它是唯一依赖于版本号的源文件。构建main.o(以及在实际项目中,每个其他对象也是如此)是不必要的。我最初使用add_definitions,它会将-D编译开关添加到每个源,我认为set_source_files_properties是我能够解决这个问题的方法,但是因为两个目标文件都是在build / CMakeFiles / version中生成的相同生成的Makefile中生成的.dir / build.make,被cmake进程触及。似乎在安全方面犯错并重建一切?

也许我正在完全咆哮错误的树,而且我还没找到正确的CMake命令,我不知道。也许还有其他可靠的方法来实现我想要做的事情?在这一点上,我花了很多时间在这上面,我并不羞于寻求帮助。

3 个答案:

答案 0 :(得分:1)

我找到了解决这个问题的方法。这里的根本问题是CMake为每个库或可执行目标创建一个Makefile,并且因为我的代码只有一个目标,所以每次触摸Makefile。所以答案是为version.c创建一个库目标!

add_library(version OBJECT version.c)
add_executable(hello main.c $<TARGET_OBJECTS:version>)

这会在build / CMakeFiles / version.dir和build / CMakeFiles / hello.dir中创建单独的文件,对VERSION数字的更改只影响其中一个,以及其中的单个目标。可执行文件的依赖项未更改,不会重建,只执行链接器步骤,从而减少了构建时间。

它有点笨重,但它对我有用。新版本的项目在这里: https://github.com/ennorehling/versioning/tree/v1.0

编辑:事实证明Ubuntu Precise还没有CMake 2.8.8,而add_library的OBJECT选项需要它。因此,我必须实际从该单个目标文件创建一个库并链接它,如下所示:

add_library(version version.c)
add_executable(hello main.c)
target_link_libraries(hello version)

不是很大,但有点烦人。

答案 1 :(得分:1)

在您的情况下,您不需要每次都重新配置。一旦编写了make / build环境,问题就可以简化为#34;文件已经改变了#34;由make本身检查的问题。

所以我可能只是在你的构建脚本中生成version.c(并将此文件添加到.gitignore或者直接将其生成到build目录中):

<强> S /构建

#!/bin/sh

if [ -z "$VERSION" ]; then
    VERSION=$(git describe --tags --match "v*.*")
    if [ -z "$VERSION" ]; then
        VERSION=1.0.0
    fi
fi

echo "const char *version(void) { return \"${VERSION}\"; }" > version.c~
if cmake -E compare_files version.c~ version.c 
then
    cmake -E remove version.c~
else
    cmake -E rename version.c~ version.c
fi        

if ! [ -d build ]; then
    cmake -E make_directory build
    cmake -H. -Bbuild
fi
cmake --build build

<强>的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(version C)

add_executable(version version.c main.c)

<强> version.c

const char *version(void) { return "1.0.0"; }

<强>的main.c

#include "stdio.h"

const char *version(void);

void main(void) {
    puts(version());
}

答案 2 :(得分:0)

这似乎是CMake Unix Makefile生成器中的一个错误。我使用Ninja生成器尝试了您的(原始)代码示例,如果您只更改版本号,ninja会设法避免重建main.c