CMakeのビルドターゲットに関連付けされたDoxygenを実行する

CMakeのターゲット設定を流用してDoxygen文書を半自動で作る。
## 確認した環境
Ubuntu16.04(をVirtualBoxで動かしたもの)

## 準備
``` bash:graphvizのインストール
sudo apt-get install graphviz
```
確か上記が必要だった気がする。

## ファイル配置
``` :Direcroty構成
.
└── Qiita
    ├── CMakeLists.txt
    ├── Doxygen
    │   ├── Doxyfile.in
    │   ├── doxygen-script.cmake
    │   └── doxygen.cmake
    └── main.cpp
```
```cmake:Qiita/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)

# add_doxygen(という自作関数)を使えるようにする
include(Doxygen/doxygen.cmake) 

set(SOURCE_FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
    )

add_executable(Hello ${SOURCE_FILES})

# Helloを対象にしたDoxygen出力をできるようにする
add_doxygen(Hello)
```
```cpp:Qiita/main.cpp
#include <iostream>

int main(void){
    std::cout << "Hello World!" << std::endl;
}
```
``` cmake:Doxygen/doxygen.cmake
find_package(Doxygen)

if (DOXYGEN_FOUND)
    # Doxygenがある場合のみ"make doxygen"というmakeのターゲットを用意しておく
    add_custom_target(doxygen)
endif ()

# add_doxygen関数
# @brief 個別のビルド対象に対する"make doxygen-${targetname}"を作り、
# "make doxygen"に関連つける関数
# @param targetname ビルド対象(add_executable,add_libraryで指定する名前を入れる)
function (add_doxygen targetname)
    # Doxygenないときは空関数
    if (NOT DOXYGEN_FOUND)
        return()
    endif ()

    #~~~~~~~~準備の作業~~~~~~~~#
    # Doxygen関連ファイル置き場へのパス
    set(doxydir ${CMAKE_SOURCE_DIR}/Doxygen)

    # CMakeコマンド実行した場所に/DoxyDocを作り、そこに実行結果を保存する
    set(outputdir ${CMAKE_BINARY_DIR}/DoxyDoc)

    # Doxygenが受け取れるようにソースファイルをスペース区切りtextにする
    get_property(sourcefiles
        TARGET ${targetname}
        PROPERTY SOURCES)
    foreach (source ${sourcefiles})
        set(source_spaces "${source_spaces} ${source}")
    endforeach ()

    # ソースファイルと同じ階層もインクルードパス扱いとする(.hを探すため)
    foreach (source ${sourcefiles})
        get_filename_component(source_dir ${source} DIRECTORY)
        set(source_dirs ${source_dirs} ${source_dir})
    endforeach ()

    # Doxygenが受け取れるようにインクルードパスをスペース区切りtextにする
    get_property(includedirs
        TARGET ${targetname}
        PROPERTY INCLUDE_DIRECTORIES)
    # 事前にインクルードパス扱いディレクトリをまとめてから・・
    list(APPEND includedirs ${source_dirs})
    list(REMOVE_DUPLICATES includedirs)
    # スペース区切りにする
    foreach (dir ${includedirs})
        set(dir_spaces "${dir_spaces} ${dir}")
    endforeach ()

    # インクルードパスにある.hもDoxygenのINPUT対象にする
    foreach (dir ${includedirs})
        file(GLOB headers ${dir}/*.h)
        foreach (h ${headers})
            set(header_spaces "${header_spaces} ${h}")
        endforeach ()
    endforeach ()

    # Doxygenが受け取れるように-Dのビルド時defineマクロをスペース区切りtextにする
    get_property(definitions
        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        PROPERTY COMPILE_DEFINITIONS)
    foreach (def ${definitions})
        set(predef_spaces "${predef_spaces} ${def}")
    endforeach ()

    #~~~~~~~~本番の作業~~~~~~~~#
    # mkdir相当の処理。依存関係解消のためにここから実際に実施されていくはず。
    add_custom_command(
        OUTPUT  ${outputdir}/${targetname}
        COMMAND cmake -E make_directory ${outputdir}/${targetname}
        COMMENT "Creating documentation directory for ${targetname}")

    # Doxyfile.inからDoxyfileを作る処理。そのためにはmkdir相当の処理が必要。
    add_custom_command(
        OUTPUT  ${outputdir}/${targetname}/Doxyfile
        COMMAND ${CMAKE_COMMAND}
                -D "DOXYGEN_TEMPLATE=${doxydir}/Doxyfile.in"
                -D "DOXY_PROJECT_INPUT=${source_spaces} ${header_spaces}"
                -D "DOXY_PROJECT_INCLUDE_DIR=${dir_spaces}"
                -D "DOXY_PROJECT_PREDEFINED=${predef_spaces}"
                -D "DOXY_PROJECT_STRIP_FROM_PATH=${CMAKE_SOURCE_DIR}"
                -D "DOXY_DOCUMENTATION_OUTPUT_PATH=${outputdir}"
                -D "DOXY_PROJECT_NAME=${targetname}"
                -P "${doxydir}/doxygen-script.cmake"
        DEPENDS ${doxydir}/Doxyfile.in
                ${outputdir}/${targetname}
        WORKING_DIRECTORY
                ${outputdir}/${targetname}
        COMMENT "Generating Doxyfile for ${targetname}")

    # Doxygenコマンドを実際に実行しindex.htmlを作る。そのためにはDoxyfileが必要。
    add_custom_command(
        OUTPUT  ${outputdir}/${targetname}/index.html
        COMMAND ${DOXYGEN_EXECUTABLE}
        DEPENDS ${outputdir}/${targetname}/Doxyfile
        WORKING_DIRECTORY
                ${outputdir}/${targetname}
        COMMENT "Creating HTML documentation for ${targetname}")

    # "make doxygen-${targetname}"により、ピンポイントでdoxygen実行できる
    add_custom_target(doxygen-${targetname}
        DEPENDS ${outputdir}/${targetname}/index.html)

    # "make doxygen"に"make doxygen-${targetname}"を登録する（依存させる）
    add_dependencies(doxygen
        doxygen-${targetname})

endfunction ()
```
``` cmake:Doxygen/doxygen-script.cmake
configure_file(
    "${DOXYGEN_TEMPLATE}"
    "${DOXY_DOCUMENTATION_OUTPUT_PATH}/${DOXY_PROJECT_NAME}/Doxyfile"
    @ONLY)
```
``` cmake:Doxygen/Doxyfile.in
# 省略。ターミナルで
# doxygen -g
# したときに生成されるDoxyfileをDoxyfile.inにリネームしてから、
# 下記に示すdiffファイル相当の変更を適用したもの。
```
``` diff:doxygen_diff.diff
diff --git a/Doxygen/Doxyfile.in b/Doxygen/Doxyfile.in
index f8dd586..1dba11e 100644
--- a/Doxygen/Doxyfile.in
+++ b/Doxygen/Doxyfile.in
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING      = UTF-8
 # title of most generated pages and in a few other places.
 # The default value is: My Project.
 
-PROJECT_NAME           = "My Project"
+PROJECT_NAME           = @DOXY_PROJECT_NAME@
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
 # could be handy for archiving the generated documentation or if some version
@@ -58,7 +58,7 @@ PROJECT_LOGO           =
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       =
+OUTPUT_DIRECTORY       = @DOXY_DOCUMENTATION_OUTPUT_PATH@/@DOXY_PROJECT_NAME@
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -68,7 +68,7 @@ OUTPUT_DIRECTORY       =
 # performance problems for the file system.
 # The default value is: NO.
 
-CREATE_SUBDIRS         = NO
+CREATE_SUBDIRS         = YES
 
 # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
 # characters to appear in the names of generated files. If set to NO, non-ASCII
@@ -118,7 +118,17 @@ REPEAT_BRIEF           = YES
 # the entity):The $name class, The $name widget, The $name file, is, provides,
 # specifies, contains, represents, a, an and the.
 
-ABBREVIATE_BRIEF       =
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
 
 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
 # doxygen will generate a detailed section even if there is only a brief
@@ -152,7 +162,7 @@ FULL_PATH_NAMES        = YES
 # will be relative from the directory where doxygen is started.
 # This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
-STRIP_FROM_PATH        =
+STRIP_FROM_PATH        = @DOXY_PROJECT_STRIP_FROM_PATH@
 
 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
 # path mentioned in the documentation of a class, which tells the reader which
@@ -416,25 +426,25 @@ LOOKUP_CACHE_SIZE      = 0
 # normally produced when WARNINGS is set to YES.
 # The default value is: NO.
 
-EXTRACT_ALL            = NO
+EXTRACT_ALL            = YES
 
 # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
 # be included in the documentation.
 # The default value is: NO.
 
-EXTRACT_PRIVATE        = NO
+EXTRACT_PRIVATE        = YES
 
 # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
 # scope will be included in the documentation.
 # The default value is: NO.
 
-EXTRACT_PACKAGE        = NO
+EXTRACT_PACKAGE        = YES
 
 # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
 # included in the documentation.
 # The default value is: NO.
 
-EXTRACT_STATIC         = NO
+EXTRACT_STATIC         = YES
 
 # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
 # locally in source files will be included in the documentation. If set to NO,
@@ -538,7 +548,7 @@ SHOW_GROUPED_MEMB_INC  = NO
 # files with double quotes in the documentation rather than with sharp brackets.
 # The default value is: NO.
 
-FORCE_LOCAL_INCLUDES   = NO
+FORCE_LOCAL_INCLUDES   = YES
 
 # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
 # documentation for inline members.
@@ -705,7 +715,7 @@ CITE_BIB_FILES         =
 # messages are off.
 # The default value is: NO.
 
-QUIET                  = NO
+QUIET                  = YES
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are
 # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
@@ -737,7 +747,7 @@ WARN_IF_DOC_ERROR      = YES
 # parameter documentation, but not about the absence of documentation.
 # The default value is: NO.
 
-WARN_NO_PARAMDOC       = NO
+WARN_NO_PARAMDOC       = YES
 
 # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
 # a warning is encountered.
@@ -759,7 +769,8 @@ WARN_FORMAT            = "$file:$line: $text"
 # messages should be written. If left blank the output is written to standard
 # error (stderr).
 
-WARN_LOGFILE           =
+WARN_LOGFILE           = @DOXY_DOCUMENTATION_OUTPUT_PATH@/@DOXY_PROJECT_NAME@.warnings
+
 
 #---------------------------------------------------------------------------
 # Configuration options related to the input files
@@ -771,7 +782,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  =
+INPUT                  = @DOXY_PROJECT_INPUT@
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -851,7 +862,7 @@ EXAMPLE_PATH           =
 # *.h) to filter out the source-files in the directories. If left blank all
 # files are included.
 
-EXAMPLE_PATTERNS       =
+EXAMPLE_PATTERNS       = *
 
 # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
 # searched for input files to be used with the \include or \dontinclude commands
@@ -952,13 +963,13 @@ STRIP_CODE_COMMENTS    = YES
 # function all documented functions referencing it will be listed.
 # The default value is: NO.
 
-REFERENCED_BY_RELATION = NO
+REFERENCED_BY_RELATION = YES
 
 # If the REFERENCES_RELATION tag is set to YES then for each documented function
 # all documented entities called/used by that function will be listed.
 # The default value is: NO.
 
-REFERENCES_RELATION    = NO
+REFERENCES_RELATION    = YES
 
 # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
 # to YES then the hyperlinks from functions in REFERENCES_RELATION and
@@ -1068,7 +1079,7 @@ GENERATE_HTML          = YES
 # The default directory is: html.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_OUTPUT            = html
+HTML_OUTPUT            =
 
 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
 # generated HTML page (for example: .htm, .php, .asp).
@@ -1604,7 +1615,7 @@ EXTRA_SEARCH_MAPPINGS  =
 # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
 # The default value is: YES.
 
-GENERATE_LATEX         = YES
+GENERATE_LATEX         = NO
 
 # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
 # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -2019,7 +2030,7 @@ SEARCH_INCLUDES        = YES
 # preprocessor.
 # This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
-INCLUDE_PATH           =
+INCLUDE_PATH           = @DOXY_PROJECT_INCLUDE_DIR@
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2037,7 +2048,7 @@ INCLUDE_FILE_PATTERNS  =
 # recursively expanded use the := operator instead of the = operator.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             =
+PREDEFINED             = @DOXY_PROJECT_PREDEFINED@
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
 # tag can be used to specify a list of macro names that should be expanded. The
```

## 使い方
### まずはCMakeする
```bash
mkdir build
cd build
cmake ../Qiita
```

### Doxygen関連のビルド
#### make doxygen
```bash
# すべてのadd_doxygen()済みターゲットに対するDoxygen文書を作成
make doxygen
```
#### make doxygen-[target_name]
```bash
# 指定したadd_doxygen()済みターゲットに対するDoxygen文書を作成
make doxygen-Hello
```

### Doxygen文書ができる場所: [build_dir]/DoxyDoc/[target_name]/html

``` bash
firefox DoxyDoc/Hello/html/index.html
```

## 参考
[qtextensions/cmake at master · Kitware/qtextensions](https://github.com/Kitware/qtextensions/tree/master/cmake)
ググったら出てきた上記をよくわからないまま写経してから、改造(改悪?)した。

## 感想
なんだか重いような気がします。