Передача дополнительных переменных из командной строки, чтобы сделать - PullRequest
526 голосов
/ 13 мая 2010

Могу ли я передать переменные в Makefile GNU в качестве аргументов командной строки? Другими словами, я хочу передать некоторые аргументы, которые в конечном итоге станут переменными в Makefile.

Ответы [ 7 ]

649 голосов
/ 13 мая 2010

У вас есть несколько вариантов установки переменных вне вашего make-файла:

  • Из среды - каждая переменная среды преобразуется в переменную make-файла с тем же именем и значением.

    Вы также можете включить параметр -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 без аргументов.

171 голосов
/ 13 мая 2010

Самый простой способ:

make foo=bar target

Тогда в вашем make-файле вы можете обратиться к $(foo). Обратите внимание, что это не будет распространяться на суб-производителей автоматически.

Если вы используете подмодели, см. Эту статью: Связь переменных с подмоделью

60 голосов
/ 13 мая 2010

Скажем, у вас есть такой make-файл:

action:
    echo argument is $(argument)

Вы бы тогда назвали это make action argument=something

19 голосов
/ 13 мая 2010

Из руководства :

Переменные в make могут исходить из среды, в которой запускается make. Каждая переменная окружения, которая видит, когда она запускается, преобразуется в переменную make с тем же именем и значением. Однако явное присваивание в make-файле или с аргументом команды переопределяет среду.

Так что вы можете сделать (из Баш):

FOOBAR=1 make

в результате чего в вашем файле Makefile FOOBAR.

4 голосов
/ 21 мая 2015

Есть еще одна опция, не упомянутая здесь, которая включена в книгу GNU Make Сталмана и МакГрата (см. 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

Имея это, вы бы:

  • построить и запустить файл w / make -r class02;
  • построить все с / make или make all;
  • собрать и запустить все с / make -r (предположим, что все они содержат какой-то определенный тип утверждений, и вы просто хотите проверить их все)
3 голосов
/ 07 января 2016
export ROOT_DIR=<path/value>

Затем используйте переменную $(ROOT_DIR) в Makefile.

3 голосов
/ 08 марта 2014

Если вы создадите файл с именем Makefile и добавите переменную, подобную этой $ (unittest) тогда вы сможете использовать эту переменную внутри Makefile даже с подстановочными знаками

пример:

make unittest=*

Я использую BOOST_TEST и, задавая шаблон для параметра --run_test = $ (unittest) тогда я смогу использовать регулярное выражение, чтобы отфильтровать тест, который я хочу, чтобы мой Makefile бежать

...