Как передать аргумент Makefile из командной строки?

109

Как передать аргумент Makefile из командной строки?

Я понимаю, что могу

$ make action VAR="value"
$ value

с участием Makefile

VAR = "default"
action:
    @echo $(VAR)

Как добиться следующего поведения?

$ make action value
value

?

Как насчет

$make action value1 value2
value1 value2
Мэн Лу
источник
3
Возможный дубликат передачи аргументов для "make run"
лесмана 08

Ответы:

212

Вероятно, вам не стоит этого делать; вы нарушаете основные принципы работы Make. Но вот оно:

action:
        @echo action $(filter-out $@,$(MAKECMDGOALS))

%:      # thanks to chakrit
    @:    # thanks to William Pursell

РЕДАКТИРОВАТЬ:
Чтобы объяснить первую команду,

$(MAKECMDGOALS) это список «целей», записанный в командной строке, например, «действие значение1 значение2».

$@- автоматическая переменная для имени цели правила, в данном случае «действие».

filter-outэто функция, которая удаляет некоторые элементы из списка. Итак, $(filter-out bar, foo bar baz)возвращается foo baz(это может быть более тонким, но нам здесь не нужны тонкости).

Соедините их вместе и $(filter-out $@,$(MAKECMDGOALS))вернет список целей, указанный в командной строке, кроме «действия», которое может быть «значение1 значение2».

Бета
источник
1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')пропустить все цели раньше и просто рассматривать следующие аргументы:make target1 target2 action value1 value2
Евгений Генералов
1
Простите мое незнание. Я пробовал поискать в Google %:и @:не могу найти информацию о том, что делают эти «директивы» (или как они там называются). Не могли бы вы объяснить?
Джон
15
@Jon: Руководство здесь . Часть, состоящая из %:и @:является правилом . Целевое имя %означает, что это правило соответствует чему угодно ; то есть, если Make не может найти другого способа построить то, что вы ему говорите, он выполнит это правило. @:Является рецепт ; что :означает ничего не делать, а @значит делать это молча.
Бета,
Спасибо. Я читал это руководство и сначала не подумал, что на %:самом деле % :это имя цели с подстановочными знаками. Я не вижу ничего на этой странице руководства, @:хотя ... оно предполагает, что правило «ничего не делать» будет просто иметь ;после целевой спецификации, поэтому не было бы более точным написать, % : ;как «подстановочный знак делает -ничего "правило?
Джон
1
filter-outне работает, когда действие является зависимостью цели, указанной в командной строке, потому что $@будет установлено имя зависимости, а не исходный аргумент, вызываемый в командной строке. Вместо этого я назначаю MAKECMDGOALSмассив оболочки, а затем @ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
удаляю
18

Вот общее рабочее решение на основе @ Beta

Я использую GNU Make 4.1 SHELL=/bin/bashповерх моего Makefile, поэтому YMMV!

Это позволяет нам принимать дополнительные аргументы (ничего не делая, когда мы получаем задание, которое не совпадает, вместо того, чтобы выдавать ошибку).

%:
    @:

И это макрос, который получает для нас аргументы:

args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`

Вот работа, которую можно назвать этой:

test:
    @echo $(call args,defaultstring)

Результат будет:

$ make test
defaultstring
$ make test hi
hi

Заметка! Возможно, вам будет лучше использовать "Taskfile", который представляет собой шаблон bash, который работает аналогично созданию, только без нюансов Maketools. См. Https://github.com/adriancooney/Taskfile

M3D
источник
Это сработало!! ЧТОБЫ другие люди пробовали это, убедитесь, что это было tabраньше @echo, а не space.
Абдулла Аль Маруф - Тухин
11

Намного проще подход. Рассмотрим задачу:

provision:
        ansible-playbook -vvvv \
        -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory \
        --private-key=.vagrant/machines/default/virtualbox/private_key \
        --start-at-task="$(AT)" \
        -u vagrant playbook.yml

Теперь, когда я хочу назвать это, я просто запускаю что-то вроде:

AT="build assets" make provision

или просто:

make provisionв данном случае ATэто пустая строка

харандзюк
источник
-2

не пытайся сделать это

$ make action value1 value2

вместо этого создайте скрипт:

#! /bin/sh
# rebuild if necessary
make
# do action with arguments
action "$@"

и сделайте так:

$ ./buildthenaction.sh value1 value2

для получения дополнительных объяснений, почему это делается, и предостережений относительно взлома make-файлов, прочтите мой ответ на другой очень похожий, но, по-видимому, не повторяющийся вопрос: Передача аргументов для "make run"

лесмана
источник