使用Automake编译可执行文件后,我希望可执行文件输出编译日期,使用的编译器和git repo版本/日期。但是,我似乎无法从Makefile.am运行shell命令。当我尝试时,会收到以下警告:
sample / C ++ / Makefile.am:1:警告:日期+%D:非POSIX变量名称
sample / C ++ / Makefile.am:1 :(可能是GNU make扩展名)
sample / C ++ / Makefile.am:2:警告:git --no-pager show --date = short --format =“%ad” --name-only | {首先阅读_; echo $ first; }:非POSIX变量名称
sample / C ++ / Makefile.am:2 :(可能是GNU make扩展名)
sample / C ++ / Makefile.am:3:警告:git --no-pager describe --tags --always --dirty:非POSIX变量名
sample / C ++ / Makefile.am:3 :(可能是GNU make扩展名)
如果除了在configure.ac中运行命令之外,还有其他更好的方法(因为这超出了进行编译时间的目的),请告诉我。
答案 0 :(得分:0)
POSIX make
和许多特定的make
实现没有提供在配方之外运行Shell命令的机制。 GNU make
也许还有其他人确实将其作为扩展来提供,但是Autotools的目标之一是支持尽可能广泛的构建环境,因此依赖于特定实现提供的扩展与Autotools惯用语相反。 / p>
一种不依赖扩展即可解决问题的方法是,使源#include
成为在构建时动态生成的标头。例如,下面是Makefile.am
部分的外观:
bin_PROGRAMS = hello
hello_SOURCES = \
hello.cpp \
build_details.h
BUILT_SOURCES = \
build_details.h
CLEANFILES = \
build_details.h
build_details.h:
echo "#define BUILDDATE \"`date +%D`\"" >$@
echo "#define COMPILER \"$(CXX)\"" >>$@
由于它被列在BUILT_SOURCES
中,因此目标build_details.h
将被尽早构建。由于构建规则没有先决条件,因此始终将其视为过时的,因此将对其进行重新构建,从而获得新鲜的细节。当然,这也意味着,每次运行make
时,都将重建所有依赖它的源,但是如果您要跟踪这种构建信息,那么实际上这就是您想要的。
另一方面,如果您愿意依赖GNU make
扩展,那么它们提供了一种将变量设置为Shell命令输出的方法。在这种情况下,您可能会执行以下操作:
bin_PROGRAMS = hello
builddate := $(shell date +%D)
CXXFLAGS = -DBUILDDATE='"$(builddate)"' -DCOMPILER='"$(CXX)"'
hello_SOURCES = \
hello.cpp
请注意双引号:内部双引号必须是要定义的宏的替换文本的一部分,因此,当它们出现在编译器命令行上时,需要对它们进行保护,以防外壳程序破坏。
这具有以下优点:较短,并且如果hello
不变,则不会导致hello.cpp
重建。但是,它仅与支持所用GNU扩展的make
一起使用。另外,这不会导致任何对象过期,因此,由于对象保持旧版本信息不在某些{{1 }}执行。
当然,尽管我已经解决了提出的问题,但值得注意的是,其中某些功能与直接存在于C和C ++语言中的功能重复。具体来说,将自动定义make
和__DATE__
宏以扩展到编译的日期和时间。它们不让您控制格式,但这可能是一个值得权衡的问题。