Я использую Makefiles.
У меня есть цель, run
которая называется цель сборки. Упрощенно это выглядит следующим образом:
prog: ....
...
run: prog
./prog
Есть ли способ передать аргументы? Так что
make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat
Спасибо!
Ответы:
Я не знаю способ сделать то, что вы хотите точно, но обходной путь может быть:
Затем:
источник
$(foo)' or
$ {foo} 'является действительной ссылкой на переменная `foo '." и продолжает приводить примеры, где используется только $ (). Ах хорошо.Этому вопросу почти три года, но все равно ...
Если вы используете GNU make, это легко сделать. Единственная проблема заключается в том, что
make
нецелевые аргументы в командной строке будут интерпретироваться как цели. Решение состоит в том, чтобы превратить их в цели бездействия, поэтомуmake
не будем жаловаться:Запуск этого дает:
источник
prog foo bar --baz
make
чтобы не интерпретировать--baz
как параметр командной строки:make -- prog foo bar --baz
.--
Означает «все после того, как это аргумент, не вариант».RUN_ARGS
использования этого?else
ветку вifeq
и установитьRUN_ARGS
там?$(eval $(RUN_ARGS):dummy;@:)
, без фиктивной цели.для стандартного make вы можете передавать аргументы, определяя макросы следующим образом
затем используйте их как это
Рекомендации по изготовлению Microsoft NMake
источник
Вы можете передать переменную в Makefile, как показано ниже:
Применение:
или:
В качестве альтернативы используйте решение, предоставленное Beta :
Применение:
источник
TL; DR не пытайтесь сделать это
вместо этого создайте скрипт:
и сделать это:
ответ на поставленный вопрос:
Вы можете использовать переменную в рецепте
затем передать переменную в качестве аргумента, чтобы сделать
это выполнится
./prog arg
.но остерегайтесь ловушек. я расскажу о подводных камнях этого метода и других методов далее.
ответ на предполагаемое намерение, стоящее за вопросом:
предположение: вы хотите запустить
prog
с некоторыми аргументами, но перезапустите его, если необходимо.ответ: создайте скрипт, который при необходимости пересобирает, затем запускает прогу с аргументами
этот сценарий делает намерение очень ясным. он использует make, чтобы делать то, для чего он хорош: building. он использует скрипт оболочки, чтобы делать то, для чего он хорош: пакетная обработка.
Кроме того, вы можете делать все, что вам может понадобиться, с полной гибкостью и выразительностью сценария оболочки без всех предостережений make-файла.
также синтаксис вызова теперь практически идентичен:
по сравнению с:
в отличие от
фон:
make не предназначен для передачи аргументов цели. Все аргументы в командной строке интерпретируются либо как цель (или цель), либо как опция, либо как присвоение переменной.
так что если вы запустите это:
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
о методе назначения переменных и почему я рекомендую против него
и переменная в рецепте
это самый «правильный» и простой способ передачи аргументов в рецепт. но хотя он может использоваться для запуска программы с аргументами, он определенно не предназначен для такого использования. см. https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
по моему мнению, у этого есть один большой недостаток: то, что вы хотите сделать, это запустить
prog
с аргументомarg
. но вместо того, чтобы писать:вы пишете:
это становится еще более неловким при попытке передать несколько аргументов или аргументов, содержащих пробелы:
по сравнению с:
для записи вот как
prog
выглядит мой :Также обратите внимание, что вы не должны помещать
$(var)
в кавычки в make-файле:потому что тогда
prog
всегда будет получен только один аргумент:Вот почему я рекомендую против этого маршрута.
для полноты здесь приведены некоторые другие методы «передачи аргументов для запуска».
способ 1:
супер краткое объяснение: отфильтровать текущую цель из списка целей. create catch all target (
%
), который ничего не делает, чтобы молча игнорировать другие цели.способ 2:
супер короткое объяснение: если цель -
run
удалить первую цель и создать ничего не делать цели для оставшихся целей, используяeval
.оба позволят вам написать что-то вроде этого
для более глубокого объяснения изучите руководство по сборке: https://www.gnu.org/software/make/manual/html_node/index.html
проблемы метода 1:
аргументы, начинающиеся с тире, будут интерпретироваться make и не будут передаваться как цель.
обходной путь
аргументы со знаком равенства будут интерпретированы make и не будут переданы
нет обходного пути
аргументы с пробелами неудобно
нет обходного пути
если аргумент окажется
run
(равен цели), он также будет удаленбудет работать
./prog foo bar
вместо./prog foo bar run
Обходной путь возможен со способом 2
если аргумент является законной целью, он также будет запущен.
будет работать,
./prog foo bar clean
но и рецепт для целиclean
(при условии, что она существует).Обходной путь возможен со способом 2
когда вы неправильно наберете легитимную цель, она будет тихо проигнорирована из-за того, что поймает всю цель.
будет просто молча игнорировать
celan
.Обходной путь - сделать все подробным. так что вы видите, что происходит. но это создает много шума для законного выхода.
проблемы метода 2:
если аргумент имеет то же имя, что и существующая цель, то make выдаст предупреждение о том, что он перезаписывается.
нет обходного пути, о котором я знаю
аргументы со знаком равенства будут по-прежнему интерпретироваться make и не передаваться
нет обходного пути
аргументы с пробелами все еще неудобны
нет обходного пути
Аргументы с пробелами,
eval
пытающимися создать ничего не значащие цели.Обходной путь: создайте глобальный перехват цели, ничего не делая, как описано выше. с проблемой, как указано выше, что он снова будет молча игнорировать опечатки законных целей.
он использует
eval
для изменения make-файла во время выполнения. насколько хуже вы можете пойти с точки зрения читабельности и отладки и принципа наименьшего удивления .Обходной путь: не делайте этого !! 1 Вместо этого напишите сценарий оболочки, который запускает make, а затем запускается
prog
.Я тестировал только с помощью GNU Make. другие марки могут иметь другое поведение.
TL; DR не пытайтесь сделать это
вместо этого создайте скрипт:
и сделать это:
источник
Вот еще одно решение, которое может помочь с некоторыми из этих случаев использования:
Другими словами, выберите некоторый префикс (
test-
в этом случае), а затем передайте имя цели непосредственно программе / исполнителю. Я предполагаю, что это в основном полезно, если есть какой-то сценарий запуска, который может развернуть целевое имя во что-то полезное для основной программы.источник
$*
чтобы передать только ту часть цели, которая соответствует%
.Нет. Глядя на синтаксис из man-страницы для GNU make
Вы можете указать несколько целей, следовательно, «нет» (по крайней мере, нет точно, как вы указали).
источник
Вы можете явно извлечь каждый n-й аргумент в командной строке. Для этого вы можете использовать переменную MAKECMDGOALS, в которой содержится список аргументов командной строки, заданных для make, который он интерпретирует как список целей. Если вы хотите извлечь n-й аргумент, вы можете использовать эту переменную в сочетании с функцией «word», например, если вам нужен второй аргумент, вы можете сохранить его в переменной следующим образом:
источник
make: *** No rule to make target 'arg'. Stop.
Анон ,
run: ./prog
выглядит немного странно, так как правая часть должна быть целью, такrun: prog
выглядит лучше.Я бы предложил просто:
и я хотел бы добавить, что аргументы могут быть переданы:
make arg1="asdf" run
arg1="asdf" make run
источник
Вот мой пример. Обратите внимание, что я пишу под Windows 7, используя mingw32-make.exe, который поставляется с Dev-Cpp. (У меня есть c: \ Windows \ System32 \ make.bat, поэтому команда все еще называется "make".)
Использование для регулярной уборки:
Использование для очистки и создания резервной копии в mydir /:
источник
Не слишком горжусь этим, но я не хотел передавать переменные окружения, поэтому я перевернул способ запуска постоянной команды:
это напечатает команду, которую вы хотите запустить, поэтому просто оцените ее в подоболочке:
источник
Я нашел способ получить аргументы со знаком равенства (=)! Ответ является особенно дополнением к ответу @lesmana (поскольку он является наиболее полным и объясненным здесь), но он был бы слишком большим, чтобы написать его в качестве комментария. Я снова повторяю его сообщение: TL; DR, не пытайтесь это сделать!
Мне нужен был способ обработать мой аргумент
--xyz-enabled=false
(так как по умолчанию - true), который мы все уже знаем, что это не цель создания и, следовательно, не часть$(MAKECMDGOALS)
.Просматривая все переменные make , повторяя,
$(.VARIABLES)
я получил следующие интересные выводы:Это позволяет нам идти двумя путями: либо получать все , начинающееся с
--
(если это относится к данному случаю), или заглянуть в сделать конкретные GNU (вероятно , не предназначенный для нас использование) переменной-*-command-variables-*-
. ** См. Нижний колонтитул для дополнительных опций ** В моем случае эта переменная содержала:С помощью этой переменной мы можем объединить ее с уже существующим решением
$(MAKECMDGOALS)
и, таким образом, определив:и используя его с (явно смешивая порядок аргументов):
вернулся:
Как видите, мы теряем общий порядок аргументов. Часть с аргументами «назначение», кажется, поменялась местами, порядок «целевых» аргументов сохраняется. Я поместил вначале аргументы «присваивания», надеюсь, вашей программе все равно, где находится аргумент.
Обновление: следующие переменные выглядят многообещающе:
источник
Еще один трюк, который я использую, - это
-n
флаг, который говоритmake
сделать пробный прогон. Например,источник