學習用 doxygen 生成源碼文檔

學習用 doxygen 生成源碼文檔

 

Arpan Sen, 資深工程師, Studio B Productions

簡介: 維護用 C/C++ 開發的遺留系統並添加新特性是一項艱難的任務。幸運的是,doxygen 可以幫助您完成這個任務。doxygen 是一種用於 C/C++、Java™、Python 和其他編程語言的文檔系統。本文在 C/C++ 項目的上下文中討論 doxygen 的特性,以及如何用 doxygen 定義的標記生成代碼文檔。

發佈日期: 2008 年 10 月 13 日
級別: 中級 其他語言版本: 英文
訪問情況 6253 次瀏覽
建議: 0 (添加評論)

1 star2 stars3 stars4 stars5 stars 平均分 (共 5 個評分 )

維護用 C/C++ 開發的遺留系統並添加新特性是一項艱難的任務。這涉及幾方面的問題:理解現有的類層次結構和全局變量,不同的用戶定義類型,以及函數調用圖分析等等。本文在 C/C++ 項目的上下文中通過示例討論 doxygen 的幾個特性。但是,doxygen 非常靈活,也可用於用 Python、Java、PHP 和其他語言開發的軟件項目。本文的主要目的是幫助您從 C/C++ 源代碼提取出信息,但也簡要描述瞭如何用 doxygen 定義的標記生成代碼文檔。

安裝 doxygen

有兩種獲得 doxygen 的方法。可以下載預編譯的可執行文件,也可以從 SVN 存儲庫下載源代碼並自己編譯。清單 1 演示的是後一種方法。


清單 1. 安裝和構建 doxygen 源代碼

                
bash-2.05$ svn co https://doxygen.svn.sourceforge.net/svnroot/doxygen/trunk doxygen-svn

bash-2.05$ cd doxygen-svn
bash-2.05$ ./configure –prefix=/home/user1/bin
bash-2.05$ make

bash-2.05$ make install

 

注意,配置腳本把編譯的源代碼存儲在 /home/user1/bin 中(進行編譯後,會在 PATH 變量中添加這個目錄),因爲並非每個 UNIX® 用戶都有寫 /usr 文件夾的權限。另外,需要用 svn 實用程序下載源代碼。

使用 doxygen 生成文檔

使用 doxygen 生成源代碼的文檔需要執行三個步驟。

生成配置文件

在 shell 提示上,輸入命令 doxygen -g 。這個命令在當前目錄中生成一個可編輯的配置文件 Doxyfile。可以改變這個文件名,在這種情況下,應該調用 doxygen -g <user-specified file name>,見 清單 2


清單 2. 生成默認的配置文件

                
bash-2.05b$ doxygen -g
Configuration file 'Doxyfile' created.
Now edit the configuration file and enter
  doxygen Doxyfile
to generate the documentation for your project
bash-2.05b$ ls Doxyfile
Doxyfile

 

編輯配置文件

配置文件採用 <TAGNAME> = <VALUE> 這樣的結構,與 Make 文件格式相似。下面是最重要的標記:

  • <OUTPUT_DIRECTORY>必須在這裏提供一個目錄名,例如 /home/user1/documentation,這個目錄是放置生成的文檔文件的位置。如果提供一個不存在的目錄名,doxygen 會以這個名稱創建具有適當用戶權限的目錄。
  • <INPUT>這個標記創建一個以空格分隔的所有目錄的列表,這個列表包含需要生成文檔的 C/C++ 源代碼文件和頭文件。例如,請考慮以下代碼片段:
    INPUT = /home/user1/project/kernel /home/user1/project/memory
    

    在這裏,doxygen 會從這兩個目錄讀取 C/C++ 源代碼。如果項目只有一個源代碼根目錄,其中有多個子目錄,那麼只需指定根目錄並把 <RECURSIVE> 標記設置爲 Yes

  • <FILE_PATTERNS>在默認情況下,doxygen 會搜索具有典型 C/C++ 擴展名的文件,比如 .c、.cc、.cpp、.h.hpp。如果 <FILE_PATTERNS> 標記沒有相關聯的值,doxygen 就會這樣做。如果源代碼文件採用不同的命名約定,就應該相應地更新這個標記。例如,如果項目使用 .c86 作爲 C 文件擴展名,就應該在 <FILE_PATTERNS> 標記中添加這個擴展名。
  • <RECURSIVE>如果源代碼層次結構是嵌套的,而且需要爲所有層次上的 C/C++ 文件生成文檔,就把這個標記設置爲 Yes。例如,請考慮源代碼根目錄層次結構 /home/user1/project/kernel,其中有 /home/user1/project/kernel/vmm 和 /home/user1/project/kernel/asm 等子目錄。如果這個標記設置爲 Yes,doxygen 就會遞歸地搜索整個層次結構並提取信息。
  • <EXTRACT_ALL>這個標記告訴 doxygen,即使各個類或函數沒有文檔,也要提取信息。必須把這個標記設置爲 Yes
  • <EXTRACT_PRIVATE>把這個標記設置爲 Yes。否則,文檔不包含類的私有數據成員。
  • <EXTRACT_STATIC>把這個標記設置爲 Yes。否則,文檔不包含文件的靜態成員(函數和變量)。

清單 3 給出一個 Doxyfile 示例。


清單 3. 包含用戶提供的標記值的 doxyfile 示例

                
OUTPUT_DIRECTORY = /home/user1/docs
EXTRACT_ALL = yes
EXTRACT_PRIVATE = yes
EXTRACT_STATIC = yes
INPUT = /home/user1/project/kernel
#Do not add anything here unless you need to. Doxygen already covers all 
#common formats like .c/.cc/.cxx/.c++/.cpp/.inl/.h/.hpp
FILE_PATTERNS = 
RECURSIVE = yes

 

運行 doxygen

在 shell 提示下輸入 doxygen Doxyfile(或者已爲配置文件選擇的其他文件名)運行 doxygen。在最終生成 Hypertext Markup Language(HTML)和 Latex 格式(默認)的文檔之前,doxygen 會顯示幾個消息。在生成文檔期間,在 <OUTPUT_DIRECTORY> 標記指定的文件夾中,會創建兩個子文件夾 htmllatex清單 4 是一個 doxygen 運行日誌示例。


清單 4. doxygen 的日誌輸出

                
Searching for include files...
Searching for example files...
Searching for images...
Searching for dot files...
Searching for files to exclude
Reading input files...
Reading and parsing tag files
Preprocessing /home/user1/project/kernel/kernel.h
…
Read 12489207 bytes
Parsing input...
Parsing file /project/user1/project/kernel/epico.cxx
…
Freeing input...
Building group list...
..
Generating docs for compound MemoryManager::ProcessSpec
…
Generating docs for namespace std
Generating group index...
Generating example index...
Generating file member index...
Generating namespace member index...
Generating page index...
Generating graph info page...
Generating search index...
Generating style sheet...

 

文檔輸出格式

除了 HTML 之外,doxygen 還可以生成幾種輸出格式的文檔。可以讓 doxygen 生成以下格式的文檔:

  • UNIX 手冊頁:<GENERATE_MAN> 標記設置爲 Yes。在默認情況下,會在 <OUTPUT_DIRECTORY> 指定的目錄中創建 man 子文件夾,生成的文檔放在這個文件夾中。必須把這個文件夾添加到 MANPATH 環境變量中。
  • Rich Text Format(RTF):<GENERATE_RTF> 標記設置爲 Yes。把 <RTF_OUTPUT> 標記設置爲希望放置 .rtf 文件的目錄;在默認情況下,文檔放在 OUTPUT_DIRECTORY 中的 rtf 子文件夾中。要想支持跨文檔瀏覽,應該把 <RTF_HYPERLINKS> 標記設置爲 Yes。如果設置這個標記,生成的 .rtf 文件會包含跨文檔鏈接。
  • Latex:在默認情況下,doxygen 生成 Latex 和 HTML 格式的文檔。在默認的 Doxyfile 中,<GENERATE_LATEX> 標記設置爲 Yes。另外,<LATEX_OUTPUT> 標記設置爲 Latex,這意味着會在 OUTPUT_DIRECTORY 中創建 latex 子文件夾並在其中生成 Latex 文件。
  • Microsoft® Compiled HTML Help(CHM)格式:<GENERATE_HTMLHELP> 標記設置爲 Yes。因爲在 UNIX 平臺上不支持這種格式,doxygen 只在保存 HTML 文件的文件夾中生成一個 index.hhp 文件。您必須通過 HTML 幫助編譯器把這個文件轉換爲 .chm 文件。
  • Extensible Markup Language(XML)格式:<GENERATE_XML> 標記設置爲 Yes。(注意,doxygen 開發團隊還在開發 XML 輸出)。

清單 5 提供的 Doxyfile 示例讓 doxygen 生成所有格式的文檔。


清單 5. 生成多種格式的文檔的 Doxyfile

                
#for HTML 
GENERATE_HTML = YES
HTML_FILE_EXTENSION = .htm

#for CHM files
GENERATE_HTMLHELP = YES

#for Latex output
GENERATE_LATEX = YES
LATEX_OUTPUT = latex

#for RTF
GENERATE_RTF = YES
RTF_OUTPUT = rtf 
RTF_HYPERLINKS = YES

#for MAN pages
GENERATE_MAN = YES
MAN_OUTPUT = man
#for XML
GENERATE_XML = YES

 

doxygen 中的特殊標記

doxygen 包含幾個特殊標記。

C/C++ 代碼的預處理

爲了提取信息,doxygen 必須對 C/C++ 代碼進行預處理。但是,在默認情況下,它只進行部分預處理 —— 計算條件編譯語句(#if…#endif),但是不執行宏展開。請考慮 清單 6 中的代碼。


清單 6. 使用宏的 C++ 代碼示例

                
#include <cstring>
#include <rope>

#define USE_ROPE

#ifdef USE_ROPE
  #define STRING std::rope
#else
  #define STRING std::string
#endif

static STRING name;

 

通過源代碼中定義的 <USE_ROPE>,doxygen 生成的文檔如下:

                Defines

    #define USE_ROPE
    #define STRING std::rope

Variables

    static STRING name

 

在這裏可以看到 doxygen 執行了條件編譯,但是沒有對 STRING 執行宏展開。Doxyfile 中的 <ENABLE_PREPROCESSING> 標記在默認情況下設置爲 Yes。爲了執行宏展開,還應該把 <MACRO_EXPANSION> 標記設置爲 Yes。這會使 doxygen 產生以下輸出:

                Defines

   #define USE_ROPE
    #define STRING std::string

Variables

    static std::rope name

 

如果把 <ENABLE_PREPROCESSING> 標記設置爲 No,前面源代碼的 doxygen 輸出就是:

                Variables

    static STRING name

 

注意,文檔現在沒有定義,而且不可能推導出 STRING 的類型。因此,總是應該把 <ENABLE_PREPROCESSING> 標記設置爲 Yes

在文檔中,可能希望只展開特定的宏。爲此,除了把 <ENABLE_PREPROCESSING><MACRO_EXPANSION> 標記設置爲 Yes 之外,還必須把 <EXPAND_ONLY_PREDEF> 標記設置爲 Yes(這個標記在默認情況下設置爲 No),並在 <PREDEFINED><EXPAND_AS_DEFINED> 標記中提供宏的細節。請考慮 清單 7 中的代碼,這裏只希望展開宏 CONTAINER


清單 7. 包含多個宏的 C++ 源代碼

                
#ifdef USE_ROPE
  #define STRING std::rope
#else
  #define STRING std::string
#endif

#if ALLOW_RANDOM_ACCESS == 1
  #define CONTAINER std::vector
#else
  #define CONTAINER std::list
#endif

static STRING name;
static CONTAINER gList;

 

清單 8 給出配置文件。


清單 8. 允許有選擇地展開宏的 Doxyfile

                
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED = CONTAINER
…

 

下面的 doxygen 輸出只展開了 CONTAINER

                Defines

#define STRING   std::string 
#define CONTAINER   std::list

Variables

static STRING name
static std::list gList

 

注意,只有 CONTAINER 宏被展開了。在 <MACRO_EXPANSION><EXPAND_ONLY_PREDEF> 都設置爲 Yes 的情況下,<EXPAND_AS_DEFINED> 標記只選擇展開等號操作符右邊列出的宏。

對於預處理過程,要注意的最後一個標記是 <PREDEFINED>。就像用 -D 開關向 C++ 編譯器傳遞預處理器定義一樣,使用這個標記定義宏。請考慮 清單 9 中的 Doxyfile。


清單 9. 定義了宏展開標記的 Doxyfile

                
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED = 
PREDEFINED = USE_ROPE= /
                             ALLOW_RANDOM_ACCESS=1

 

下面是 doxygen 生成的輸出:

                Defines

#define USE_CROPE 
#define STRING   std::rope 
#define CONTAINER   std::vector

Variables

static std::rope name 
static std::vector gList

 

在使用 <PREDEFINED> 標記時,宏應該定義爲 <macro name>=<value> 形式。如果不提供值,比如簡單的 #define,那麼只使用 <macro name>=<spaces> 即可。多個宏定義以空格或反斜槓(/)分隔。

從文檔生成過程中排除特定文件或目錄

在 Doxyfile 中的 <EXCLUDE> 標記中,添加不應該爲其生成文檔的文件或目錄(以空格分隔)。因此,如果提供了源代碼層次結構的根,並要跳過某些子目錄,這將非常有用。例如,如果層次結構的根是 src_root,希望在文檔生成過程中跳過 examples/ 和 test/memoryleaks 文件夾,Doxyfile 應該像 清單 10 這樣。


清單 10. 使用 EXCLUDE 標記的 Doxyfile

                
INPUT = /home/user1/src_root
EXCLUDE = /home/user1/src_root/examples /home/user1/src_root/test/memoryleaks
…

 

生成圖形和圖表

在默認情況下,Doxyfile 把 <CLASS_DIAGRAMS> 標記設置爲 Yes。這個標記用來生成類層次結構圖。要想生成更好的視圖,可以從 Graphviz 下載站點 下載 dot 工具。Doxyfile 中的以下標記用來生成圖表:

  • <CLASS_DIAGRAMS>在 Doxyfile 中這個標記默認設置爲 Yes。如果這個標記設置爲 No,就不生成繼承層次結構圖。
  • <HAVE_DOT>如果這個標記設置爲 Yes,doxygen 就使用 dot 工具生成更強大的圖形,比如幫助理解類成員及其數據結構的協作圖。注意,如果這個標記設置爲 Yes<CLASS_DIAGRAMS> 標記就無效了。
  • <CLASS_GRAPH>如果 <HAVE_DOT> 標記和這個標記同時設置爲 Yes,就使用 dot 生成繼承層次結構圖,而且其外觀比只使用 <CLASS_DIAGRAMS> 時更豐富。
  • <COLLABORATION_GRAPH>如果 <HAVE_DOT> 標記和這個標記同時設置爲 Yes,doxygen 會生成協作圖(還有繼承圖),顯示各個類成員(即包含)及其繼承層次結構。

清單 11 提供一個使用一些數據結構的示例。注意,在配置文件中 <HAVE_DOT><CLASS_GRAPH><COLLABORATION_GRAPH> 標記都設置爲 Yes


清單 11. C++ 類和結構示例

                
struct D {
  int d;
};

class A {
  int a;
};

class B : public A {
  int b;
};

class C : public B {
  int c;
  D d;
};

 

圖 1 給出 doxygen 的輸出。


圖 1. 使用 dot 工具生成的類繼承圖和協作圖
類繼承圖

代碼文檔樣式

到目前爲止,我們都是使用 doxygen 從原本沒有文檔的代碼中提取信息。但是,doxygen 也鼓勵使用文檔樣式和語法,這有助於生成更詳細的文檔。本節討論 doxygen 鼓勵在 C/C++ 代碼中使用的一些常用標記。更多信息參見 參考資料

每個代碼元素有兩種描述:簡短的和詳細的。簡短描述通常是單行的。函數和類方法還有第三種描述體內描述(in-body description),這種描述把在函數體中找到的所有註釋塊集中在一起。比較常用的一些 doxygen 標記和註釋樣式如下:

  • 簡短描述:使用單行的 C++ 註釋,或使用 </brief> 標記。
  • 詳細描述:使用 JavaDoc 式的註釋 /** … test … */(注意開頭的兩個星號 [*])或 Qt 式的註釋 /*! … text … */
  • 體內描述:類、結構、聯合體和名稱空間等 C++ 元素都有自己的標記,比如 </class></struct></union></namespace>

爲了爲全局函數、變量和枚舉類型生成文檔,必須先對對應的文件使用 </file> 標記。清單 12 給出的示例包含用於四種元素的標記:函數標記(</fn>)、函數參數標記(</param>)、變量名標記(</var>)、用於 #define 的標記(</def>)以及用來表示與一個代碼片段相關的問題的標記(</warning>)。


清單 12. 典型的 doxygen 標記及其使用方法

                
/*! /file globaldecls.h
      /brief Place to look for global variables, enums, functions
           and macro definitions
  */

/** /var const int fileSize
      /brief Default size of the file on disk
  */
const int fileSize = 1048576;

/** /def SHIFT(value, length)
      /brief Left shift value by length in bits
  */
#define SHIFT(value, length) ((value) << (length))

/** /fn bool check_for_io_errors(FILE* fp)
      /brief Checks if a file is corrupted or not
      /param fp Pointer to an already opened file
      /warning Not thread safe!
  */
bool check_for_io_errors(FILE* fp);

 

下面是生成的文檔:

                Defines

#define SHIFT(value, length)   ((value) << (length))  
             Left shift value by length in bits.

Functions

bool check_for_io_errors (FILE *fp)  
        Checks if a file is corrupted or not.

Variables

const int fileSize = 1048576;
Function Documentation
bool check_for_io_errors (FILE* fp)
Checks if a file is corrupted or not.

Parameters

              fp: Pointer to an already opened file

Warning

Not thread safe! 

 

結束語

本文討論如何用 doxygen 從遺留的 C/C++ 代碼提取出大量相關信息。如果用 doxygen 標記生成代碼文檔,doxygen 會以容易閱讀的格式生成輸出。只要以適當的方式使用,doxygen 就可以幫助任何開發人員維護和管理遺留系統。

 

參考資料

學習

  • 您可以參閱本文在 developerWorks 全球站點上的 英文原文
  • doxygen 站點 包含關於 doxygen 的非常有價值的手冊和幾篇文章。
  • 下載 dot 實用程序
  • AIX and UNIX 專區:developerWorks 的“AIX and UNIX 專區”提供了大量與 AIX 系統管理的所有方面相關的信息,您可以利用它們來擴展自己的 UNIX 技能。
  • AIX and UNIX 新手入門:訪問“AIX and UNIX 新手入門”頁面可瞭解更多關於 AIX 和 UNIX 的內容。
  • AIX and UNIX 專題彙總:AIX and UNIX 專區已經爲您推出了很多的技術專題,爲您總結了很多熱門的知識點。我們在後面還會繼續推出很多相關的熱門專題給您,爲了方便您的訪問,我們在這裏爲您把本專區的所有專題進行彙總,讓您更方便的找到您需要的內容。
  • developerWorks 技術活動和網絡廣播:隨時關注 developerWorks 技術活動和網絡廣播。
  • Podcasts:收聽 IBM 技術專家的訪談錄。

獲得產品和技術

  • 下載 doxygen。
  • IBM 試用軟件:使用可從 developerWorks 直接下載的軟件構建您的下一個開發項目。

討論

關於作者

Arpan Sen 是一位資深工程師,從事電子設計自動化行業的軟件開發。他花了好幾年研究多種風格的 UNIX,包括 Solaris、SunOS、HP-UX 和 IRIX,以及 Linux 和 Microsoft Windows。他主要對軟件性能優化技術、圖形理論和並行計算感興趣。Arpan 擁有軟件系統研究生學位。



blog.csdn.net/caspiansea/article/details/6571232


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章