Doxygen - automatische Dokumentation von Quellcode
Grundprinzip:
Aus Kommentaren im Quellcode und aus allgemeinen sprachspezifischen Strukturbeziehungen
(z.B. Vererbung, Verwendung, Include) wird ein HTML-Dokument generiert.
Zusätzlich zur Darstellung von Diagrammen (z.B. Vererbung, Abhängigkeit):
Doxygen -g MyDoxygenConfigfile.dxyIst das Konfigurationsfile erstellt und an die eigenen Vorstellungen angepasst, so erfolgt die Erzeugung der Dokumentation über:
Doxygen MyDoxygenConfigfile.dxyEine detaillierte Beschreibung aller Optionen findet sich unter http://www.stack.nl/~dimitri/doxygen/manual.html.
EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES
QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = NO
SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO
GENERATE_HTML = YES GENERATE_TREEVIEW = YES GENERATE_LATEX = NO
HAVE_DOT = YES CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = NO COLLABORATION_GRAPH = YES
STRIP_CODE_COMMENTS = NO
DoxyGen generiert Fehler und Warnungen. Um zu diesen Ausgaben das automatische Springen zur betreffenden Stelle im Quellcode zu ermöglichen, sollte folgender Eintrag im Doxygen-Konfigfile vorhanden sein:
WARN_FORMAT = "$file($line) : $text"
::-------------------------------------------------------------- :: :: File: GenerateDocumentation.cmd :: :: Generate Doxygen documentation for a SW project :: Syntax: GenerateDocumentation [ProjectPath] [ProjectName] :: :: Remark: Syntax when used as external tool within Visual Studio: :: GenerateDocumentation $(ProjectDir) $(ProjectFileName) :: ::-------------------------------------------------------------- @echo off setlocal set thisFile=GenerateDocumentation.cmd set relativePathToDoxyGenFiles=BuildAll set nameGenericDoxyFile=DoxygenTemplateForDocGeneration.dxy set nameSpecificDoxyFile=GeneratedDoxyFileDoNotEditManually.dxy set nameDoxygenOutputDir=DoxyGenDoc ::----- Command line params ----- echo Generating DoxyGen documentation... (%thisFile%)) echo. :: remove quotes set inputProjectDir=%~1% set inputProjectName=%~2% echo ProjectDir from cmd line : %inputProjectDir% echo ProjectName from cmd line : %inputProjectName% if "%inputProjectDir%" == "" goto :ERR_MISSING_CMDLINE_PARAMS if "%inputProjectName%" == "" goto :ERR_MISSING_CMDLINE_PARAMS :: cut trailing "" set projectDir=%inputProjectDir:=% :: cut extension from project file name for /f "tokens=1,2 delims=/." %%a in ("%inputProjectName%") do set projectName=%%a echo ProjectDir : %projectDir% echo ProjectName : %projectName% ::----- Get specific environment paths ----- set sourceDir=%MY_SOURCE_DIR% :: cut trailing "" set sourceDir=%sourceDir:=% if "%sourceDir%" == "" goto :ERR_SOURCE_DIR_NOT_SET set sourceDrive=%sourceDir:~0,2% echo SourceDir from env : %sourceDir% set targetDir=%MY_TARGET_DIR% :: cut trailing "" set targetDir=%targetDir:=% if "%targetDir%" == "" goto :ERR_TARGET_DIR_NOT_SET set targetDrive=%targetDir:~0,2% echo TargetDir from env : %targetDir% echo SourceDrive : %sourceDrive% echo TargetDrive : %targetDrive% ::----- Create target directory ----- %targetDrive% cd %targetDir% if not exist %nameDoxygenOutputDir% ( mkdir %nameDoxygenOutputDir% ) set targetDir=%targetDir%%nameDoxygenOutputDir% if not exist %targetDir% goto :ERR_TARGET_DIR_NOT_CREATABLE cd %targetDir% if not exist %projectName% ( mkdir %projectName% ) set targetDir=%targetDir%%projectName% echo TargetDir : %targetDir% if not exist %targetDir% goto :ERR_TARGET_DIR_NOT_CREATABLE ::----- Build names for doxy files ----- set doxyTemplatePath=%sourceDir%%relativePathToDoxyGenFiles%%nameGenericDoxyFile% :: replace "" with "" set doxyTemplatePath=%doxyTemplatePath:=% echo Generic doxy template : %doxyTemplatePath% set nameSpecificDoxyFile=%targetDir%%nameSpecificDoxyFile% :: replace "" with "" set nameSpecificDoxyFile=%nameSpecificDoxyFile:=% echo Specific doxy file : %nameSpecificDoxyFile% ::----- Generating specific doxy config file ----- echo. echo Generating specific doxy file %nameSpecificDoxyFile% ... set d="%nameSpecificDoxyFile%" echo # Automatically generated file > %d% echo # DO NOT EDIT MANUALLY! >> %d% echo. >> %d% echo # BEGIN ------- Contents of generic doxy file >> %d% type %doxyTemplatePath% >> %d% echo # END ------- Contents of generic doxy file >> %d% echo. >> %d% echo # BEGIN ------- Project specific settings >> %d% echo PROJECT_NAME = "%projectName%" >> %d% echo OUTPUT_DIRECTORY = "%targetDir%" >> %d% echo # END -------- Project specific settings >> %d% ::----- Generating docoment ----- pushd . echo. echo ----- doc generation in progress ... echo. echo scanning for contents in directory: %sourceDrive% cd %projectDir% cd echo. echo calling doxygen %nameSpecificDoxyFile% ... doxygen.exe "%nameSpecificDoxyFile%" echo. echo ----- doc generation finished ----- popd endlocal goto :eof ::----- Error handling ----- :ERR_MISSING_CMDLINE_PARAMS echo ERROR: Expected calling syntax with params: projectDir projectName echo Hint: When called from Visual Studio Tools menu you can use: echo $(ProjectDir) $(ProjectFileName) goto :TERMINATE_WITH_ERROR :ERR_SOURCE_DIR_NOT_SET echo ERROR: Source dir MY_SOURCE_DIR not set as environment variable! goto :TERMINATE_WITH_ERROR :ERR_TARGET_DIR_NOT_SET echo ERROR: Target dir MY_TARGET_DIR not set as environment variable! goto :TERMINATE_WITH_ERROR :ERR_TARGET_DIR_NOT_CREATABLE echo ERROR: Target dir %targetDir% could not be created goto :TERMINATE_WITH_ERROR :TERMINATE_WITH_ERROR echo. echo ...%thisFile% terminated with error goto :eof
Folgende Elemente sollten in jedem Fall in die Dokumentation aufgenommen werden:
Nach Bedarf können folgende Elemente zusätzlich aufgenommen werden:
//////////////////////////////////////////////////////////////////////////////// /// /// file /// author Gerald Fahrnholz /// /// defgroup GrpRunner Using Runner (-1-) /// @{ /// ingroup GrpTestUtils (-2-) /// brief /// Class Runner executes a user defined set of test functions /// containing arbitrary test cases. /// /// The test functions have to be declared within /// macros ref TTB_TEST_FUNC or ref TTB_TEST_FUNC_DESC. /// /// <b>n Supported features</b> /// /// - provides a controlling main function, users have only to define the /// test functions (similar to automatic test cases within Boost::Test) /// /// - possibility to select and sort the test functions for execution /// /// ... /// /// sa Runner.h (File documentation) (-3-) /// sa TestToolBox::Runner (class documentation) /// //////////////////////////////////////////////////////////////////////////////// #include "TestToolBox/TestEvents.h" /// brief This class runs user defined test functions and organizes /// their execution. (-4-) /// /// nosubgrouping /// sa Runner.h (File documentation) /// sa GrpRunner (Usage documentation) class Runner { public: /// Automatically execute the defined test functions (-5-) int Execute(RunnerExtensionPoints* in_pExtensionPoints = 0); private: ///cond (-6-) // some not interesting details ///endcond }; /// @} // endGrpRunnerErläuterungen
(-1)
Die Usage-Dokumentation wird über defgroup als separate
Gruppe mit dem eindeutigen Namen
"GrpRunner" und dem Titel "Using Runner" definiert. Der dazugehörige Bereich wird über
"@{" und "@}" festgelegt.
(-2-)
Über ingroup wird die Usage-Dokumentation einer hierarchisch höherstehenden
Gruppe zugeordnet. In der generierten Dokumentation wird diese logische Gliederung der
Usage-Dokumentationen als Baumstruktur unterhalb "Modules" angezeigt.
(-3-)
Es ist hilfreich auf die unterschiedlichen Dokumentationsarten zu einem Thema zu verweisen.
Typischerweise gibt es stets eine File- und eine Klassendokumentation.
(-4-)
Hier beginnt die Klassendokumentation. Neben einer kurzen Beschreibung solte auch hier ein Verweis
auf die File-Dokumentation und eine evtl. existierende Usage-Dokumantation erfolgen.
In der generierten Dokumentation werden alle Klassen unterhalb "ClassList" in einer flachen Liste
aufgeführt.
(-5-)
Eine Kurzbeschreibung zu einer Methode kann ohne besondere Kennzeichnung in einer Textzeile erfolgen.
Werden mehrere Zeilen benötigt, so ist "brief" voranzustellen
(-6-)
Weniger interessante Klassenanteile werden über cond ausgeblendet
Kurzbeschreibungen, brief
Der Kommentartext zu einem dokumentierten Element gliedert sich in eine Kurzbeschreibung und in eine erweiterte Gesamtbeschreibung, die in der erzeugten Dokumentation auch separat aufgeführt werden.
Für einfache Sachverhalte sollte lediglich eine Kurzbeschreibung angelegt werden, da dann auch im generierten Dokument unnötige Textabschnitte vermieden werden.
Ein Text wird nach folgenden Regeln als Kurzbeschreibung identifiziert:
Aufzählungen über "-"
Einfache Strich-Aufzählungen können über "-" und einen auch mehrzeiligen Textabsatz
definiert werden. Untergeordnete Aufzählungspunkte werden über eingerückte Strichzeilen definiert. Größere Abstände zwischen den Aufzählungen können über einfache Leerzeichen
(Absätze) erreicht werden, allerdings wird danach stets mit Aufzählungsebene 1 fortgesetzt.
Beispiel:
/// - Aufzählungspunkt 1 /// - Aufzählungspunkt 2 /// - Unterpunkt 2.1 /// - Unterpinkt 2.2 /// - Aufzählungspunkt 3 /// dies gehört auch noch zur Aufzählung
Fettschrift <b>
Abschnittsüberschriften oder wichtige Ausdrücke innerhalb des Textes können über das HTML-Tag
<b> als Fettschrift formatiert werden. Um bei Überschriften einen zusätzlichen Abstand einzufügen kann dem Text einfach "n" vorangestellt werden.
Code-Beispiele code ... endcode
Mehrzeilige Codebeispiele können über code ... endcode definiert werden
direkte http-Hyperlinks
können ohne besondere Formatierung direkt im Text verwendet werden
ref, Referenz
Hyperlink auf anderswo im Dokument beschriebenes Thema, Textformat wird nicht beeinflusst
sa, "see also"
abgesetzter Block mit Verweisen (Hyperlinks) auf anderswo im Dokument beschriebene Themen
Trotz dieser Unsicherheiten kann es in größeren Projekten hilfreich und notwendig sein, zumindest zur Beschreibung von Basisdiensten (Frameworks) und wichtigen Komponenten-Schnittstellen eine erläuternde und aktuelle Dokumentation zur Verfügung zu haben. Zielsetzung ist dabei die Unterstützung des korrekten Einsatzes der beschriebenen SW-Anteile innerhalb des Projektteams.
Zur Erreichung dieses Ziels kann Doxygen entsprechend folgender Prinzipien konfiguriert werden:
Im nachfolgenden Beispiel werden alle Dateien aus dem Verzeichnis "FolderA" und die Dateien "ClassB2.h" und "ClassB4.h" aus "FolderB" ausgewählt:
INPUT = ../FolderA ../FolderB/ClassB2.h ../FolderB/ClassB4.hInnerhalb der ausgewählten Dateien können wie weiter oben beschrieben nicht zu dokumentierende Code-Abschnitte über "cond / endcond" ausgeblendet werden:
// file ClassB2.h ... ///cond // some not interesting details ///endcond
EXAMPLE_PATH = ../Innerhalb beliebiger DoxyGen-Kommentare können dann Codefragmente aus anderen Dateien eingebunden werden:
// File: SomeSourceFile.h/.cpp /// This is the DoxyGen documentation for ... /// /// Code snippet to demonstrate usage of class ADerived: /// \snippet UnitTest/TestClassADerived.cpp access ADerivedDer zugehörige Quellcode in UnitTest/TestClassADerived.cpp muss dann einen Codeabschnitt mit der Kennnzeichnung "access ADerived" als Start und End-Tag enthalten:
// File: TestClassADerived.cpp ... void SomeOtherFunction() { /// [access ADerived] ADerived* pAd = new ADerived; pAd->DoIt(); delete pAd; /// [access ADerived] }Die generierte Dokumentation sieht dann in etwa folgendermaßen aus:
Code snippet to demonstrate usage of class ADerived:
ADerived* pAd = new ADerived; pAd->DoIt(); delete pAd;
Die Codebeispiele können dabei auch aus Dateien stammen, die gar nicht für die Generierung der Dokumentation ausgewählt sind.
INPUT = .. ../doc/MainPage.hInnerhalb der Datei MainPage.h muss über das Tag "\mainpage" deklariert werden, dass die Inhalte auf die Einstiegsseite generiert werden.
/// File: MainPage.h /// \mainpage SW component X /// /// Short introduction to SW component X /// ... /// (all DoxyGen tags can be used here to directly enter /// infos or to refer to information in other files)