clang-uml
ist ein automatischer C++-zu-UML-Generator für Klassen, Sequenzen, Pakete und Include-Diagramme, der von YAML-Konfigurationsdateien gesteuert wird. Die Hauptidee des Projekts besteht darin, auf einfache Weise aktuelle Diagramme innerhalb einer Codebasis oder eines Dokument-Legacy-Codes zu verwalten. Die Konfigurationsdatei(en) für clang-uml
definieren die Typen und Inhalte jedes generierten Diagramms. Die Diagramme können in den Formaten PlantUML, MermaidJS und JSON generiert werden.
clang-uml
unterstützt derzeit C++ bis Version 20 sowie C und Objective-C.
Die vollständige Dokumentation finden Sie unter clang-uml.github.io.
Um zu sehen, was clang-uml
leisten kann, sehen Sie sich die hier für Unit-Testfälle generierten Diagramme oder Beispiele im clang-uml-examples-Repository an.
Zu den bisher unterstützten Hauptfunktionen gehören:
Eine umfassendere Dokumentation finden Sie unter clang-uml.github.io.
Installationsanleitungen für Linux
, macos
und Windows
finden Sie hier.
clang-uml
erfordert eine aktuelle Datei „compile_commands.json“, die die Liste der Befehle enthält, die zum Kompilieren des Quellcodes verwendet werden.
Hier finden Sie Anweisungen zum Generieren von compile_commands.json
mit einigen der vorhandenen C++-Buildsysteme.
Standardmäßig geht clang-uml
davon aus, dass sich die Konfigurationsdatei .clang-uml
und die Kompilierungsdatenbank compile_commands.json
im aktuellen Verzeichnis befinden. Wenn sie sich also im obersten Verzeichnis eines Projekts befinden, führen Sie einfach Folgendes aus:
clang-uml
Der Ausgabepfad für Diagramme sowie der alternative Speicherort der Kompilierungsdatenbank können in .clang-uml
Konfigurationsdatei oder über Befehlszeilenparameter angegeben werden.
Weitere Optionen finden Sie in der Hilfe:
clang-uml --help
Konfigurationsdateien werden in YAML geschrieben und bieten Definitionen von Diagrammen, die von clang-uml
generiert werden sollen. Das grundlegende Beispiel lautet wie folgt:
compilation_database_dir : .
output_directory : diagrams
diagrams :
myproject_class :
type : class
glob :
- src/*.cc
using_namespace : myproject
include :
namespaces :
- myproject
exclude :
namespaces :
- myproject::detail
plantuml :
after :
- ' note left of {{ alias("MyProjectMain") }}: Main class of myproject library. '
Hier finden Sie eine ausführliche Referenzanleitung zur Konfigurationsdatei.
Um zu sehen, was clang-uml
kann, durchsuchen Sie hier die Testfalldokumentation.
Um Diagramme für die clang-uml
selbst anzuzeigen, führen Sie basierend auf ihrer eigenen Konfiguration Folgendes aus:
make clanguml_diagrams
und öffnen Sie die SVG-Diagramme im Ordner docs/diagrams
.
Der folgende C++-Code:
template < typename T, typename P> struct A {
T t;
P p;
};
struct B {
std::string value;
};
template < typename T> using AString = A<T, std::string>;
template < typename T> using AStringPtr = A<T, std::unique_ptr<std::string>>;
template < typename T>
using PairPairBA = std::pair<std::pair<B, A< long , T>>, long >;
template < class T > using VectorPtr = std::unique_ptr<std::vector<T>>;
template < class T > using APtr = std::unique_ptr<A< double , T>>;
template < class T > using ASharedPtr = std::shared_ptr<A< double , T>>;
template < class T , class U >
using AAPtr = std::unique_ptr<std::pair<A< double , T>, A< long , U>>>;
template < typename T> using SimpleCallback = std::function< void (T, int )>;
template < typename ... T> using GenericCallback = std::function< void (T..., int )>;
using VoidCallback = GenericCallback< void *>;
using BVector = std::vector<B>;
using BVector2 = BVector;
using AIntString = AString< int >;
using ACharString = AString< char >;
using AStringString = AString<std::string>;
using BStringString = AStringString;
template < typename T> class R {
using AWCharString = AString< wchar_t >;
PairPairBA< bool > bapair;
APtr< bool > abool;
AAPtr< bool , float > aboolfloat;
ASharedPtr< float > afloat;
A< bool , std::string> boolstring;
AStringPtr< float > floatstring;
AIntString intstring;
AStringString stringstring;
BStringString bstringstring;
AAPtr<T, float > atfloat;
protected:
BVector bs;
public:
BVector2 bs2;
SimpleCallback<ACharString> cb;
GenericCallback<AWCharString> gcb;
VoidCallback vcb;
VectorPtr<B> vps;
};
ergibt das folgende Diagramm (über PlantUML):
Öffnen Sie hier das Rohbild und sehen Sie sich die Hover-Tooltips und Hyperlinks zu Klassen und Methoden an.
Der folgende C++-Code:
# include < atomic >
# include < functional >
# include < iostream >
# include < memory >
# include < string >
namespace clanguml {
namespace t20029 {
std::string encode_b64 (std::string &&content) { return std::move (content); }
template < typename T> class Encoder : public T {
public:
bool send (std::string &&msg)
{
return T::send ( std::move (
// Encode the message using Base64 encoding and pass it to the next
// layer
encode ( std::move (msg))));
}
protected:
std::string encode (std::string &&msg) { return encode_b64 ( std::move (msg)); }
};
template < typename T> class Retrier : public T {
public:
bool send (std::string &&msg)
{
std::string buffer{ std::move (msg)};
int retryCount = 5 ;
// Repeat until send() succeeds or retry count is exceeded
while (retryCount--) {
if ( T::send (buffer))
return true ;
}
return false ;
}
};
class ConnectionPool {
public:
void connect ()
{
if (!is_connected_. load ())
connect_impl ();
}
bool send ( const std::string &msg) { return true ; }
private:
void connect_impl () { is_connected_ = true ; }
std::atomic< bool > is_connected_;
};
int tmain ()
{
auto pool = std::make_shared<Encoder<Retrier<ConnectionPool>>>();
// Establish connection to the remote server synchronously
pool-> connect ();
// Repeat for each line in the input stream
for (std::string line; std::getline (std::cin, line);) {
if (!pool-> send ( std::move (line)))
break ;
}
return 0 ;
}
}
}
ergibt das folgende Diagramm (über PlantUML):
Der folgende C++-Code:
namespace clanguml {
namespace t30003 {
namespace ns1 {
namespace ns2_v1_0_0 {
class A {
};
}
namespace [ [deprecated]] ns2_v0_9_0 {
class A {
};
}
namespace {
class Anon final {
};
}
}
namespace [ [deprecated]] ns3 {
namespace ns1 ::ns2 {
class Anon : public t30003 ::ns1::ns2_v1_0_0::A {
};
}
class B : public ns1 ::ns2::Anon {
};
}
}
}
ergibt das folgende Diagramm (über PlantUML):
Falls Sie nach einem einfacheren Tool zum Visualisieren und Analysieren von Include-Diagrammen suchen, schauen Sie sich mein anderes Tool an – clang-include-graph
Die folgende C++-Codestruktur:
tests/t40001
├── include
│ ├── lib1
│ │ └── lib1.h
│ └── t40001_include1.h
└── src
└── t40001.cc
ergibt das folgende Diagramm (über PlantUML), basierend auf Include-Direktiven im Code:
UML | PlantUML | MermaidJS |
---|---|---|
Nachlass | ||
Verein | ||
Abhängigkeit | ||
Aggregation | ||
Zusammensetzung | ||
Vorlagenspezialisierung/Instanziierung | ||
Verschachtelung (innere Klasse/Aufzählung) | ||
Einschließen (lokal) | ||
Einschließen (System) |
Bei typischen Codebasen kann ein einzelnes Diagramm, das aus einem gesamten Code oder sogar einem einzelnen Namespace generiert wird, zu groß sein, um nützlich zu sein, z. B. als Teil der Dokumentation. clang-uml
ermöglicht die Angabe von Inhalten, die in jedes Diagramm ein- und ausgeschlossen werden sollen, mithilfe einer einfachen YAML-Konfiguration:
include :
# Include only elements from these namespaces
namespaces :
- clanguml::common
- clanguml::config
# Include all subclasses of ClassA (including ClassA)
subclasses :
- clanguml::common::ClassA
# and specializations of template Class<T> (including Class<T>)
specializations :
- clanguml::common::ClassT<T>
# and all classes depending on Class D
dependants :
- clanguml::common::ClassD
# and all dependencies of ClassE
dependencies :
- clanguml::common::ClassE
# and classes in direct relation to ClassB (including ClassB)
context :
- clanguml::common::ClassB
# Include only inheritance relationships
relationships :
- inheritance
exclude :
# Exclude all elements from detail namespace
namespaces :
- clanguml::common::detail
# and also exclude ClassF
elements :
- clanguml::common::ClassF
Weitere Einzelheiten hierzu finden Sie im Dokumentationsabschnitt zu Diagrammfiltern.
Die integrierten Testfälle, die für Unit-Tests von clang-uml
verwendet werden, können hier durchsucht werden.
Dieses Projekt basiert auf den folgenden großartigen Tools:
Wenn Sie zum Projekt beitragen möchten, lesen Sie bitte die Richtlinien für Beiträge.
Copyright 2021-present Bartek Kryza <[email protected]>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.