Как разрешить Makefile видеть цель из другого файла

#makefile #gnu-make

#makefile #gnu-make

Вопрос:

У меня есть такое Makefile с содержимым для создания скрипта:

 .PHONY cluster-run 
cluster-run:
        make $(TARGET) --just-print >> tmp_script.sh;
 

И еще один nn.mk :

 .PHONY nn-model
include Makefile

nn-model:
    python run-nn.py 
 

У меня есть два отдельных Make-файла для удобства чтения, потому что их содержимое большое, и у меня есть другие файлы ‘* .mk’, например nn-lstm.mk , nn-conv.mk , и т.д.

Я запускаю следующим образом:

 make -f nn.mk cluster-run TARGET=nn-model
 

Но make выдает ошибку:

 make nn-model --just-print >> tmp_script.sh;
make[1]: *** No rule to make target `nn-model'.  Stop.
make: *** [cluster-run] Error 2
 

Для меня такое поведение странно, потому что цель nn-model действительно существует. Как я могу решить эту проблему?

Ответ №1:

Во-первых, вы никогда не должны использовать raw make в рецептах. Всегда используйте $(MAKE) переменную.

Во-вторых, проблема заключается в том, что при запуске вложенного make вы не предоставляете эту -f опцию:

 make nn-model --just-print >> tmp_script.sh;
 

Из-за этого он читает Makefile , но нет nn.mk , и поэтому нет правила для построения цели nn-model .

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

Я не знаю, что вы подразумеваете под тем, что цель nn_model действительно существует, но там определенно нет файла с именем nn_model , иначе вы не получили бы эту ошибку.

Комментарии:

1. Как я могу получить путь, переданный с -f аргументом родительскому процессу?

2. Я не думаю, что понимаю вопрос, но у дочернего make нет возможности запросить родительский make, чтобы выяснить, что он использовал. Вы должны изменить рецепт родительского make, который вызывает дочерний make, чтобы он передавал правильные параметры. Действительно, я думаю, что ваша организация makefile проблематична, и вам следует сделать что-то другое. Я думаю, что это может быть проблемой XY: если бы вы более четко описали, какую проблему вы пытаетесь решить, структурировав свои makefile таким образом, возможно, мы могли бы предложить лучшие альтернативы.

Ответ №2:

Итак, что происходит, так это то, что при сборке cluster-run он вызывает рекурсивный make, который считывает Makefile и запрашивает сборку $(TARGET) (которая будет включать nn-model ).

Обратите внимание, что рекурсивный make является новым make и не наследует переменные или правила от родительского make, поэтому этот экземпляр make понятия не имеет, как строить nn-model , если вы хотите, чтобы дочерний make видел это, тогда дочерний make должен включать родительский…