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

Makefile kompiliert immer alles

Beitrag von Kobe » 11.01.2009 00:02:30

Hallo

Mein Makefile kompiliert immer alles, obwohl sich nichts geändert hat. Das Projekt ist nun schon so groß, dass es langsam nervt. Es soll doch der große Vorteil sein, sich ein Makefile zu erstellen um nicht jedes mal alles neu erstellen zu müssen.

Mein Makefile ist

Code: Alles auswählen

# variablen fuer compiler, makros
CC = g++

# binary name, den das programm bekommen soll
TARGET=pansolver

# sql makros
SQLDIR = ./db
SQL = $(SQLDIR)/sql.cpp
SQLFLAGS = -c -w
# pansolver makros
ALGOS_DIR = ./algo
ALGOS = $(ALGOS_DIR)/algo*.cpp $(ALGOS_DIR)/pansolver.cpp
INCLUDES = -I$(SQLDIR)
# die einzelnen schritte
STEPS = $(ALGOS_DIR)/step*.cpp
# die einzelnen regeln
RULES = $(ALGOS_DIR)/rule*.cpp
# klasse node
NODE = $(ALGOS_DIR)/node.cpp
# das PAN
PAN = $(ALGOS_DIR)/pan.cpp
# Tinahandling fuer die Arbeit mit Tina
TINAHANDLING = $(ALGOS_DIR)/tinahandling.cpp

all : pansolver

sql : $(SQL)
	$(CC) $(SQL) $(SQLFLAGS)

pansolver : sql $(ALGOS) steps pan path tinahandling help
	$(CC) $(ALGOS) $(INCLUDES) *.o -lsqlite3 -o $(TARGET)

steps : $(STEPS) path
	$(CC) -c $(STEPS)

node : $(NODE) help
	$(CC) -c $(NODE)

pan : rules $(NODE) $(PAN) help tuple term
	$(CC) -c $(PAN)

help : $(ALGOS_DIR)/help.cpp
	$(CC) -c $(ALGOS_DIR)/help.cpp

tuple : $(ALGOS_DIR)/tuple.cpp
	$(CC) -c $(ALGOS_DIR)/tuple.cpp

path : $(ALGOS_DIR)/path.cpp tuple
	$(CC) -c $(ALGOS_DIR)/path.cpp

term : $(ALGOS_DIR)/term.cpp help
	$(CC) -c $(ALGOS_DIR)/term.cpp

rules : $(RULES)
	$(CC) -c $(RULES)

tinahandling : $(TINAHANDLING) node help
	$(CC) -c $(TINAHANDLING)

clean : 
	rm -f *.o pansolver
	@echo alles entfernt
Habt ihr eine Idee, wieso alles stets neu kompiliert wird??

mfg
Stephan

PS: Wenn ihr Unschönheiten im Makefile entdeckt, würde ich mich über konstruktive Kritik freuen. Das ist mein allererstes Makefile.

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 14.01.2009 11:36:05

Weil die Ziele (z.B. "rules") nicht existieren?

Gruß,
Ulf

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 14.01.2009 16:21:42

Hallo Ulf

Wie kommst du darauf, dass Ziele nicht existieren sollten? Alle Dateien existieren, es wird auch korrekt übersetzt und eine ausführbare Datei erstellt

Code: Alles auswählen

$ make
g++ ./db/sql.cpp -c -w
g++ -c ./algo/tuple.cpp
g++ -c ./algo/path.cpp
g++ -c ./algo/step*.cpp
g++ -c ./algo/rule*.cpp
g++ -c ./algo/help.cpp
g++ -c ./algo/term.cpp
g++ -c ./algo/pan.cpp
g++ -c ./algo/node.cpp
g++ -c ./algo/tinahandling.cpp
g++ ./algo/algo*.cpp ./algo/pansolver.cpp -I./db *.o -lsqlite3 -o pansolver
$ ls pansolver
pansolver
Falls etwas nicht existieren sollte, müsste doch ein Fehler auftreten?

Oder was meintest du genau?

PS: Die Dateilisten

Code: Alles auswählen

$ ls db/sql.*
db/sql.cpp  db/sql.cpp~  db/sql.h
$ ls algo/*.h
algo/help.h  algo/pan.h        algo/path.h    algo/rule1p.h  algo/rule.h    algo/steps.h  algo/tinahandling.h
algo/node.h  algo/pansolver.h  algo/rule11.h  algo/rule1s.h  algo/rulep1.h  algo/term.h   algo/tuple.h
$ ls algo/*.cpp
algo/algo0.cpp  algo/algo3.cpp  algo/pan.cpp        algo/rule11.cpp  algo/rule.cpp    algo/step2.cpp  algo/term.cpp
algo/algo1.cpp  algo/help.cpp   algo/pansolver.cpp  algo/rule1p.cpp  algo/rulep1.cpp  algo/step3.cpp  algo/tinahandling.cpp
algo/algo2.cpp  algo/node.cpp   algo/path.cpp       algo/rule1s.cpp  algo/step1.cpp   algo/steps.cpp  algo/tuple.cpp

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 14.01.2009 19:38:47

Existiert eine Datei names "rules" (als Beispiel)?

Wenn nein, wird so etwas wie

Code: Alles auswählen

all: rules
        echo $@

rules: foo
        echo $@

foo:
        echo $@
immer dazu führen, daß "alles" neu erstellt wird:
"rules" gibt's nicht, also erstellen,
"foo" gibt's nicht, also erstellen,
...

Im Endeffekt wird eben alles neu compiliert.

tjb
Beiträge: 1
Registriert: 14.01.2009 22:43:56

Re: Makefile kompiliert immer alles

Beitrag von tjb » 14.01.2009 23:32:27

Hallo,

Naja, make ist halt dazu gedacht, dass es prüft, welche targets nicht mehr aktuell sind und daher neu erstellt werden müssen.
Und das heißt... wenn natürlich in einem Programmteil noch gearbeitet wird - und dieser muss ins gesamtpaket eingebunden werden, dann wird nur "make" feststellen, dass die eine cpp datei verändert wurde. Die wird dann kompiliert. Daraus folgt, dass ein anderes Target nun nicht mehr aktuell ist, in dem die kopilierte Datei als Abhängigkeit drin steht. noch mal was zum kompilieren... und so zieht sich das durch.
bsp:
- du arbeitest an help.cpp
- dann muss das target "help" erneuert werden
- "help" ist als abhängigkeit bei den targets tinahandling, term, pan, node und pansolver eingetragen
- nachdem "help" nun neu ist, stimmen die anderen nicht mehr... werden also neu kompiliert.
- usw.

wenn du nur teile kompilieren möchtest (um zu sehen, ob noch syntaktische fehler drin sind z.b.) gib einfach mal das target an, das du erreichen möchtest.
Machst ja bei "make clean" auch so.

Oder hab ich dich da jetzt falsch verstanden? du arbeitest ja wohl noch an dem programm, oder? sonst würde dir das gar nicht auffallen ;)

Gruß,

Tobi

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 15.01.2009 18:47:35

Hallo tjb, du hast mich nicht ganz verstanden:
Kobe hat geschrieben:Hallo

Mein Makefile kompiliert immer alles, obwohl sich nichts geändert hat.
[...]
Sprich, 2x 'make' aufrufen sollte beim 2. Aufruf nichts machen. Es kompiliert aber immer alles.

@ulf
Es existiert keine Datei namens "rules", nur das Target "rules".
Bin ich fehlinformiert?

Code: Alles auswählen

TARGET: DEPENDENCIES
(TABULATOR) COMMAND
Pro TARGET (Sprungmarke), wird das / die Kommando(s) COMMAND ausgeführt. Bevor das ausgeführt wird, werden die DEPENDENCIES geprueft, ob diese aktuell sind, falls nein, wird rekursiv alles aktualisiert. Bei DEPENDENCIES kann man auch andere TARGETS angeben. So habe ich das gemacht.

Code: Alles auswählen

node : $(NODE) help
   $(CC) -c $(NODE)
Das TARGET "node" erstellt mir eine Node-Klasse (node.cpp + node.h), da ich in node.h aber help.h einbinde, habe ich dem TARGET node das TARGET help als Abhängigkeit gegeben. "help" ist also keine Datei, sondern ein TARGET im Makefile.

Habe ich da ein Misverständnis drin?

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 15.01.2009 19:04:39

Das TARGET "node" erstellt mir eine Node-Klasse (node.cpp + node.h), da ich in node.h aber help.h einbinde, habe ich dem TARGET node das TARGET help als Abhängigkeit gegeben. "help" ist also keine Datei, sondern ein TARGET im Makefile.

Habe ich da ein Misverständnis drin?
Ja. Wenn 'help' keine Datei ist, "glaubt" das make-Programm, diese Datei erstellen zu müssen.
Bei den anderen Dateien genauso. Daher wird wohl immer wieder alles neu compiliert.

Grundsätzlich sollten Ziele und Abhängigkeiten tatsächlich existierende oder zu erstellende Dateien sein.

Code: Alles auswählen

foo: foo.c foo.h
        gcc -o $@ $<
erstellt die Datei "foo" dann, wenn foo.c oder foo.h neuer als foo sind oder foo gar nicht existiert.

Code: Alles auswählen

gibsnich: foo.c foo.h
        gcc -o foo foo.c
wird immer ausgeführt, solange es "gibsnich" nicht gibt.

Gruß,
Ulf

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 16.01.2009 00:41:33

Hallo Ulf

wenn das so ist, dann verstehe ich, warum er immer wieder neu kompiliert.
Aber wie mache ich folgende Situation dynamisch genug, dass ich nicht immer per Hand aktualisieren muss:
  • A : a.h und a.cpp
  • B: b.h , b.cpp und bX.cpp wobei X aus {0,...,n}: b0.cpp ,..., b3.cpp existieren, später kommen b4.cpp und b5.cpp dazu. (Pro X eine Funktion, die in b.h definiert wurde). Benötigen alle A.
  • Main: main.h und main.cpp, benötigt B und somit auch A.
Ich dachte das ginge so

Code: Alles auswählen

all: main

main : B main.h main.cpp
    g++ -o main B.o A.o

B : A b.h b.cpp
    g++ -c b*.cpp

A : a.h a.cpp
    g++ -c a.cpp
Das dynamische steckt indem man dem gcc "b*.cpp" übergibt.
Wie kann ich make sagen, dass B von allen bX.cpp abhängt?
Wie kann ich main sagen, dass es von allen bX.cpp bzw. was auch immer ich da erstelle abhängt?

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 16.01.2009 18:52:33

(Was Du genau mit "dynamisch" meinst, habe ich nicht verstanden,
ich versuche es mal mit folgender Erklärung:)

Wie gesagt, grundsätzlich Dateien als Ziele und Abhängigkeiten verwenden.
Wenn Du "A.o" und "B.o" erzeugen willst, dann sind das die Ziele, nicht
"A" und "B":

Code: Alles auswählen

all: main

main: A.o B.o main.cpp main.h
    $(CC) -o $@ B.o A.o main.cpp

B.o: b.h b*.cpp
    $(CC) -c -o $@ b*.cpp

A.o: a.h a.cpp
    $(CC) -c -o $@ a.cpp
Typischerweise ist die Ausgabe des/der Kommandos (hier: g++ ...)
das Ziel, und alle benötigten (Eingabe-)Dateien sind die
Abhängigkeiten.

Wenn also das Kommando "g++ -o main B.o A.o" lautet, ist "main"
das Ziel und (mindestens) "B.o" und "A.o" die Abhängigkeiten.

Und andersherum: wenn "A.o" für das Erzeugen von "main" benötigt
wird, gehört "A.o" in die Liste der Abhängigkeiten von "main".
Wenn "A.o" nicht für "B.o" benötigt wird, gehört es auch nicht in
die entsprechende Liste der Abhängigkeiten.

Im obigen Beispiel kann man auch die "all"-Zeile weglassen und
dann einfach "make" aufrufen, weil "main" ja das erste Ziel ist.

Tip1: wenn Du das Prinzip verstanden hast, probier einmal
"make -d [ziel] 2>&1 | less"
dann zeigt Dir 'make' den ganzen Vorgang.

Tip2: danach solltest Du Dir vielleicht einmal die Doku zur
Kommandozeilen-Option "-M" von g++ ansehen.

Gruß,
Ulf

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 17.01.2009 12:19:57

Hallo ulf
ulf hat geschrieben:(Was Du genau mit "dynamisch" meinst, habe ich nicht verstanden,
ich versuche es mal mit folgender Erklärung:)

Wie gesagt, grundsätzlich Dateien als Ziele und Abhängigkeiten verwenden.
Wenn Du "A.o" und "B.o" erzeugen willst, dann sind das die Ziele, nicht
"A" und "B":

Code: Alles auswählen

all: main

main: A.o B.o main.cpp main.h
    $(CC) -o $@ B.o A.o main.cpp

B.o: b.h b*.cpp
    $(CC) -c -o $@ b*.cpp

A.o: a.h a.cpp
    $(CC) -c -o $@ a.cpp
Das Problem ist, dass es nicht B.o gibt, sondern B.o, B1.o, B2.o, ... weil B = Oberklasse, Bi = Unterklassen und mit dynamisch meine ich, dass ich mir eine neue Unterklasse Bj.cpp + Bj.h schreiben möchte, die von der Oberklasse B (B.h + B.cpp) abgeleitet ist. Ich möchte dann in der Makefile diese Klasse Bj nicht extra (per Hand) eintragen müssen, sondern durch B*.cpp "dynamisch" erfasst haben.

Es gibt also nicht nur B.o, sondern pro Ober- und Unterklasse (werden "dynamisch" mehr) muss eine .o erzeugt werden. Wenn es geht, dass man alle Klassen in eine .o stecken kann, dann würde mich das interessieren. Ich bin da jeweils dran gescheitert, dass der gcc keine main findet, er mit

Code: Alles auswählen

g++ -o B.o B*.cpp
aber immer eine main braucht. Die Parameter -c und -o sind nicht kombinierbar.

Tip1: wenn Du das Prinzip verstanden hast, probier einmal
"make -d [ziel] 2>&1 | less"
dann zeigt Dir 'make' den ganzen Vorgang.
Ganz schön lange Ausgabe.
Tip2: danach solltest Du Dir vielleicht einmal die Doku zur
Kommandozeilen-Option "-M" von g++ ansehen.
Die Ausgabe der benötigten Header hilft mir hier nicht weiter.


mfg
Stephan

Benutzeravatar
GoKi
Beiträge: 2068
Registriert: 04.07.2003 23:08:56
Lizenz eigener Beiträge: MIT Lizenz

Re: Makefile kompiliert immer alles

Beitrag von GoKi » 17.01.2009 13:20:49

Kobe hat geschrieben:
Tip2: danach solltest Du Dir vielleicht einmal die Doku zur
Kommandozeilen-Option "-M" von g++ ansehen.
Die Ausgabe der benötigten Header hilft mir hier nicht weiter.
Doch, dadurch können Abhängigkeiten erkannt werden und man kann gewährleisten, dass bei Änderung einer eingebundenen Header-Datei das cpp neu kompiliert wird.

Ich benutze in einem Makefile System allgemeine Regeln für die Erstellung von .o

Code: Alles auswählen

%.o: %.cpp
	$(CXX) -fPIC $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
Dann müssen "nur" noch die Abhängigkeiten erkannt werden, dabei kann

Code: Alles auswählen

$(OBJDEPS): %.d: %.cpp
	$(CXX) $(CPPFLAGS) -MM -MG $< -MF $@
helfen.
Das sind beides nur Auszüge aus einem längeren Makefile, das ich beruflich einsetze.
Siehe z.B. auch
http://www.ijon.de/comp/tutorials/makefile.html#dep (erster Treffer in Google)

Ich persönlich finde auch Systeme wie Debiancmake ganz interessant, da man sich dabei nicht um alles selbst kümmern muss und man vergleichsweise schnell ein brauchbares Ergebnis bekommt.
MfG GoKi
:wq

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 17.01.2009 15:11:05

Kobe hat geschrieben: Das Problem ist, dass es nicht B.o gibt, sondern B.o, B1.o, B2.o, ... weil B = Oberklasse, Bi = Unterklassen und mit dynamisch meine ich, dass ich mir eine neue Unterklasse Bj.cpp + Bj.h schreiben möchte, die von der Oberklasse B (B.h + B.cpp) abgeleitet ist. Ich möchte dann in der Makefile diese Klasse Bj nicht extra (per Hand) eintragen müssen, sondern durch B*.cpp "dynamisch" erfasst haben.

Es gibt also nicht nur B.o, sondern pro Ober- und Unterklasse (werden "dynamisch" mehr) muss eine .o erzeugt werden. Wenn es geht, dass man alle Klassen in eine .o stecken kann, dann würde mich das interessieren.
Dann helfen Dir vermutlich folgende Features weiter:

Code: Alles auswählen

B_SOURCES = B*.cpp
definiert eine Variable, die alle B-Quelldateien enthält
(in diesem konkreten Beispiel allerdings auch B.cpp),

Code: Alles auswählen

B_OBJECTS = $(B_SOURCES:.cpp=.o)
definiert eine Variable, die davon abgeleitet die Liste der
Objekt-Dateien enthält,

Code: Alles auswählen

B%.o: B%.cpp B%.h
        $(CC) -o $@ $<
ist eine generelle Regel, wie ein B*.o aus der Source-Datei
erstellt wird,

Code: Alles auswählen

%.o : %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
ist eine vordefiniert Regel von GNU-Make, gibt's sicher auch
für .cpp-Dateien.
Die Parameter -c und -o sind nicht kombinierbar.
Das wage ich zu bezweifeln!
Tip1: wenn Du das Prinzip verstanden hast, probier einmal
"make -d [ziel] 2>&1 | less"
dann zeigt Dir 'make' den ganzen Vorgang.
Ganz schön lange Ausgabe.
Tip 1a: Mit den richtigen Kommandozeilen-Optionen von (GNU-)make
kann man die Ausgabe vereinfachen.

Gruß,
Ulf

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 17.01.2009 19:51:36

Hallo ulf

Ich bin jetzt bei

Code: Alles auswählen

RULES_SOURCES = $(ALGOS_DIR)/rule*.cpp
RULES_OBJECTS = $(RULES_SOURCES:.cpp=.o)

rules%.o: rules%.cpp rules%.h
	$(CC) -o $@ $<
und komme jetzt nicht weiter. Ich kann das TARGET rules%.o nicht erstellen

Code: Alles auswählen

$ make rules%.o
make: *** Keine Regel, um »rules%.o« zu erstellen.  Schluss.
Das verstehe ich nicht ganz.
ulf hat geschrieben:

Code: Alles auswählen

%.o : %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
ist eine vordefiniert Regel von GNU-Make, gibt's sicher auch
für .cpp-Dateien.
Es soll doch aus allen .c Dateien jeweils .o Dateien erstellen? Wieso nennst du es extra, wenn dein zuvor genannter Befehl doch schon aus allen B*.cpp (bzw. rule*.cpp) die .o jeweils erstellt.
Die Parameter -c und -o sind nicht kombinierbar.
Das wage ich zu bezweifeln!
Ich verstehe die folgende Ausgabe aber so

Code: Alles auswählen

$ g++ -c algo/rule*.cpp
$ g++ -c algo/rule*.cpp -o rules.o
g++: cannot specify -o with -c or -S with multiple files
Tip1: wenn Du das Prinzip verstanden hast, probier einmal
"make -d [ziel] 2>&1 | less"
dann zeigt Dir 'make' den ganzen Vorgang.
Ganz schön lange Ausgabe.
Tip 1a: Mit den richtigen Kommandozeilen-Optionen von (GNU-)make
kann man die Ausgabe vereinfachen.
Wie meinst du das?

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 18.01.2009 12:23:44

Kobe hat geschrieben: Ich kann das TARGET rules%.o nicht erstellen

Code: Alles auswählen

$ make rules%.o
make: *** Keine Regel, um »rules%.o« zu erstellen.  Schluss.
Hmm, ich glaube, als erstes solltest Du Dir einmal ganz in Ruhe das
von GoKi erwähnte Tutorial durchlesen - das ist auf Deutsch, schön kurz
und scheint ganz gut zu sein, also die ideale Einstiegslektüre.

Dann würde sich Deine Frage auch erübrigen...

("rules%.o" steht für alle Dateien, die mit "rules" anfangen und mit
"*.o" aufhören, "rules%.cpp" für die entsprechenden Dateien mit der
Endung ".cpp" statt ".o").
Es soll doch aus allen .c Dateien jeweils .o Dateien erstellen? Wieso nennst du es extra, wenn dein zuvor genannter Befehl doch schon aus allen B*.cpp (bzw. rule*.cpp) die .o jeweils erstellt.
Die erste war auf das angegebene Beispiel bezogen (ich sehe gerade,
ich habe ein "-c" im Befehl vergessen), die zweite habe ich aus dem
GNU-make-Handbuch (auch da mal reinschauen!):

http://www.gnu.org/software/make/manual ... mples.html

Die eingebaute Regel gibt's ganz umsonst, mußt Du nicht einmal
hinschreiben. (Du kannst sie aber mit einer eigenen Regel überschreiben.)

Eigentlich solltest Du, eben weil es die eingebauten Regeln gibt, ganz
ohne solche Regeln auskommen. Make "weiß" schon, wie man bei Bedarf
eine Objektdatei aus der cpp-Datei erstellt. Konzentriere Dich lieber
auf die Abhängigkeitsbeschreibungen:

Welche Datei muß erstellt oder aktualisiert werden, wenn sich welche
Datei ändert?
Die Parameter -c und -o sind nicht kombinierbar.
Das wage ich zu bezweifeln!
Ich verstehe die folgende Ausgabe aber so

Code: Alles auswählen

$ g++ -c algo/rule*.cpp
$ g++ -c algo/rule*.cpp -o rules.o
g++: cannot specify -o with -c or -S with multiple files
Da steht aber definitiv nichts von "-c" und "-o" sind nicht (=niemals)
kombinierbar...
Tip 1a: Mit den richtigen Kommandozeilen-Optionen von (GNU-)make
kann man die Ausgabe vereinfachen.
Wie meinst du das?
Hmm, was hat denn "man make" gesagt, als Du wegen der möglichen
Kommandozeilen-Optionen nachgesehen hast?

Gruß,
Ulf

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 19.01.2009 22:51:17

ulf hat geschrieben:Hmm, ich glaube, als erstes solltest Du Dir einmal ganz in Ruhe das
von GoKi erwähnte Tutorial durchlesen - das ist auf Deutsch, schön kurz
und scheint ganz gut zu sein, also die ideale Einstiegslektüre.
Kannst du mir bitte einen Link geben, ich weiß / finde nicht, was du meinst.

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 20.01.2009 18:32:50

Kobe hat geschrieben:
ulf hat geschrieben:Hmm, ich glaube, als erstes solltest Du Dir einmal ganz in Ruhe das
von GoKi erwähnte Tutorial durchlesen - das ist auf Deutsch, schön kurz
und scheint ganz gut zu sein, also die ideale Einstiegslektüre.
Kannst du mir bitte einen Link geben, ich weiß / finde nicht, was du meinst.
Äääh, das ist jetzt nicht Dein Ernst, oder?

Es gibt in dem ganzen Thread nur einen Beitrag von GoKi, und wenn Du Dir den einmal
durchliest, kannst Du's gar nicht übersehen.

Gruß,
Ulf

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 21.01.2009 11:52:09

Hallo Ulf
ulf hat geschrieben:Äääh, das ist jetzt nicht Dein Ernst, oder?

Es gibt in dem ganzen Thread nur einen Beitrag von GoKi, und wenn Du Dir den einmal
durchliest, kannst Du's gar nicht übersehen.
Entschuldige, habe zur Zeit zuviel um die Ohren und zuviele offene Baustellen, die dringed gefixt werden müssen :( Ich habe es wirklich mehrmals übersehen.

Danke, ich werde es mir genauer angucken.

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 24.01.2009 22:33:10

Hallo ulf und GoKi

Habe mich nun nochmals genauer mit make beschäftigt und bin nicht voran gekommen:

Der %-Operator
  • Wie kann ich mit '%' umgehen?
  • Dass es wie der *-Operator zu handhaben ist, weiß ich.
  • Aber siehe weiter oben, ich kann damit nicht umgehen, wenn ein '%' im Target ist.
  • Wie heißt der Operator? Ich kann nicht nach Sonderzeichen wie % googlen (oder doch?).
Ich habe im Moment

Code: Alles auswählen

[...]
sql.o : $(SQL)
	$(CC) $(SQL) $(SQLFLAGS)

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

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

steps%.o: algo/step%.cpp algo/step%.h
	$(CC) -c $<
[...]
Die Abhängigkeiten trage ich vorerst noch per Hand ein, da das mein erstes Makefile ist und ich erstmal die grundlegenden Dinge verstehen möchte. Beispielsweise erstmal einmal korrekt zum laufen bekommen.

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 » 24.01.2009 23:36:21

Kobe hat geschrieben: Entschuldige, habe zur Zeit zuviel um die Ohren und zuviele offene Baustellen, die dringed gefixt werden müssen :( ....
dann würde ich die Empfehlung von GoKi in Erwägung ziehen und mir "cmake" genauer anschauen.
Kobe hat geschrieben: [*]Wie heißt der Operator? Ich kann nicht nach Sonderzeichen wie % googlen (oder doch?).
hier könntest das einseitige HTML Manual helfen, darin kannst du mit jedem Browser nach '%' suchen

http://www.gnu.org/software/make/manual/make.html
Kobe hat geschrieben: Die Abhängigkeiten trage ich vorerst noch per Hand ein, da das mein erstes Makefile ist und ich erstmal die grundlegenden Dinge verstehen möchte. Beispielsweise erstmal einmal korrekt zum laufen bekommen.
ok, aber was "lauft" den jetzt eigentlich nicht ?

Code: Alles auswählen

gms@gms1 ~ $ cat Makefile
CXX=g++

all: myprog

myprog: stepaa.o stepab.o
        $(CXX) -o $@ $<

steps%.o: step%.cpp step%.h
        $(CXX) -o $@ -c $<

gms@gms1 ~ $ touch stepaa.h stepab.cpp stepab.h
gms@gms1 ~ $ echo "int main() {}" >stepaa.cpp
gms@gms1 ~ $ make
g++    -c -o stepaa.o stepaa.cpp
g++    -c -o stepab.o stepab.cpp
g++ -o myprog stepaa.o
gms@gms1 ~ $ ./myprog
gms@gms1 ~ $   
Kobe hat geschrieben: Habt ihr eine Idee, wieso alles stets neu kompiliert wird??
solche Fragen kann die Ausgabe von "make -d" beantworten

Gruß
gms

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 25.01.2009 13:57:54

Hallo gms
gms hat geschrieben:dann würde ich die Empfehlung von GoKi in Erwägung ziehen und mir "cmake" genauer anschauen.
Ich möchte gerne auf Standard-Linuxsystemen entwickeln, da das Program im fertigen Zustand an mehreren Plätzen eingerichtet werden soll. Dazu möchte ich so wenig wie möglich extra Packages benötigen. Ich vermute einfach mal, dass cmake nicht so häufig auf System vertreten ist, als make.
gms hat geschrieben:hier könntest das einseitige HTML Manual helfen, darin kannst du mit jedem Browser nach '%' suchen

http://www.gnu.org/software/make/manual/make.html
Auch das Tutorial bin ich bereits überflogen. Allerdings wurde dort % immernur im Makefile angegeben, wie z.B.

Code: Alles auswählen

     foo:
             frobnicate > foo
     
     %: force
             @$(MAKE) -f Makefile $@
     force: ;

The way this works is that the pattern rule has a pattern of just `%', so it matches any target whatever.
aber ohne Beispiel wie man nun das "Target '%'" erstellen lässt. Du hast mir endlich das erste Beispiel gegeben.
ok, aber was "lauft" den jetzt eigentlich nicht ?

Code: Alles auswählen

[...]
myprog: stepaa.o stepab.o
        $(CXX) -o $@ $<

steps%.o: step%.cpp step%.h
        $(CXX) -o $@ -c $<
[...]
Sowas läuft. Aber ich wollte genau sowas ja nicht haben: Im Target myprog muss jedes step*.o per Hand eingetragen werden. Das wollte ich mit

Code: Alles auswählen

myprog: steps%.o
oder

Code: Alles auswählen

myprog: steps
        [...]
steps: step%.cpp step%.h
        [...]
abfangen. Somit müsste ich das Makefile hinsichtlich step*.h und step*.cpp nie wieder anfassen. Aber das läuft so nicht

Code: Alles auswählen

make: *** Keine Regel vorhanden, um das Target »step%.o«,
Geht denn mein Gedanke überhaupt mit make in die Tat umzusetzen oder muss ich jedes step* per Hand in das gewünschte Target eintragen?

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 » 25.01.2009 17:07:34

Kobe hat geschrieben: Geht denn mein Gedanke überhaupt mit make in die Tat umzusetzen oder muss ich jedes step* per Hand in das gewünschte Target eintragen?
in einer Pattern-Rule muß in jedem Fall das Target als Pattern definiert sein

Du kannst soetwas aber auf diese Weise lösen:

Code: Alles auswählen

gms@gms1 ~ $ cat Makefile

MYOBJECTS=$(patsubst %.cpp,%.o,$(wildcard step*.cpp))

myprog: $(MYOBJECTS)
        $(CXX) -o $@ $<

steps%.o: step%.cpp step%.h
        $(CXX) -o $@ -c $<
gms@gms1 ~ $
gms@gms1 ~ $ echo "int main(){}">stepaa.cpp
gms@gms1 ~ $ touch stepaa.h stepab.h stepab.cpp
gms@gms1 ~ $ make
g++    -c -o stepaa.o stepaa.cpp
g++    -c -o stepab.o stepab.cpp
g++ -o myprog stepaa.o
gms@gms1 ~ $              

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

Re: Makefile kompiliert immer alles

Beitrag von Kobe » 26.01.2009 14:17:32

Ich komme sehr zäh voran. Stehe momentan bei

Makefile

Code: Alles auswählen

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

Code: Alles auswählen

$ ls algo/step*
algo/step1.cpp  algo/step2.cpp  algo/step3.cpp  algo/steps.cpp  algo/steps.h
$ make steps.o
make: *** Keine Regel vorhanden, um das Target »algo/step%.cpp«,
  benötigt von »steps.o«, zu erstellen.  Schluss.
Wieso steht da im Target das Verzeichnis "algo/" mit drin? Das Target steps.o benötigt die step*.cpp und steps.h aus algo/ und soll in das aktuelle Verzeichnis erstellt werden (-o steps.o).

und das zweite (gleiche Makefile, andere Stelle) wieder Probleme mit dem Unterverzeichnis

Code: Alles auswählen

$ ls algo/rule*
algo/rule11.cpp  algo/rule1p.cpp  algo/rule1s.cpp  algo/rule.cpp  algo/rulep1.cpp
algo/rule11.h    algo/rule1p.h    algo/rule1s.h    algo/rule.h    algo/rulep1.h
probiert mit

Code: Alles auswählen

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

test2: rule%.o
	@echo $(RULE_OBJS)
	$(CC) -o $@ $<
endet in

Code: Alles auswählen

$ make test2
make: *** Keine Regel vorhanden, um das Target »rule%.o«,
  benötigt von »test2«, zu erstellen.  Schluss.
oder

Code: Alles auswählen

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

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

test2: $(RULE_OBJS)
	@echo $(RULE_OBJS)
	$(CC) -o $@ $<
endet in

Code: Alles auswählen

$ make test2
g++    -c -o algo/rule11.o algo/rule11.cpp
g++    -c -o algo/rule1p.o algo/rule1p.cpp
g++    -c -o algo/rule1s.o algo/rule1s.cpp
g++    -c -o algo/rule.o algo/rule.cpp
g++    -c -o algo/rulep1.o algo/rulep1.cpp
RULE_OBJS = algo/rule11.o algo/rule1p.o algo/rule1s.o algo/rule.o algo/rulep1.o
g++ -o test2 algo/rule11.o
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
[... Error, weil keine main da ist ...]
Auch hier soll er es ins aktuelle Verzeichnis erstellen und nicht in algo/rule*.cpp.
Die RULE_SRC müssten ohne "algo/" sein, schreibe ich aber

Code: Alles auswählen

RULE_OBJS = $(patsubst %.cpp,%.o, $(wildcard rule*.cpp))
ist RULE_OBJS leer.

Ich bin langsam am verzweifeln :(

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 » 26.01.2009 20:06:42

Kobe hat geschrieben: Auch hier soll er es ins aktuelle Verzeichnis erstellen und nicht in algo/rule*.cpp.
es gibt auch noch andere Funktionen, die alle in dem Manual beschrieben werden, wie z.B die Funktion "notdir":

Code: Alles auswählen

gms@gms1 ~ $ cat Makefile
RULE_OBJS=$(notdir $(patsubst %.cpp,%.o,$(wildcard algo/*.cpp)))

all:
        echo obj=$(RULE_OBJS)
gms@gms1 ~ $ mkdir algo
gms@gms1 ~ $ touch algo/step1.cpp algo/step2.cpp
gms@gms1 ~ $ make
echo obj=step1.o step2.o
obj=step1.o step2.o

Benutzeravatar
schorsch_76
Beiträge: 2629
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Makefile kompiliert immer alles

Beitrag von schorsch_76 » 26.01.2009 21:07:04

Wiso nutzt du nicht die GNU Buildchain mit automake/autoconf/configure?

Wenn du dich damit nicht auskennst: Hier eine klasse Erklärung: http://www.lrde.epita.fr/~adl/autotools.html

Gruß

schorsch

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Re: Makefile kompiliert immer alles

Beitrag von ulf » 26.01.2009 22:09:49

Kobe hat geschrieben: Auch das Tutorial bin ich bereits überflogen.
Dir fehlen die elementaren Grundlagen. Also nimm Dir die Zeit zum
Lesen, "überfliegen" reicht nicht!
Allerdings wurde dort % immer nur im Makefile angegeben
Natürlich, wo denn sonst? In der Kommandozeile hat es nichts zu suchen.

Code: Alles auswählen

     foo:
             frobnicate > foo

     %: force
             @$(MAKE) -f Makefile $@
     force: ;
Dieses Beispiel hat mit Deinem Problem überhaupt nichts zu tun!

Code: Alles auswählen

The way this works is that the pattern rule has a pattern of just `%', so it
matches any target whatever.
aber ohne Beispiel wie man nun das "Target '%'" erstellen lässt. Du hast mir
endlich das erste Beispiel gegeben.
Nein! Ein Target '%' erstellt man nicht. Lies Dir im Handbuch den Text
vor und nach den obigen drei Regel durch, damit Du weißt, um was es
dort überhaupt geht. Der von Dir noch zitierte Text ("This way...")
bescheibt doch etwas völlig anderes.

Nochmal: Dir fehlen die elementaren Grundlagen! Investiere eine
halbe Stunde, um das Tutorial durchzulesen! (Dort sind im übrigen
auch einige leichte Beispiele zu den "Pattern Rules" enthalten.)
Am besten noch eine weitere halbe Stunde, um die Beispiele einmal
einzugeben und auszuprobieren. Dann bist Du auch in der Lage,
beispielsweise den Text des GNU-Handbuchs zu verstehen.

"Investieren" ist hier auch genau der richtige Begriff, denn die Zeit,
die Du einmal für das Studium der Dokumentation hineinsteckst, erhälst
Du später vielfach wieder zurück.

Im Moment reden alle an Dir vorbei (d.h. Du kannst mit den Antworten
nichts anfangen), weil Dir das Grundverständnis fehlt.
  • Wie kann ich mit '%' umgehen?
  • Dass es wie der *-Operator zu handhaben ist, weiß ich.
Nein, das ist es nicht!
  • Aber siehe weiter oben, ich kann damit nicht umgehen, wenn ein '%' im Target ist.
Das muß sogar im Target vorkommen!

Code: Alles auswählen

myprog: steps%.o
Dasselbe Problem. Diese Zeile ist sinnlos, weil im Ziel (myprog) kein
Muster '%' enthalten ist, auf das sich das Muster in den Abhängigkeiten
beziehen kann.

Links (im Target) muß (bei einer Patter-Regel) ein '%' vorkommen,
ersetze das in Gedanken durch "eine_beliebige_zeichenkette". Rechts
vom Doppelpunkt (in den Abhängigkeiten) kann das '%' ein- oder
mehrmals vorkommen (muß aber nicht), ersetze das in Gedanken durch
"dieselbe_beliebige_zeichenkette_wie_im_target".

Code: Alles auswählen

myprog: steps*.o
wäre zumindest syntaktisch korrekt, auch wenn es sicher nicht das
tut, was Du erwartest. '%' und '*' sind nicht dasselbe.
Geht denn mein Gedanke überhaupt mit make in die Tat umzusetzen oder
muss ich jedes step* per Hand in das gewünschte Target eintragen?
Es geht, es ist sogar sehr einfach, und die entsprechenden Beispiele
dazu findest Du zum Beispiel im von GoKi erwähnten Tutorial. Ein
Beispiel paßt übrigens zu Deinem Problem wie die Faust aufs Auge...

Und wenn Du jetzt den Fehler machst, schnell die entsprechende Stelle
(und nur diese Stelle!) zu suchen und das Beispiel zu übernehmen, ohne
es zu verstehen - was glaubst Du, wie Du das nächste Problem lösen
kannst?

Gruß,
Ulf

Antworten