Передача дополнительных переменных из командной строки, чтобы сделать
Могу ли я передать переменные в Makefile GNU в качестве аргументов командной строки? Другими словами, я хочу передать некоторые аргументы, которые в конечном итоге станут переменными в Makefile.
7 ответов
У вас есть несколько вариантов установки переменных вне вашего make-файла:
Из среды - каждая переменная среды преобразуется в переменную makefile с тем же именем и значением.
Вы также можете установить
-e
вариант (иначе--environments-override
), и ваши переменные среды будут переопределять назначения, сделанные в make-файле (если только эти назначения сами не используютoverride
директива Тем не менее, это не рекомендуется, и это гораздо лучше и гибче в использовании?=
присваивание (условный оператор присваивания переменной, он действует только в том случае, если переменная еще не определена):FOO?=default_value_if_not_set_in_environment
Обратите внимание, что некоторые переменные не наследуются от окружения:
MAKE
получается из названия скриптаSHELL
либо установлен в make-файле, либо по умолчанию/bin/sh
(Обоснование: команды указываются в make-файле, и они зависят от оболочки).
Из командной строки -
make
может принимать переменные в составе своей командной строки, смешавшись с целями:make target FOO=bar
Но тогда все назначения
FOO
переменная в make-файле будет игнорироваться, если вы не используетеoverride
директива в назначении. (Эффект такой же, как с-e
опция для переменных среды).Экспорт из родительского Make - если вы вызываете Make из Makefile, вам обычно не следует явно писать назначения переменных следующим образом:
# Don't do this! target: $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
Вместо этого лучшим решением может быть экспорт этих переменных. Экспорт переменной превращает ее в среду каждого вызова оболочки, и вызовы Make из этих команд выбирают эти переменные среды, как указано выше.
# Do like this CFLAGS=-g export CFLAGS target: $(MAKE) -C target
Вы также можете экспортировать все переменные, используя
export
без аргументов.
Самый простой способ это:
make foo=bar target
Тогда в вашем make-файле вы можете обратиться к $(foo)
, Обратите внимание, что это не будет распространяться на суб-производителей автоматически.
Если вы используете подкоманды, см. Эту статью: Связь переменных с подзадачей
Скажем, у вас есть такой файл:
action:
echo argument is $(argument)
Вы бы тогда назвали это make action argument=something
Это выглядит
аргументы команды перезаписать переменную среды
Makefile
send:
echo $(MESSAGE1) $(MESSAGE2)
Пример выполнения
$ MESSAGE1=YES MESSAGE2=NG make send MESSAGE2=OK
echo YES OK
YES OK
Из руководства:
Переменные в make могут происходить из среды, в которой запускается make. Каждая переменная окружения, которая делает make, видит, когда она запускается, преобразуется в переменную make с тем же именем и значением. Однако явное присваивание в make-файле или с аргументом команды переопределяет окружение.
Так что вы можете сделать (из Баш):
FOOBAR=1 make
в результате чего переменная FOOBAR
в вашем Makefile.
Есть еще один вариант, не упомянутый здесь, который включен в книгу GNU Make Stallman и McGrath (см. http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html). Это обеспечивает пример:
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
+touch archive.a
+ranlib -t archive.a
else
ranlib archive.a
endif
Это включает в себя проверку, если данный параметр появляется в MAKEFLAGS
, Например... предположим, что вы изучаете темы в C++11 и разделите свое исследование на несколько файлов (class01
,..., classNM
) и вы хотите: скомпилировать затем все и запустить по отдельности или скомпилировать по одному и запустить его, если указан флаг (-r
, например). Итак, вы могли бы придумать следующее Makefile
:
CXX=clang++-3.5
CXXFLAGS = -Wall -Werror -std=c++11
LDLIBS = -lpthread
SOURCES = class01 class02 class03
%: %.cxx
$(CXX) $(CXXFLAGS) -o $@.out $^ $(LDLIBS)
ifneq (,$(findstring r, $(MAKEFLAGS)))
./$@.out
endif
all: $(SOURCES)
.PHONY: clean
clean:
find . -name "*.out" -delete
Имея это, вы бы:
- построить и запустить файл с
make -r class02
; - построить все ж /
make
или жеmake all
; - построить и запустить все без
make -r
(предположим, что все они содержат определенные виды утверждений, и вы просто хотите проверить их все)
Если вы создадите файл с именем Makefile и добавите переменную, подобную этой $(unittest), то вы сможете использовать эту переменную внутри Makefile даже с подстановочными знаками
пример:
make unittest=*
Я использую BOOST_TEST и, задав подстановочный знак для параметра --run_test=$(unittest), я смогу использовать регулярное выражение для фильтрации теста, который я хочу, чтобы мой Makefile запустил
export ROOT_DIR=<path/value>
Затем используйте переменную, $(ROOT_DIR)
в Makefile.