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, щоб робити те, що добре: будівництво. він використовує скрипт оболонки, щоб зробити те, що добре: пакетна обробка.
плюс ви можете робити все, що вам може знадобитися, з повною гнучкістю та виразністю скрипту оболонки без усіх застережень makefile.
також синтаксис виклику тепер практично ідентичний:
$ ./buildandrunprog.sh foo "bar baz"
порівняти з:
$ ./prog foo "bar baz"
на відміну від
$ make run var="foo bar\ baz"
фон:
make не призначений для передачі аргументів цілі. всі аргументи в командному рядку інтерпретуються або як мета (aka target), як варіант, або як змінне призначення.
тож якщо запустити це:
$ 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)
лапки в makefile:
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
суперкоротке пояснення: відфільтруйте поточну мету зі списку цілей. створити ловити всю ціль ( %
), яка не робить нічого, щоб мовчки ігнорувати інші цілі.
спосіб 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 run --foo --bar
обхідний шлях
$ make run -- --foo --bar
аргументи зі знаком рівності будуть інтерпретуватися складеними та не переданими
$ 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 print надрукує попередження про його перезапис.
ніякого вирішення, про яке я знаю
аргументи зі знаком рівності все одно будуть інтерпретуватися складеними та не переданими
ніякого вирішення
аргументи з пробілами все ще незручні
ніякого вирішення
аргументи з пробілами у просторі, eval
намагаючись створити, нічого не націлюють.
вирішення проблеми: створити глобальну лову всіх цілей, не роблячи нічого, як зазначено вище. з вищезгаданою проблемою, що вона знову мовчки ігнорує помилково законні цілі.
він використовує eval
для зміни makefile під час виконання. наскільки гірше ви можете піти з точки зору читабельності та виправданості та принципу найменшого здивування .
обхідне рішення: не робіть цього !! 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