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.
-
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 gegebenDoch 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-forEs 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-forEs 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 einemain.o
gibt aus der dannmain
erstellt werden kann. Undmain.o
kann nach der double suffix rule ausmain.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