Comment appeler Makefile depuis un autre Makefile?

125

J'obtiens des résultats inattendus en appelant un makefile à partir d'un autre. J'ai deux makefiles, un appelé /path/to/project/makefileet un appelé /path/to/project/gtest-1.4.0/make/Makefile. J'essaye de faire appeler le premier le second. Dans / chemin / vers / projet / makefile, j'ai

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

Et dans /path/to/project/gtest-1.4.0/make/Makefilej'ai

all: $(TESTS)

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

Émettant ce qui suit:

cd /path/to/project
make

Les sorties:

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'

Cependant, lorsque j'émets ces commandes:

cd /path/to/project
make clean

Je vois:

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'

Je ne comprends pas: dans les deux cas, /path/to/project/makefilecela me dit qu'il entre dans le répertoire de travail actuel. Dans le premier cas, il ne pense pas avoir de travail à faire (quand c'est le cas) et dans le second cas, il est capable de trouver la directive appropriée (lorsque la sortie me dit qu'il cherche dans le mauvais répertoire) mais il essaie pour exécuter la rmcommande au /path/to/projectlieu de /path/to/makefile/gtest-1.4.0/make/.

Est-ce que je manque quelque chose de fondamental pour appeler des makefiles les uns des autres? Ai-je commis une grave erreur conceptuelle ou ai-je rencontré un piège courant? Comment modifier efficacement les répertoires et appeler un deuxième makefile depuis le premier? Je croyais comprendre que simplement appeler make -f <name>suffirait.

C'est make / gmake 3.81 dans bash.

Chris Tonkinson
la source
3
Je pense, au lieu de make -f gtest-1.4.0/make/Makefile cleanvous dire $(MAKE) -C gtest-1.4.0/make clean. Pourquoi n'avez-vous pas défini de fausses cibles?
dma_k

Réponses:

113

Je ne suis pas vraiment trop clair sur ce que vous demandez, mais l'utilisation de l' -foption de ligne de commande spécifie simplement un fichier - cela ne dit pas à make de changer de répertoire. Si vous souhaitez effectuer le travail dans un autre répertoire, vous devez accéder cdau répertoire:

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

Notez que chaque ligne de Makefiles'exécute dans un shell séparé, il n'est donc pas nécessaire de modifier le répertoire.

Kenorb
la source
67
Au lieu d cd'entrer manuellement dans le gtest-1.4.0répertoire, vous devez utiliser l' -Coption make.
Tader
29
Ou du moins, vous devriez certainement utiliser &&entre la commande cd et make. Sinon, si le cd échoue, il fonctionnera toujours make clean... dans le mauvais répertoire !! Aussi, vous devez toujours utiliser UNIQUEMENT $(MAKE), jamais le mot nu make, lors de la récurrence. Donc quelque chose comme: cd gtest-1.4.0 && $(MAKE) clean
MadScientist
3
@Tader: -Cn'est pas dans les spécifications
Janus Troelsen
1
Cette question sur gnu-make et -Cest dans la spécification: gnu.org/software/make/manual/make.html#Recursion
Cas
123

Au lieu de -fde makevous voudrez peut - être utiliser l' -C <path>option. Cela change d'abord le chemin d'accès ' <path>', puis makey appelle .

Exemple:

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
la source
1
Cette façon semble la meilleure. Viennent les autres réponses qui utilisent cdfont entrer le terminal dans une boucle infinie.
gbmhunter
$ (MAKE) -C gtest-1.4.0 / make clean ne fonctionne pas pour moi. Je pense que ça devrait être $ (MAKE) -C gtest-1.4.0 clean
Arigion le
1

Il semble clair que $(TESTS)c'est vide donc votre makefile 1.4.0 est effectivement

all: 

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

En effet, tout n'a rien à voir. et clean fait exactement ce qu'il ditrm -f gtest.a ...

John Knoeller
la source
$ (TESTS) est défini avec a wildcardet a patsubst, cependant ceux-ci retournent vides du makefile principal, car le répertoire n'est pas effectivement changé. Bon oeil.
Chris Tonkinson