• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[Gelöst] Makefile für verteilten Code

Phillinger

Member
Hi,

ich beiße mir hier die Zähne an einer Makefile aus, die ich erstellen möchte/muss. Es geht um folgendes:

Es befinden sich C-Quellcodedateien in verschiedenen Verzeichnissen. Es befinden sich selbst erstellte Header-Dateien in verschiedenen Verzeichnissen. Der Code muss mit Präprozessor-Direktiven übersetzt werden, damit gewisse Code-Bereiche beim Compilieren ausgelassen oder überhaupt genutzt werden. Das echte Szenario ist viel zu umfangreich, um es zu erklären, daher eine sehr(!) vereinfachte Version:

/exe_lin/
Hier drin befindet sich das Makefile, hier soll die Binary entstehen.

/prog/
Hier drin ist eine Quellcode-Datei: source.c
Die sieht so aus:
Code:
#ifdef HELLO

#include <stdio.h>
#include <extern.h>

int main(void)
{
	printf("Hello, world!\n");
	return 0;
}

#endif /* HELLO */

/def/
Hier drin ist eine selbsterstellte Headerdatei: extern.h
Die ist in diesem Beispiel leer, er soll sie einfach finden und inkludieren.

Hier nun die Makefile:
Code:
CC      = mxscaleb-gcc
PREPROC = -DHELLO
INCLUDE = -I../def/

release: ../prog/source.o
	$(CC) -o hello ../prog/source.o
	
source.o: ../prog/source.c
	$(CC) $(INCLUDE) $(PREPROC) -o ../prog/source.o -c  ../prog/source.c

clean:
	rm hello ../prog/source.o

Wenn ich nun make eingebe, zeigt er beim Kompilieren Fehler an, er würde keine main finden (Präprozessor-Direktive fehlt). Entferne ich in diesem Beispiel die #ifdef-Anweisung, meckert er dann, das er keine extern.h finden kann. Die Objekt-Datei ist zu diesem Zeitpunkt schon erstellt, er stolpert also über die Regel von release.

Gebe ich allerdings zuerst "make source.o" und dann "make" ein, funktioniert alles. Wie kann das sein?

Es ist gerade so, als bräuchte er für das Linken (die .o-Datei steht ja schon) nochmal die Präprozessor-Direktiven und die Includepfade. Das kann doch eigentlich nicht sein?
 
Schau mal hier. Ich kopier mal Dein Makefile und markiere die entscheidenden Bereiche fett:

##########################################################################################
CC = mxscaleb-gcc
PREPROC = -DHELLO
INCLUDE = -I../def/

release: ../prog/source.o
$(CC) -o hello ../prog/source.o

source.o: ../prog/source.c
$(CC) $(INCLUDE) $(PREPROC) -o ../prog/source.o -c ../prog/source.c

clean:
rm hello ../prog/source.o
##########################################################################################

Siehst Du es jetzt?

Falls nicht, kann ich es auch sagen: "../prog/source.o" ist nicht gleich "source.o". "release" hängt von "../prog/source.o", die Regel dafür heißt bei Dir aber "source.o". Das ist nicht dasselbe, deswegen kann "make" nicht erkennen, was Du meinst. "make" ist dafür "zu dumm".

Probier mal die Variante:

##########################################################################################
CC = mxscaleb-gcc
PREPROC = -DHELLO
INCLUDE = -I../def/

release: ../prog/source.o
$(CC) -o hello ../prog/source.o

../prog/source.o: ../prog/source.c
$(CC) $(INCLUDE) $(PREPROC) -o ../prog/source.o -c ../prog/source.c

clean:
rm -f hello ../prog/source.o
##########################################################################################

PS: Ich habe oben auch gleich noch eine Option hinzugefügt, die sehr empfehlenswert ist, nämlich die Option "-f" für das "clean"-target. Ist sehr nützlich, wenn man nur teilweise gebaut hat (z.B. weil es einen Fehler gab oder weil man abgebrochen hat) und trotzdem "make clean" ausführen will.

Funktionieren wird das Ganze natürlich nur nach einem "make clean" (weil sonst noch das alte source.o rumliegt, welches kein "main" hat und deswegen nicht gelinkt werden kann).
 
OP
Phillinger

Phillinger

Member
traffic, du bist mein Held! Es funktioniert.

Argh, das muss wohl Betriebsblindheit gewesen sein, natürlich kann make nicht riechen, woher er ../prog/source.o bekommen soll, wenn ich es ihm nicht sage.

Vielen Dank, auch für den Tip mit der -f Option! :D
 
Oben