Makefile kompiliert immer alles

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Kobe
Beiträge: 45
Registriert: 30.11.2008 23:59:01

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 29.01.2009 23:22:59

Hallo Ihr

ein neuer Versuch

Code: Alles auswählen

rule%.o : algo/rule%.cpp algo/rule%.h
	$(CC) -c $< -o $@

RULE_SRC = $(patsubst %.cpp,%.o, $(wildcard algo/rule*.cpp))
RULE_OBJS = $(notdir $(RULE_SRC))

foo% :
	@echo "% Regel: " $@

test2: $(RULE_OBJS)
	@echo RULE_OBJS = $(RULE_OBJS)
	@echo RULE_SRC = $(RULE_SRC)
	@echo $+
mit

Code: Alles auswählen

$ rm *.o algo/*.o
rm: Entfernen von „*.o“ nicht möglich: Datei oder Verzeichnis nicht gefunden
rm: Entfernen von „algo/*.o“ nicht möglich: Datei oder Verzeichnis nicht gefunden
$ make rule.o
make: *** Keine Regel, um »rule.o« zu erstellen.  Schluss.
$ g++ -c algo/rule.cpp -o rule.o
$ make foo
% Regel:  foo.o
g++   foo.o   -o foo
g++: foo.o: Datei oder Verzeichnis nicht gefunden
g++: no input files
make: *** [foo] Fehler 1
$ make test2
g++ -c algo/rule11.cpp -o rule11.o
g++ -c algo/rule1p.cpp -o rule1p.o
g++ -c algo/rule1s.cpp -o rule1s.o
g++ -c algo/rulep1.cpp -o rulep1.o
RULE_OBJS = rule11.o rule1p.o rule1s.o rule.o rulep1.o
RULE_SRC = algo/rule11.o algo/rule1p.o algo/rule1s.o algo/rule.o algo/rulep1.o
rule11.o rule1p.o rule1s.o rule.o rulep1.o
$ rm rule.o
$ make test2
make: *** Keine Regel vorhanden, um das Target »rule.o«,
  benötigt von »test2«, zu erstellen.  Schluss.
Dazu habe meine Fragen:

Wieso geht "make rule.o" nicht? Darf '%' nicht leer sein?

Wieso kommt bei "make foo" zusätzlich zur Ausgabe noch mehr?

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Makefile kompiliert immer alles

Beitrag von gms » 30.01.2009 08:28:16

Kobe hat geschrieben:Wieso kommt bei "make foo" zusätzlich zur Ausgabe noch mehr?
wenn du dir "make -d foo" anschauen würdest:
make -d foo
....
Betrachte Target-Datei »foo«.
Die Datei »foo« existiert nicht.
Suche nach einer impliziten Regel für »foo«.
...
Versuche Muster-Regel mit Ersetzung »foo«.
Versuche implizite Voraussetzung »foo.o«.
Suche nach einer Regel mit der Zwischendatei »foo.o«.
Vermeide Rekursion in den impliziten Regeln.
Versuche Muster-Regel mit Ersetzung ».o«.
Eine implizite Regel für »foo« gefunden.
Betrachte Target-Datei »foo.o«.
Die Datei »foo.o« existiert nicht.
Fertig mit den Voraussetzungen für die Ziel-Datei »foo.o«.
Das Target »foo.o« muss neu erzeugt werden.
...
% Regel: foo.o
Das Target »foo« muss neu erzeugt werden.
cc foo.o -o foo
....
dann würdest du erkennen, daß hier eine implizite Regel zugeschlagen hat. Wenn du das nicht möchtest, kannst du die default Suffixes löschen:

Code: Alles auswählen

gms@gms2 ~/tmp/test $ echo ".SUFFIXES:" >>Makefile
gms@gms2 ~/tmp/test $ make foo
make: *** Keine Regel, um »foo« zu erstellen.  Schluss.
Kobe hat geschrieben:Wieso geht "make rule.o" nicht? Darf '%' nicht leer sein?
siehe:
http://www.gnu.org/software/make/manual/make.html#Pattern-Rules hat geschrieben: A pattern rule looks like an ordinary rule, except that its target contains the character `%' (exactly one of them). The target is considered a pattern for matching file names; the `%' can match any nonempty substring
Beachte auch, daß auch bei "make foo" die Pattern-Regel nicht für "foo" sondern nur für "foo.o" angewendet wurde:
$ make foo
% Regel: foo.o
...
Gruß
gms

edit:
Kobe hat geschrieben:

Code: Alles auswählen

RULE_SRC = $(patsubst %.cpp,%.o, $(wildcard algo/rule*.cpp))
RULE_OBJS = $(notdir $(RULE_SRC))
[code]
[/quote]
wenn diese Namen "SRC" vs "OBJS" auch einen Sinn ergeben sollen, dann solltest du den Variablen auch entsprechende Werte zuweisen:

[code]
RULE_SRC = $(wildcard algo/rule*.cpp)
RULE_OBJS = $(notdir $(patsubst %.cpp,%.o, $(RULE_SRC)))
[code]

Kobe
Beiträge: 45
Registriert: 30.11.2008 23:59:01

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 25.02.2009 03:26:56

Hallo ihr geduldigen Helfer

Ich habe dank euch einiges mehr verstanden. Dankeschön.

Meine jetzige Makefile sieht wiefolgt aus (wer Lust hat, kann ja mal drüber fliegen und Verbesserungsvorschläge o.ä. äußern, außerdem stehen darunter noch 2 Fragen)

Anmerkung: Alle nicht mit .o endenden Dateien, sind ausführbar. So für mich als "flag".

Code: Alles auswählen

# variablen fuer compiler, makros
CC = g++

# sql makros
SQLDIR = ./db
SQLFLAGS = -c -w

# die einzelnen Algos
ALGOS_SRC = $(wildcard algo/algo*.cpp)
ALGOS_OBJS = $(notdir $(patsubst %.cpp,%.o, $(ALGOS_SRC)))

# fuer die ausfuehrbare Binary werden noch Bibliotheken benoetigt
INCLUDES = -I$(SQLDIR)
LIBS = -lsqlite3 -lginac

# die einzelnen Schritte
STEP_SRC = $(wildcard algo/step*.cpp)
STEP_OBJS = $(notdir $(patsubst %.cpp,%.o, $(STEP_SRC)))

# die regeln
RULE_SRC = $(wildcard algo/rule*.cpp)
RULES_OBJS = $(notdir $(patsubst %.cpp,%.o, $(RULE_SRC)))

# abhaengigkeiten von der wurzel aus betrachten
#SRC2=algo/pansolver.h
#SRC = algo/algo0.cpp algo/tinhandling.cpp db/sql.h db/sql.cpp
#DEPENDFILE = .depend
#dep: $(SRC)
#	$(CC) -MM -Idb/ -Ialgo/ $< > $(DEPENDFILE)
#dep2: $(SRC2)
#	$(CC) -MM -Idb/ -Ialgo/ $< > $(DEPENDFILE)2
#
#-include $(DEPENDFILE)


all : pansolver

sql.o : db/sql.cpp db/sql.h
	$(CC) $< $(SQLFLAGS) -o $@

tuple.o : algo/tuple.cpp algo/tuple.h
	$(CC) -c $< -o $@

path.o : algo/path.cpp tuple.o
	$(CC) -c $< -o $@

step%.o: algo/step%.cpp algo/steps.h
	$(CC) -c $< -o $@

help.o : algo/help.cpp algo/help.h
	$(CC) -c $< -o $@

node.o : algo/node.cpp algo/node.h help.o
	$(CC) -c $< -o $@

tinahandling.o : algo/tinahandling.cpp algo/tinahandling.h node.o help.o tuple.o path.o
	$(CC) -c $< -o $@

term.o : algo/term.cpp algo/term.h help.o
	$(CC) -c $< -o $@

# alle rule?.cpp => .o
rule%.o : algo/rule%.cpp algo/rule%.h
	$(CC) -c $< -o $@

# rule.o , das von rule%.o nicht abgefangen wird : % = not empty
rule.o : algo/rule.cpp algo/rule.h
	$(CC) -c $< -o $@

pan.o : algo/pan.cpp algo/pan.h $(RULES_OBJS) node.o help.o tuple.o term.o
	$(CC) -c $< -o $@

algo%.o : algo/algo%.cpp algo/pansolver.h
	$(CC) -c $< $(INCLUDES) -o $@

sequence.o : algo/sequence.cpp algo/sequence.h
	$(CC) -c $< -o $@

ginachandling.o : algo/ginachandling.cpp algo/ginachandling.h sequence.o
	$(CC) -c $< -o $@

nodes.o : algo/nodes.cpp algo/nodes.h node.o
	$(CC) -c $< -o $@

pansolver : algo/pansolver.cpp algo/pansolver.h sql.o $(ALGOS_OBJS) $(STEP_OBJS) pan.o path.o tinahandling.o help.o node.o tuple.o $(RULES_OBJS) nodes.o term.o sequence.o ginachandling.o
	$(CC) $^ $(LIBS) $(INCLUDES) -o $@

th : $(TINAHANDLING) node help tuple.o path.o
	$(CC) $(TINAHANDLING) -Dthmain node.o help.o tuple.o path.o -o $@

gh : algo/ginachandling.cpp algo/ginachandling.h sequence.o
	$(CC) $^ -lginac -Dginac_main -o $@

pan : algo/testmain.cpp node.o  help.o $(RULES_OBJS) tuple.o ginachandling.o term.o pan.o nodes.o node.o sequence.o
	$(CC) $^ -lginac -o $@

clean : 
	rm -f *.o pansolver
	@echo alles entfernt
1.
Bei rule%.o und rule.o habe ich nun 2 Regeln erstellt. Kann man das mit einer Regel abfangen? Aber nicht mit rul%.o , das wäre ein Hack, den ich nicht möchte ;)

2.
Bei step%.o: step.h beschreibt eine Klasse mit mehreren Funktionen. In step.cpp ist nur Standardkram (im Moment nur ein Konstruktor). In step%.cpp stehen jeweils die Implementierungen der einzelnen Funktionen, die in step.h beschrieben sind.
Am liebsten (warum auch immer) hätte ich alles in einer .o (wenn das mit g++ ginge):

Code: Alles auswählen

$ g++ -c algo/step*.cpp -o steps.o
g++: cannot specify -o with -c or -S with multiple files
Geht sowas überhaupt?

Das sind jetzt nur noch Schönheitsoperationen, keine lebenswichtigen. Immerhin läuft mein Makefile jetzt :P

Antworten