Передача додаткових змінних з командного рядка для виконання


613

Чи можу я передати змінні файлу GNU Makefile як аргументи командного рядка? Іншими словами, я хочу передати деякі аргументи, які з часом стануть змінними в Makefile.

Відповіді:


752

У вас є кілька варіантів налаштування змінних поза вашим makefile:

  • З середовища - кожна змінна середовища перетворюється на змінну makefile з тим самим назвою та значенням.

    Ви також можете встановити -eпараметр (aka --environments-override) увімкнено, і ваші змінні середовища замінять завдання, внесені в makefile (якщо тільки ці призначення самі не використовують overrideдирективу . Однак це не рекомендується, і набагато краще та гнучкіше використовувати ?=призначення (умовна змінна) Оператор присвоєння, він має ефект, лише якщо змінна ще не визначена):

    FOO?=default_value_if_not_set_in_environment
    

    Зауважте, що певні змінні не успадковуються від середовища:

    • MAKE отримується від імені сценарію
    • SHELLабо встановлюється в makefile, або за замовчуванням /bin/sh(обгрунтування: команди задаються в makefile, і вони специфічні для оболонки).
  • З командного рядка - makeможе приймати змінні завдання як частину його командного рядка, змішану з цілями:

    make target FOO=bar
    

    Але тоді всі присвоєння FOOзмінній в makefile будуть ігноруватися, якщо ви не використовуєте overrideдирективу при призначенні. (Ефект такий же, як і -eдля параметра змінних оточуючих середовищ).

  • Експорт з батьківського Make - якщо ви викликаєте Make з Makefile, зазвичай не слід явно писати змінні завдання, як це:

    # Don't do this!
    target:
            $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
    

    Натомість, кращим рішенням може бути експорт цих змінних. Експорт змінної перетворює її в середовище кожного виклику оболонки, і Виконувати дзвінки з цих команд вибирають ці середовища змінними, як зазначено вище.

    # Do like this
    CFLAGS=-g
    export CFLAGS
    target:
            $(MAKE) -C target
    

    Ви також можете експортувати всі змінні, використовуючи exportбез аргументів.


10
перейти з командного рядка щось з пробіламиmake A='"as df"'
Ciro Santilli 郝海东 li 病 六四 事件 六四

4
Здається, ви вимагаєте неприємностей, якщо піклуєтесь про змінні середовища. По-перше, це кошмар налагодження, якщо він працює на місці А, а не на місці Б, тільки тому, що вони мають різні умови.
Джеймс Мур

12
Виходячи з досвіду, експорт таких матеріалів, як CFLAGS, є рецептом кошмару для великих проектів. У великих проектах часто є сторонні бібліотеки, які компілюються лише із заданим набором прапорів (що ніхто не турбує виправлення). Якщо ви експортуєте CFLAGS, CFLAGS вашого проекту в кінцевому рахунку перевизначає сторонні бібліотеки і запускає помилки компіляції. Альтернативним способом може бути визначення export PROJECT_MAKE_ARGS = CC=$(CC) CFLAGS=$(CFLAGS)та передавання його як make -C folder $(PROJECT_MAKE_FLAGS). Якщо є спосіб сказати файл файлу бібліотеки ігнорувати оточення, це було б ідеально (навпроти -e).
РД

24
ПОПЕРЕДЖЕННЯ: У розділі "Експорт з батьківського" Зробити "вище:" Не роби цього! " є критично оманливим . Передача змінних у командному рядку переосмислює призначення в підмайстровому файлі, але експортовані змінні не змінюють призначення у підмайстровому файлі. Ці два способи передачі змінних у суб-makefile не є еквівалентними і їх не слід плутати.
Джонатан Бен-Аврахам

4
Будь-яка різниця? make target FOO=bar make FOO=bar target?
gfan

213

Найпростіший спосіб:

make foo=bar target

Потім у вашому makefile ви можете посилатися $(foo). Зауважте, що це не поширюватиметься на підмайстри автоматично.

Якщо ви використовуєте підмайстри, перегляньте цю статтю: Повідомлення змінних підмайстру


2
під підмайстрами ви маєте на увазі під makefiles includedв основному makefile?
Пабло

2
@Michael: Це означає, що виклик зробити знову зсередини makefile. Я оновив свою відповідь, оскільки вас, здається, цікавить ця деталь.
Марк Байєрс

2
"Зауважте, що це не поширюватиметься на підмайстри автоматично." Неправда! "За замовчуванням до рекурсивних викликів передаються лише змінні, що надійшли з середовища або командного рядка. Ви можете використовувати директиву експорту для передачі інших змінних." gnu.org/software/make/manual/html_node/…
ThomasMcLeod

82

Скажіть, у вас є такий файл файлів:

action:
    echo argument is $(argument)

Тоді ви б це назвали make action argument=something


5
тож ціль та аргументи можна міняти з точки зору позиції?
Пабло

4
@Michael: Так (див. Відповідь Марка
Байерса

25

З посібника :

Змінні в make можуть надходити з середовища, в якому використовується запуск. Кожна змінна середовище, яка бачить, коли вона запускається, перетворюється на змінну make з тим самим іменем та значенням. Однак явне призначення в makefile або з аргументом команди перекриває середовище.

Так ви можете зробити (з bash):

FOOBAR=1 make

що призводить до змінної FOOBARу вашому Makefile.


2
Інший спосіб справді кращий майже у всіх випадках. Я залишу це для повноти.
Томас

Це єдина відповідь, яка показує призначення змінних перед командою make в одному рядку - варто знати, що це не синтаксична помилка.
M_M

7

Тут не вказана інша опція, яка включена до книги GNU Make by Stallman and 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) і хочете: компілювати потім усі та запускати окремо або компілювати один у a час і запустіть його, якщо вказано прапор ( -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;
  • будувати всі w / makeабо make all;
  • створити та запустити всі w / make -r(припустимо, всі вони містять певний тип аргументів, і ви просто хочете перевірити їх)

6

здається

командні аргументи перезаписують змінну середовища

Makefilefile

send:
    echo $(MESSAGE1) $(MESSAGE2)

Виконати приклад

$ MESSAGE1=YES MESSAGE2=NG  make send MESSAGE2=OK
echo YES OK
YES OK

5

Якщо ви створите файл під назвою Makefile і додасте таку змінну, як ця $ (unittest), то ви зможете використовувати цю змінну всередині Makefile навіть із символами підстановки

приклад:

make unittest=*

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.