Makefile für Windows anpassen?



  • Ich habe ein einfaches Makefile für Linux geschrieben, das unter Linux mit GNU make auch funktioniert:

    INCDIRS = 
    LIBDIRS = 
    
    CC = cc
    LD = cc
    CFLAGS=-Wall --pedantic -std=c99 -O -g
    LIBS=-lX11 -lXi -lXmu -lglut -lGL -lGLU -lm 
    
    all: example-1-1 example-1-2 
    
    example-1-1: example-1-1.c
    	$(CC) $(CFLAGS) example-1-1.c -o example-1-1 $(LIBS)
    
    example-1-2: example-1-2.c
    	$(CC) $(CFLAGS) example-1-2.c -o example-1-2 $(LIBS)
    clean:
    	rm example-1-1 example-1-2
    

    Das Problem ist jetzt nur, daß ich gerne eines hätte, daß auch unter Windows funktioniert, also anpassbar ist.

    In Windows würden meine Binarydateien z.b. alle mit *.exe enden, dann wären die Linker Anweisungen anders und der Befehl um die Binaries wieder zu löschen wäre del.

    Im Sourcecode ist mit #ifdef _WIN32 usw. schon alles für Windows und Linux angepaßt, nur beim MAKEFILE stimmt es halt noch nicht.
    Gibt es hier auch so eine Art #ifdef Anweisungen für MAKEFILES, so daß GNU Make das jeweils für das entsprechende System passende heraussuchen kann?

    Unter Windows verwende ich als Compiler GCC in Form des mingw Pakets.
    D.h. mein make Progamme wäre ebenfalls GNU Make.
    nmake nutze ich nicht.



  • schieb.



  • Hat wirklich keiner Ahnung?



  • wo liegt das Problem, einfach zwei Makefiles mitzugeben?

    Die Dateiendung der Binary übernimmt eh der Linker, also reicht ein TARGET = myapp

    für einen switch könntest du so was machen:

    PLATFORM = win32
    #PLATFORM = unix
    
    ...
    
    ifeq ($(PLATFORM), win32)
      RM = del
    else
      RM = rm -f
    endif
    
    ...
    clean:
      $(RM) ...
    

    dann einfach je nach Platform umkommentieren



  • Windowsanfänger schrieb:

    In Windows würden meine Binarydateien z.b. alle mit *.exe enden,

    ...
    TARGET_EXT:=
    ifeq ($(OS),Windows_NT)
    	TARGET_EXT:=.exe
    endif
    TARGET:=$(PROJECT)$(TARGET_EXT)
    ...
    


  • Windowsanfänger schrieb:

    In Windows würden meine Binarydateien z.b. alle mit *.exe enden, dann wären die Linker Anweisungen anders und der Befehl um die Binaries wieder zu löschen wäre del.

    Du könntest dir auch überlegen, MSYS zu verwenden, damit kannst du dann das Makefile für UNIX auch unter Windows verwenden. Die exe-Erweiterung brauchst du dann nicht extra angeben (die Datei heißt dann zwar ....exe, aber wird auch gefunden, wenn du den Dateinamen ohne .exe verwendest), und du kannst normale UNIX-Befehle wie rm verwenden.



  • Oder du verwendest einen Makefile-generator wie CMake, mit dem du dann entweder Linux-Makes oder Windows-Makes beziehungsweise Projekt-Files generierst. Alternativ kann man einen Linux-Make auch mit cygwin zum laufen bringen.

    Gruß Kimmi



  • zwutz schrieb:

    wo liegt das Problem, einfach zwei Makefiles mitzugeben?

    Die Dateiendung der Binary übernimmt eh der Linker, also reicht ein TARGET = myapp

    für einen switch könntest du so was machen:

    PLATFORM = win32
    #PLATFORM = unix
    
    ...
    
    ifeq ($(PLATFORM), win32)
      RM = del
    else
      RM = rm -f
    endif
    
    ...
    clean:
      $(RM) ...
    

    dann einfach je nach Platform umkommentieren

    Wenn ich das so mache, dann meldet
    make clean
    keine Fehler mehr.

    clean:
      $(RM) *.o
    

    Wenn es z.b. keine *.o Dateien gibt, dann meldet make clean normalerweise wenn der Befehl rm lautet nen Fehler, nach dem Motto ERROR *.o not found.
    mit $(RM) löscht er zwar, aber er meldet nichts mehr.

    Ich habe jetzt mal folgendes Makefile geschrieben

    #PLATFORM = win32
    PLATFORM = unix
    
    INCDIRS =
    LIBDIRS =
    
    CC = cc
    LD = cc
    CFLAGS=-Wall --pedantic -std=c99 -O -g
    LIBS=-lX11 -lXi -lXmu -lglut -lGL -lGLU -lm  $(LIBDIRS)
    
    # Determine Unix or Windows OS
    TARGET_EXT:=
    ifeq ($(PLATFORM), win32)
      RM = del
      TARGET_EXT:=.exe
    else
      RM = rm -f
      TARGET_EXT:=.bin
    endif
    
    # Determine Unix OS Type
    ifeq ($PLATFORM),unix)
    	sysname = $(shell uname -s)
    	ifeq ($(sysname),Linux)
       		hardware = $(shell uname -m)
       		ifeq ($(hardware),x86_64)
         		sysname = x86_64
         		MACHINE = x86_64
       		endif
    	endif
    	ifeq ($(sysname),SunOS)
       		LIBDIRS = -L. -L/usr/openwin/lib
       		hardware = $(shell uname -m)
       		ifeq ($(hardware),sun4v)
    	 		sysname = sun4v
    	 		MACHINE = sun4v
       		endif
       		ifeq ($(hardware),i86pc)
         		sysname = i86pc
         		MACHINE = i86pc
       		endif
    	endif
    endif
    
    all: example-1-1 example-1-2 
    
    example-1-1: example-1-1.c
    	$(CC) $(CFLAGS) $< -o $@$(TARGET_EXT) $(LIBS)
    
    example-1-2: example-1-2.c
    	$(CC) $(CFLAGS) $< -o $@$(TARGET_EXT) $(LIBS)
    
    clean:
    	$(RM) *.o example-1-1$(TARGET_EXT) example-1-2$(TARGET_EXT)
    

    Momentan nutze ich also für unix die Endung *.bin, weil das so dann auch einfach zum löschen ist.
    Ich könnte damit die Zeile
    (RM).oexample11(RM) *.o example-1-1(TARGET_EXT) example-1-2(TARGET_EXT)z.B.durch:(TARGET\_EXT) z.B. durch: (RM) *.o *.bin
    ersetzen.

    Aber die *.bin Endung will ich weglassen, so daß meine Programme keine Punktendung mehr haben.
    Wenn ich das aber nun tue, wie kann ich dann mit einem make clean
    alle Programme löschen, ohne jedesmal den Programmnamen example-1-1, example-1-2 usw. einzeln aufzählen zu müssen?



  • So, das Problem mit rm konnte ich nun lösen, ich mußte nur das -f hinter rm entfernen, die anderen Probleme bleiben aber.



  • all: $(TARGETS)
    
    clean: 
      rm $(TARGETS)
    


  • volkard schrieb:

    all: $(TARGETS)
    
    clean: 
      rm $(TARGETS)
    

    Dann muß ich $(TARGETS) aber dennoch definieren:

    $(TARGETS):= example-1-1 example-1-2 usw.

    Oder?
    Denn wenn ich das nicht mache, dann sagt make all " nichts zu tun."



  • Windowsanfänger schrieb:

    Dann muß ich $(TARGETS) aber dennoch definieren:

    $(TARGETS):= example-1-1 example-1-2 usw.

    Ja.
    Und vielleicht noch die TARGET_EXT an jedes dranpappen. Geht sogar auch per Funktion irgendwie.



  • volkard schrieb:

    Und vielleicht noch die TARGET_EXT an jedes dranpappen.

    Ja, hab's gerade gemerkt, beim ausführen von make clean.
    Wenn die Endung nicht drangepack ist, dann geht zwar make all,
    aber beim make clean kann er die Dateien dann nicht löschen, da für ihn $(TARGETS) ein kompletter String ist und der nicht durchiteriert ist um die Endung dranzuhängen.

    Das macht er z.B. nicht:

    clean.
      rm $(TARGETS)$(TARGETS_EXT)
    

    Dann löscht er nur bestensfalls die letzte Datei, die in TARGETS aufgeführt ist.

    Wenn ich aber jetzt in TARGETS die TARGETS_EXT anhänge, dann muß ich alle meine
    einzelnen TARGET Befehle anpassen und dann kann ich diese nicht mehr einzeln compilieren, weil da ja dann die Anweisungen für die Enden dann wieder fehlen.
    Mal abgesehen davon, daß er dann auch dort ein Problem mit so einem kompletten Strin hätte.
    Der würde dann für z.B.

    example-1-1: 
      gcc -c bla1.c bla2.c bla3.c -o bla
    

    versuchen und das kann es ja auch nicht sein.

    Geht das nicht irgendwie eleganter mit gmake Bordmitteln (also ohne cmake und so)?



  • http://www.gnu.org/software/make/manual/make.html#Text-Functions
    rm $(addsuffix (TARGETEXT),(TARGET_EXT),(TARGETS))
    ?

    Ich habe zwar immer nur ein target, aber ich benutze mit Vorliebe plattform- und projektunabhängige makefiles. Das geht ganz gut.



  • volkard schrieb:

    http://www.gnu.org/software/make/manual/make.html#Text-Functions
    rm $(addsuffix (TARGETEXT),(TARGET_EXT),(TARGETS))
    ?

    Besten Dank. Das klappt jetzt.

    Ich habe zwar immer nur ein target, aber ich benutze mit Vorliebe plattform- und projektunabhängige makefiles. Das geht ganz gut.

    Da müßte ich zuviel doppelt pflegen.
    Deswegen ist das automatisiert eigentlich recht praktisch und inzwischen läuft das Makefile eigentich recht gut.


Log in to reply