makefile-Problem



  • Ich versuche seit Tagen ein Makefile zu bauen, steige aber nicht durch die Syntax durch.
    Mein GTK+2-Programm benötigt unter Linux eine weitere Bibliothek und einen etwas
    anderen Compiler-Aufruf als unter OpenBSD.

    Mein Versuch:

    all: prog
    CC = gcc
    CFLAGS=-O3 -std=c99 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0`
    CFLAGS_L=-O3 -std=c99 -lbsd -D_GNU_SOURCE -D_BSD_SOURCE -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0`
    LDFLAGS=`pkg-config --libs gtk+-2.0`
    prog: prog.c
    	export OS=`uname`; \
    	if [ $(OS)$ = "Linux" ]; 
    	then\
    	.include <bsd/stdlib.h>; \
    	$(CC) -o prog prog.c $(CFLAGS_L) $(LDFLAGS);\
    	else\
    	$(CC) -o prog prog.c $(CFLAGS) $(LDFLAGS);\
    	endif
    

    Als Fehlerausgabe bekomme ich:

    export OS=`uname`; if [ OpenBSD= "Linux" ];
    /bin/sh: syntax error: `if' unmatched
    

    Der Vergleich der beiden Strings sollte doch syntaktisch richtig sein, oder?
    Vor den Shell-Befehlen steht immer ein Tab.

    Vielen Dank für Hilfe, bin am Verzweifeln.



  • Mach keine ifs in Makefiles. Das bringts nicht. Nimm lieber include.
    Makefile:

    ifndef OS
    OS:=$(shell uname)
    endif
    
    # Defaultwerte hier
    CC = cc
    
    # Überschreiben da
    include Variablen-fuer-$(OS).mk
    
    all: prog
    
    prog: $(wildcard *.c)
      $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)
    

    Variablen-fuer-Linux.mk:

    CFLAGS=-O3 -std=c99 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0` -DLINUX
    LDFLAGS=`pkg-config --libs gtk+-2.0`
    

    Variablen-fuer-OpenBSD.mk:

    CFLAGS=-O3 -std=c99 -lbsd -D_GNU_SOURCE -D_BSD_SOURCE -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0` -DOPEN_BSD
    LDFLAGS=`pkg-config --libs gtk+-2.0`
    

    Im Code:

    #if OPEN_BSD
    #include <bsd/stdlib.h> // so hab ich das zumindest verstanden
    #endif
    

    So sieht ein schönes Build-System aus. Plattformabhängige Sachen in externe Dateien auslagern. Und natürlich ist es wichtig, die Syntax zu lernen, das hättest du in den Tagen, in denen du dein Makefile versuchen hast zu erstellen, lernen können.



  • Vielen Dank für deine Hilfe, das werde ich gleich ausprobieren.
    Natürlich habe ich versucht, die Syntax zu lernen, aber ich muss sagen,
    dass mich die Komplexität von make echt überfordert hat.

    Danke 🙂



  • Hallo nochmal, habe es jetzt so umgesetzt, wie in dem Beispiel.

    Bekomme aber folgende Fehlermeldung:

    *** Parse error in /home/user/code: Need an operator in 'OS' (Makefile 1)
    *** Parse error: Need an operator in 'endif' (Makefile 3)
    *** Parse error: Could not find Variablen-fuer-.mk (Makefile 9)
    


  • In der Manpage steht:

    The ! operator is a BSD extension.

    Wenn ich im Makefile den operator ! setze:

    !ifndef OS
    OS:=$(shell uname)
    !endif
    

    verschwinden die ersten beiden Parse-Fehler, aber die Variable OS wird trotzdem
    nicht in den Dateinamen eingesetzt. Hat vielleicht noch jemand eine Idee?

    Danke



  • Makefiles sind echt übel. Das Problem mit dem if ist, dass da ein Backslash am Ende fehlt:

    if [ $(OS)$ = "Linux" ]; \
    	then\
    	.include <bsd/stdlib.h>; \
    	$(CC) -o prog prog.c $(CFLAGS_L) $(LDFLAGS);\
    	else\
    	$(CC) -o prog prog.c $(CFLAGS) $(LDFLAGS);\
    	endif
    

    Wobei ich das .include nicht kenne.

    Es seien Dir die Autotools Mythbuster ans Herz gelegt. Autotools sind echt nicht so schwer, wie sie zunächst scheinen. Insbesondere im Vergleich zu händisch geschriebenen Makefiles sind die Autotools weit besser.



  • tntnet schrieb:

    Makefiles sind echt übel.

    Danke. Ich dachte schon, dass nur mir das so geht.

    GNU-autotools habe ich ausprobiert und war nachher noch verwirrter, da es ja noch einige Dateien mehr zu konfigurieren gibt und ein korrektes Makefile auch erstmal Voraussetzung ist. Das Beispiel für das build-system finde ich ganz gut, habe jetzt auch schon ein bisschen mehr begriffen. Ich programmiere unter OpenBSD, es scheint hier doch einige Eigenheiten zu geben, die ich berücksichtigen muss. Es geht eigentlich nur noch darum, der Variable OS die shell-Ausgabe des Befehls 'uname' zu übergeben. Warum das nicht klappt, verstehe ich nicht.



  • Das OpenBSD make funktioniert echt anders. Habe es jetzt folgendermaßen gelöst:

    OS!=uname
    CC = cc
    .include <$(OS).mk>
    
    all: prog
    
    prog: $(.c)
      $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)	all: prog
    

    Das funktioniert unter OpenBSD, allerdings nicht unter Linux.

    Ich werde einfach make so aufrufen:

    make OS=Linux
    

    oder eben

    make OS=OpenBSD
    

    So bin ich das Problem los. Vielen Dank für eure Hilfe.


Anmelden zum Antworten