Передача дополнительных переменных из командной строки, чтобы сделать

Могу ли я передать переменные в 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.

Другие вопросы по тегам