GNUmake verhält sich merkwürdig



  • Hallo zusammen,

    ich bin mir recht sicher, dass GNUmake hier falsche Dinge tut. Betrachtet diesen Thread als Warung.

    main.c:

    int main(void){}
    

    Makefile:

    .POSIX:
    .SUFFIXES:
    
    .SUFFIXES: .o
    .o:
    	@echo single
    	$(CC) $(CFLAGS) -o $@ $<
    
    .SUFFIXES: .c .o
    .c.o:
    	@echo double
    	$(CC) $(CFLAGS) -c -o $@ $<
    
    clean:
    	rm -f main main.o
    

    Die Befehle

    make main.o
    make main
    

    rufen wie erwartet erst die double suffix rule und dann die single suffix rule auf. Ausgabe bei mir:

    double
    c99 -O -c -o main.o main.c
    
    single
    c99 -O -o main main.o
    

    Wenn ich aber nur

    make main
    

    aufrufe, wird

    c99 -O    main.c   -o main
    

    aufgerufen. Das scheint eine built-in implizite Regel von GNUmake zu sein, denn mit

    make -r main
    

    erhalte ich die gewünschte Ausgabe

    double
    c99 -O -c -o main.o main.c
    single
    c99 -O -o main main.o
    

    Und dieses Verhalten macht mir gerade meine ganze Makefile kaputt 😞

    Ich habe die Makefile auch mit NetBSDs make getestet und das tut genau das, was ich mir gewünscht habe.


  • Gesperrt

    Dieser Beitrag wurde gelöscht!


  • Dein Beispiel ist nicht vollständig, daher kann es schlecht nachvollzogen werden.
    z.b. ist dein Makefile unvollständig, denn die definition von CC und CFLAGS ist nicht gegeben



  • @firefly sagte in GNUmake verhält sich merkwürdig:

    Dein Beispiel ist nicht vollständig, daher kann es schlecht nachvollzogen werden.
    z.b. ist dein Makefile unvollständig, denn die definition von CC und CFLAGS ist nicht gegeben

    Doch es ist vollständig. CC und CFLAGS müssen Defaultwerte haben.



  • Und wiso gibt es keine regel für das target main?
    Denn wenn ich eine regel für main erstelle klappt es

    .POSIX:
    .SUFFIXES:
    
    .SUFFIXES: .o
    .o:
    	@echo single
    	$(CC) $(CFLAGS) -o $@ $<
    
    .SUFFIXES: .c .o
    %.o : %.c
    	@echo double
    	$(CC) $(CFLAGS) -c -o $@ $<
    main: main.o
    
    clean:
    	rm -f main main.o
    

    hab die .o.c regel ersetzt, da diese veraltet ist (zu mindestens bei gnu make):
    https://stackoverflow.com/questions/9233447/what-is-the-makefile-target-c-o-for

    Es funktioniert wirft bei gnu make aber folgende Warnung (wenn die main regel existiert):

    make: Circular main.c <- main.o dependency dropped.
    


  • @firefly sagte in GNUmake verhält sich merkwürdig:

    hab die .o.c regel ersetzt, da diese veraltet ist (zu mindestens bei gnu make):
    https://stackoverflow.com/questions/9233447/what-is-the-makefile-target-c-o-for

    Es funktioniert wirft bei gnu make aber folgende Warnung (wenn die main regel existiert):

    make: Circular main.c <- main.o dependency dropped.
    

    Ich versuche möglichst kein GNUism zu verwenden, daher auch das .POSIX: am Anfang.

    @firefly sagte in GNUmake verhält sich merkwürdig:

    Und wiso gibt es keine regel für das target main

    Dafür gib es extra die single suffix rule. Wenn es kein Target mit dem Namen main gibt, wird geschaut, ob es eine main.o gibt aus der dann main erstellt werden kann. Und main.o kann nach der double suffix rule aus main.c erstellt werden. Siehe POSIX make.



  • Und wo steht es da genau?



  • @firefly sagte in GNUmake verhält sich merkwürdig:

    Und wo steht es da genau?

    So in der Mitte des Abschnitts „Inference Rules“.



  • Und wiso willst du auf die main rule verzichten?
    Da in der clean rule main vorkommt, sehe ich da keinen vorteil keine main rule anzugeben



  • gnu make erzeugt folgende regel, wenn es keine im Makefile findet:

    main: main.c
    #  Command line target.
    #  Implicit rule search has been done.
    #  Implicit/static pattern stem: 'main'
    #  Last modified 2019-01-12 20:48:20.207699282
    #  File has been updated.
    #  Successfully updated.
    # automatic
    # @ := main
    # automatic
    # % := 
    # automatic
    # * := main
    # automatic
    # + := main.c
    # automatic
    # | := 
    # automatic
    # < := main.c
    # automatic
    # ^ := main.c
    # automatic
    # ? := main.c
    # variable set hash-table stats:
    # Load=8/32=25%, Rehash=0, Collisions=1/21=5%
    #  recipe to execute (built-in):
            $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
    

    Und LINK.c ist $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)

    Vermutlich erzeugt bsd make eine andere regel für main (das übergebene target via cmd line) wenn es keine passende regel im Makefile gibt



  • Habs gerade mal unter freebsd ausprobiert. bsd make scheint überhaupt keine impliziten regeln zu besitzen. Das scheint eine gnu make erweiterung zu sein.

    Daher ist klar wieso das nicht funktioniert.

    Es stellt sich aber weiterhin die Frage wiso du auf die explizite main regel verzichten möchtest, wo doch in der clean regel main bzw main.o referenziert werden


Anmelden zum Antworten