HOWTO · C++
C++-Include-Pfade: Header-Suche konfigurieren
Erfahren Sie, wie C++-Include-Pfade dem Compiler helfen, Header zu finden, und konfigurieren Sie die Header-Verzeichnisse Ihres Projekts mit Compiler-Flags, IDE-Einstellungen oder einem Makefile.
Auf dieser Seite
Ein Include-Pfad ist ein Verzeichnis, das ein C++-Compiler bei der Auflösung eines Headers berücksichtigt, der in einer #include-Anweisung genannt wird. Fügen Sie das Header-Verzeichnis Ihres Projekts zur Build-Konfiguration hinzu, wenn eine Quelldatei einen Header einbindet, der sich nicht an einem Ort befindet, den der Compiler bereits durchsucht. Die Anweisung gehört in den Quellcode; der Include-Pfad gehört in die Compiler- oder Build-Einstellungen.
Was ist ein C++-Include-Pfad?
Ein Projekt kann Deklarationen in einem Header-Verzeichnis und die Implementierung in Quelldateien halten. Im Bash-Beispiel unten enthält das temporäre Projektverzeichnis diese Struktur: tmp_dir/ → include/message.h und src/main.cpp.
Wenn main.cpp die Anweisung #include <message.h> enthält, muss der Compiler wissen, dass include/ ein Suchverzeichnis ist. Ein Include-Pfad ist keine Kopie des Headers und verändert dessen Inhalt nicht; er teilt dem Compiler mit, wo er bei der Verarbeitung der Einbindung suchen darf. System- und Toolchain-Header werden ebenfalls über Orte gefunden, die der Compiler und die Build-Umgebung konfigurieren.
C++-Include-Pfade konfigurieren
Wählen Sie die Einstellung, die zu Ihrem Build gehört. Halten Sie das Header-Verzeichnis und seinen Pfad in lokalen Builds, IDE-Konfigurationen und Automatisierung konsistent.
Compiler-Flags
Bei GCC oder einem kompatiblen Compiler fügt -I ein Verzeichnis zur Header-Suchkonfiguration hinzu. Dieses in sich abgeschlossene Bash-Beispiel erstellt ein kleines Projekt in einem temporären Verzeichnis, sodass Sie es aus jedem Arbeitsverzeichnis ausführen können.
tmp_dir=$(mktemp -d)
trap 'rm -rf "$tmp_dir"' EXIT
mkdir -p "$tmp_dir/include" "$tmp_dir/src"
cat > "$tmp_dir/include/message.h" <<'HEADER'
#pragma once
#define MESSAGE "Hello from the project header"
HEADER
cat > "$tmp_dir/src/main.cpp" <<'SOURCE'
#include <iostream>
#include <message.h>
int main() {
std::cout << MESSAGE << '\n';
}
SOURCE
g++ -I"$tmp_dir/include" "$tmp_dir/src/main.cpp" -o "$tmp_dir/app"
"$tmp_dir/app"
Hello from the project header
Die Option -I nimmt das Verzeichnis, das den Header enthält, nicht den Dateinamen des Headers. Hier erhält der Compiler src/main.cpp und schreibt die ausführbare Datei mit -o in das temporäre Verzeichnis. Verwenden Sie bei Microsoft C++ (cl) stattdessen /I gefolgt vom Verzeichnis; die Flag-Syntax hängt vom Compiler ab.
IDE-Projekteinstellungen
Fügen Sie in Visual Studio das Header-Verzeichnis zur Projekteinstellung Additional Include Directories unter den C/C++-Include-Optionen hinzu. Die genauen Bezeichnungen der Eigenschaftsseiten können je nach Visual-Studio-Version und Projekttyp variieren. Wenden Sie die Einstellung auf die Konfiguration und Plattform an, die Sie erstellen, etwa Debug und x64, und verwenden Sie die Verzeichnisvariablen des Projekts, wenn sie helfen, Pfade portierbar zu halten. Andere IDEs bieten gleichwertige Include-Verzeichnis-Einstellungen für Compiler oder Projekt; prüfen Sie, dass die aktive Build-Konfiguration sie verwendet.
Makefile
Tragen Sie das Compiler-Flag in die Compile-Flags des Makefiles ein, damit es jede Quellkompilierung erhält. Die relevante Einstellung kann zum Beispiel als CXXFLAGS += -Iinclude geschrieben werden; die Build-Regel sollte beim Kompilieren der Quelldateien $(CXXFLAGS) verwenden. Der gewählte Compiler bestimmt das Flag: Ein Makefile, das Microsoft cl aufruft, braucht stattdessen /Iinclude. Dies ist eine Syntaxillustration, kein vollständiges Makefile und kein ausgeführter Build.
Wie die C++-Header-Suche funktioniert
Die #include-Anweisung weist den Präprozessor an, einen benannten Header zu verarbeiten. Die berücksichtigten Orte hängen von der Form der Anweisung, der Datei, die sie enthält, den Compileroptionen und der Implementierung ab. Gehen Sie nicht davon aus, dass jeder Compiler eine universelle Liste in derselben Reihenfolge durchsucht oder automatisch die übergeordneten Verzeichnisse eines Projekts prüft.
Wenn ein Header nicht gefunden wird, prüfen Sie Schreibweise und Groß-/Kleinschreibung und bestätigen Sie dann, dass das konfigurierte Verzeichnis dasjenige ist, das die Datei enthält. Stellen Sie sicher, dass das Flag oder die IDE-Eigenschaft den Compileraufruf für die Konfiguration erreicht, die Sie erstellen. Wenn der Header aus einem anderen Header eingebunden wird, berücksichtigen Sie den Ort der einbindenden Datei und die dokumentierten Regeln des Compilers. Ein ausführlicher Build oder eine Compileroption, die Suchpfade ausgibt, kann zeigen, welche Konfiguration aktiv ist; der verfügbare Diagnosbefehl variiert je nach Toolchain.
#include "..." vs #include <...>
Die Form mit Anführungszeichen, #include "message.h", durchsucht üblicherweise zuerst das Verzeichnis der einbindenden Datei und folgt dann den weiteren Suchregeln der Implementierung. Die Form mit spitzen Klammern, #include <message.h>, verwendet die konfigurierten Suchorte der Implementierung. Das genaue übrige Suchverhalten ist implementierungsdefiniert; konsultieren Sie daher Ihre Compilerdokumentation, wenn die Reihenfolge wichtig ist.
Diese Formen sind keine strengen Etiketten für „eigene" und „Standard"-Header. Ein Projektheader kann spitze Klammern verwenden, wenn sein Verzeichnis konfiguriert ist, wie im Beispiel oben; eine Form mit Anführungszeichen kann jeden Header benennen, der nach den Suchregeln der Implementierung erreichbar ist. Wählen Sie eine Form, die den Konventionen des Projekts entspricht, und bedenken Sie, dass die konfigurierten Pfade des Compilers weiterhin bestimmen, ob der Name aufgelöst wird.