TL; DR не пытайтесь сделать это
$ make run arg
вместо этого создайте скрипт:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
и сделать это:
$ ./buildandrunprog.sh arg
ответ на поставленный вопрос:
Вы можете использовать переменную в рецепте
run: prog
./prog $(var)
затем передать переменную в качестве аргумента, чтобы сделать
$ make run var=arg
это выполнится ./prog arg
.
но остерегайтесь ловушек. я расскажу о подводных камнях этого метода и других методов далее.
ответ на предполагаемое намерение, стоящее за вопросом:
предположение: вы хотите запустить prog
с некоторыми аргументами, но перезапустите его, если необходимо.
ответ: создайте скрипт, который при необходимости пересобирает, затем запускает прогу с аргументами
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
этот сценарий делает намерение очень ясным. он использует make, чтобы делать то, для чего он хорош: building. он использует скрипт оболочки, чтобы делать то, для чего он хорош: пакетная обработка.
Кроме того, вы можете делать все, что вам может понадобиться, с полной гибкостью и выразительностью сценария оболочки без всех предостережений make-файла.
также синтаксис вызова теперь практически идентичен:
$ ./buildandrunprog.sh foo "bar baz"
по сравнению с:
$ ./prog foo "bar baz"
в отличие от
$ make run var="foo bar\ baz"
фон:
make не предназначен для передачи аргументов цели. Все аргументы в командной строке интерпретируются либо как цель (или цель), либо как опция, либо как присвоение переменной.
так что если вы запустите это:
$ make run foo --wat var=arg
make будет интерпретировать run
и foo
как цели (цели) обновлять согласно своим рецептам. --wat
как вариант для изготовления. и var=arg
как присвоение переменной.
для получения более подробной информации см .: https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
терминологию см .: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
о методе назначения переменных и почему я рекомендую против него
$ make run var=arg
и переменная в рецепте
run: prog
./prog $(var)
это самый «правильный» и простой способ передачи аргументов в рецепт. но хотя он может использоваться для запуска программы с аргументами, он определенно не предназначен для такого использования. см. https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
по моему мнению, у этого есть один большой недостаток: то, что вы хотите сделать, это запустить prog
с аргументом arg
. но вместо того, чтобы писать:
$ ./prog arg
вы пишете:
$ make run var=arg
это становится еще более неловким при попытке передать несколько аргументов или аргументов, содержащих пробелы:
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
по сравнению с:
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
для записи вот как prog
выглядит мой :
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
Также обратите внимание, что вы не должны помещать $(var)
в кавычки в make-файле:
run: prog
./prog "$(var)"
потому что тогда prog
всегда будет получен только один аргумент:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
Вот почему я рекомендую против этого маршрута.
для полноты здесь приведены некоторые другие методы «передачи аргументов для запуска».
способ 1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
супер краткое объяснение: отфильтровать текущую цель из списка целей. create catch all target ( %
), который ничего не делает, чтобы молча игнорировать другие цели.
способ 2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
супер короткое объяснение: если цель - run
удалить первую цель и создать ничего не делать цели для оставшихся целей, используя eval
.
оба позволят вам написать что-то вроде этого
$ make run arg1 arg2
для более глубокого объяснения изучите руководство по сборке: https://www.gnu.org/software/make/manual/html_node/index.html
проблемы метода 1:
аргументы, начинающиеся с тире, будут интерпретироваться make и не будут передаваться как цель.
$ make run --foo --bar
обходной путь
$ make run -- --foo --bar
аргументы со знаком равенства будут интерпретированы make и не будут переданы
$ make run foo=bar
нет обходного пути
аргументы с пробелами неудобно
$ make run foo "bar\ baz"
нет обходного пути
если аргумент окажется run
(равен цели), он также будет удален
$ make run foo bar run
будет работать ./prog foo bar
вместо./prog foo bar run
Обходной путь возможен со способом 2
если аргумент является законной целью, он также будет запущен.
$ make run foo bar clean
будет работать, ./prog foo bar clean
но и рецепт для цели clean
(при условии, что она существует).
Обходной путь возможен со способом 2
когда вы неправильно наберете легитимную цель, она будет тихо проигнорирована из-за того, что поймает всю цель.
$ make celan
будет просто молча игнорировать celan
.
Обходной путь - сделать все подробным. так что вы видите, что происходит. но это создает много шума для законного выхода.
проблемы метода 2:
если аргумент имеет то же имя, что и существующая цель, то make выдаст предупреждение о том, что он перезаписывается.
нет обходного пути, о котором я знаю
аргументы со знаком равенства будут по-прежнему интерпретироваться make и не передаваться
нет обходного пути
аргументы с пробелами все еще неудобны
нет обходного пути
Аргументы с пробелами, eval
пытающимися создать ничего не значащие цели.
Обходной путь: создайте глобальный перехват цели, ничего не делая, как описано выше. с проблемой, как указано выше, что он снова будет молча игнорировать опечатки законных целей.
он использует eval
для изменения make-файла во время выполнения. насколько хуже вы можете пойти с точки зрения читабельности и отладки и принципа наименьшего удивления .
Обходной путь: не делайте этого !! 1 Вместо этого напишите сценарий оболочки, который запускает make, а затем запускается prog
.
Я тестировал только с помощью GNU Make. другие марки могут иметь другое поведение.
TL; DR не пытайтесь сделать это
$ make run arg
вместо этого создайте скрипт:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
и сделать это:
$ ./buildandrunprog.sh arg