Hmm, ich dachte die erste Regel entspricht in etwa genau deinem Bsp.?!
Welche meinst du? Die in der .depend-Datei? Die gibt nur die Abhängigkeit an, allerdings matcht die Regel nicht das Pattern, das normalerweise für das Kompilieren von .cpp-Dateien nach .o-Dateien verwendet wird. Deswegen wird der Compiler nicht aufgerufen.
Es ist keine Fehlermeldung ausgegeben worden, weil die leeren Regeln aus der .depend-Datei (kernel.o: ../../../../src/platform/x86_32/kernel.cpp usw...) auch die Dependencies von kernel.ko erfüllen.
Da kann ich dir gerade gar nicht folgen.
Vielleicht hilft das: Ich hab mir um meine Theorie zu testen folgende Makefile gebaut.
all: kernel.ko
VPATH=fl
kernel.ko: kernel.o string.o
$(CXX) -o $@ $+
kernel.o: fl/platform/kernel.cpp
string.o:
clean:
$(RM) kernel.ko string.o kernel.o
%.o: fl/platform/%.cpp
g++ -o $@ $<
(Um Variablen zu sparen ist fl dein $(PREFIX), und platform dein $(PLATFORM). Die Dateien ./fl/platform/kernel.cpp und ./string.cpp existieren.)
Die beiden Zeilen mit kernel.o und string.o am Anfang stellen den Inhalt von .depend dar. Ich hab mal auf Header verzichtet, weil die nicht relevant für das Problem sind, aber die würden da natürlich auch noch stehen.
Wenn make jetzt die Abhängigkeiten von kernel.ko untersucht, findet es diese beiden Regeln und außerdem hat es noch diese implizite Regel in der Datenbank (kannste dir mit make -p ausgeben lassen), um C++-Dateien zu kompilieren:
%.o: %.cpp
# commands to execute (built-in):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
Wenn make jetzt string.o bauen will matcht die Regel aus der .depend-Datei und die built-in-Regel. Die eine ist für die Abhängigkeiten und die andere für den Compileraufruf.
Wenn hingegen kernel.o gebaut werden soll, matcht die built-in-Regel nicht weil der %-Operator ja erwarten würde, dass die .cpp-Datei im aktuellen Verzeichnis liegt. Nur die Regel aus der .depend-Datei matcht, und damit sieht make seine Arbeit getan, weil make denkt, dass kernel.o keine Datei ist, sondern eine Aktion darstellt (wie all oder clean).
Zum Testen: Du kannst dir anschauen, was make denkt, wenn du -d als Parameter übergibst. Das sind allerdings ziemlich viele Ausgaben aufgrund der built-in-Regeln. Du kannst diese mit dem weiteren Parameter -r deaktivieren. Dann fehlt natürlich wieder die Regel für %.o: %.cpp, die du einfach auch noch in die Makefile schreibst:
%.o: %.cpp
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
Der Unterschied ist, dass make ohne die zusätzliche Regel für Sourcen in $(PLATFORM) folgendes ausgibt:
Must remake target `kernel.o'.
Successfully remade target file `kernel.o'.
Aber mit der Regel führt es den GCC aus:
Must remake target `kernel.o'.
g++ -c -o kernel.o fl/platform/kernel.cpp
Putting child 0x0a01c2b0 (kernel.o) PID 4112 on the chain.
Live child 0x0a01c2b0 (kernel.o) PID 4112
Reaping winning child 0x0a01c2b0 PID 4112
Removing child 0x0a01c2b0 PID 4112 from chain.
Successfully remade target file `kernel.o'.
Ich hoffe das verwirrt jetzt nicht noch mehr ^^