POSIX make
and many specific make
implementations provide no mechanism for running shell commands outside of recipes. GNU make
and perhaps others do provide that as an extension, but one of the objectives of the Autotools is to support the widest variety of build environments possible, so relying on extensions provided by specific implementations is contrary to Autotools idiom.
One way to approach the problem without relying on extensions would be to make your sources #include
a header that is generated dynamically at build time. For example, here's how the Makefile.am
part might look:
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)\"" >>$@
Because it is listed among the BUILT_SOURCES
, target build_details.h
will be built early. Because the rule for building it has no prerequisites, it is always considered out of date, so it will be rebuilt, thus getting the fresh details. Of course, this also means that all sources that depend it will be rebuilt every time you run make
, but maybe that's actually what you want if you're tracking this kind of build info.
On the other hand, if you're willing to depend on GNU make
extensions, then they provide a way to set variables to the output of shell commands. In that case you might do something more like this:
bin_PROGRAMS = hello
builddate := $(shell date +%D)
CXXFLAGS = -DBUILDDATE='"$(builddate)"' -DCOMPILER='"$(CXX)"'
hello_SOURCES = \
hello.cpp
Note the double quotation: the inner double quotes need to be part of the replacement text of the macros being defined, so they need to be protected from the shell as they appear on the compiler command line.
This has the advantages that it is shorter, and that it will not cause hello
to be rebuilt if hello.cpp
has not changed. But it will only work with a make
that supports the GNU extensions used. Also, this does not cause any objects to be out of date, so it may leave open the possibility of stale build info being recorded in the binary as a result of the object that holds it not being among those rebuilt on some given make
execution.
Of course, although I've addressed the question as posed, it is worthwhile to note that some of this is duplicative of features that exist directly in the C and C++ languages. Specifically, the __DATE__
and __TIME__
macros are automatically defined to expand to the date and time of compilation. They don't give you control over the format, but that might be a worthwhile tradeoff.