POSIX make
и многие конкретные реализации make
не предоставляют механизма для запуска команд оболочки вне рецептов. GNU make
и, возможно, другие предоставляют это как расширение, но одна из целей Autotools - поддерживать самое широкое разнообразие возможных сред сборки, поэтому использование расширений, предоставляемых конкретными реализациями, противоречит идиоме Autotools.
Один из способов решения проблемы без использования расширений - сделать ваши источники #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
, то они обеспечивают способ установки переменных для вывода команд оболочки. В этом случае вы можете сделать что-то более похожее на это:
bin_PROGRAMS = hello
builddate := $(shell date +%D)
CXXFLAGS = -DBUILDDATE='"$(builddate)"' -DCOMPILER='"$(CXX)"'
hello_SOURCES = \
hello.cpp
Обратите внимание на двойные кавычки: внутренние двойные кавычки должны быть частью замещающего текста определяемых макросов, поэтому они должны быть защищены от оболочки, как они появляются в командной строке компилятора.
Преимущество этого в том, что оно короче и не приводит к перестройке hello
, если hello.cpp
не изменилось. Но он будет работать только с make
, который поддерживает используемые расширения GNU. Кроме того, это не приводит к устареванию каких-либо объектов, поэтому может оставить открытой возможность записи устаревшей информации о сборке в двоичном виде в результате того, что объект, который ее удерживает, не входит в число тех, которые были перестроены для некоторых заданных make
выполнение.
Конечно, хотя я и рассмотрел вопрос как поставленный, стоит отметить, что некоторые из них дублируют функции, которые существуют непосредственно в языках C и C ++. В частности, макросы __DATE__
и __TIME__
автоматически определяются для расширения до даты и времени компиляции. Они не дают вам контроль над форматом, но это может быть полезным компромиссом.