Frage

Jede empfohlene Praktiken zur Reinigung „Kopfsalat“, die extrem verursacht langsam Kompilierungszeiten (Linux / Unix)?

Gibt es einen Vorbehalt, zu "#pragma once" mit GCC?
(Gefunden widersprüchliche Meldungen bezüglich dieser)

Danke.

War es hilfreich?

Lösung

Sie sind vertraut mit „umfassen Wachen“ Unter der Annahme (#ifdef am Anfang des Headers ..) eine zusätzliche Möglichkeit, um Zeit zu beschleunigen Build ist durch Verwendung von externer Schutztruppe geschaffen werden. Es wurde in „ Large Scale C ++ Software Design diskutiert “. Die Idee ist, dass klassische Wachen sind, im Gegensatz zu #pragma once, nicht verschonen Sie den Präprozessor Parsing auf den Header aus der zweiten Zeit zu ignorieren erforderlich (dh es hat immer noch und für den Beginn und das Ende der Wache gehören aussehen zu analysieren. Mit Außen umfassen Wachen Sie die # ifdef die rund um die # include-Linie selbst setzen.

So ist es wie folgt aussieht:

#ifndef MY_HEADER
#include "myheader.h"
#endif

und natürlich in der H-Datei haben Sie die klassischen umfassen Wache

#ifndef MY_HEADER
#define MY_HEADER

// content of header

#endif

Auf diese Weise der myheader.h Datei nicht einmal geöffnet / vom Präprozessor analysiert, und es kann Ihnen eine Menge Zeit in großen Projekten sparen, vor allem, wenn die Header-Dateien auf gemeinsam genutzten Remote-Standorten sitzen, wie sie manchmal tun.

wieder, es ist alles in diesem Buch. hth

Andere Tipps

Wenn Sie eine vollständige Bereinigung zu tun und die Zeit haben, es zu tun, dann ist die beste Lösung zu löschen ist, alle #includes in allen Dateien (mit Ausnahme von offensichtlichen zB abc.h in abc.cpp) und kompilieren das Projekt. Fügen Sie die erforderliche Vorwärtsdeklaration oder Kopf die ersten Fehler zu beheben und dann wiederholen, bis Sie sauber comple.

Dieses behebt nicht zugrunde liegenden Probleme, die in enthalten Probleme zur Folge haben kann, aber es ist sicher, dass die einzige enthält die erforderlichen diejenigen sind.

Ich habe gelesen, dass GCC veraltet hält #pragma once, obwohl sogar #pragma once nur so viel tun kann, um Dinge zu beschleunigen.

Um zu versuchen, die #include Spaghetti zu entwirren, können Sie sich in doxygen . Es sollte in der Lage sein, grafische Darstellungen des enthaltenen Header zu erzeugen, die Ihnen einen Vorteil über die Vereinfachung Dinge geben kann. Ich kann mich nicht daran erinnern, die Details Stegreif, aber die Diagrammfunktionen können Sie GraphViz installieren benötigen und sagen doxygen die Pfad, in dem es GraphViz die dotty.exe finden.

Ein weiterer Ansatz, den Sie betrachten könnte, wenn der Kompilierung ist das primäre Anliegen ist die Einrichtung vorkompilierte Header .

Ich las neulich über einen netten Trick-Header-Abhängigkeiten zu reduzieren: Schreiben Sie ein Skript, das wird

  • finden alle # include-Anweisungen
  • entfernen Sie eine Erklärung zu einem Zeitpunkt und Neukompilierungen
  • wenn Kompilierung fehlschlägt, fügen Sie die Include-Anweisung zurück in

Am Ende werden Sie hoffentlich mit einem Minimum an benötigten am Ende enthält in Ihrem Code. Sie könnten ein ähnliches Skript schreiben, das neu anordnet, um herauszufinden, enthält, wenn sie autark sind, oder erfordern andere Header, bevor sie aufgenommen werden (einschließlich der Header zuerst sehen, ob Kompilierung fehlschlägt, melden Sie es). Das sollte eine gewisse Art und Weise zu bereinigen Ihres Code gehen.

Einige weitere Hinweise:

  • Moderne Compiler (gcc unter ihnen) Kopfschutz erkennen und in der gleichen Art und Weise optimiert, wie Pragma einmal würde, nur die Datei einmal zu öffnen.
  • Pragma kann einmal problematisch sein, wenn die gleiche Datei unterschiedliche Namen im Dateisystem (das heißt mit Soft-Links)

  • hat
  • gcc unterstützt pragma einmal, sondern nennt es "veraltet"
  • Pragma einmal nicht von allen Compilern unterstützt wird und nicht Teil des C-Standard

  • nicht nur Compiler kann problematisch sein. Tools wie IncrediBuild auch Probleme mit #pragma haben einmal

Richard war etwas rechts (Warum seine Lösung wurde notiert?).

Wie auch immer, alle C / C ++ Header sollten interne verwenden Wache umfassen.

Dieser sagte, entweder:

1 - Ihr Legacy-Code nicht mehr wirklich eingehalten wird, und Sie sollten Header vorkompilierte verwenden (das ist ein Hack, aber hey ... Ihr Bedarf ist Ihre Zusammenstellung zu beschleunigen, nicht unmaintained Code Refactoring)

2 - Ihr Legacy-Code lebt noch. Dann wird entweder Sie die vorkompilierte Header verwenden und / oder die Wachen / externen Wachen für eine temporäre Lösung, aber am Ende werden Sie müssen alle entfernen Ihre enthält, ein .C oder CPP zu einem Zeitpunkt, und jeder kompilieren. C oder CPP einer nach dem anderen Datei, Korrektur ihrer mit zukunfts Erklärungen beinhaltet oder umfasst bei bedarf (oder sogar eine große umfassen in kleinere Bruch sicher sein jede .C oder CPP-Datei nur die Header bekommen es braucht). Wie auch immer, zu testen und zu entfernen veraltet ist Teil der Wartung eines Projektes enthält, so ...

Meine eigene Erfahrung mit vorkompilierte Header war nicht gerade ein guter, weil die Hälfte der Zeit, der Compiler ein Symbol nicht ich hatte definiert finden konnte, und so habe ich versucht, ein voll „sauber / rebuild“, um sicherzustellen, dass es nicht die vorkompilierte Header, der veraltet war. Also meine Vermutung ist es für externe Bibliotheken verwenden Sie nicht einmal berühren (wie die STL, C-API-Header, Boost, was auch immer). Trotzdem war meine eigene Erfahrung mit Visual C ++ 6, so dass ich denke, (Hoffnung?) Sie es richtig, jetzt.

Nun

, eine letzte Sache: Header sollte immer autark. Das bedeutet, dass, wenn die Aufnahme von Headern auf der Reihenfolge der Aufnahme abhängt, dann haben Sie ein Problem. Zum Beispiel, wenn Sie schreiben:

#include "AAA.hpp"
#include "BBB.hpp"

Aber nicht:

#include "BBB.hpp"
#include "AAA.hpp"

da BBB auf AAA abhängt, dann alles, was Sie haben, ist eine Abhängigkeit Sie nie im Code anerkannt. Nicht anerkannt es mit einem definieren wird nur Ihre compilation ein Alptraum. BBB sollte AAA gehören auch (auch wenn es etwas langsamer sein könnte: Am Ende, zukunfts Erklärungen ohnehin reinigen nutzlos enthält, so dass Sie ein schneller kompilieren Timer haben sollte).

Verwenden Sie eine oder mehr von denen, für die Build-Zeit beschleunigen

  1. Verwenden eines vorkompilierten Headers
  2. Verwenden Sie einen Caching-Mechanismus (scons zum Beispiel)
  3. Verwenden Sie eine verteilte Build-System (distcc, IncrediBuild ($))

In Header: include Header nur, wenn Sie nicht verwenden Erklärung nach vorn, aber # include immer jede Datei, die Sie benötigen (einschließlich Abhängigkeiten sind böse!)

.

Wie in der anderen Antwort erwähnt, sollten Sie auf jeden Fall Erklärungen verwenden vorwärts, wenn möglich. Mein Wissen hat GCC hat nichts gleichwertig einmal #PRAGMA, weshalb ich auf den alten Mode-Stil-Stick Wachen sind.

Danke für die Antworten, aber die Frage ist in Bezug auf vorhandenen Code, die „enthalten, um“ strenge enthält usw. Die Frage ist, ob es irgendwelche Tools / Skripte zu klären, was eigentlich los ist.

Rubrik Wachen Arent die Lösung, wie sie den Compiler aus der Lektüre der gesamten Datei wieder und wieder und ...

verhindern nicht,

PC-Lint wird ein langer Weg zu Reinigung Spaghetti-Header gehen. Auch wird es andere Probleme zu lösen, auch für Sie wie uninitialised Variablen gehen ungesehen, etc.

Als onebyone.livejournal.com in einer Antwort auf Ihre Frage kommentierte einige Compiler-Unterstützung umfassen Wache Optimierung , die die Seite, die ich definiert verknüpft wie folgt:

  

Die sind guard-Optimierung ist, wenn ein Compiler die interne umfassen guard Idiom oben beschrieben erkennt und unternimmt Schritte mehrere Male Öffnen der Datei zu vermeiden. Der Compiler kann in einer Datei enthalten aussieht, Streifen aus Kommentaren und Leerraum und arbeitet, wenn die Gesamtheit der Datei innerhalb der Include-Guard ist. Wenn es ist, speichert er die Dateinamen und umfasst Wachzustand in einer Karte. Das nächste Mal, wenn der Compiler aufgefordert, die Datei aufgenommen werden, kann es die Guard-Bedingung enthalten und die Entscheidung, ob die Datei überspringen oder # include, ohne die Datei zu öffnen.

Dann wieder, beantwortet Sie schon, dass externe umfassen Wachen nicht die Antwort auf Ihre Frage sind. Für die Header-Dateien zu entwirren, die in einer bestimmten Reihenfolge enthalten sein muss, würde ich schlage vor, die folgenden:

  • Jede .c oder .cpp Datei sollte die entsprechende Datei #include .h zuerst, und der Rest seiner #include Richtlinien sollten alphabetisch sortiert werden. Sie erhalten in der Regel Fehler bauen, wenn diese nicht genannten Abhängigkeiten zwischen den Header-Dateien bricht.
  • Wenn Sie eine Header-Datei, die für Grundtypen oder globale #define Richtlinien global typedefs definiert, die für die meisten des Codes verwendet werden, jede .h Datei zuerst die Datei #include sollte, und der Rest seiner #include Richtlinien sollte alphabetisch sortiert werden.
  • Wenn diese Änderungen zu Fehlern führen kompilieren, werden Sie in der Regel eine explizite Abhängigkeit von einer Header-Datei in eine andere, in Form eines #include haben hinzuzufügen.
  • Wenn diese Änderungen verursachen keine Fehler kompilieren, sie könnten Verhaltensänderungen führen. Hoffentlich haben Sie irgendeine Art von Test-Suite, die Sie verwenden können, um die Funktionalität der Anwendung zu überprüfen.

Es klingt auch wie ein Teil des Problems könnte sein, dass inkrementale Builds viel langsamer als sie sein sollten. Diese Situation kann mit Vorwärtsdeklarationen oder ein verteiltes Build-System verbessert werden, wie andere haben darauf hingewiesen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top