Moin,
größere Pakete (z.B den Kernel) übersetze ich in Linux mit make -j6, um
alle Cores zu auszulasten. Hin und wieder bricht make jedoch mit einem
Fehler ab (mit einer unverständlichen Fehlermeldung). Bei einem weiteren
Aufruf macht make dann an dieser Stelle weiter, und fast immer läuft es
dann durch. Wird nur ein Core verwendet, tritt der Fehler nicht auf. Das
Problem tritt bei allen Versionen und Backends des gcc auf, die ich
bisher verwendet habe.
Ist kein Weltuntergang, nervt aber. Kennt jemand das Problem?
proggen schrieb:> Vancouver schrieb:>> (mit einer unverständlichen Fehlermeldung)>> mit der könnte man dir hier vll. helfen, aber so bleibt nur die> Glaskugel...
Ich bezweifle es.
Das passiert hin und wieder, weiß auch nicht woran es liegt. Den
QtWebKit-Build muss man auch grundsätzlich zweimal starten ...
Das Problem ist, dass schon ein Modul gebaut werden soll, wofuer die
abhaengigkeit vielleicht noch gar nicht gebaut ist.
Das kann bei -j1 nicht passieren.
Beispiel:
Du hast Modul A und Modul B. A braucht 30 Sekunden zum compilieren und B
nur 10 Sekunden. B ist aber abhaengig von A.
Bei -j1 wird brav Modul A gebaut und dann Modul B. Somit ist die
Abhaengigkeit fuer B vorhanden.
Bei -j6 ist das aber nicht mehr gegeben. Jetzt werden A und B
gleichzeitig compiliert und das compilieren schlaegt natuerlich fehl,
weil die abhaengigkeit fuer B noch nicht vorhanden ist.
Ja, es gibt tatsaechlich faelle, wo sowas auftreten kann. Es gibt Pakete
die mit -j1 gebaut werden muessen.
Das kann z.B. auftreten, wenn Modul A zu einer Lib gebaut wird, und
Modul B auf diese Lib zugreifen will. Ist die Lib nicht vorhanden kann
es nicht compiliert werden.
> mit der könnte man dir hier vll. helfen, aber so bleibt nur die> Glaskugel...
Ja, da hast Du grundsätzlich recht. Aber ich habe die Fehlermeldung
nicht parat, da müsste ich das ganze nochmal ausprobieren. Ich habe
gehofft, das jemand das Problem kennt.
@Kaj: Ich habe auch schon orakelt, dass es ein Dependency-Problem ist,
aber eigentlich sollte make solche Abhängigkeiten doch auflösen.
Also gut, dann eben Neustarten. Das geht immernoch schneller als
Singlethreaded.
Danke für Eure Hilfe!
Vancouver schrieb:> @Kaj: Ich habe auch schon orakelt, dass es ein Dependency-Problem ist,> aber eigentlich sollte make solche Abhängigkeiten doch auflösen.
Aber nur, wenn diese im Makefile auch angegeben sind, stelle dir
volgendes (ungetestetes) szenario vor:
1
all: a b
2
cat a b > all
3
a: c
4
cat c > a
5
b: c
6
cat a c > b
7
c:
8
echo test > c
In diesem Beispiel braucht b a, aber a ist nicht als dependency
angegeben. "make all -j1" wird zuerst a und dann b erstellen, aber "make
all -j2" wird es gleichzeitig versuchen, weil es von der Abhängigkeit,
die nicht richtig angegeben wurde, nichts weiss.
Daniel A. schrieb:> In diesem Beispiel braucht b a, aber a ist nicht als dependency> angegeben.Oliver S. schrieb:> Und eigentlich deutet sowas auf Fehler im makefile hin.
Qed
Oliver
> Und eigentlich deutet sowas auf Fehler im makefile hin.
Ich würde das nicht einen Fehler nennen. Die Abhängigkeit ist implizit
gegeben durch die Reihenfolge der Regeln im Makefile. Eigentlich wäre es
die Aufgabe vom make, die Regeln beim Multithreading so zu schedulen,
dass bei -jN das Gleiche herauskommt wie bei -j1, aber dazu müsste make
die Regeln tiefer analysieren, sonst wäre alles wieder sequenziell. Das
ist vermutlich viel zu aufwändig, schließlich ist make kein
parallelisierender Compiler.
Vancouver schrieb:> Die Abhängigkeit ist implizit> gegeben durch die Reihenfolge der Regeln im Makefile. Eigentlich wäre es> die Aufgabe vom make, die Regeln beim Multithreading so zu schedulen,> dass bei -jN das Gleiche herauskommt wie bei -j1,
Wie soll das denn gehen?
Er muß ja dann die Reihenfolge einhalten, und damit geht nichts mehr
parallel...
Nein, patrallele Builds (das ist doch eher Multi-Processing als
Multi-Threading, oder?) gehen nur problemlos mit komplett sauberen
Abhängigkeiten. Ansonsten muß man halt restarten...
Bernhard M. schrieb:> Er muß ja dann die Reihenfolge einhalten, und damit geht nichts mehr> parallel...
Das nicht, aber er muss die Abhängigkeiten selbst analysieren um
herauszufinden, was parallel machbar ist. Parallelisierende Compiler tun
genau das, aber make nicht, deswegen muss der Anwender die
Abhängigkeiten explizit angeben.
>(das ist doch eher Multi-Processing als Multi-Threading, oder?)
Ja, richtig.
Kaj schrieb:> Das Problem ist, dass schon ein Modul gebaut werden soll, wofuer die> abhaengigkeit vielleicht noch gar nicht gebaut ist.>> Das kann bei -j1 nicht passieren.
Ja, genau so ist es.
Vancouver schrieb:>> Und eigentlich deutet sowas auf Fehler im makefile hin.>> Ich würde das nicht einen Fehler nennen. Die Abhängigkeit ist implizit> gegeben durch die Reihenfolge der Regeln im Makefile.
Nein. Der ganze Sinn hinter einem Makefile ist, dass man ihm die
Abhängigkeiten explizit nennt. Die Reihenfolge der Regeln ist dabei
völlig egal.
> Eigentlich wäre es die Aufgabe vom make, die Regeln beim Multithreading> so zu schedulen, dass bei -jN das Gleiche herauskommt wie bei -j1, aber> dazu müsste make die Regeln tiefer analysieren, sonst wäre alles wieder> sequenziell.
Nein, die Regeln müssen korrekt angegeben sein. Wie soll make durch
"tieferes Analysieren" der Regeln wissen, was wovon abhängig ist? Genau
damit make das weiß, gibt man die Abhängigkeiten doch an.
> Das ist vermutlich viel zu aufwändig, schließlich ist make kein> parallelisierender Compiler.
Make kümmert sich vor allem nicht darum, was da überhaupt erzeugt wird.
Man sagt ihm nur: "Ich will eine Datei x haben. Die wird von Kommando k
erzeugt, und dafür muss Datei y schon vorhanden sein". Und das kann man
dann wiederum rekursiv machen, um z.B. wiederum Datei y zu erzeugen,
wenn dafür eine Regel vorhanden ist.
Ob k jetzt ein C-Compiler oder ein xslt-Konverter oder ein mp3-Encoder
ist und wie der Erzeugungsvorgang funktioniert, ist make dabei völlig
wurscht. Dementsprechend kann es da auch nix analysieren, um auf
magische Weise die Abhängigkeiten zu finden.
Vancouver schrieb:>>(das ist doch eher Multi-Processing als Multi-Threading, oder?)>> Ja, richtig.
Es ist ein "parallel build". Make führt einfach mehrere Regeln
gleichzeitig aus, wenn die nicht von einander abhängen.
Übrigens wirken sich solche fehlenden Abhängigkeiten nicht nur beim
parallelen Bauen aus, sondern auch, wenn man was am Code ändert. Dann
werden ggf. Teile nicht gebaut, weil make nicht weiß, dass die von der
geänderten Datei abhängig sind.
Rolf M. schrieb:> Nein. Der ganze Sinn hinter einem Makefile ist, dass man ihm die> Abhängigkeiten explizit nennt. Die Reihenfolge der Regeln ist dabei> völlig egal.
Unabhängige Regeln werden bei -j1 in der Reihenfolge abgearbeitet, wie
sie im Makefile stehen, richtig? Damit werden implizit Abhängigkeiten
aufgelöst, wie im cat-Beispiel oben. Das ist nicht schön, aber erlaubt
und es funktioniert zuverlässig bei Single-processing.
> Wie soll make durch "tieferes Analysieren" der Regeln wissen, was wovon
abhängig ist?
make könnte sich diese Regel anschauen:
b: c
cat a c > b
und erkennen, dass neben der expliziten Abhängigkeit von c
offensichtlich auch noch a verwendet wird. make selbst kann übrigens
selbst Dependencies erkennen, wenn man es ihm sagt, siehe
http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
Oder viel einfacher, wenn eine Regel wegen einer fehlenden Abhängigkeit
einen Fehler liefert, könnte man sie zu einem späteren Zeitpunkt
wiederholen. Genau das tue ich, wenn ich einen abgebrochen make-Lauf neu
starte. Erst wenn am Schluss noch Regeln übrigbleiben, die nicht
bearbeitet werden können, gibt es wirklich einen Fehler. Auf diese Weise
gehen viele andere Build-Tools vor, z.B. für FPGA-Synthese, die die
gesamte Dependency-Analyse selbst duchführen.
Mir ist (jetzt) schon klar, dass make explizite Abhängigkeiten braucht,
um immer korrekt zu funktionieren. Aber leider ist das bei vielen großen
Projekten nicht der Fall (Kernel, GNURadio, um nur zwei zu nennen), und
ich verspüre relativ wenig Lust, hunderte verschachtelte Makefiles zu
durchforsten.
Vancouver schrieb:> Das ist nicht schön, aber erlaubt> und es funktioniert zuverlässig bei Single-processing.
und geht bei Multithreading halt in die Hose.
Ist wie mit jedem Stück Software: nur, weil es unter ganz bestimmten
Randbedingungen den Anschein hat, daß es tut, was es soll, ist es noch
lange nicht fehlerfrei.
Oliver
Vancouver schrieb:> make könnte sich diese Regel anschauen:>> b: c> cat a c > b>> und erkennen, dass neben der expliziten Abhängigkeit von c> offensichtlich auch noch a verwendet wird.
Das ist einfach unrealistisch. Make würde dafür wissen müssen, was der
Befehl tut. Wäre da z.B. echo stat cat, brauchte man weder a noch c.
Make kann unmöglich jedes Kommando kennen.
Vancouver schrieb:> make selbst kann übrigens> selbst Dependencies erkennen, wenn man es ihm sagt, siehe> http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
Die methode scheint mir eher alles komplizierter zu machen.
Vancouver schrieb:> Oder viel einfacher, wenn eine Regel wegen einer fehlenden Abhängigkeit> einen Fehler liefert, könnte man sie zu einem späteren Zeitpunkt> wiederholen.
Dazu müsste aber make von jeder Anwendung jede Fehlermeldung kennen, was
nicht möglich ist, oder die Dateizugriffs syscalls abfangen, und einer
Abhängigkeit zuordnen, was auch nicht möglich ist.
Daniel A. schrieb:> Die methode scheint mir eher alles komplizierter zu machen.
Ist sie auch, das gibt die absolut kryptischen makefiles. Aber sie
funktioniert.
> Dazu müsste aber make von jeder Anwendung jede Fehlermeldung kennen, was
Nein, wenn eine Regel irgendeinen Fehler liefert, wird sie später
wiederholt. Wenn der Fehler nicht durch eine Dependency ausgelöst wurde,
wird er dann wieder auftreten.
Aber das wird jetzt alles sehr hypothetisch. Lassen wir make so wie es
ist.
Schönes Wochenende :-)
Vancouver schrieb:> Das> Problem tritt bei allen Versionen und Backends des gcc auf, die ich> bisher verwendet habe.
Das hat nichts mit dem GCC/Compiler ansich zutun.
Wo kommen die Makefiles her? Die sind offensichtlich nicht richtig
konfiguriert.
Vancouver schrieb:>> Dazu müsste aber make von jeder Anwendung jede Fehlermeldung kennen, was> Nein, wenn eine Regel irgendeinen Fehler liefert, wird sie später> wiederholt.
Make wiederholt nichts.
Rene H. schrieb:> Weshalb nimmst Du nicht cmake? Das baut Dir ein funktionierendes> makefile mit allem drum und dran.
Weil cmake auch kein Selbstläufer ist und falsche nicht eingetragenen
Abhängigkeiten (falsche Konfigurationen) führen auch hier zu Fehlern.
;-)
Daniel A. schrieb:> Vancouver schrieb:>> make selbst kann übrigens>> selbst Dependencies erkennen, wenn man es ihm sagt, siehe>> http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/> Die methode scheint mir eher alles komplizierter zu machen.
Die Dependencies macht make da auch nicht. Das sind nur "clever"
geschriebene Regeln, die bspw. auf sed oder gcc -M basieren, und so
Dependencies "automatisch" erstellen.
Bspw. durch Durchsuchen der C Files nach #includes, Schreiben einer
neuen Datei mit den gefundenen Abhängigkeiten; und diese Datei wird
wiederum vom Makefile geladen. Funktioniert. :-)
Das hat aber nix mit speziellen Fähigkeiten von make zu tun, wie
@Vancouver behauptet. Wie auch? Make ist einfach nur ein Regelwerk das
nichts von C oder welcher Sprache auch immer weiß.
Kann es eventuell sein daß das verwendete Dateisystem eine von einem
Prozess neu erzeugte Datei für einem anderen Prozess erst mit etwas
Verzögerung sichtbar werden lässt? Vielleicht kann man irgendwelche
Speicherbarrieren in den mount options abschalten um es performanter zu
machen, vielleicht ist das der Fall?
Vancouver schrieb:> Unabhängige Regeln werden bei -j1 in der Reihenfolge abgearbeitet, wie> sie im Makefile stehen, richtig?
Nein. Sie werden in der Reihenfolge ausgeführt, in der sie benötigt
werden. Die Reihenfolge im Makefile spielt wie schon gesagt keine Rolle.
Ein Makefile definiert keinen Sequenziellen Ablauf, auch nicht bei
-j1.
Beispiel:
1
a: b c
2
3
b: d
4
5
c:
6
@echo "c"
7
8
d:
9
@echo "d"
c und d sind nicht von einander abhängig. Die Ausgabe ist aber:
1
d
2
c
>> Wie soll make durch "tieferes Analysieren" der Regeln wissen, was wovon> abhängig ist?>> make könnte sich diese Regel anschauen:>> b: c> cat a c > b>> und erkennen, dass neben der expliziten Abhängigkeit von c> offensichtlich auch noch a verwendet wird.
Dazu müßte es wissen, dass an dieser Stelle a ein Dateiname sein soll.
Das heißt, es müsste wissen, was die Kommandozeilenparameter von cat
bedeuten. Anderes sehr änliches Beispiel:
1
b: c
2
grep a c > b
hier ist a keine Datei, sondern das Pattern, nach dem mit grep gesucht
werden soll. Also müßte make auch grep kennen. Als nächstes kommt dann:
1
b: c
2
meintollestool a c > b
Und jetzt? Was ist a?
> Oder viel einfacher, wenn eine Regel wegen einer fehlenden Abhängigkeit> einen Fehler liefert, könnte man sie zu einem späteren Zeitpunkt> wiederholen.
Das ist Murks.
> Mir ist (jetzt) schon klar, dass make explizite Abhängigkeiten braucht,> um immer korrekt zu funktionieren. Aber leider ist das bei vielen großen> Projekten nicht der Fall (Kernel, GNURadio, um nur zwei zu nennen), und> ich verspüre relativ wenig Lust, hunderte verschachtelte Makefiles zu> durchforsten.
Natürlich nicht. Aber es ist dennoch kein Fehler in make, sondern einer
in den Makefiles des Projekts.
Rene H. schrieb:> Weshalb nimmst Du nicht cmake? Das baut Dir ein funktionierendes> makefile mit allem drum und dran.
Und dann lässt du cmake am besten noch ein ninja file generieren statt
make (-GNinja), dann ist make ganz raus und alles ein gutes Stück
schneller ;)