최신 Doxygen 1.4.6 버전의 사용법을 알아본다.
=== 순서 ===
1. 개요
2. 기본설정
3. 전문설정
4. 문서화 명령 사용법
5. Tips
========================================================================
1. 개요
먼저 Doxygen 을 실행시키면 다음과 같은 UI 가 나온다.
Doxygen 을 이용해서 문서를 생성하는 과정은 크게
1) 설정하기 (혹은 설정 불러오기)
2) 설정 저장하기
3) 실행하기
로 나뉘어지며 메인 UI 에서 step1,2,3,4 가 각 과정에 해당한다.
각자가 원하는 스타일의 문서를 생성하기 위해서 알아야 할 점들은 대부분 step1 설정하기에 있으므로 step1 의 메뉴를 중점적으로 파헤쳐 보자.
2. 기본설정
Step1. 문서를 생성하기 위한 각종 옵션을 설정하는 방법은 3가지가 있다.
첫번째는 Wizard 를 이용하는 방법이다. Wizard를 이용하면 복잡한 옵션설정 없이 디폴트 설정을 따라 손쉽게 여러 프로젝트를 문서화 할 수 있다.
두번째는 설정을 아주 상세하게 할 수 있는 방법이다. Expert 버튼을 누르면 자세한 설정을 위한 별도의 창이 나타난다. 자신만의 문서포맷을 설정하거나 특정 파일들만 설정하는 등등의 경우 Expert 로 설정한다.
세번째는 이미 설정된 파일을 불러오는 방법으로 Load 버튼을 누르면 불러오기 창이 뜬다.
먼저 첫번째 방법 Wizard 부터 알아보자.
Wizard 버튼을 부르면 다음과 같은 설정창이 뜬다.
첫번째 탭 Project 는 작업하고자 하는 문서화프로젝트의 개괄적 정보를 입력하는 화면이다.
Project name 과 version 칸은 적절히 이름을 부여한다.
Source code directory 에는 doxygen 으로 문서화할 소스코드가 있는 폴더를 지정한다. Scan recursively 를 체크하면 하위 폴더까지 포함하게된다. 단, Doxygen 은 한글을 지원하지만 Doxygen 프로그램에서는 한글이 지원되지 않아서 한글이 들어간 폴더를 인식하지 못한다. 소스코드가 있는 경로명에 한글이 포함되어 있다면 영어로 바꾸어야 한다.
Destination directory 는 doxygen 에서 만들어진 문서가 저장될 디렉토리를 지정한다.
Mode 탭에서는 기본적인 문서화 방법에 대한 옵션을 설정한다.
Documented entities only 를 선택하면 코드에서 문서화태그가 있는 부분만 문서화된다. 이 옵션을 선택하면 실제로는 EXTRACT_ALL, EXTRACT_PRIVATE, EXTRACT_STATIC 옵션이 제거된다.
All entities 를 체크하면 코드의 모든 부분을 문서화 한다. 특별한 이유가 없다면 All entities 를 선택한다.
Include cross-referenced source code in the output 을 체크하면 실제로는 SOURCE_BROWSER 옵션이 설정된다. 이 옵션이 설정되면 문서화된 코드의 entity 들이 실제 코드 어디에 해당하는지 그 링크를 보여준다. 문서가 좀 지저분해지는 경향이 있지만 문서를 보면서 해당 소스코드를 바로 참고할 필요가 있다면 선택한다.
아래쪽 영역은 소스코드에 있는 언어에 맞게 최적화하는 옵션으로 해당 언어를 선택해준다.
output 탭은 출력되는 포맷에 대한 정보를 설정한다.
HTML 을 체크하면 문서를 HTML 형식으로 생성한다. LaTeX 는 수학기호등을 미려하게 표현해야할 경우 체크한다. RTF 나 XML 로 만들경우 해당 옵션을 체크한다.
Diagrams 는 Doxygen 에서 생성되는 문서에 클래스들의 다이어그램을 표현하고자 할 때 사용하는 옵션이다. 미려한 클래스들의 다이그램을 보고싶다면 GraphViz 의 dot 툴을 사용하는 것이 좋으며 보고싶은 다이어그램에 체크한다. 단, GraphViz 는 Doxygen 과 별도로 설치해야 하며 Expert 설정에서 자세히 설명하기로 한다.
3. 전문 설정
Expert 버튼을 누르면 전문적인 설정을 할 수 있는 설정창이 뜬다. 이 창에는 총 17개 의 탭이 있으며 내가 살펴볼 탭들은 일반적인 문서화작업에서 중요한 Project,Build,Input, Source Browser, Dot 탭과 그 탭에서 중요한 옵션들을 살펴보도록 하겠다.
* Project 탭
BRIEF_MEMBER_DESC : 멤버 리스트 후에 멤버각각에 대한 자세한 설명을 문서화할 지 여부.
REPEAT_BRIEF : 만약 BRIEF_MEMBER_DESC 를 설정했다면 이 옵션을 켤 경우 멤버에 대한 설명이 클래스 개요 부분(보통 앞쪽)에도 나오고 멤버설명 부분에도 나온다. BRIEF_MEMBER_DESC 를 끄면 결과적으로 멤버설명 부분에만 설명이 나온다. HIDE_UNDOC_MEMBERS 와 BRIEF_MEMBER_DESC 가 다 꺼지면 이 옵션은 아무련 영향을 미치지 않는다. 또 REPEAT_BRIEF 를 끄면 brief 태그의 설명은 클래스 리스트에서만 나오고 해당 클래스 페이지에서는 출력되지 않는다.
ALWAYS_DETAIL_SEC : 항상 상세정보를 보여준다. REPEAT_BRIEF 가 같이 켜지면 개략 정보가 없어도 상세정보 영역을 생성한다.
INLINE_INHERITED_MEMB : 상속된 모든 멤버들도 보여준다. 단, 생성자와 파괴자 제외.
JAVADOC_AUTOBRIEF : QT스타일 대신 자바스타일의 주석을 BRIEF 로 해석한다. C++ 코드의 경우 체크하는 것이 좋으며, 이 옵션이 꺼지면 BRIEF 가 멀티라인으로 나타나지 않는다.
SEPARATE_MEMBER_PAGES : 멤버들에 대한 문서를 클래스와 오퍼레이션들의 설명이 있는 페이지와 분리한다. 멤버가 많을 경우 분리하는 쪽이 보기 좋다.
TAB size 는 8 이 이쁘다.
* Build 탭
EXTRACT_ALL : 클래스의 모든 멤버를 문서화한다. 단 EXTRACT_PRIVATE 과 EXTRACT_STATIC 이 체크되지 않는다면 주석없는 멤버는 보이지 않는다.
EXTRACT_LOCAL_CALSSES : 체크하지 않으면 헤더에 있는 클래스만 문서화된다.
HIDE_UNDOC_MEMBERS : 주석없는 멤버는 보여주지 않는다.
HIDE_UNDOC_CLASSES : 주석없는 클래스는 보여주지 않는다.
HIDE_IN_BODY_DOCS : 함수의 안쪽에 있는 주석을 모두 보여주지 않는다.
SORT_MEMBER_DOCS : 멤버를 알파벳순으로 보여준다. 체크안하면 선언된 순으로 보여준다.
GENERATE_TODOLIST : 문서화에 ‘관련된 페이지’ 탭이 추가되고 그 탭에서 todo tag 들만 모아서 보여주는 페이지를 생성해준다. 클래스 설명에 todo tag 를 넣으면 유용.
GENERATE_TESTLIST : 위 와 마찬가지로 test 태그의 내용만 보여주는 페이지가 추가된다.
GENERATE_BUGLIST : 마찬가지로 bug 태그의 내용만 보여주는 페이지가 추가된다.
* Input 탭
문서화할 대상을 선택한다. Wizard 를 이용할 경우 폴더만 선택할 수 있지만 여기서는 특정파일만 복수개로 선택할 수도 있다. 물론 폴더도 선택가능.
* Source Browser 탭
SOURCE_BROWSER : 소스파일의 리스트를 생성한다. 만약 문서화 소스를 상호참조하고자 한다면 체크한다. 단, 지저분 해질 수도 있다.
INLINE_SOURCES : 문서화에 구현파일의 내용도 포함한다. C++ 이라면 CPP 파일도 문서화에 포함된다. 만약 보안상 CPP 파일을 공개하지 말아야 한다면 체크 하지 말것.
* Index 탭
ALPHABETICAL_INDEX : 알파벳 순서로 클래스들의 인덱스를 만든다. 클래스들의 brief 를 표시하도록 설정했다면 클래스의 brief 가 알파벳순으로 나오므로 굳이 이 옵션을 쓸 필요 없음. (좀 지저분함)
* HTML 탭
GNENERATE_HTML : 문서를 HTML 형식으로 생성한다.
GENERATE_HTMLHELP : chm파일 형식으로 만든다. 문서화를 도움말 형태의 파일로 배포하려면 체크.
* LaTex 탭
수학 서식표현등에 적합한 LaTex 포맷으로 문서를 생성할 경우 사용
* RTF 탭
word 같은 RTF 포맷을 생성할 경우 사용
* Preprocessor
doxygen 이 소스코드를 문서화 하기 전에 소스코드와 관계하는 파일들을 미리 처리하도록 하는 기능. 문서화에 포함하지는 않지만 문서화 하는 소스파일들과 연관성이 있는 파일들을 포함시킨다.
* Dot 탭
클래스에 대한 참조와 구조의 그래프를 보여주고 싶다면 GraphViz 의 Dot 를 Doxygen 에 설치하기를 권장한다. 먼저 GraphViz 를 설치한 다음 이 탭에서 설정을 해야만 문서에 그래프가 나타난다.
DOT_PATH : Dot 가 설치된 폴더의 bin 폴더의 절대경로를 지정해준다. 그 다음 HAVE_DOT 을 꼭 체크한다.
CLASS_DIAGRAMS : 클래스의 상속구조를 보여준다.
INCLUDE_GRAPH : 클래스의 include 종속성을 그래프로 보여준다.
GRAPHICAL_HIERARCHY : 그래프를 text가 아닌 그래픽 버전으로 보여준다. 당근 필수 첵!
UML_LOOK : UML 형식으로 보여준다. 이걸 체크하면 컴파일 시간과 용량이 무지하게 증가하므로 신중히 선택할 것.
INCLUDE_GRAPH : 파일들의 include 구조를 그래프로 보여준다. 매우 유용.
DOT_IMAGE_FORMAT : 그래프들은 모두 이미지파일로 생성된다. 이미지의 포맷을 선택. png, jpg, gif 중 하나 택일. (사진이 아니므로 png 나 gif 가 jpg 보다 나은 품질과 효율을 보일지도…)
4. 문서화 명령 사용법
1) 메인페이지
doxygen 으로 만든 문서를 열면 가장 먼저 보이는 페이지가 메인페이지다. 여기에는 프로젝트의 정보, 개요 및 개발자 정보등을 기록하면 유용하다. 메인페이지를 서술하는 명령어는 mainpage 이다. 이 명령을 특정 소스코드가 있는 헤더파일에 적기 보다는 메인페이지만을 위한 별도의 파일에 쓰는것이 더욱 깔끔하다. Mainpage.dox 라는 파일을 만들고 편집기로 넣어 다음과 같이 쓴다.
[mainpage.dox 파일 예제]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/** \mainpage Doxygen Test \section 프로젝트 설명 - 설명 블라블라 \section 소스 작성자 - 날나리 \section 추가정보 - 글머리는 '-' 태그를 사용하면 되며 - 탭으로 들여쓸경우 하위 항목이 된다. -# 번호매기기는 '-#' 방식으로 할수 있다. -# 위와 같이 탭으로 들여쓸경우 하위 항목이 된다. -# 두번째 하위 항목 - 그림을 넣으려면 다음과 같이 \image html 그림.jpg */ |
2) 클래스 설명
특정 클래스에 대한 설명을 만들면 해당 클래스 페이지 상단에 설명이 출력된다. 클래스의 용도, 제작자 등을 기입하면 유용하다. 먼저 클래스가 선언된 헤더파일을 열고 클래스 이름 위에 다음과 같은 주석을 삽입하면 된다.
1 2 3 4 5 6 7 8 9 10 11 |
/** \brief CNPhoneCommand 의 실행결과에 대한 옵저버 인터페이스 \remarks 잘 사용합시다. \return 리턴값 없어요. \par 적절한 것들... - 들여쓰기 - 탭으로 동작 \author taekwonv */ template <class T> class ICommandObservable {}; |
3) 그룹핑
클래스의 수가 많을 경우 ygen 으로 문서를 만들어보면 전체 구조를 파악하기가 힘들다. 수많은 클래스들이 그냥 나열되어 있기 때문이다. 이럴때는 비슷한 역할을 하는 클래스들 끼리 그룹을 만들고 그룹별로 구조화 시키면 보다 구조적이고 사용성이 높은 문서를 만들 수 있다. 이렇게 그룹핑한 클래스들은 doxygen 으로 만든 문서에서 모듈 탭에 구조적으로 출력된다. 아래의 예제를 참고.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
/** @defgroup group1 The First Group //그룹을 정의 * This is the first group * @{ */ /** @brief class C1 in group 1 */ class C1 {}; /** @brief class C2 in group 1 */ class C2 {}; /** function in group 1 */ void func() {} /** @} */ // end of group1 // 그룹 정의를 끝냄. 정의 안쪽에 있는 클래스는 죄다 이 그룹소속 // 이제 그룹정의 부터 먼저 하고 코드에서 해당 그룹에 속하도록 해보자. /** * @defgroup group2 The Second Group // 그룹을 정의 * This is the second group */ /** @defgroup group3 The Third Group // 그룹을 정의 * This is the third group */ /** @defgroup group4 The Fourth Group // 그룹을 정의 * @ingroup group3 // group4 는 group3 의 서브그룹으로 정의 * Group 4 is a subgroup of group 3 */ // 이제 코드에서 정의된 그룹을 사용해보자. /** * @ingroup group2 // 그룹2에 속한다고 정의 * @brief class C3 in group 2 */ class C3 {}; /** @ingroup group2 // 그룹2에 속한다고 정의 * @brief class C4 in group 2 */ class C4 {}; /** @ingroup group3 // 그룹3에 속한다고 정의 * @brief class C5 in @link group3 the third group@endlink. */ class C5 {}; /** @ingroup group1 group2 group3 group4 // N1 namespace가 1,2,3,4 모두에 속한다고 정의. (이 namespace 설명이 각 그룹에 다 나타난다.) * namespace N1 is in four groups * @sa @link group1 The first group@endlink, group2, group3, group4 * * Also see @ref mypage2 */ namespace N1 {}; /** @file * @ingroup group3 * @brief this file in group 3 */ /** @defgroup group5 The Fifth Group * This is the fifth group * @{ */ /** @page mypage1 This is a section in group 5 * Text of the first section */ /** @page mypage2 This is another section in group 5 * Text of the second section */ /** @} */ // end of group5 /** @addtogroup group1 * * More documentation for the first group. * @{ */ /** another function in group 1 */ void func2() {} /** yet another function in group 1 */ void func3() {} /** @} */ // end of group1 |
4) Predefine
표준 C++ 구문이 아니거나 개발자가 직접 정의한 전처리문 혹은 MFC 나 ATL 의 전처리문이 있을 경우 doxygen 이 이를 제대로 parsing 할 수 없다. 이럴 경우에는 PREDEFINE 옵션을 사용한다.
example 1)
C++ 에서 interface 키워드를 사용할 경우 doxygen 은 이를 class 와 같은 레벨의 엔티티로 취급하지 않아서 문서화 되지 않는다. 이럴경우 Exper/Perprosessor 탭에 들어가서 MACRO_EXPANSION 를 체크한 뒤 PREDEFINED 란에서 “interface=class” 를 추가하면 doxygen이 코드를 파싱하기 전에 interface 키워드를 class 로 치환하므로 class 와 같이 취급된다.
example 2)
다음은 MFC 와 ATL 을 위한 PREDEFINE 의 예제
1 |
PREDEFINED = "DECLARE_INTERFACE(name)=class name" \ "STDMETHOD(result,name)=virtual result name" \ "PURE= = 0" \ THIS_= \ THIS= \ DECLARE_REGISTRY_RESOURCEID=// \ DECLARE_PROTECT_FINAL_CONSTRUCT=// \ "DECLARE_AGGREGATABLE(Class)= " \ "DECLARE_REGISTRY_RESOURCEID(Id)= " \ DECLARE_MESSAGE_MAP= \ BEGIN_MESSAGE_MAP=/* \ END_MESSAGE_MAP=*/// \ BEGIN_COM_MAP=/* \ END_COM_MAP=*/// \ BEGIN_PROP_MAP=/* \ END_PROP_MAP=*/// \ BEGIN_MSG_MAP=/* \ END_MSG_MAP=*/// \ BEGIN_PROPERTY_MAP=/* \ END_PROPERTY_MAP=*/// \ BEGIN_OBJECT_MAP=/* \ END_OBJECT_MAP()=*/// \ DECLARE_VIEW_STATUS=// \ "STDMETHOD(a)=HRESULT a" \ "ATL_NO_VTABLE= " \ "__declspec(a)= " \ BEGIN_CONNECTION_POINT_MAP=/* \ END_CONNECTION_POINT_MAP=*/// \ "DECLARE_DYNAMIC(class)= " \ "IMPLEMENT_DYNAMIC(class1, class2)= " \ "DECLARE_DYNCREATE(class)= " \ "IMPLEMENT_DYNCREATE(class1, class2)= " \ "IMPLEMENT_SERIAL(class1, class2, class3)= " \ "DECLARE_MESSAGE_MAP()= " \ TRY=try \ "CATCH_ALL(e)= catch(...)" \ END_CATCH_ALL= \ "THROW_LAST()= throw"\ "RUNTIME_CLASS(class)=class" \ "MAKEINTRESOURCE(nId)=nId" \ "IMPLEMENT_REGISTER(v, w, x, y, z)= " \ "ASSERT(x)=assert(x)" \ "ASSERT_VALID(x)=assert(x)" \ "TRACE0(x)=printf(x)" \ "OS_ERR(A,B)={ #A, B }" \ __cplusplus \ "DECLARE_OLECREATE(class)= " \ "BEGIN_DISPATCH_MAP(class1, class2)= " \ "BEGIN_INTERFACE_MAP(class1, class2)= " \ "INTERFACE_PART(class, id, name)= " \ "END_INTERFACE_MAP()=" \ "DISP_FUNCTION(class, name, function, result, id)=" \ "END_DISPATCH_MAP()=" \ "IMPLEMENT_OLECREATE2(class, name, id1, id2, id3, id4,\ id5, id6, id7, id8, id9, id10, id11)=" |
5) 예제 코드 삽입방법
특정 함수나 클래스의 예제코드를 만들고 문서에 예제 코드를 링크시키고 싶을 때 다음과 같이 예제파일을 작성하고 doxygen 으로 생성된 문서에 링크가 삽입되도록 할 수 있다.
* 특정 함수에 대한 예제파일을 링크하고 싶다면
* 다음과 같이 함수 설명 아래에 @example 명령을 써준다. 뒤 파라미터는 예제코드가 있는 파일 이름.
1 2 3 4 5 6 |
/** * 이 함수는 블라블라 입니다. * @return 성공시 true */ bool MyFunc(); ///< @example ex_MyFunc.cpp |
* doxygen 설정에서 EXAMPLE_PATH 에 ex_MyFunc.cpp 파일이 있는 폴더를 지정해준다.
주의) example 명령은 함수 바로 아래에 쓴다. 함수 설명 주석과 같이 쓰면 doxygen 으로 생성된 문서에서 예제 코드 위에 함수 설명이 같이 나오므로 적절치 않다. 또 예제 파일은 소스와 다른 폴더에 두는게 좋다. 같은 폴더에 있으면 cpp 파일 확장명으로 인해 소스코드 문서화에 포함되기 때문.
5. Tips
몇가지 팁들에 대해 알아보자. (사용하면서 지속적으로 추가하고 있음)
– C++ Keyword ‘interface’ 는 인식되지 않는다?
: pure virtual 클래스를 정의하기 위해 interface 키워드를 쓰면 문서화에서 제외된다. class 를 써야 doxygen 에서 문서를 생성한다. (Predefine을 써서 해결가능하다.)
– brief 명령의 내용은 클래스리스트에서도 내용이 표시되므로 모든 클래스에 쓰는게 좋다.
– 장문의 단락을 만들경우 줄바꿈이 필요할 수 있다. 이럴 경우 HTML 태그
을 사용하면 된다.
– 서식을 꾸미려면 HTML 태그를 쓰면 된다. (물론 결과물이 HTML일 경우)
아래는 dot 로 만들어진 클래스다이어그램의 범례이다. 표준UML 과 다른점이 있으므로 참고할 것.
상자들은 다음을 뜻한다.
– 검은 상자는 그래프를 산출한 구조체나 클래스를 말한다.
– 검은선으로된 상자는 문서화된 구조체나 클래스를 표시한다.
– 회색선으로된 상자는 문서화되지 않은 구조체나 클래스를 표시한다.
– 빨간선으로된 상자는 모든 상속/containment 관계를 보이지 않은 문서화된 구조체나 클래스를 나타낸다. 지정된 경계안에 들어가지 않으면 그래프는 짤려진다.
화살표는 다음을 뜻한다.
– 어두운 파란 화살표는 두 클래스간의 public 상속관계를 나타낸다.
– 어두운 녹색 화살표는 protected 상속관계를 나타낸다.
– 어두운 빨강 화살표는 private 상속관계를 나타낸다.
– 밝은 자주색 화살표는 클래스에 의해 포함되거나 사용된 클래스를 나타낸다. 이 화살표의 라벨은 접근 가능한 변수명을 나타낸다.
– 밝은 노랑색 화살표는 템플릿 인스턴스와 템플릿 클래스를 나타낸다. 이 화살표의 라벨은 그 인스턴스의 템플릿 매개변수를 나타낸다.
이상으로 Doxygen 을 이용해 최소한의 문서화 작업을 핸들링할 수 있는 사용법을 알아보았다. 나머지 옵션들은 디폴트를 사용하면 큰 무리가 없을 것으로 보이며, 이 외에 세세한 설정은 http://www.stack.nl/~dimitri/doxygen/manual.html 에서 매뉴얼을 참고하기 바란다.
참고 : http://cafe.naver.com/architect1/5