什麼是Doxygen?
Doxygen 是一個程式的檔案產生工具,可將程式中的特定批註轉換成為說明檔案。
通常我們在寫程式時,或多或少都會寫上批註,但是對於其它人而言,要直接探索程式裡的 批註,與打撈鐵達尼號同樣的辛苦。大部分有用的批註都是屬於針對函數,類等等的說明。所以,如果能依據程式本身的結構,將批註經過處理重新整理成為一個純粹的參考手冊,對於後面利用您的程式碼的人而言將會減少許多的負擔。不過,反過來說,整理檔案的工作對於您來說,就是沉重的負擔。
對於未歸檔的源檔案,也可以通過配置Doxygen來提取代碼結構。或者藉助自動產生的包含依賴圖(includedependency graphs)、繼承圖(inheritance diagram)以及共同作業圖表(collaborationdiagram)來可視化文檔之間的關係。Doxygen產生的協助文檔的格式可以是CHM、RTF、PostScript、PDF、HTML和Unixmanpage等。
一個好的程式設計師,在寫程式時,都會在適當的地方加上合適的批註。如果,能夠在撰寫批註時,稍微符合某種格式,接著就可以透過一個工具程式依據程式結構及您的批註產生出漂亮的檔。這將令許多工作繁重的程式設計師有時間多喝幾杯咖啡。
Doxygen 就是這樣的一個工具。在您寫批註時,稍微按照一些它所制訂的規則。接著,他就可以幫您產生出漂亮的檔了。因此,Doxygen 的使用可分為兩大部分。首先是特定格式的批註撰寫,第二便是利用Doxygen的工具來產生檔。
目前Doxygen可處理的程式語言套件含:
- C/C++
- Java
- IDL (Corba, Microsoft及KDE-DCOP類型)
而可產生出來的檔格式有:
- HTML
- XML
- LaTeX
- RTF
- Unix Man Page
而其中還可衍生出不少其它格式。如有了LaTeX 檔後,就可以透過一些工具產生出PS或是PDF檔案。
在多國語言的支援方面,Doxygen 目前可支援的約有2,30種。自Doxygen 1.2.16開始支援繁體中文(這正是小弟做的好事)。所以在目前一些Open Source 的程式檔案產生器中,Doxygen 算是相當完整的一套。在程式語言處理上面,Doxygen也算是少數在Borland C++ Builder 的文法下還能夠正常運作的工具之一(若非如此,小弟也不會推薦它)。
本文的目的是希望在經過仔細閱讀本文之後能夠給大家一個概略性的瞭解。以便可以很容易的上手使用Doxygen。至於Doxygen本身的詳細使用,各位可以參考隨著Doxygen 所附的檔。實際上,Doxygen 自己的使用手冊就是使用Doxygen 產生的。您可以看到他實際上能夠產生遠比Reference Book更複雜的檔案。
安裝Doxygen
Doxygen 的安裝可說十分的簡單,本文僅介紹binary檔案的安裝,若您有興趣從source code重新compile起來,請自行查閱參考手冊。
首先,請您先至doxygen 的網站上面抓取最新版本的doxygen 回來。目前,只要您是Linux, Solaris, Mac OS X,HP-UX, 甚至是UnixWare,都有compile好的binary版本可以抓取。如果是Windows 95/98/ME/NT/2000/XP,甚至還有Setup的版本可以抓取。所以安裝過程可說十分簡單。只要給予正確的安裝目錄,相信一般在安裝上是不會遇到什麼問題的。
另外,如果您是Linux或是Windows,可以另外抓取Doxygen Wizard的程式。這是一個協助工具輔助,可以很快的幫您建立一個Doxygen 的組態檔案。透過這個組態檔案,您就可以很快的將檔產生出來。另外,若沒有使用Doxygen Wizard,還是可以使用一般的文字編輯器將這個組態檔製作出來。
若安裝成功,您應該可以看到doxygen 這個執行檔案出現在您的系統中。若是Windows 平台,則可看到在程式集中有Doxygen 這個Folder出現。
設定Project的doxygen組態
Doxygen 產生檔可以分為三個步驟。一是為Project 建立組態檔案,二是在程式碼中加上符合Doxygen所定義批註格式。三是使用Doxygen來產生批註。
因此,第一步就是為您的Project 製作Doxygen 的組態檔案。這個所謂的組態檔案,格式其實與很簡單。就是一些Key 與值的設定。每個設定為一行。若第一行開頭為"#" 表示該行為批註。Doxygen 會忽略它。每個設定行的格式有兩種,分別如下:
TAG = value [value, ...]
及
TAG += value [value, ...]
第一種形式是最常見的,也就是要設定一個TAG (也就是一個Key ),他的值為右邊所定義的部分。原則上每個值都是單一的英文字,如果您要定義的值有空格符包含在內,可使用雙引號將它括住。如果要定義的值超過一個以上,可使用逗號","予以分隔開來。
如果您要定義的TAG 是屬於表列型態的,也就是他會有很多的值分別以逗號隔開。在Doxygen 組態檔中允許您在不同的地方重複定義。只是後面的定義應使用上面所說的第二種形式。此種形式會將前後兩個定義的值合并在一起。
知道這個基本格式後,剩下就是根據各個TAG 的意義來進行設定。關於TAG 的定義很多,此處我們僅針對必要用到的TAG 進行說明,剩下的部分請自行翻閱使用說明。
由於Doxygen 的TAG 還算不少,為了方便使用,Doxygen 自身提供了一個方便的選項,可以幫您建立一份空白的Doxygen檔案(Doxygen 是Doxygen 預設的組態檔名)。
> doxygen Doxygen
透過這個命令,您可以得到一個Doxygen 檔案,接下來就可使用一般的文字編輯器來進行編輯。
下面將針對幾個必要的TAG 進行說明:
PROJECT_NAME |
Project 的名字,以一個單字為主,多個單字請使用雙引號括住。 |
PROJECT_VERSION |
Project的版本號碼。 |
OUTPUT_DIRECTORY |
輸出路徑。產生的檔案會放在這個路徑之下。如果沒有填這個路徑,將會以目前所在路徑來作為輸出路徑。 |
OUTPUT_LANGUAGE |
輸出語言。預設為English。1.2.16 版後,您可以使用Chinese-Traditional 來輸出中文繁體的格式。 |
INPUT |
指定載入或找尋要處理的程式碼檔案路徑。這邊是一個表列式的型態。並且可指定檔案及路徑。舉例來說若您有a.c, b.c, c.c 三個檔案。您可使用INPUT = a.c, b.c, c.c 的方式。若您給定一個目錄,該目錄下面所有檔案都會被處理。 |
FILE_PATTERNS |
如果您的INPUT Tag 中指定了目錄。您可以透過這個Tag來要求Doxygen在處理時,只針對特定的檔案進行動作。例如:您希望對目錄下的副檔名為.c, .cpp及.h的檔案作處理。您可設定FILE_PATTERNS = *.c, *.cpp, *.h。 |
RECURSIVE |
這是一個布爾值的Tag,只接受YES或NO。當設定為YES時,INPUT所指定目錄的所有子目錄都會被處理。 |
EXCLUDE |
如果您有某幾個特定檔案或是目錄,不希望經過Doxygen處理。您可在這個Tag中指定。 |
EXCLUDE_PATTERNS |
類似於FILE_PATTERNS的用法,只是這個Tag是供EXCLUDE所使用。 |
SOURCE_BROWSER |
如果設定為YES,則Doxygen會產生出源檔案的列表,以供查閱。 |
INLINE_SOURCES |
如果設定為YES ,則程式碼也會被嵌入於說明檔案中。 |
ALPHABETICAL_INDEX |
如果設定為YES,則一個依照字母排序的列表會加入在產生的檔案中。 |
GENERATE_HTML |
若設定為YES ,就會產生HTML版本的說明檔。HTML檔是Doxygen預設產生的格式之一。 |
HTML_OUTPUT |
HTML檔案的輸出目錄。這是一個相對路徑,所以實際的路徑為OUTPUT_DIRECTORY加上HTML_OUTPUT。這個設定預設為html。 |
HTML_FILE_EXTENSION |
HTML檔案的副檔名。預設為.html。 |
HTML_HEADER |
要使用在每一頁HTML檔中的Header。如果沒有指定,Doxygen會使用自己預設的Header。 |
HTML_FOOTER |
要使用在每一頁HTML檔中的Footer。如果沒有指定,Doxygen會使用自己預設的Footer。 |
HTML_STYLESHEET |
您可給定一個CSS 的設定,讓HTML的輸出結果更完美。 |
GENERATE_HTMLHELP |
如設定為YES,Doxygen會產生一個索引檔案。這個索引檔案在您需要製作windows 上的HTML格式的HELP檔案時會用的上。 |
GENERATE_TREEVIEW |
若設定為YES,Doxygen會幫您產生一個樹狀結構,在畫面左側。這個樹狀結構是以JavaScript所寫成。所以需要新版的Browser才能正確顯示。 |
TREEVIEW_WIDTH |
用來設定樹狀結構在畫面上的寬度。 |
GENERATE_LATEX |
設定為YES 時,會產生LaTeX 的檔案。不過您的系統必需要有安裝LaTeX 的相關工具。 |
LATEX_OUTPUT |
LaTeX檔案的輸出目錄,與HTML_OUTPUT用法相同,一樣是指在OUTPUT_DIRECTORY之下的路徑。預設為latex。 |
LATEX_CMD_NAME |
LaTeX程式的命令名稱及檔案所在。預設為latex。 |
GENERATE_RTF |
若設定為YES ,則會產生RTF 格式的說明檔。 |
RTF_OUTPUT |
與HTML_OUTPUT 用法相同,用來指定RTF 輸出檔案路徑。預設為rtf。 |
GENERATE_MAN |
若設定為YES ,則會產生Unix Man Page 格式的說明檔。 |
MAN_OUTPUT |
與HTML_OUTPUT 用法相同,用來指定Man Page的輸出目錄。預設為man。 |
GENERATE_XML |
若設定為YES ,則會產生XML 格式的說明檔。 |
ENABLE_PREPROCESSING |
若設定為YES ,則Doxygen 會啟動C 的前置處理器來處理原始檔。 |
PREDEFINED |
可以讓您自行定義一些宏。類似於gcc 中的-D選項。 |
若上面這些基本的Tag 都設定正確,接下來就是將您的Source Code 批註修改成為正確的格式。若您覺得用一般文字編輯器來編輯組態檔很麻煩,建議您可以使用Doxygen Wizard這個工具程式。他可以很快的建構出您所需要的Doxygen檔案。
撰寫正確格式的批註
並非所有程式碼中的批註都會被Doxygen所處理。您必需依照正確的格式撰寫。原則上,Doxygen 僅處理與程式結構相關的批註,如Function,Class ,檔案的批註等。對於Function內部的批註則不做處理。
Doxygen可處理下面幾種類型的批註。
JavaDoc類型:
/**
* ... 批註 ...
*/
Qt類型:
/*!
* ... 批註 ...
*/
單行型式的批註:
/// ... 批註 ...
或
//! ... 批註 ...
要使用哪種型態完全看自己的喜好。以筆者自己來說,大範圍的註解我會使用JavaDoc 型的。單行的批註則使用"///" 的類型。
此外,由於Doxygen 對於批註是視為在解釋後面的程式碼。也就是說,任何一個批註都是在說明其後的程式碼。
如果要批註前面的程式碼則需用下面格式的批註符號。
/*!< ... 批註 ... */
/**< ... 批註 ... */
//!< ... 批註 ...
///< ... 批註 ...
上面這個方式並不適用於任何地方,只能用在class 的member或是function的參數上。
舉例來說,若我們有下面這樣的class。
class MyClass {
public:
int member1;
int member2:
void member_function();
};
加上批註後,就變成這樣:
/**
* 我的自定類說明 ...
*/
class MyClass {
public:
int member1; ///< 第一個member說明 ...
int member2: ///< 第二個member說明 ...
int member_function(int a, int b);
};
/**
* 自定類的member_funtion說明 ...
*
* @param a 參數a的說明
* @param b 參數b的說明
*
* @return 返回a+b。
*/
int MyClass::member_function(int a, int b )
{
return a+b ;
}
當您使用Doxygen 產生說明檔時,Doxygen 會parsing 您的程式碼。並且依據程式結構建立對應的檔案。然後再將您的批註,依據其位置套入於正確的地方。
您可能已經注意到,除了一般文字說明外,還有一些其它特別的指令,像是@param及@return 等。這正是Doxygen另外一個重要的部分,因為一個類或是函數其實都有固定幾個要說明的部分。為了讓Doxygen 能夠判斷,所有我們就必需使用這些指令,來告訴Doxygen 後面的批註是在說明什麼東西。Doxygen 在處理時,就會幫您把這些部分做特別的處理或是排版。甚至是製作引用超連結。
首先,我們先說明在Doxygen 中對於類或是函數批註的一個特定格式。
/**
* class或function的簡易說明...
*
* class或function的詳細說明...
* ...
*/
上面這個例子要說的是,在Doxygen 處理一個class 或是function註解時,會先判斷第一行為簡易說明。這個簡易說明將一直到空一行的出現。或是遇到第一個"." 為止。
之後的批註將會被視為詳細說明。兩者的差異在於Doxygen在某些地方只會顯示簡易說明,而不顯示詳細說明。如:class 或function的列表。
另一種比較清楚的方式是@brief指令。這將會明確的告訴Doxygen,何者是簡易說明。例如:
/**
* @brief class或function的簡易說明...
*
* class或function的詳細說明...
* ...
*/
除了這個class 及function外,Doxygen 也可針對檔案做說明,條件是該批註需置於檔案的前面。主要也是利用一些指令,通常這部分註解都會放在檔案的開始地方。如:
/*! \file myfile.h
\brief 檔案簡易說明
詳細說明.
\author 作者資訊
*/
如您所見,檔案批註約略格式如上,請別被"\" 所搞混。其實,"\" 與"@" 都是一樣的,都是告訴Doxygen 後面是一個指令。兩種在Doxygen 都可使用。筆者自己比較偏好使用"@"。
接著我們來針對一些常用的指令做說明:
@file |
檔案的批註說明。 |
@author |
作者的資訊 |
@brief |
用於class 或function的批註中,後面為class 或function的簡易說明。 |
@param |
格式為 @param arg_name 參數說明 主要用於函數說明中,後面接參數的名字,然後再接關於該參數的說明。 |
@return |
後面接函數返回說明。用於function的批註中。說明該函數的返回結果。 |
@retval |
格式為 @retval value 傳回值說明 主要用於函數說明中,說明特定傳回值的意義。所以後面要先接一個傳回值。然後在放該傳回值的說明。 |
Doxygen 所支援的指令很多,有些甚至是關於輸出排版的控制。您可從Doxygen的使用說明中找到詳盡的說明。
下面我們準備一組example.h 及example.cpp 來說明Doxygen 批註的使用方式:
example.h:
/**
* @file 本範例的include檔案。
*
* 這個檔案只定義example這個class。
*
* @author garylee@localhost
*/
#define EXAMPLE_OK 0 ///< 定義EXAMPLE_OK的宏為0。
/**
* @brief Example class的簡易說明
*
* 本範例說明Example class。
* 這是一個極為簡單的範例。
*
*/
class Example {
private:
int var1 ;///< 這是一個private的變數
public:
int var2 ;///< 這是一個public的變數成員。
int var3 ;///< 這是另一個public的變數成員。
void ExFunc1(void);
int ExFunc2(int a, char b);
char* ExFunc3(char *c) ;
};
example.cpp:
/**
* @file 本範例的程式碼檔案。
*
* 這個檔案用來定義example這個class的
* member function。
*
* @author garylee@localhost
*/
/**
* @brief ExFunc1的簡易說明
*
* ExFunc1沒有任何參數及傳回值。
*/
void Example::ExFunc1(void)
{
// empty funcion.
}
/**
* @brief ExFunc2的簡易說明
*
* ExFunc3()返回兩個參數相加的值。
*
* @param a 用來相加的參數。
* @param b 用來相加的參數。
* @return 返回兩個參數相加的結果。
*/
int ExFunc2(int a, char b)
{
return (a+b);
}
/**
* @brief ExFunc3的簡易說明
*
* ExFunc3()只返回參數輸入的指標。
*
* @param c 傳進的字元指標。
* @retval NULL Null 字元串。
* @retval !NULL 非Null 字元串。
*/
char * ExFunc2(char * c)
{
return c;
}
上面這兩個檔案很簡單的說明了Doxygen 批註的使用方式。您可依照此要領在你自己的程式碼中加上對應的批註。
其實,無論您有無使用Doxygen ,都不妨依照他的格式將批註寫入,一方面是依照他的格式,並不會干擾您程式的運作。另一方面,Doxygen 所定義的都是基本程式批註應當要有的東西。撰寫清楚的批註是好的程式設計師應當的工作。
製作說明檔案
當您前面所有的步驟都正確無誤執行後,只需要執行下面的命令就可建立出您要的檔案了:
> doxygen Doxygen
如果有錯誤產生,請檢查您的Doxygen 組態檔設定是否有誤,目錄的存取許可權是否足夠。如果輸出的結果不正確,請檢查您的批註是否符合格式。批註的位置是否正確。舉例來說,您不可在說明class 的批註與class 本身插入其它的程式碼或宣告。否則Doxygen 就無法將批註與該class對應起來。
如果您使用Doxygen Wizard,可直接使用上面的Run的按鈕或選單項目來製作說明檔案。如果是產生HTML檔,在HTML_OUTPUT所指定的目錄中的index.html將是您說明檔案的首頁。
在中文繁體方面,目前我僅成功製作出HTML與RTF 格式的說明檔。其它格式的過程比較複雜,需要搭配其它工具,有待各位自行嘗試。
常見問題:
1:如何支援中文?(預設代碼裡面的中文注釋為亂碼)
修改 Step2-Expert標籤-Input-INPUT_ENCODING=cp936
2:如何產生chm?
修改 Step2-Expert標籤-HTML-CHM_FILE = D:/yours.chm
HHC_LOCATION = C:/Program Files/HTML Help Workshop/hhc.exe
附:注釋的書寫
注釋應該怎麼寫,寫多還是寫少。過多的注釋甚至會干擾對代碼的閱讀。寫注釋的一個總的原則就是注釋應該盡量用來表明作者的 意圖,至少也應該是對一部分代碼的總結,而不應該是對代碼的重複或者解釋。對代碼的重複或者解釋的代碼,看代碼可能更容易理解。反映作者意圖的注釋解釋代碼的目的,從解決問題的層次上進行注釋,而代碼總結性注釋則是從問題的解答的層次上進行注釋。
推薦的寫注釋的過程是首先使用注釋勾勒出代碼的主要架構,然後根據注釋撰寫相應的代碼。對各種主要的資料結構、輸出的函數、多個函數公用的變數進行詳細地注釋。對代碼中控制結構,單一目的的語句集進行注釋。下面是一些寫注釋時需要注意的要點:
避免對單獨語句進行注釋;
通過注釋解釋為什麼這麼做、或者要做什麼,使代碼的讀者可以只閱讀注釋理解代碼;
對讀者可能會有疑問的地方進行注釋;
對資料定義進行注釋,而不是對其使用過程進行注釋;
對於難於理解的代碼,進行改寫,而不要試圖通過注釋加以說明;
對關鍵的控制結構進行注釋;
對資料和函數的邊界、使用前提等進行注釋;