我已将问题分离到一个非常小的双源项目: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命令,我不知道。也许还有其他可靠的方法来实现我想要做的事情?在这一点上,我花了很多时间在这上面,我并不羞于寻求帮助。
答案 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
。