Ich hatte kürzlich Grund, mit einigen Visual Studio C ++ - Projekten mit den üblichen Debug- und Release-Konfigurationen zu arbeiten, aber auch mit 'Release All' und 'Debug All', die ich noch nie zuvor gesehen hatte.
Es stellt sich heraus, dass der Autor der Projekte eine einzige ALL.cpp hat, die alle anderen .cpp-Dateien enthält. Die * Alle Konfigurationen erstellen nur diese eine ALL.cpp-Datei. Es ist natürlich von den regulären Konfigurationen ausgeschlossen, und reguläre Konfigurationen erstellen nicht ALL.cpp
Ich habe mich nur gefragt, ob dies eine gängige Praxis ist. Welche Vorteile bringt es? (Meine erste Reaktion war, dass es schlecht roch.)
Auf welche Fallstricke werden Sie wahrscheinlich stoßen? Eine, an die ich denken kann, ist, wenn Sie anonyme Namespaces in Ihren .cpps haben, diese für diese cpp nicht mehr "privat" sind, sondern jetzt auch in anderen cpps sichtbar sind?
Alle Projekte erstellen DLLs, daher wäre es keine gute Idee, Daten in anonymen Namespaces zu haben, oder? Aber Funktionen wären OK?
Prost.
quelle
Antworten:
Es wird von einigen (und Google-fähigen) als "Unity Build" bezeichnet. Es verbindet sich wahnsinnig schnell und kompiliert auch ziemlich schnell. Es eignet sich hervorragend für Builds, auf denen Sie nicht iterieren müssen, wie z. B. ein Release-Build von einem zentralen Server, aber nicht unbedingt für inkrementelle Builds.
Und es ist eine PITA zu pflegen.
BEARBEITEN: Hier ist der erste Google-Link für weitere Informationen: http://buffered.io/posts/the-magic-of-unity-builds/
Das macht es schnell, dass der Compiler alles nur einmal einlesen, kompilieren und dann verknüpfen muss, anstatt dies für jede CPP-Datei zu tun.
Bruce Dawson hat dies in seinem Blog viel besser beschrieben: http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/
quelle
Unity erstellt aus drei Hauptgründen verbesserte Build-Geschwindigkeiten. Der erste Grund ist, dass alle freigegebenen Header-Dateien nur einmal analysiert werden müssen. Viele C ++ - Projekte enthalten viele Header-Dateien, die in den meisten oder allen CPP-Dateien enthalten sind, und das redundante Parsen dieser Dateien ist der Hauptaufwand für die Kompilierung, insbesondere wenn Sie viele kurze Quelldateien haben. Vorkompilierte Header-Dateien können bei diesen Kosten helfen, aber normalerweise gibt es viele Header-Dateien, die nicht vorkompiliert sind.
Der nächste Hauptgrund dafür, dass Unity-Builds die Build-Geschwindigkeit verbessern, liegt darin, dass der Compiler weniger oft aufgerufen wird. Das Aufrufen des Compilers verursacht einige Startkosten.
Schließlich bedeutet die Reduzierung der redundanten Header-Analyse eine Reduzierung des redundanten Code-Gens für Inline-Funktionen, sodass die Gesamtgröße der Objektdateien kleiner ist, was die Verknüpfung beschleunigt.
Unity-Builds können auch zu einem besseren Code-Gen führen.
Unity-Builds sind aufgrund reduzierter Festplatten-E / A NICHT schneller. Ich habe viele Builds mit xperf profiliert und weiß, wovon ich spreche. Wenn Sie über ausreichend Speicher verfügen, vermeidet der Betriebssystem-Festplatten-Cache die redundante E / A - nachfolgende Lesevorgänge eines Headers werden aus dem Betriebssystem-Festplatten-Cache gesendet. Wenn Sie nicht über genügend Speicher verfügen, können Unity-Builds die Build-Zeiten sogar verschlechtern, da der Speicherbedarf des Compilers den verfügbaren Speicher überschreitet und ausgelagert wird.
Festplatten-E / A sind teuer, weshalb alle Betriebssysteme Daten aggressiv zwischenspeichern, um redundante Festplatten-E / A zu vermeiden.
quelle
Ich frage mich, ob ALL.cpp versucht, das gesamte Projekt in einer einzigen Kompilierungseinheit zusammenzufassen, um die Fähigkeit des Compilers zu verbessern, das Programm auf Größe zu optimieren.
Normalerweise werden einige Optimierungen nur innerhalb bestimmter Kompilierungseinheiten durchgeführt, z. B. Entfernen von doppeltem Code und Inlining.
Trotzdem scheine ich mich daran zu erinnern, dass neuere Compiler (Microsoft, Intel, aber ich glaube nicht, dass dies GCC einschließt) diese Optimierung über mehrere Kompilierungseinheiten hinweg durchführen können, daher vermute ich, dass dieser "Trick" nicht notwendig ist.
Trotzdem wäre es neugierig zu sehen, ob es tatsächlich einen Unterschied gibt.
quelle
Ich stimme Bruce zu; Aus meiner Erfahrung heraus hatte ich versucht, den Unity Build für eines meiner DLL-Projekte zu implementieren, das eine Menge Header-Includes und viele CPPs enthielt. Um die Gesamtkompilierungszeit auf dem VS2010 zu verkürzen (hatte die inkrementellen Build-Optionen bereits ausgeschöpft), aber anstatt die Kompilierungszeit zu verkürzen, ging mir der Speicher aus und der Build konnte die Kompilierung nicht einmal beenden.
Jedoch hinzuzufügen; Ich habe festgestellt, dass das Aktivieren der Kompilierungsoption für mehrere Prozessoren in Visual Studio sehr hilfreich ist, um die Kompilierungszeit zu verkürzen. Ich bin nicht sicher, ob eine solche Option für andere Plattform-Compiler verfügbar ist.
quelle
Zusätzlich zu Bruce Dawsons hervorragender Antwort bietet der folgende Link weitere Einblicke in die Vor- und Nachteile von Unity Builds - https://github.com/onqtam/ucm#unity-builds
quelle
Wir haben ein Multi-Plattform-Projekt für MacOS und Windows. Wir haben viele große Vorlagen und viele Header. Wir haben die Erstellungszeit mit Visual Studio 2017 msvc mithilfe vorkompilierter Header halbiert. Für MacOS haben wir mehrere Tage versucht, die Erstellungszeit zu reduzieren, aber vorkompilierte Header haben die Erstellungszeit nur auf 85% reduziert. Die Verwendung einer einzelnen CPP-Datei war der Durchbruch. Wir erstellen diese ALL.cpp einfach mit einem Skript. Unsere ALL.cpp enthält eine Liste der Includes aller .cpp-Dateien unseres Projekts. Mit XCode 9.0 reduzieren wir die Bauzeit auf 30%. Der einzige Nachteil war, dass wir allen privaten Namespaces für unbenannte Kompilierungseinheiten in .cpp-Files Namen geben mussten. Andernfalls kollidieren die lokalen Namen.
quelle