Может ли --always-make не повлиять на суб-make? - PullRequest
2 голосов
/ 03 августа 2020

Использование GNU Make 4.1

Резюме

Я вызываю под-make b.mk из make-файла a.mk. b.mk вызывается, чтобы гарантировать построение подсистемы. Иногда я хочу принудительно переделать цель a.mk:

make -f a.mk <target> --always-make

Когда я это делаю, b.mk также считает, что все цели устарели, но я не хочу этого.

Неудачное решение

Я пробовал использовать make -f b.mk MAKEFLAGS=, как это было предложено в руководстве 5.7.3 Передача параметров подпрограмме , но безуспешно.

Вот суть a.mk:

.PHONY: all
$(info ===> a.mk MAKEFLAGS: $(MAKEFLAGS))
all:
    $(MAKE) -f b.mk y MAKEFLAGS=

и b.mk:

$(info ===> b.mk MAKEFLAGS: $(MAKEFLAGS))
y: x
    cp $< $@

Теперь, даже когда b.mk обычно рассматривает y как актуальность:

$ make -f b.mk y
===> b.mk MAKEFLAGS: 
make: 'y' is up to date.

... y переделывается, когда a.mk вызывается с --always-make (-B):

$ make -f a.mk --always-make
===> a.mk MAKEFLAGS: B
make -f b.mk y MAKEFLAGS=
make[1]: Entering directory '/home/matt/junk/make-b'
===> b.mk MAKEFLAGS: 
cp x y
make[1]: Leaving directory '/home/matt/junk/make-b'

Как видите, * 1041 Флаг * появляется в MAKEFLAGS a.mk, но не в b.mk. Однако y переделан b.mk.

Вопросы

  • Почему?
  • Есть ли способ обойти это?
  • С помощью GNU make Я ожидал, что для такого поведения есть очень веская причина. В чем причина?

Обновление: 2020-08-05

Зачем (черт возьми) мне это нужно?

В ответе { ссылка }, была просьба увидеть пример желания принудительно переделать конкретную цель, но без принудительного создания дополнительных компонентов.

Вместо того, чтобы что-то изобретать, вот извлечение из фактического make-файла, которое привело к моему вопросу:

WWW_SVG := score.svg

%Score.app/$(WWW_SVG): %Score.svg | %Score.app/
    cd $(MUSIC_SCORE_PLAYER) && $(MAKE) -f $(MUSIC_SCORE_PLAYER_MAKEFILE) $(MUSIC_SCORE_PLAYER_TGT) MAKEFLAGS=
    cp $< $(MUSIC_SCORE_PLAYER_DIR)$(WWW_SVG)
    node $(MUSIC_SCORE_PLAYER_SVG_CONVERTER) > $@

Цель правила - создать один SVG из другого. Новый отражает состояние SVG-части модели DOM после того, как веб-приложение загружает и изменяет исходный SVG.

  • В первой строке рецепта используется sub-make, чтобы убедиться, что веб-приложение является актуальным, что может быть не так, поскольку я сейчас его разрабатываю. Веб-приложение - это отдельный проект от проекта с make-файлом, из которого был извлечен приведенный выше фрагмент.
  • Вторая строка копирует исходный SVG в каталог развертывания веб-приложения, чтобы его можно было загрузить с помощью веб-приложения.
  • Третья строка вызывает сценарий узла для запуска веб-приложения, извлечения SVG из его DOM и записи его в стандартный вывод. Затем это перенаправляется для обновления цели SVG.

Пока я тестирую, я хочу иметь возможность принудительно переделывать цели, у которых есть предварительные условия, соответствующие %FooScore/score.svg, но без перестройки веб-приложение, , если оно не устарело.

Конечно, я мог бы переместить строку, которая вызывает подделку, так, чтобы она вызывалась только один раз, а не один раз для каждой цели что соответствует правилу. Но это оптимизация, а не решение.

Ответы [ 2 ]

2 голосов
/ 03 августа 2020

Смысл «всегда строить» заключается в том, что вызываются все части сборки. Было бы бессмысленно передавать не суб-производителям. Фактически, во многих make-файлах почти ничего не происходит с make-файлом верхнего уровня: они просто вызывают набор под-make. Если бы «всегда строить» не было передано, это было бы бесполезно.

К сожалению, все ваши примеры основаны на том, что вещи работают таким образом, а они нет. Чтобы предложить решение, нам понадобится более реалистичный пример c. В частности, вы говорите, что хотите принудительно переделать конкретную цель c, но в приведенных выше примерах вы этого не показываете. Какую цель нужно переделать? Как он взаимодействует с вызовом sub-make для b.mk?

В качестве примечания, я должен сказать, что вы не должны никогда использовать make для вызова sub-make. Вы должны всегда использовать $(MAKE) (или, что то же самое, ${MAKE}).

0 голосов
/ 09 августа 2020

Это основано на этом ответе и комментариях к нему.

Глядя на a.mk из исходного вопроса, необходимо изменить одну строку:

.PHONY: all
$(info ===> a.mk MAKEFLAGS: $(MAKEFLAGS))
all:
    MAKEFLAGS=  $(MAKE) -f b.mk y    # This line has changed

Теперь он использует MAKEFLAGS как переменную envirnoment вместо параметра командной строки. См. Комментарии в этот ответ , чтобы узнать, почему это имеет значение.

Теперь мы видим, что -B (--always-make) не передается в подпрограммы make и , что, в отличие от того, когда MAKEFLAGS передается как переменная командной строки, подделка не выполняет «всегда-make»:

$ make -B -f a.mk 
===> a.mk MAKEFLAGS: B
MAKEFLAGS= make -f b.mk y
make[1]: Entering directory '/home/matt/junk/make-b'
===> b.mk MAKEFLAGS: w
make[1]: 'y' is up to date.
make[1]: Leaving directory '/home/matt/junk/make-b'

Другое отличие здесь, по сравнению с выводом, показанным в исходный вопрос заключается в том, что флаг -w (--print-directory) передается под-make, и это нормально.

...