Wie rufe ich das Clang-Format über einen CPP-Projektordner auf?

88

Gibt es eine Möglichkeit, so etwas wie clang-format --style=Webkiteinen gesamten cpp-Projektordner aufzurufen , anstatt ihn für jede Datei separat auszuführen?

Ich benutze clang-format.pyund vimmache das, aber ich gehe davon aus, dass es eine Möglichkeit gibt, dies einmal anzuwenden.

user3639557
quelle

Antworten:

47

Wie wäre es mit:

clang-format -i -style=WebKit *.cpp *.h

im Projektordner. Die Option -i macht es an Ort und Stelle (standardmäßig wird die formatierte Ausgabe in stdout geschrieben).

sbarzowski
quelle
1
oder wenn Sie eine Konfigurationsdatei verwenden und mehrere Dateitypen formatieren möchten: clang-format-3.6 -i -style=file *.cpp *.h *.hpp
mBardos
43
Leider wird dies nicht in Unterverzeichnisse zurückgeführt.
Antimon
4
Ja, * .cpp wird von der Shell erweitert. clang braucht nur eine Liste von Dateien. Erweiterte Optionen (wie rekursives Globbing) hängen von den Funktionen Ihrer Shell ab. Informationen zur Verwendung von **Konstrukten finden Sie unter unix.stackexchange.com/questions/49913/recursive-glob .
Sbarzowski
Was ist mit clang-tidy?
Aaron Franke
@AaronFranke Das *.cppGenerieren einer Liste von Dateien sollte funktionieren. Der clang-tidyBefehl ermöglicht die Übergabe mehrerer Dateien. `USAGE: clang-tidy [options] <source0> [... <sourceN>]` In der Praxis ist dies jedoch möglicherweise nicht der beste Weg. Clang-tidy führt eine viel tiefere Analyse durch, daher sind die Compiler-Flags für jede Datei usw. erforderlich. Wenn ich clang-tidy verwendete, hatte ich normalerweise eine "Kompilierungsdatenbank" - eine JSON-Datei mit den Befehlen für jede Datei und einem Skript, das ausgeführt wurde darüber. Es war vor ein paar Jahren, vielleicht gibt es jetzt einen besseren Weg.
Sbarzowski
88

Leider gibt es keine Möglichkeit, das Clang-Format rekursiv anzuwenden. *.cppstimmt nur mit Dateien im aktuellen Verzeichnis überein, nicht mit Unterverzeichnissen. Auch **/*funktioniert nicht.

Zum Glück gibt es eine Lösung: greift alle Dateinamen mit dem findBefehl und Rohr sie in zum Beispiel, wenn Sie alle formatieren möchten. .hUnd .cppDateien im Verzeichnis foo/bar/rekursiv, können Sie tun

find foo/bar/ -iname *.h -o -iname *.cpp | xargs clang-format -i

Weitere Informationen finden Sie hier .

Antimon
quelle
6
Nun, **/*.cppscheint in (einigermaßen moderner) Bash zu funktionieren. Möglicherweise müssen Sie shopt -s globstarvorher.
Sbarzowski
1
Wenn Sie CMake verwenden, zeigt Ihnen dieser Beitrag , wie Sie mit CMake GLOB_RECURSEalle .cppDateien finden und an diese übergeben können clang-format.
Phoenix
5
Die Kombination von findund xargssollte verwenden find ... -print0und xargs -0 ...sicherstellen, dass alle Arten von Dateinamen korrekt behandelt werden.
Alexander
4
Dieser Befehl schlägt fehl, wenn in pwd CPP- oder H-Dateien vorhanden sind. find foo/bar/ -iname '*.h' -o -iname '*.cpp' | xargs clang-format -iwird das Problem beheben.
Nyanpasu64
29

Erstellen Sie zuerst eine .clang-formatDatei, falls diese nicht vorhanden ist:

clang-format -style=WebKit -dump-config > .clang-format

Wählen Sie den gewünschten vordefinierten Stil oder bearbeiten Sie die resultierende .clang-formatDatei.

Der Konfigurator im Clang-Format ist hilfreich.

Dann renne:

find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \;

Andere Dateiendungen als cpp, hpp, ccund cxxkönnen im regulären Ausdruck verwendet werden, stellen Sie sicher , sie mit zu trennen \|.

Alexander
quelle
Gibt -style=filees eine Möglichkeit, einen benutzerdefinierten Dateipfad anzugeben? Ich habe es versucht -style=~/.clang-formatund es funktioniert nicht.
Aaron Franke
Nicht das ich wüsste, abgesehen vom Ändern des aktuellen Verzeichnisses.
Alexander
Die Ghetto-Lösung, die ich mir ausgedacht habe, besteht darin, eine Funktion zu erstellen, die zuerst cp ~/.clang-format .den Befehl find in Ihrer Antwort ausführt.
Aaron Franke
12

Ich habe kürzlich ein Bash-Skript gefunden, das genau das tut, was Sie brauchen:

https://github.com/eklitzke/clang-format-all

Dies ist ein Bash-Skript, das clang-format -iauf Ihrem Code ausgeführt wird.

Eigenschaften:

  • Findet den richtigen Pfad zu clang-formatUbuntu / Debian, das die LLVM-Version im clang-formatDateinamen codiert
  • Behebt Dateien rekursiv
  • Erkennt die am häufigsten von C / C ++ - Projekten verwendeten Dateierweiterungen

Unter Windows habe ich es erfolgreich in Git Bash und WSL verwendet.

Julius Bullinger
quelle
3

Für Windows-Benutzer: Wenn Sie Powershell 3.0 unterstützen, können Sie Folgendes tun:

Get-ChildItem -Path . -Directory -Recurse |
    foreach {
        cd $_.FullName
        &clang-format -i -style=WebKit *.cpp
    }

Hinweis 1: Verwenden Sie pushd .und, popdwenn Sie vor und nach dem Skript dasselbe aktuelle Verzeichnis haben möchten

Hinweis 2: Das Skript wird im aktuellen Arbeitsverzeichnis ausgeführt

Hinweis 3: Dies kann wahrscheinlich in einer einzigen Zeile geschrieben werden, wenn Ihnen das wirklich wichtig war

Tim Meyer
quelle
0

Ich verwende den folgenden Befehl, um alle Objective-C-Dateien unter dem aktuellen Ordner rekursiv zu formatieren :

$ find . -name "*.m" -o -name "*.h" | sed 's| |\\ |g' | xargs clang-format -i

Ich habe den folgenden Alias ​​in meinem definiert .bash_profile, um die Sache zu vereinfachen:

# Format objC files (*.h and *.m) under the current folder, recursively
alias clang-format-all="find . -name \"*.m\" -o -name \"*.h\" | sed 's| |\\ |g' | xargs clang-format -i"
marcelosalloum
quelle
0

Hier ist eine Lösung, die rekursiv sucht und alle Dateien in einem Befehl als Dateiliste in das Clang-Format weiterleitet. Es schließt auch das "build" -Verzeichnis aus (ich verwende CMake), aber Sie können einfach den "grep" -Schritt weglassen, um das zu entfernen.

shopt -s globstar extglob failglob && ls **/*.@(h|hpp|hxx|c|cpp|cxx) | grep -v build | tr '\n' ' ' | xargs clang-format -i
Bim
quelle
0

In der modernen Bash können Sie den Dateibaum rekursiv crawlen

for file_name in ./src/**/*.{cpp,h,hpp}; do
    if [ -f "$file_name" ]; then
        printf '%s\n' "$file_name"
        clang-format -i $file_name
    fi
done

Hier wird angenommen, dass sich die Quelle in befindet ./srcund .clang-formatdie Formatierungsinformationen enthält.

Mikhail
quelle
Ich glaube nicht, dass Globstar in Bash standardmäßig aktiviert ist, also müssten Sie es einstellen.
Eric Backus