#makefile
Вопрос:
Я пытаюсь заставить Make запускать команды из вложенных папок, о которых он не знает в корневом файле makefile.
У меня есть следующий файл makefile в корне проекта:
ARGS=$(filter-out $@, $(MAKECMDGOALS))
.PHONY: build
build:
@$(MAKE) -C ${ARGS} build
%:
@$(MAKE) -C ${ARGS}
У меня есть следующее в ./folder
build:
@echo "Mushrooms!"
.PHONY: build
badgers:
@echo "Badgers!"
.PHONY: badger
Итак, когда я бегу make build folder
, я получаю эхо «Грибы!», как и ожидалось. Однако, когда я бегу make folder badgers
, я получаю то же самое эхо.
Я предположил, что он правильно работал при первом запуске, но, похоже, он игнорирует любые аргументы (т. Е. подкоманду, которую я хочу запустить) и просто запускает первую запись ./folder/makefile
.
Кто-нибудь знает, как я могу обмануть, чтобы вызвать правильную команду из вложенной папки?
Комментарии:
1. Никогда не отключайте повторение команд (с помощью добавления
@
), пока вы не будете уверены, что файл makefile работает должным образом. А может быть, и не тогда. Подавление эха команды скрывает информацию, которая может иметь решающее значение для отладки.
Ответ №1:
Если бы вы включили повторение команд в своем файле makefile верхнего уровня, вы бы увидели, что в данном make folder badgers
случае рекурсивная make
команда , которая выполняется make -C folder
, отсутствует make -C folder badgers
. Почему? Потому что когда ${ARGS}
расширяется в контексте правила соответствия чему-либо, цель есть badgers
, и вы явно отфильтровываете цель из расширения!
Вы также могли быть осведомлены о том, что обе ваши make
команды печатают сообщение о folder
том, что они актуальны. Это говорит вам о том, что он выбирает, а не выполняет рецепт построения folder
. В этом случае make build folder
марка верхнего уровня запускает только рецепт для цели build
, который повторно вводит «сборку» в список целей под-марки. В случае make folder badgers
, он выполняет только рецепт для badgers
, который не повторно вводит эту цель в субподписку, поэтому субподписка строит цель по умолчанию.
Я бы предложил что-то менее волшебное: полагайтесь на определение макроса в командной строке. Файл makefile будет выглядеть следующим образом:
.PHONY: build
# Just for the purpose of having a default target
build:
make -C $(subdir) "$@"
%:
make -C $(subdir) "$@"
Вы бы тогда побежали make
вот так:
make subdir=folder
make subdir=folder build
make subdir=folder badgers
Это все еще оставляет несколько пробелов, например , что произойдет, если пользователь не укажет значение subdirs
, но, как минимум, это более прочный фундамент для строительства.