Как я могу проверить, можно ли вызвать программу из Makefile?
(То есть программа должна существовать в пути или иным образом быть вызываемой.)
Его можно использовать, например, для проверки того, какой компилятор установлен.
Например, что-то вроде этого вопроса , но без предположения, что базовая оболочка совместима с POSIX.
automake
сценарий, который проверяет различные предварительные условия и записывает подходящийMakefile
.Ответы:
Иногда вам нужен Makefile, чтобы иметь возможность работать в разных целевых ОС, и вы хотите, чтобы сборка завершилась сбоем раньше, если требуемый исполняемый файл отсутствует,
PATH
а не запускался в течение, возможно, долгого времени до сбоя.Превосходное решение, предоставленное инженером, требует постановки цели . Однако, если у вас есть много исполняемых файлов для тестирования и ваш Makefile имеет много независимых целей, каждая из которых требует тестов, то каждая цель требует тестовой цели в качестве зависимости. Это требует много дополнительного набора текста, а также времени обработки, когда вы задаете более одной цели за раз.
Решение, предоставляемое 0xf, может тестировать исполняемый файл без создания цели. Это экономит много времени на ввод и выполнение, когда есть несколько целей, которые могут быть созданы либо по отдельности, либо вместе.
Мое улучшение последнего решения состоит в том, чтобы использовать
which
исполняемый файл (where
в Windows), а не полагаться на наличие--version
опции в каждом исполняемом файле непосредственно вifeq
директиве GNU Make , а не определять новую переменную, и использовать GNU Makeerror
функция, чтобы остановить сборку, если необходимый исполняемый файл отсутствует${PATH}
. Например, чтобы проверитьlzop
исполняемый файл:Если у вас есть несколько исполняемых файлов для проверки, вы можете использовать
foreach
функцию сwhich
исполняемым файлом:Обратите внимание на использование
:=
оператора присваивания, который требуется для немедленного вычисления выражения RHS. Если ваш Makefile изменитPATH
, то вместо последней строки выше вам понадобится:Это должно дать вам результат, похожий на:
источник
where my_exe 2>NUL
вместоwhich
.Bash
, нет необходимости делать внешний вызовwhich
.command -v
Вместо этого используйте встроенный . Больше информации .Я смешал решения из @kenorb и @ 0xF и получил следующее:
Это прекрасно работает, потому что команда «-v» ничего не выводит, если исполняемый файл недоступен, поэтому переменная DOT никогда не определяется, и вы можете просто проверить ее, когда захотите, в своем коде. В этом примере я выдаю ошибку, но вы можете сделать что-нибудь более полезное, если хотите.
Если переменная доступна, «команда -v» выполняет недорогую операцию печати пути команды, определяя переменную DOT.
источник
$(shell command -v dot)
не работаетmake: command: Command not found
. Чтобы это исправить, перенаправление вывода в STDERR / DEV / нуль:$(shell command -v dot 2> /dev/null)
. Объяснениеcommand
это встроенный bash, для большей переносимости рассмотрите возможность использованияwhich
?command
утилита требуется для posix (включая-v
опцию). С другой стороны, уwhich
нее нет стандартизированного поведения (о котором я знаю), и она иногда совершенно непригодна для использованияcommand -v
требуется среда оболочки, подобная POSIX. Это не будет работать в Windows без эмуляции cygwin или аналогичной.command
часто не работает, не из-за ее отсутствия , а из-за особой оптимизации, которую делает GNU Make: если команда «достаточно проста», она будет обходить оболочку; это, к сожалению, означает, что встроенные программы иногда не работают, если вы немного не измените команду.это то, что ты сделал?
кредит моему коллеге.
источник
Используйте эту
shell
функцию для вызова вашей программы таким образом, чтобы она выводила что-то на стандартный вывод. Например, пройти--version
.GNU Make игнорирует статус выхода переданной команды
shell
. Чтобы избежать потенциального сообщения «команда не найдена», перенаправьте стандартную ошибку на/dev/null
.Затем вы можете проверить результат, используя
ifdef
,ifndef
и$(if)
т. Д.В качестве бонуса вывод (например, версия программы) может быть полезен в других частях вашего Makefile.
источник
*** missing separator. Stop.
если я добавляю табуляции во все строки послеall:
получения ошибкиmake: ifdef: Command not found
ifdef
будет оценивать как истину, даже еслиyour_program
не существует gnu.org/software/make/manual/make.html#Conditional-Syntaxifdef
,else
,endif
линий. Просто убедитесь, что@echo
строки начинаются с табуляции.ifdef
проверяется непустое значение переменной. Если ваша переменная не пуста, что она оценивает?ifdef
илиifndef
(как в принятом ответе) работает только в том случае, если оцениваемая переменная немедленно устанавливается (:=
), а не лениво set (=
). Однако обратная сторона использования немедленно установленных переменных заключается в том, что они оцениваются во время объявления, тогда как переменные с отложенным набором вычисляются при их вызове. Это означает, что вы будете выполнять команды для переменных,:=
даже если Make выполняет только правила, которые никогда не используют эти переменные! Вы можете избежать этого, используя=
сifneq ($(MY_PROG),)
Здесь убраны некоторые из существующих решений ...
$(info ...)
Можно исключить , если вы хотите , чтобы это было спокойнее.Это быстро потерпит неудачу . Цель не требуется.
источник
Мое решение включает в себя небольшой вспомогательный сценарий 1, который помещает файл флага, если все необходимые команды существуют. Это имеет то преимущество, что проверка необходимых команд выполняется только один раз, а не при каждом
make
вызове.check_cmds.sh
Makefile
1 Подробнее о
command -v
технике можно прочитать здесь .источник
if
утверждению.Для меня все вышеперечисленные ответы основаны на Linux и не работают с окнами. Я новичок, поэтому мой подход может быть не идеальным. Но полный пример, который работает для меня как в Linux, так и в Windows, таков:
при необходимости, когда мне нужно найти больше инструментов, я могу использовать:
источник
Вы можете использовать встроенные команды bash, такие как
type foo
илиcommand -v foo
, как показано ниже:Где
foo
твоя программа / команда. Перенаправьте на,> /dev/null
если хотите, чтобы он был тихим.источник
Предположим, у вас разные цели и строители, для каждого из которых требуется свой набор инструментов. Составьте список таких инструментов и рассмотрите их как цель для принудительной проверки их доступности.
Например:
источник
Я лично определяю
require
цель, которая выполняется раньше всех остальных. Эта цель просто запускает команды версии всех требований по одной и печатает соответствующие сообщения об ошибках, если команда недействительна.Результат нижеприведенного скрипта:
источник
Решается путем компиляции специальной небольшой программы в другой целевой файл makefile, единственная цель которого - проверить все, что я искал во время выполнения.
Затем я вызвал эту программу в еще одном целевом файле makefile.
Это было примерно так, если я правильно помню:
источник
Проверка решений для
STDERR
вывода--version
не работает для программ, которые печатают свою версиюSTDOUT
вместоSTDERR
. Вместо того, чтобы проверять их вывод вSTDERR
илиSTDOUT
, проверьте код возврата программы. Если программа не существует, ее код выхода всегда будет отличным от нуля.источник