Как вызвать Makefile из другого Makefile?

125

Я получаю неожиданные результаты, вызывая один make-файл из другого. У меня есть два make-файла, один вызываемый, /path/to/project/makefileа другой вызываемый /path/to/project/gtest-1.4.0/make/Makefile. Я пытаюсь сделать так, чтобы первое называлось вторым. В / path / to / project / makefile у меня есть

dev: $(OBJ_FILES)
  $(CPPC) $(LIBS) $(FLAGS_DEV) $(OBJ_FILES) -o $(BIN_DIR)/$(PROJECT)
  $(MAKE) -f ./gtest-1.4.0/make/Makefile

clean:
  rm -f ./*~ ./gmon.out ./core $(SRC_DIR)/*~ $(OBJ_DIR)/*.o
  rm -f ../svn-commit.tmp~
  rm -f $(BIN_DIR)/$(PROJECT)
  make -f gtest-1.4.0/make/Makefile clean

И у /path/to/project/gtest-1.4.0/make/Makefileменя есть

all: $(TESTS)

clean:
  rm -f $(TESTS) gtest.a gtest_main.a *.o

Выдача следующего:

cd /path/to/project
make

Выходы:

make -f ./gtest-1.4.0/make/Makefile
make[1]: Entering directory `/path/to/project'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/path/to/project'

Однако, когда я запускаю эти команды:

cd /path/to/project
make clean

Я вижу:

make -f gtest-1.4.0/make/Makefile clean
make[1]: Entering directory `/path/to/project'
rm -f  gtest.a gtest_main.a *.o
make[1]: Leaving directory `/path/to/project'

Я не понимаю: в обоих случаях /path/to/project/makefileон сообщает мне, что входит в текущий рабочий каталог. В первом случае он не думает, что у него есть работа (когда он это делает), а во втором случае он может найти соответствующую директиву (когда выходные данные говорят мне, что он ищет в неправильном каталоге), но он пытается для запуска rmкоманды /path/to/projectвместо /path/to/makefile/gtest-1.4.0/make/.

Я упустил что-то важное для вызова make-файлов друг от друга? Совершил ли я вопиющую концептуальную ошибку или попал в общую ловушку? Как эффективно менять каталоги и вызывать второй make-файл из первого? Насколько я понимаю, простого звонка make -f <name>будет достаточно.

Это make / gmake 3.81 в bash.

Крис Тонкинсон
источник
3
Думаю, вместо make -f gtest-1.4.0/make/Makefile cleanтебя лучше сказать $(MAKE) -C gtest-1.4.0/make clean. Почему вы не определили фальшивые цели?
dma_k
stackoverflow.com/questions/3494999/…
Джаред Берроуз

Ответы:

113

Я не совсем понимаю, о чем вы спрашиваете, но при использовании параметра -fкомандной строки просто указывается файл - он не сообщает программе make изменить каталоги. Если вы хотите выполнить работу в другом каталоге, вам необходимо cdперейти в каталог:

clean:
    cd gtest-1.4.0 && $(MAKE) clean

Обратите внимание, что каждая строка Makefileвыполняется в отдельной оболочке, поэтому нет необходимости менять каталог обратно.

kenorb
источник
67
Вместо того, чтобы вручную cdпереходить в gtest-1.4.0каталог, вы должны использовать -Cопцию make.
Тадер
29
Или, по крайней мере, вы обязательно должны использовать &&команду cd и make. В противном случае, если компакт-диск выйдет из строя, он все равно будет работать make clean... в неправильном каталоге !! Также вы всегда должны использовать ТОЛЬКО $(MAKE), а не голое слово make, при рекурсии. Так что-то вроде: cd gtest-1.4.0 && $(MAKE) clean
MadScientist
3
@Tader: -Cотсутствует в спецификации
Янус Троелсен
1
Этот вопрос о gnu-make -Cнаходится в спецификации: gnu.org/software/make/manual/make.html#Recursion
Cas
123

Вместо того , чтобы -fиз makeвас , возможно , захотите использовать -C <path>опцию. Это сначала меняет путь на путь ' <path>', а затем вызывает makeтам.

Пример:

clean:
  rm -f ./*~ ./gmon.out ./core $(SRC_DIR)/*~ $(OBJ_DIR)/*.o
  rm -f ../svn-commit.tmp~
  rm -f $(BIN_DIR)/$(PROJECT)
  $(MAKE) -C gtest-1.4.0/make clean
Tader
источник
1
Этот способ кажется лучшим. Приходите из других ответов, которые cdвызывают зацикливание терминала.
gbmhunter
$ (MAKE) -C gtest-1.4.0 / make clean у меня не работает. Я думаю, что это должно быть $ (MAKE) -C gtest-1.4.0 clean
Arigion
1

Кажется очевидным, что $(TESTS)он пуст, поэтому ваш make-файл 1.4.0 эффективно

all: 

clean:
  rm -f  gtest.a gtest_main.a *.o

Действительно, все не при чем. и clean делает именно то, что говоритrm -f gtest.a ...

Джон Кнеллер
источник
$ (TESTS) определяется с помощью a wildcardи a patsubst, однако они возвращаются пустыми из основного make-файла, потому что каталог не изменяется эффективно. Хороший глаз.
Крис Тонкинсон