Как выполнять команды оболочки в Automake / Makefile.am? - PullRequest
0 голосов
/ 22 января 2019

После того, как я скомпилирую свой исполняемый файл с помощью Automake, я хочу, чтобы исполняемый файл выводил скомпилированную дату, использованный компилятор и версию / дату git repo. Однако я не могу заставить команды оболочки запускаться из Makefile.am. Когда я пытаюсь, я получаю эти предупреждения:

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 description --tags --always --dirty: имя переменной не POSIX

sample / C ++ / Makefile.am:3: (возможно, расширение make для GNU)

Если есть лучший способ сделать это, кроме запуска команд в configure.ac (потому что это лишает цель иметь время компиляции), пожалуйста, дайте мне знать.

1 Ответ

0 голосов
/ 23 января 2019

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__ автоматически определяются для расширения до даты и времени компиляции. Они не дают вам контроль над форматом, но это может быть полезным компромиссом.

...