Ich finde oft, dass die Kopfzeilen einer Datei immer größer werden, aber niemals kleiner. Während der gesamten Lebensdauer einer Quelldatei konnten Klassen verschoben und umgestaltet werden, und es ist sehr wahrscheinlich, dass es einige #includes
gibt, die nicht mehr vorhanden sein müssen. Wenn Sie sie dort belassen, verlängert dies nur die Kompilierzeit und fügt unnötige Abhängigkeiten beim Kompilieren hinzu. Der Versuch herauszufinden, welche noch benötigt werden, kann recht mühsam sein.
Gibt es ein Werkzeug, das überflüssige # include-Direktiven erkennt und vorschlägt, welche ich sicher entfernen kann?
Macht Flusen das vielleicht?
Es ist nicht automatisch, aber doxygen erzeugt Abhängigkeitsdiagramme für #included
-Dateien. Sie müssen sie visuell durchgehen, aber sie können sehr nützlich sein, um ein Bild davon zu erhalten, was mit was verwendet wird.
Googles cppclean (Links zu: download , documentation ) kann verschiedene Kategorien von C++ - Problemen finden und kann nun überflüssige # -Inhalte enthalten.
Es gibt auch ein Clang-basiertes Werkzeug, include-what-you-use , das dies tun kann. include-what-you-use kann sogar Vorwärtsdeklarationen vorschlagen (so dass Sie nicht so viel # enthalten müssen) und optional Ihre # -Inhalte für Sie bereinigen.
Aktuelle Versionen von Eclipse CDT haben auch diese Funktion eingebaut: Wenn Sie im Source-Menü auf Organize Includes klicken, werden Ihre # include's alphabetisch sortiert, fügen Sie alle Header hinzu, die Eclipse verwendet, ohne sie direkt einzubinden, und kommentieren Sie diese aus Header, die es nicht für nötig hält. Diese Funktion ist jedoch nicht zu 100% zuverlässig.
Check out include-what-you-use , was ein ähnliches Problem löst.
Das Problem beim Erkennen überflüssiger Include-Elemente ist, dass es sich nicht nur um eine Typabhängigkeitsprüfung handeln kann. Ein überflüssiges Include ist eine Datei, die der Kompilierung nichts Wertvolles verleiht. und ändert nichts an einem anderen Element, von dem andere Dateien abhängen. Es gibt viele Möglichkeiten, wie eine Header-Datei eine Kompilierung ändern kann, z. B. durch Definieren einer Konstante, Neudefinieren und/oder Löschen eines verwendeten Makros, wobei ein Namespace hinzugefügt wird, der die Suche nach einem Namen entlang der Zeile ändert. Um Elemente wie den Namespace zu erkennen, benötigen Sie weit mehr als einen Präprozessor. Sie benötigen fast einen vollständigen Compiler.
Lint ist eher ein Stilprüfer und wird sicherlich nicht die volle Leistungsfähigkeit haben.
Ich denke, der einzige Weg, ein überflüssiges Include zu erkennen, besteht darin, Suites zu entfernen, zu kompilieren und auszuführen.
Ich dachte, dass PCLint dies tun würde, aber es ist einige Jahre her, seit ich es angeschaut habe. Sie könnten es überprüfen.
Ich schaute in dieses Blog und der Autor sprach ein wenig über die Konfiguration von PCLint, um ungenutzte Includes zu finden. Vielleicht einen Blick wert.
Sie können ein schnelles Skript schreiben, das eine einzelne # include-Direktive löscht, die Projekte kompiliert und den Namen in # include und die Datei protokolliert, aus der sie entfernt wurde, falls keine Kompilierungsfehler aufgetreten sind.
Lassen Sie es während der Nacht laufen, und am nächsten Tag haben Sie eine 100% korrekte Liste der Include-Dateien, die Sie entfernen können.
Manchmal funktioniert Brute-Force einfach :-)
edit: und manchmal auch nicht :-). Hier ein paar Informationen aus den Kommentaren:
Ich habe noch nie ein vollwertiges Werkzeug gefunden, mit dem Sie erreichen können, was Sie fragen. Das, was ich am häufigsten verwendet habe, ist IncludeManager , das den Header-Einschlussbaum grafisch darstellt, sodass Sie Dinge wie in nur einer Datei enthaltene Header und kreisförmige Header-Einschlüsse visuell erkennen können.
Es tut mir leid, hier (neu) posten zu müssen. Die Leute erweitern die Kommentare oft nicht.
Überprüfen Sie meinen Kommentar zu crashmstr, FlexeLint/PC-Lint erledigt dies für Sie. Informationsnachricht 766. In Abschnitt 11.8.1 meines Handbuchs (Version 8.0) wird dies erläutert.
Auch und das ist wichtig, iteriere weiter, bis die Nachricht verschwindet . Mit anderen Worten: Nach dem Entfernen unbenutzter Header und erneutem Ausführen von Flusen sind möglicherweise mehr Headerdateien "nicht mehr erforderlich", wenn Sie einige nicht benötigte Header entfernen. (Das hört sich vielleicht dumm an, liest es langsam und parst es, es macht Sinn.)
Wenn Sie Eclipse CDT verwenden, können Sie http://includator.com ausprobieren, das für Betatester (zum Zeitpunkt der Erstellung dieses Dokuments) kostenlos ist und automatisch überflüssige # enthält oder fehlende entfernt. Für Benutzer, die über FlexeLint oder PC-Lint verfügen und Elicpse CDT verwenden, könnte http://linticator.com eine Option sein (auch für Betatests kostenlos). Während die Analyse von Lint verwendet wird, werden schnelle Korrekturen zum automatischen Entfernen der überflüssigen # include-Anweisungen bereitgestellt.
Um diese Diskussion zu beenden, ist der C++ - Präprozessor fertig. Es ist eine semantische Eigenschaft, ob ein Include überflüssig ist. Aus dem Satz von Rice folgt daher, dass es unentscheidbar ist, ob ein Include überflüssig ist oder nicht. Es kann NICHT ein Programm geben, das (immer richtig) erkennt, ob ein Include überflüssig ist.
Es gibt ein kostenloses Tool Include File Dependencies Watcher , das in das Visual Studio integriert werden kann. Es zeigt überflüssiges # in rot an.
Dieser Artikel erläutert eine Technik zum Entfernen von #include mithilfe der Analyse von Doxygen. Das ist nur ein Perl-Skript, daher ist es sehr einfach zu benutzen.
Ich habe es mit Flexelint (der Unix-Version von PC-Lint) versucht und hatte etwas gemischte Ergebnisse. Dies liegt wahrscheinlich daran, dass ich an einer sehr großen und knotigen Codebasis arbeite. Ich empfehle, jede Datei, die als nicht verwendet gemeldet wird, sorgfältig zu prüfen.
Die Hauptsorge ist falsch positiv. Mehrere Includes desselben Headers werden als nicht benötigter Header gemeldet. Dies ist schlecht, da Flexelint Ihnen nicht sagt, in welcher Zeile der Header enthalten ist oder wo er zuvor eingefügt wurde.
Eine der Möglichkeiten, mit der automatisierte Tools das falsch machen können:
In A.hpp:
class A {
// ...
};
In B.hpp:
#include "A.hpp
class B {
public:
A foo;
};
In C. cpp:
#include "C.hpp"
#include "B.hpp" // <-- Unneeded, but lint reports it as needed
#include "A.hpp" // <-- Needed, but lint reports it as unneeded
Wenn Sie den Nachrichten von Flexelint blind folgen, werden Sie Ihre Abhängigkeiten mit #include aufmischen. Es gibt mehr pathologische Fälle, aber im Grunde müssen Sie die Header selbst überprüfen, um beste Ergebnisse zu erzielen.
Ich empfehle diesen Artikel zu Physical Structure und C++ aus den Blog-Spielen von innen. Sie empfehlen einen umfassenden Ansatz zur Beseitigung des Chaos von #include:
Richtlinien
Hier finden Sie eine Reihe von Richtlinien aus dem Buch von Lakos, die die Anzahl der physischen Abhängigkeiten zwischen Dateien minimieren. Ich benutze sie seit Jahren und war mit den Ergebnissen immer sehr zufrieden.
- Jede cpp-Datei enthält zuerst eine eigene Header-Datei. [schnippen]
- Eine Header-Datei muss alle Header-Dateien enthalten, die zum Analysieren erforderlich sind. [schnippen]
- Eine Header-Datei sollte über die minimale Anzahl von Header-Dateien verfügen, die zum Analysieren erforderlich sind. [schnippen]
Hier ist eine einfache brute force-Methode zum Identifizieren überflüssiger Header-Includes . Es ist nicht perfekt, eliminiert jedoch die "offensichtlichen" unnötigen Einschlüsse. Wenn Sie diese Informationen entfernen, können Sie den Code aufräumen.
Auf die scripts kann direkt über GitHub zugegriffen werden.
Vielleicht etwas spät, aber ich habe einmal ein WebKit-Perl-Skript gefunden, das genau das tat, was Sie wollten. Ich glaube, ich brauche ein paar Anpassungen (ich bin nicht mit Perl vertraut), aber es sollte den Trick tun:
(Dies ist ein alter Zweig, da Trunk die Datei nicht mehr besitzt.)
Es gibt zwei Arten von überflüssigen # include-Dateien:
Nach meiner Erfahrung gibt es zwei Möglichkeiten, die es gut erkennen können:
gcc -H oder cl.exe/showincludes (Problem 2 beheben)
In der Praxis können CFLAGS = -H vor make, Exportiert werden, wenn nicht alle Makefile-Optionen die CFLAGS-Optionen überschreiben. Oder, wie ich es verwendet habe, können Sie einen C++ - Wrapper erstellen, um die Optionen -H Zwangsweise zu jedem Aufruf von $ (CC) und $ (CXX) hinzuzufügen. und stellen Sie das Verzeichnis wrapper der Variablen $ PATH voran. Dann werden alle von Ihnen erstellt. Natürlich sollte Ihr Wrapper den Real gcc-Compiler aufrufen. Diese Tricks Müssen geändert werden, wenn Ihr Makefile Gcc direkt verwendet. anstelle von $ (CC) oder $ (CXX) oder durch implizierte Regeln.
Sie können eine einzelne Datei auch kompilieren, indem Sie die Befehlszeile verwenden. Aber wenn Sie die Header für das gesamte Projekt löschen möchten. Sie können alle Ausgaben erfassen, indem Sie:
mach sauber
mach 2> & 1 | tee result.txt
PC-Lint/FlexeLint (Problem 1 und 2 beheben.)
stellen Sie sicher, dass Sie die + e766-Optionen hinzufügen. Diese Warnung betrifft: ungenutzte Header-Dateien.
pclint/flint -vf ...
Dies führt dazu, dass die pclint-Ausgabe Header-Dateien enthält. Verschachtelte Header-Dateien werden entsprechend eingerückt.
CLion , das C/C++ IDE von JetBrains, erkennt redundante Include-of-the-Box. Diese sind im Editor ausgegraut, aber es gibt auch Funktionen für Optimierungen umfassen die aktuelle Datei oder das gesamte Projekt .
Ich habe jedoch festgestellt, dass Sie für diese Funktionalität bezahlen. CLion benötigt beim ersten Laden eine Weile, um Ihr Projekt zu scannen und zu analysieren.