我尝试使用内部版本号自动标记我的应用程序登录行。这个应用程序是一个没有图形UI的普通香草C;它适用于命令行,因此它是一个简单的"之一。
登录ID位于"模板"由CMake使用configure_file()
命令自定义的源文件。最近,我想在这个登录ID中包含一个内部版本号。因此,无法再在CMake时间静态地完成自定义,但每次调用make都会被调用。
为实现这一目标,CMake有两种可能性:
我选择了第二种解决方案并没有成功。
以下是 CMakeLists.txt 的摘录,登录ID位于文件 ErrAux.c (PROJECT_SOURCE_DIR中的模板,在PROJECT_BINARY_DIR中配置):
add_executable(anathem ... ${PROJECT_BINARY_DIR}/ErrAux.c ...)
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
这将在链接步骤之前启动脚本 BuildNumber.cmake 。它计算下一个内部版本号,并使用configure_file()
自定义 ErrAux.c 。
它工作正常,除了......
它发生在 make 序列的后期,而对 ErrAux.c 的更新却没有引起注意。可执行文件中的登录ID包含先前的内部版本号。
下次运行 make 时, make 会注意到生成的 ErrAux.c 比其对象模块更年轻并导致它再次被编译,这反过来导致一个触发内部版本号更新的链接。即使没有其他文件发生更改也无法解决此循环,也会发生这种情况。这在编译日志中清楚地显示:
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-45
[ 36%] Built target anathem
关键似乎是add_custom_command(TARGET ...)
无法指定add_custom_command(OUTPUT ...)
之类的输出文件。但后一种形式无法在PRE_LINK模式下触发。
作为一种解决方法,我强制编译为"刷新"对象模块:
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
COMMAND echo "Numbering"
COMMAND echo "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
COMMAND "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
登录ID自定义后强制显式编译。它模仿了各种 Makefile 中的内容,而且我对生产不安全。这是 CMake 和 make 的作弊技巧。
更新:需要选项-c
推迟链接步骤,直到最终的应用程序liniking过程。
此添加会在链接中造成破坏,如日志所示,您可以在其中看到双重编译(标准 make 一个和add_custom_command()
一个):
德尔>
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-47
Numbering
/usr/bin/cc -DANA_DEBUG=1 -I/home/prog/projects/AnaLLysis/build/AnaThem -I/home/prog/projects/AnaLLysis/AnaThem -g /home/prog/projects/AnaLLysis/build/AnaThem/ErrAux.c
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
AnaThem/CMakeFiles/anathem.dir/build.make:798: recipe for target 'AnaThem/anathem' failed
make[2]: *** [AnaThem/anathem] Error 1
<德尔>
如果我强制完全重新编译,为了确保编译所有源代码,包括* main.c *,我在`main`上得到相同的错误。
唯一合乎逻辑的解释是我的手动C调用是错误的,并以某种方式破坏重要信息。我用* readelf *检查了`main`仍然在* main.c.o *的符号表中,并且它仍然被链接步骤(来自file * link.txt *)考虑在内。
德尔>
更新:即使链接正确,我仍然会遇到无限循环综合症。生成的应用程序的登录ID仍然落后于实际的构建计数器。
有人能给我一个正确方向的线索吗?
仅供参考我是CMake的新手,所以我可能做错了。不要批评我的错误。
答案 0 :(得分:0)
解决方案的关键是将生成的模块放在 make 期望找到它的位置。 CMake 以非平凡的方式组织构建树。
我在add_custom_command()
中添加的编辑中的缺点是相信默认情况下二进制文件将存储在&#34;通常&#34; CMake 位置。由于我手动伪造我的编译器命令,情况并非如此。
我在源目录中找到了该模块,这是WORKING_DIRECTORY
选项的结果,名称为 ErrAux.o ,而不是 ErrAux.co 。
为了获得正确的行为,我强制输出位置:
-o "${PROJECT_BINARY_DIR}/CMakeFiles/anathem.dir/ErrAux.c.o"
现在,当我再次运行 make 时,没有任何反应,因为没有任何改变。
附带问题
要使解决方案可移植(如果需要), CMakeFiles 和 anathem.dir 目录是否有CMake变量?或者在后一种情况下,对于当前目标为&#34; anathem&#34;作为add_custom_command()
中的目标名称?