Wie rufe ich Makefile von einem anderen Makefile aus auf?

125

Ich erhalte einige unerwartete Ergebnisse, wenn ich ein Makefile von einem anderen aufrufe. Ich habe zwei Makefiles, eines mit dem Namen /path/to/project/makefileund eines mit dem Namen /path/to/project/gtest-1.4.0/make/Makefile. Ich versuche, den ersteren den letzteren anrufen zu lassen. In / path / to / project / makefile habe ich

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

Und in /path/to/project/gtest-1.4.0/make/Makefilehabe ich

all: $(TESTS)

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

Folgendes ausgeben:

cd /path/to/project
make

Ausgänge:

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'

Wenn ich jedoch folgende Befehle erteile:

cd /path/to/project
make clean

Aha:

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'

Ich verstehe nicht: In beiden Fällen /path/to/project/makefilewird mir mitgeteilt, dass das aktuelle Arbeitsverzeichnis eingegeben wird. Im ersten Fall glaubt es nicht, dass es Arbeit zu erledigen hat (wenn dies der Fall ist), und im zweiten Fall kann es die entsprechende Direktive finden (wenn die Ausgabe mir sagt, dass es im falschen Verzeichnis sucht), versucht es jedoch um den rmBefehl /path/to/projectanstelle von auszuführen /path/to/makefile/gtest-1.4.0/make/.

Vermisse ich etwas Grundlegendes, um Makefiles voneinander abzurufen? Habe ich einen ungeheuren konzeptionellen Fehler gemacht oder bin ich auf eine häufige Falle gestoßen? Wie ändere ich effektiv Verzeichnisse und rufe ein zweites Makefile aus dem ersten heraus auf? Mein Verständnis war, dass make -f <name>es ausreichen würde , einfach anzurufen .

Dies ist make / gmake 3.81 in bash.

Chris Tonkinson
quelle
3
Ich denke, anstatt dass make -f gtest-1.4.0/make/Makefile cleandu es besser sagst $(MAKE) -C gtest-1.4.0/make clean. Warum haben Sie keine falschen Ziele definiert?
dma_k

Antworten:

112

Ich bin mir nicht ganz sicher, was Sie fragen, aber wenn Sie die -fBefehlszeilenoption verwenden, wird nur eine Datei angegeben - es wird nicht angegeben, dass make Verzeichnisse ändern soll. Wenn Sie die Arbeit in einem anderen Verzeichnis erledigen möchten, müssen Sie cdin das Verzeichnis:

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

Beachten Sie, dass jede Zeile in Makefileeiner separaten Shell ausgeführt wird, sodass das Verzeichnis nicht zurück geändert werden muss.

Kenorb
quelle
67
Anstatt manuell in cddas Verzeichnis zu gtest-1.4.0wechseln, sollten Sie die -COption von verwenden make.
Tader
29
Oder zumindest sollten Sie auf jeden Fall &&zwischen der CD und dem Befehl make verwenden. Andernfalls wird die CD, wenn sie ausfällt, immer noch ausgeführt make clean... im falschen Verzeichnis !! Außerdem sollten Sie beim Rekursieren immer NUR $(MAKE)das Barwort verwenden , niemals das makeBarwort. Also so etwas wie: cd gtest-1.4.0 && $(MAKE) clean
MadScientist
3
@Tader: -Cist nicht in der Spezifikation
Janus Troelsen
1
Diese Frage zu gnu-make und -Cist in der Spezifikation: gnu.org/software/make/manual/make.html#Recursion
Cas
122

Statt der -fvon makemöchten Sie vielleicht die verwenden -C <path>Option. Dies ändert zuerst den Pfad ' <path>' und ruft dann makedort auf.

Beispiel:

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
quelle
1
Dieser Weg scheint am besten. Kommen Sie von den anderen Antworten, die dazu cdführen, dass das Terminal in eine Endlosschleife gerät.
gbmhunter
1

Es scheint klar zu sein, dass $(TESTS)es leer ist, so dass Ihr 1.4.0-Makefile effektiv ist

all: 

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

In der Tat hat alles nichts zu tun. und sauber macht genau das, was es sagtrm -f gtest.a ...

John Knoeller
quelle
$ (TESTS) wird mit a wildcardund a definiert patsubst, diese werden jedoch aus dem Haupt-Makefile leer zurückgegeben, da das Verzeichnis nicht effektiv geändert wird. Gutes Auge.
Chris Tonkinson