Anzeige:
Ergebnis 1 bis 10 von 10

Thema: Makefile - Argumente f. unterschiedliche Builds?

  1. #1
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38

    Makefile - Argumente f. unterschiedliche Builds?

    Hi,

    ich schreibe momentan an einem Programm, das nun ein *optionales* GUI bekommen soll.
    Die Frage ist nun, wie muss eine Makefile aussehen, damit ich über die Makefile steuern kann, ob der Code für das GUI mitkompiliert wird?
    Der Code ist in 2 Dateien, gui.c und gui.h enthalten. gui.h wird in einer einzigen anderen Datei per #include eingebunden.

    Mein Ziel ist es nun, ein "make" und ein "make no-gui" zu bekommen, in letzterem soll die GUI nicht mitkompiliert werden. (Um auch Systeme ohne X nutzen zu können)

    Weiterer Haken: Für die GUI brauche ich CFLAGS und LIBS, die in der no-gui-Version ebenfalls nicht genutzt werden sollen.

    Das Ganze ist ein Linuxprojekt, nur falls das noch etwas zur Sache tut.

    Hier mal meine aktuelle Makefile:

    Code:
    CC = gcc
    INSTALL = install
    LIBS = `pkg-config --libs gtk+-2.0`
    CFLAGS = -O2 -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0`
    
    TARGET = chpchk
    SRCS = intel.c amd.c toolkit.c gui.c chpchk.c
    OBJS = intel.o amd.o toolkit.o gui.o chpchk.o
    BLBS = intel_data.o amd_data.o
    
    all: $(TARGET)
    
    install: $(TARGET)
    	$(INSTALL) -s -m 0755 $(TARGET) /usr/bin/$(TARGET)
    
    suid-install: $(TARGET)
    	$(INSTALL) -s -o root -g root -m 4755 $(TARGET) /usr/bin/$(TARGET)
    
    intel_data.o:
    	ld -r -b binary -o intel_data.o intel.csv
    amd_data.o:
    	ld -r -b binary -o amd_data.o amd.csv
    
    $(TARGET): $(BLBS) $(OBJS)
    	$(CC) -o $(TARGET) $(OBJS) $(BLBS) $(LIBS)
    
    %.o: %.c
    	$(CC) -o $@ -c $< $(CFLAGS)
    
    clean:
    	rm -f $(OBJS) $(BLBS) core $(TARGET)
    
    strip:
    	strip $(TARGET)
    Alles was fett markiert ist, soll in der no-gui-Version aussen vor bleiben.

    Wie stelle ich das Ganze an?
    Ich habe mit Makefiles bisher kaum Erfahrung (ist um genau zu sein meine Erste).
    Und wie schon gesagt, ich habe auch keine Ahnung, wie ich die #include gui.h-Zeile im Code dann "deaktivieren" kann...

    Wäre für Hilfe extrem dankbar!!!

    Peter

  2. #2
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    zuerst die einfache Frage ;-) Optionales Einbinden kannst Du im Source natürlich mit #ifdef machen:
    Code:
    #ifdef GUI
    #include gui.h
    #endif
    Du definierst dann einfach ein Flag -DGUI für die GUI-Version und lässt ihn in der non-GUI-Version weg.

    Für die non-GUI-Version definierst Du ein eigenes Target, die CFLAGS, SRCS und OBJS teilst Du in einen allgemeinen Teil und einen GUI-spezifischen und fütterst damit die Targets, z. B. so (ungetestet):
    Code:
    # ...
    CFLAGS = -O2 -D_FILE_OFFSET_BITS=64
    GUI_CFLAGS = -DGUI `pkg-config --cflags gtk+-2.0`
    
    TARGET = chpchk
    CLI_TARGET = cli_chpchk
    SRCS = intel.c amd.c toolkit.c chpchk.c
    GUI_SRCS = gui.c
    OBJS = intel.o amd.o toolkit.o chpchk.o
    GUI_OBJS = gui.o
    BLBS = intel_data.o amd_data.o
    
    all: $(TARGET)
    
    # install-Targets noch anpassen
    
    # ...
    
    $(TARGET): $(BLBS) $(OBJS) $(GUI_OBJS)
            $(CC) -o $(TARGET) $(OBJS) $(GUI_OBJS) $(BLBS) $(LIBS) $(GUI_LIBS)
    
    $(CLI_TARGET): $(BLBS) $(OBJS)
            $(CC) -o $(TARGET) $(OBJS) $(BLBS) $(LIBS)
    
    $(OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS)
    
    $(GUI_OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS) $(GUI_CFLAGS)
    
    # usw.
    Jan

  3. #3
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Sieht vielversprechend aus, als kleiner Hobby/Amateur-Programmierer werde ich das wohl nochmal lesen müssen um es zu 100% zu durchblicken
    Das grobe Vorgehen habe ich jedenfalls verstanden, mit dem Beispiel kriege ich das gebacken - vielen Dank!!!

    Peter

  4. #4
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Zitat Zitat von jan61 Beitrag anzeigen
    Code:
    $(OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS)
    
    $(GUI_OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS) $(GUI_CFLAGS)
    Jan
    Scheinbar gibt es hier noch ein Problem: Das -DGUI CFLAG wird hier nur den OBJS, die die GUI betreffen übergeben - d.h. das CFLAG wird in allen anderen OBJS nicht gesetzt und ich habe keine Möglichkeit, mit #ifdef zu prüfen, ob -DGUI gesetzt ist...

    Peter

  5. #5
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Ich habe das Problem gelöst, allerdings mit einem wahrscheinlich etwas unschönem "Hack":

    Code:
    CC = gcc
    INSTALL = install
    LIBS = 
    LIBS_GUI = `pkg-config --libs gtk+-2.0`
    CFLAGS = -O2 -D_FILE_OFFSET_BITS=64
    CFLAGS_GUI = -DGUI `pkg-config --cflags gtk+-2.0`
    
    TARGET = chpchk
    TARGET_GUI = chpchk-gui
    SRCS = intel.c amd.c toolkit.c terminal.c chpchk.c
    SRCS_GUI = gui.c
    OBJS = intel_.o amd_.o toolkit_.o terminal_.o chpchk_.o
    OBJS_GUI = intel.o amd.o toolkit.o terminal.o chpchk.o gui.o
    BLBS = intel_data.o amd_data.o
    
    all: $(TARGET_GUI)
    
    cmdline: $(TARGET)
    
    install: $(TARGET)
    	$(INSTALL) -s -m 0755 $(TARGET) /usr/bin/$(TARGET)
    
    suid-install: $(TARGET)
    	$(INSTALL) -s -o root -g root -m 4755 $(TARGET) /usr/bin/$(TARGET)
    
    intel_data.o:
    	ld -r -b binary -o intel_data.o intel.csv
    amd_data.o:
    	ld -r -b binary -o amd_data.o amd.csv
    
    $(TARGET_GUI): $(BLBS) $(OBJS_GUI)
    	$(CC) -o $(TARGET) $(OBJS_GUI) $(BLBS) $(LIBS) $(LIBS_GUI)
    
    $(TARGET): $(BLBS) $(OBJS)
    	$(CC) -o $(TARGET) $(OBJS) $(BLBS) $(LIBS)
    
    $(OBJS): %_.o: %.c
    	$(CC) -o $@ -c $< $(CFLAGS)
    
    $(OBJS_GUI): %.o: %.c
    	$(CC) -o $@ -c $< $(CFLAGS) $(CFLAGS_GUI)
    
    clean:
    	rm -f $(OBJS) $(OBJS_GUI) $(BLBS) core $(TARGET)
    
    strip:
    	strip $(TARGET)
    Ein "make cmdline" erzeugt hier OBJS mit der Endung "_.o" und ein normales "make" bzw "make all" erzeugt ".o" OBJS. Damit kann ich die CFLAGS auf alle OBJS anwenden und es funktioniert wie gewollt.

    Gibt es evtl "schönere" Lösungen?

    Peter

  6. #6
    Registrierter Benutzer Avatar von undefined
    Registriert seit
    01.03.2004
    Beiträge
    1.255
    Also du machst vieles sehr umständlich. Verwende AUTOMAKE mit libtool und nicht eine reines Make. Dann wird dir mehr wie 80% an Arbeit abgenommen. Einzelne Programme kannst du dann mit AC_ARG_WITH ein abschalten und mit einfachen IF Anweisungen in der Makefile.am einschränken.
    siehe auch:
    info:/autoconf/Generic Programs

    Ich habe dir mal eines meiner Bibliotheken start Templates angehängt, hier kannst du vielleicht etwas besser ableiten.
    mfg undefined
    --
    Undefined Behavior (undefiniertes Verhalten) bedeutet meistens etwas ungültiges.
    xhtml Debugger

  7. #7
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von undefined Beitrag anzeigen
    Also du machst vieles sehr umständlich. Verwende AUTOMAKE mit libtool und nicht eine reines Make.
    ich halte es bei einem kleinen, überschaubaren Projekt schon für sinnvoll, auch mal in die Untiefen von Makefiles hinabzutauchen - das hilft mir u. a. oft, wenn ich die von anderen Projekten verstehen will (um herauszukriegen, warum zum Geier ein make mal wieder nicht durchläuft z. B.).

    Wenn man dann in Zukunft professioneller arbeiten will, dann sind solche Hilfsmittel wie automake, autoconf etc. natürlich angebracht.

    Jan

  8. #8
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    das geht IMHO auch eleganter (wieder ungetestet):
    Code:
    # ...
    CFLAGS = -O2 -D_FILE_OFFSET_BITS=64
    GUI_CFLAGS = -DGUI `pkg-config --cflags gtk+-2.0`
    
    TARGET = chpchk
    CLI_TARGET = cli_chpchk
    OBJS = intel.o amd.o toolkit.o chpchk.o
    GUI_OBJS = $(OBJS) gui.o
    BLBS = intel_data.o amd_data.o
    
    all: $(TARGET)
    
    # install-Targets analog
    
    # ...
    
    $(TARGET): $(BLBS) $(GUI_OBJS)
            $(CC) -o $(TARGET) $(GUI_OBJS) $(BLBS) $(LIBS) $(GUI_LIBS)
    
    $(CLI_TARGET): $(BLBS) $(OBJS)
            $(CC) -o $(TARGET) $(OBJS) $(BLBS) $(LIBS)
    
    $(OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS)
    
    $(GUI_OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS) $(GUI_CFLAGS)
    
    # usw.
    Der Trick ist hier einfach, in die GUI-Objekte alle .o-Dateien aufzunehmen und die Abhängigkeiten entsprechend zu definieren.

    2 Anmerkungen noch:

    1. Die SRCS-Definitionen nutzt Du nirgends - müsste auch ohne diese Variablen funktionieren. Die Targets für die Objekt-Dateien nutzen ja eine Ersetzung der .o- durch .c-Endungen, um die Quellen zu definieren.

    2. Wenn Du mehrmals nacheinander CLI- und GUI-Target kompilierst, dann musst Du drauf achten, zwischendurch ein make clean zu machen, weil sonst nicht alle Objekte mit den geänderten CFLAGS neu kompiliert werden (der Zeitstempel der Dateien ändert sich ja nicht).

    Jan

  9. #9
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Nur eine kleine Info: offenbar geht ihr davon aus, dass ich in meinem Projekt mehrere verschiedene Programme habe - es handelt sich nur um ein einziges Programm, das eben eine optionale GUI bekommen soll bzw momentan bekommt.
    autoconf & Co sind daher wohl wirklich ein bisschen Overkill, die Makefile habe ich auch nur, weil der Code mittlerweile unübersichtlich genug war, dass sich mehrere .c-Dateien lohnen.

    Da es mein erstes etwas grösseres Projekt und meine erste Makefile sind, kenne ich mich auf dem Gebiet eben auch noch so gut wie gar nicht aus.
    Wo müsste ich die $(SRCS) eigentlich nutzen? Die stehen wirklich ungenutzt rum...

    Kann es sein, dass die irgendwo bei
    Code:
    $(OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS)
    stehen sollten? (z.B. anstatt "%.c" ?)
    Dadurch würden sich meine Probleme glaube ich auflösen, da die Sache sich an der Stelle IMHO etwas beisst.

    Auf jeden Fall Danke für die Hilfe!!!

    Peter

  10. #10
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von shutdown Beitrag anzeigen
    Nur eine kleine Info: offenbar geht ihr davon aus, dass ich in meinem Projekt mehrere verschiedene Programme habe - es handelt sich nur um ein einziges Programm, das eben eine optionale GUI bekommen soll bzw momentan bekommt.
    Nein, ich hatte Dich schon so verstanden. Deshalb auch mein Hinweis wegen des make clean - da es sich um die gleichen Zieldateien (.o und Executable) handelt, würde ein make mit neuem Target bei unveränderten Quellen sonst eben kein Neukompilieren mit geänderten Flags auslösen.

    Zitat Zitat von shutdown Beitrag anzeigen
    ...Wo müsste ich die $(SRCS) eigentlich nutzen? Die stehen wirklich ungenutzt rum...

    Kann es sein, dass die irgendwo bei
    Code:
    $(OBJS): %.o: %.c
            $(CC) -o $@ -c $< $(CFLAGS)
    stehen sollten? (z.B. anstatt "%.c" ?)
    Dadurch würden sich meine Probleme glaube ich auflösen, da die Sache sich an der Stelle IMHO etwas beisst.
    Die musst Du gar nicht nutzen - Du kannst die Definitionen entfernen. Der Witz ist ja eben, dass die Konstruktion in obigem Target aus jeder in OBJS angegebenen Datei den Namen der als Abhängigkeit zu behandelnden Source über die Substitution (%.o: %.c) ermittelt. Du hast an der Stelle IMHO kein Problem.

    Jan

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •