# ============================================================================ # Copyright (c) 2011-2012 University of Pennsylvania # Copyright (c) 2013-2014 Carnegie Mellon University # Copyright (c) 2013-2014 Andreas Schuh # All rights reserved. # # See COPYING file for license information or visit # http://opensource.andreasschuh.com/cmake-basis/download.html#license # ============================================================================ ############################################################################## # @file DocTools.cmake # @brief Tools related to gnerating or adding software documentation. # # @ingroup CMakeTools ############################################################################## if (__BASIS_DOCTOOLS_INCLUDED) return () else () set (__BASIS_DOCTOOLS_INCLUDED TRUE) endif () # ============================================================================ # adding / generating documentation # ============================================================================ # ---------------------------------------------------------------------------- ## @brief Add documentation target. # # This function is used to add a software documentation files to the project # which are either just copied to the installation or generated from input # files such as in particular source code files and documentation files # marked up using one of the supported lightweight markup languages. # # The supported generators are: # <table border="0"> # <tr> # @tp @b None @endtp # <td>This generator simply installs the given file or all files within # the specified directory.</td> # </tr> # <tr> # @tp @b Doxygen @endtp # <td>Used to generate API documentation from in-source code comments and # other related files marked up using Doxygen comments. See # basis_add_doxygen_doc() for more details.</td> # </tr> # <tr> # @tp @b Sphinx @endtp # <td>Used to generate documentation such as a web site from reStructuredText. # See basis_add_sphinx_doc() for more details.</td> # </tr> # </table> # # @param [in] TARGET_NAME Name of the documentation target or file. # @param [in] ARGN Documentation generator as "GENERATOR generator" option # and additional arguments for the particular generator. # The case of the generator name is ignored, i.e., # @c Doxygen, @c DOXYGEN, @c doxYgen are all valid arguments # which select the @c Doxygen generator. The default generator # is the @c None generator.</td> # # @returns Adds a custom target @p TARGET_NAME for the generation of the # documentation. # # @sa basis_install_doc() # @sa basis_add_doxygen_doc() # @sa basis_add_sphinx_doc() # # @ingroup CMakeAPI function (basis_add_doc TARGET_NAME) CMAKE_PARSE_ARGUMENTS (ARGN "" "GENERATOR" "" ${ARGN}) if (NOT ARGN_GENERATOR) set (ARGN_GENERATOR "NONE") else () string (TOUPPER "${ARGN_GENERATOR}" ARGN_GENERATOR) endif () if (ARGN_GENERATOR MATCHES "NONE") basis_install_doc (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS}) elseif (ARGN_GENERATOR MATCHES "DOXYGEN") basis_add_doxygen_doc (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS}) elseif (ARGN_GENERATOR MATCHES "SPHINX") basis_add_sphinx_doc (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS}) else () message (FATAL_ERROR "Unknown documentation generator: ${ARGN_GENERATOR}.") endif () endfunction () # ---------------------------------------------------------------------------- ## @brief Install documentation file(s). # # This function either adds an installation rule for a single documentation # file or a directory containing multiple documentation files. # # Example: # @code # basis_install_doc ("User Manual.pdf" OUTPUT_NAME "BASIS User Manual.pdf") # basis_install_doc (DeveloperManual.docx COMPONENT dev) # basis_install_doc (SourceManual.html COMPONENT src) # @endcode # # @param [in] SOURCE Documentation file or directory to install. # @param [in] ARGN List of optional arguments. Valid arguments are: # @par # <table border="0"> # <tr> # @tp @b COMPONENT component @endtp # <td>Name of the component this documentation belongs to. # Defaults to @c BASIS_RUNTIME_COMPONENT.</td> # </tr> # <tr> # @tp @b DESTINATION dir @endtp # <td>Installation directory prefix. Defaults to @c INSTALL_DOC_DIR.</td> # </tr> # <tr> # @tp @b OUTPUT_NAME name @endtp # <td>Name of file or directory after installation.</td> # </tr> # </table> # # @sa basis_add_doc() function (basis_install_doc SOURCE) CMAKE_PARSE_ARGUMENTS (ARGN "" "COMPONENT;DESTINATION;OUTPUT_NAME" "" ${ARGN}) if (NOT IS_ABSOLUTE "${SOURCE}") get_filename_component (SOURCE "${SOURCE}" ABSOLUTE) endif () if (NOT ARGN_DESTINATION) set (ARGN_DESTINATION "${INSTALL_DOC_DIR}") endif () if (NOT ARGN_COMPONENT) set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}") endif () if (NOT ARGN_COMPONENT) set (ARGN_COMPONENT "Unspecified") endif () if (NOT ARGN_OUTPUT_NAME) basis_get_filename_component (ARGN_OUTPUT_NAME "${SOURCE}" NAME) endif () basis_get_relative_path ( RELPATH "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${ARGN_OUTPUT_NAME}" ) message (STATUS "Adding documentation ${RELPATH}...") if (IS_DIRECTORY "${SOURCE}") basis_install_directory ( "${SOURCE}" "${ARGN_DESTINATION}/${ARGN_OUTPUT_NAME}" COMPONENT "${ARGN_COMPONENT}" ) else () install ( FILES "${SOURCE}" DESTINATION "${ARGN_DESTINATION}" COMPONENT "${ARGN_COMPONENT}" RENAME "${ARGN_OUTPUT_NAME}" ) endif () message (STATUS "Adding documentation ${RELPATH}... - done") endfunction () # ---------------------------------------------------------------------------- ## @brief Add documentation to be generated by Doxygen. # # This function adds a build target to generate documentation from in-source # code comments and other related project pages using # <a href="http://www.stack.nl/~dimitri/doxygen/index.html">Doxygen</a>. # # @param [in] TARGET_NAME Name of the documentation target. # @param [in] ARGN List of arguments. The valid arguments are: # @par # <table border="0"> # <tr> # @tp @b EXCLUDE_FROM_DOC @endtp # <td>By default, the specified target is build as part of the global # @c doc target. If this option is given, however, the added # documentation will not be build as part of this target.</td> # </tr> # <tr> # @tp @b COMPONENT component @endtp # <td>Name of the component this documentation belongs to. # Defaults to @c BASIS_LIBRARY_COMPONENT.</td> # </tr> # <tr> # @tp @b DESTINATION dir @endtp # <td>Installation directory prefix. Defaults to # @c BASIS_INSTALL_<TARGET>_DIR in case of HTML output if set. # Otherwise, the generated HTML files are not installed.</td> # </tr> # <tr> # @tp @b DOXYFILE file @endtp # <td>Name of the template Doxyfile.</td> # </tr> # <tr> # @tp @b PROJECT_NAME name @endtp # <td>Value for Doxygen's @c PROJECT_NAME tag which is used to # specify the project name.@n # Default: @c PROJECT_NAME.</td> # </tr> # <tr> # @tp @b PROJECT_NUMBER version @endtp # <td>Value for Doxygen's @c PROJECT_NUMBER tag which is used # to specify the project version number.@n # Default: @c PROJECT_RELEASE.</td> # </tr> # <tr> # @tp @b PROJECT_WEBSITE url @endtp # <td>Used for links to project website.@n # Default: @c PROJECT_PACKAGE_WEBSITE </td> # </tr> # <tr> # @tp @b INPUT path1 [path2 ...] @endtp # <td>Value for Doxygen's @c INPUT tag which is used to specify input # directories/files. Any given input path is added to the default # input paths.@n # Default: @c PROJECT_CODE_DIRS, @c BINARY_CODE_DIR, # @c PROJECT_INCLUDE_DIRS, @c BINARY_INCLUDE_DIR.</td> # </tr> # <tr> # @tp @b EXCLUDE_BASIS_MODULES @endtp # <td>Do not add project CMake files used and generated by BASIS to @b INPUT.</td> # </tr> # <tr> # @tp @b EXCLUDE_BASIS_UTILITIES @endtp # <td>Do not add documentation (.dox) files for used CMake BASIS Utilities to @b INPUT.</td> # </tr> # <tr> # @tp @b INPUT_FILTER filter @endtp # <td> # Value for Doxygen's @c INPUT_FILTER tag which can be used to # specify a default filter for all input files.@n # Default: @c doxyfilter of BASIS. # </td> # </tr> # <tr> # @tp @b FILTER_PATTERNS pattern1 [pattern2...] @endtp # <td>Value for Doxygen's @c FILTER_PATTERNS tag which can be used to # specify filters on a per file pattern basis.@n # Default: None.</td> # </tr> # <tr> # @tp @b INCLUDE_PATH path1 [path2...] @endtp # <td>Doxygen's @c INCLUDE_PATH tag can be used to specify one or more # directories that contain include files that are not input files # but should be processed by the preprocessor. Any given directories # are appended to the default include path considered. # Default: Directories added by basis_include_directories().</td> # </tr> # <tr> # @tp @b EXCLUDE_PATTERNS pattern1 [pattern2 ...] @endtp # <td>Additional patterns used for Doxygen's @c EXCLUDE_PATTERNS tag # which can be used to specify files and/or directories that # should be excluded from the INPUT source files.@n # Default: No exclude patterns.</td> # </tr> # <tr> # @tp @b PREDEFINED name1|name1=value1 [name2|name2=value2...] @endtp # <td>Add preprocessor definitions to be expanded by Doxygen.</td> # </tr> # <tr> # @tp @b OUTPUT fmt @endtp # <td>Specify output formats in which to generate the documentation. # Currently, only @c html and @c xml are supported.</td> # </tr> # <tr> # @tp @b OUTPUT_DIRECTORY dir @endtp # <td>Value for Doxygen's @c OUTPUT_DIRECTORY tag which can be used to # specify the output directory. The output files are written to # subdirectories named "html", "latex", "rtf", and "man".@n # Default: <tt>CMAKE_CURRENT_BINARY_DIR/TARGET_NAME</tt>.</td> # </tr> # <tr> # @tp @b COLS_IN_ALPHA_INDEX n @endtp # <td>Number of columns in alphabetical index. Default: 3.</td> # </tr> # <tr> # @tp @b IGNORE_PREFIX prefix1 [prefix2...] @endtp # <td>In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers.</td> # </tr> # <tr> # @tp @b PROVIDER_NAME name @endtp # <td>Value for provider name, such as a company name, # that will be used for pages in the doxygen output.@n # Default: @c PROJECT_PROVIDER_NAME.</td> # </tr> # <tr> # @tp @b PROVIDER_WEBSITE url @endtp # <td>Value for provider website, such as a company website, # that will be used for pages in the doxygen output.@n # Default: @c PROJECT_PROVIDER_WEBSITE.</td> # </tr> # <tr> # @tp @b PROVIDER_LOGO image_file @endtp # <td>Value for provider logo file, such as a company logo, # that will be used for pages in the doxygen output.@n # Default: @c PROJECT_PROVIDER_LOGO.</td> # </tr> # <tr> # @tp @b DIVISION_NAME name @endtp # <td>Value for division name, such as a company division name, # that will be used for pages in the doxygen output.@n # Default: @c PROJECT_DIVISION_NAME.</td> # </tr> # <tr> # @tp @b DIVISION_WEBSITE url @endtp # <td>Value for division website, such as a company division website, # that will be used for pages in the doxygen output.@n # Default: @c PROJECT_DIVISION_WEBSITE.</td> # </tr> # <tr> # @tp @b DIVISION_LOGO image_file @endtp # <td>Value for division logo file, such as a company division logo, # that will be used for pages in the doxygen output.@n # Default: @c PROJECT_DIVISION_LOGO.</td> # </tr> # <tr> # @tp @b ENABLED_SECTIONS section1 [section2 ...] @endtp # <td>The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by "\if sectionname ... \endif".</td> # </tr> # <tr> # @tp @b HTML_HEADER html_file @endtp # <td>The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If none specified, the # @c "PROJECT_SOURCE_DIR/doc/doxygen_header.html(.in)?" file is used if present. # Otherwise, a default header is used. Specify the value @c Doxygen to use the # standard header generated by Doxygen instead.</td> # </tr> # <tr> # @tp @b HTML_FOOTER html_file @endtp # <td>The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If none specified, the # @c "PROJECT_SOURCE_DIR/doc/doxygen_footer.html(.in)?" file is used if present. # Otherwise, a default footer is used. Specify the value @c Doxygen to use the # standard footer generated by Doxygen instead.</td> # </tr> # <tr> # @tp @b HTML_EXTRA_STYLESHEET css_file @endtp # <td>The HTML_EXTRA_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If none specified, the # @c "PROJECT_SOURCE_DIR/doc/doxygen_extra.css(.in)?" file is used if present.</td> # </tr> # <tr> # @tp @b HTML_EXTRA_FILES file1 [file2...] @endtp # <td>The HTML_EXTRA_FILES tag can be used to specify additional files needed # for the HTML output of the API documentation.</td> # </tr> # <tr> # @tp @b DISABLE_PROJECT_NAME_DISPLAY@endtp # <td>The DISABLE_PROJECT_NAME_DISPLAY option causes Doxygen's # @c PROJECT_NAME text not to be displayed in the header. # Use this if the project name is already part of the logo # so it won't be there twice in the logo image and title text.</td> # </tr> # </table> # @n # See <a href="http://www.stack.nl/~dimitri/doxygen/manual/config.html">here</a> for a # documentation of the Doxygen tags. # @n@n # Example: # @code # basis_add_doxygen_doc ( # apidoc # DOXYFILE "Doxyfile.in" # PROJECT_NAME "${PROJECT_NAME}" # PROJECT_VERSION "${PROJECT_VERSION}" # COMPONENT dev # ) # @endcode # # @sa basis_add_doc() function (basis_add_doxygen_doc TARGET_NAME) # check target name basis_check_target_name ("${TARGET_NAME}") basis_make_target_uid (TARGET_UID "${TARGET_NAME}") string (TOLOWER "${TARGET_NAME}" TARGET_NAME_L) string (TOUPPER "${TARGET_NAME}" TARGET_NAME_U) # verbose output message (STATUS "Adding documentation ${TARGET_UID}...") # find Doxygen find_package (Doxygen QUIET) if (NOT DOXYGEN_EXECUTABLE) if (BUILD_DOCUMENTATION) message (FATAL_ERROR "Doxygen not found! Either install Doxygen and/or set DOXYGEN_EXECUTABLE or disable BUILD_DOCUMENTATION.") endif () message (STATUS "Doxygen not found. Generation of ${TARGET_UID} documentation disabled.") message (STATUS "Adding documentation ${TARGET_UID}... - skipped") return () endif () # parse arguments set (VALUEARGS PROJECT_NAME PROJECT_NUMBER PROJECT_WEBSITE PROVIDER_NAME PROVIDER_WEBSITE DIVISION_NAME DIVISION_WEBSITE COMPONENT DESTINATION HTML_DESTINATION MAN_DESTINATION OUTPUT_DIRECTORY COLS_IN_ALPHA_INDEX MAN_SECTION ) set (OPTIONAL_FILE_OPTIONS HTML_FOOTER HTML_HEADER HTML_EXTRA_STYLESHEET PROJECT_LOGO PROVIDER_LOGO DIVISION_LOGO DOXYFILE TAGFILE ) CMAKE_PARSE_ARGUMENTS ( DOXYGEN "EXCLUDE_FROM_DOC;DISABLE_PROJECT_NAME_DISPLAY;EXCLUDE_BASIS_MODULES;EXCLUDE_BASIS_UTILITIES" "${VALUEARGS};${OPTIONAL_FILE_OPTIONS}" "INPUT;OUTPUT;INPUT_FILTER;FILTER_PATTERNS;EXCLUDE_PATTERNS;INCLUDE_PATH;IGNORE_PREFIX;ENABLED_SECTIONS;PREDEFINED;HTML_EXTRA_FILES" ${ARGN} ) unset (VALUEARGS) # handle special arguments set (DOXYGEN_HTML_HEADER_IS_DEFAULT FALSE) if (DOXYGEN_HTML_HEADER MATCHES "^(Doxygen|doxygen|DOXYGEN|none|None|NONE)$") set (DOXYGEN_HTML_HEADER) elseif (NOT DOXYGEN_HTML_HEADER OR DOXYGEN_HTML_HEADER MATCHES "^(Default|default|DEFAULT)$") set (DOXYGEN_HTML_HEADER "${BASIS_MODULE_PATH}/doxygen_header.html.in") set (DOXYGEN_HTML_HEADER_IS_DEFAULT TRUE) endif () if (DOXYGEN_HTML_FOOTER MATCHES "^(Doxygen|doxygen|DOXYGEN|none|None|NONE)$") set (DOXYGEN_HTML_FOOTER) elseif (NOT DOXYGEN_HTML_FOOTER OR DOXYGEN_HTML_FOOTER MATCHES "^(Default|default|DEFAULT)$") set (DOXYGEN_HTML_FOOTER "${BASIS_MODULE_PATH}/doxygen_footer.html.in") endif () # make file paths absolute and check if files exist foreach (opt IN LISTS OPTIONAL_FILE_OPTIONS) if (DOXYGEN_${opt}) get_filename_component (DOXYGEN_${opt} "${DOXYGEN_${opt}}" ABSOLUTE) if (NOT EXISTS "${DOXYGEN_${opt}}") message (FATAL_ERROR "File ${DOXYGEN_${opt}} does not exist. Check value of the ${opt} option and make sure the file is present.") endif () endif () endforeach () set (TMP_DOXYGEN_HTML_EXTRA_FILES) foreach (path IN LISTS DOXYGEN_HTML_EXTRA_FILES) get_filename_component (abspath "${path}" ABSOLUTE) if (NOT EXISTS "${path}") message (FATAL_ERROR "File ${path} does not exist. Check value of the HTML_EXTRA_FILES option and make sure the file is present.") endif () list (APPEND TMP_DOXYGEN_HTML_EXTRA_FILES "${path}") endforeach () set (DOXYGEN_HTML_EXTRA_FILES "${TMP_DOXYGEN_HTML_EXTRA_FILES}") unset (TMP_DOXYGEN_HTML_EXTRA_FILES) # default component if (NOT DOXYGEN_COMPONENT) set (DOXYGEN_COMPONENT "${BASIS_LIBRARY_COMPONENT}") endif () if (NOT DOXYGEN_COMPONENT) set (DOXYGEN_COMPONENT "Unspecified") endif () # configuration file if (NOT DOXYGEN_DOXYFILE) set (DOXYGEN_DOXYFILE "${BASIS_DOXYGEN_DOXYFILE}") endif () if (NOT EXISTS "${DOXYGEN_DOXYFILE}") message (FATAL_ERROR "Missing option DOXYGEN_FILE or Doxyfile ${DOXYGEN_DOXYFILE} does not exist.") endif () # default project attributes and logos if (NOT DOXYGEN_PROJECT_NAME) set (DOXYGEN_PROJECT_NAME "${PROJECT_NAME}") endif () if (NOT DOXYGEN_PROJECT_NUMBER) set (DOXYGEN_PROJECT_NUMBER "${PROJECT_RELEASE}") endif () if (NOT DOXYGEN_PROJECT_LOGO) set (DOXYGEN_PROJECT_LOGO "${PROJECT_PACKAGE_LOGO}") elseif (DOXYGEN_PROJECT_LOGO MATCHES "^None|none|NONE$") set (DOXYGEN_PROJECT_LOGO) endif () if (NOT DOXYGEN_PROJECT_WEBSITE) set (DOXYGEN_PROJECT_WEBSITE "${PROJECT_PACKAGE_WEBSITE}") endif () if (NOT DOXYGEN_PROVIDER_NAME) set (DOXYGEN_PROVIDER_NAME "${PROJECT_PROVIDER_NAME}") endif () if (NOT DOXYGEN_PROVIDER_WEBSITE) set (DOXYGEN_PROVIDER_WEBSITE "${PROJECT_PROVIDER_WEBSITE}") endif () if (NOT DOXYGEN_PROVIDER_LOGO) set (DOXYGEN_PROVIDER_LOGO "${PROJECT_PROVIDER_LOGO}") endif () if (NOT DOXYGEN_DIVISION_NAME) set (DOXYGEN_DIVISION_NAME "${PROJECT_DIVISION_NAME}") endif () if (NOT DOXYGEN_DIVISION_WEBSITE) set (DOXYGEN_DIVISION_WEBSITE "${PROJECT_DIVISION_WEBSITE}") endif () if (NOT DOXYGEN_DIVISION_LOGO) set (DOXYGEN_DIVISION_LOGO "${PROJECT_DIVISION_LOGO}") endif () # set visibility property of project logos if (DOXYGEN_PROJECT_LOGO) set (DOXYGEN_PROJECT_LOGO_DISPLAY "block") else () set (DOXYGEN_PROJECT_LOGO_DISPLAY "none") endif () if (DOXYGEN_PROVIDER_LOGO) set (DOXYGEN_PROVIDER_LOGO_DISPLAY "inline") else () set (DOXYGEN_PROVIDER_LOGO_DISPLAY "block") endif () if (DOXYGEN_DIVISION_LOGO) set (DOXYGEN_DIVISION_LOGO_DISPLAY "inline") else () set (DOXYGEN_DIVISION_LOGO_DISPLAY "block") endif () # allow the user to disable the text header if desired if(DOXYGEN_DISABLE_PROJECT_NAME_DISPLAY) set (DOXYGEN_PROJECT_NAME_DISPLAY "none") else() set (DOXYGEN_PROJECT_NAME_DISPLAY "inline") endif() # standard input files if (NOT EXCLUDE_BASIS_MODULES) list (APPEND DOXYGEN_INPUT "${PROJECT_SOURCE_DIR}/BasisProject.cmake") if (EXISTS "${PROJECT_CONFIG_DIR}/Depends.cmake") list (APPEND DOXYGEN_INPUT "${PROJECT_CONFIG_DIR}/Depends.cmake") endif () if (EXISTS "${BINARY_CONFIG_DIR}/Directories.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_CONFIG_DIR}/Directories.cmake") endif () if (EXISTS "${BINARY_CONFIG_DIR}/BasisSettings.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_CONFIG_DIR}/BasisSettings.cmake") endif () if (EXISTS "${BINARY_CONFIG_DIR}/ProjectSettings.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_CONFIG_DIR}/ProjectSettings.cmake") endif () if (EXISTS "${BINARY_CONFIG_DIR}/Settings.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_CONFIG_DIR}/Settings.cmake") elseif (EXISTS "${PROJECT_CONFIG_DIR}/Settings.cmake") list (APPEND DOXYGEN_INPUT "${PROJECT_CONFIG_DIR}/Settings.cmake") endif () if (EXISTS "${BASIS_SCRIPT_CONFIG_FILE}") list (APPEND DOXYGEN_INPUT "${BASIS_SCRIPT_CONFIG_FILE}") endif () if (EXISTS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_CONFIG_DIR}/ScriptConfig.cmake") endif () if (EXISTS "${PROJECT_CONFIG_DIR}/ConfigSettings.cmake") list (APPEND DOXYGEN_INPUT "${PROJECT_CONFIG_DIR}/ConfigSettings.cmake") endif () if (EXISTS "${PROJECT_SOURCE_DIR}/CTestConfig.cmake") list (APPEND DOXYGEN_INPUT "${PROJECT_SOURCE_DIR}/CTestConfig.cmake") endif () if (EXISTS "${PROJECT_BINARY_DIR}/CTestCustom.cmake") list (APPEND DOXYGEN_INPUT "${PROJECT_BINARY_DIR}/CTestCustom.cmake") endif () # package configuration files - only exist *after* this function executed list (APPEND DOXYGEN_INPUT "${BINARY_LIBCONF_DIR}/${PROJECT_PACKAGE_CONFIG_PREFIX}Config.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_LIBCONF_DIR}/${PROJECT_PACKAGE_CONFIG_PREFIX}ConfigVersion.cmake") list (APPEND DOXYGEN_INPUT "${BINARY_LIBCONF_DIR}/${PROJECT_PACKAGE_CONFIG_PREFIX}Use.cmake") # add .dox files with definition of BASIS Modules groups if (BASIS_DIR) list (APPEND DOXYGEN_INPUT "${BASIS_MODULE_PATH}/Modules.dox") endif () endif () # input directories foreach (_DIR IN LISTS BINARY_INCLUDE_DIR PROJECT_INCLUDE_DIRS BINARY_CODE_DIR PROJECT_CODE_DIRS) if (IS_DIRECTORY ${_DIR}) list (APPEND DOXYGEN_INPUT "${_DIR}") endif () endforeach () foreach (M IN LISTS PROJECT_MODULES_ENABLED) foreach (_DIR IN LISTS ${M}_INCLUDE_DIRS ${M}_CODE_DIRS) if (IS_DIRECTORY ${_DIR}) list (APPEND DOXYGEN_INPUT "${_DIR}") endif () endforeach () endforeach () # in case of scripts, have Doxygen process the configured versions for the # installation which are further located in proper subdirectories instead # of the original source files basis_get_project_property (TARGETS) foreach (T IN LISTS TARGETS) get_target_property (BASIS_TYPE ${T} BASIS_TYPE) get_target_property (IS_TEST ${T} TEST) if (NOT IS_TEST AND BASIS_TYPE MATCHES "SCRIPT") get_target_property (SOURCES ${T} SOURCES) if (SOURCES) list (GET SOURCES 0 BUILD_DIR) # CMake <3.1 stores path to internal build directory here if (BUILD_DIR MATCHES "CMakeFiles") list (REMOVE_AT SOURCES 0) endif () get_target_property (BUILD_DIR ${T} BUILD_DIRECTORY) list (APPEND DOXYGEN_INPUT "${BUILD_DIR}.dir/build") foreach (S IN LISTS SOURCES) list (APPEND DOXYGEN_EXCLUDE_PATTERNS "${S}") endforeach () endif () endif () endforeach () # add .dox files as input file (GLOB_RECURSE DOX_FILES "${PROJECT_DOC_DIR}/*.dox") list (SORT DOX_FILES) # alphabetic order list (APPEND DOXYGEN_INPUT ${DOX_FILES}) # add .dox files of used BASIS utilities if (BASIS_DIR AND NOT EXCLUDE_BASIS_UTILITIES) list (APPEND DOXYGEN_INPUT "${BASIS_MODULE_PATH}/Utilities.dox") list (APPEND DOXYGEN_INPUT "${BASIS_MODULE_PATH}/CxxUtilities.dox") foreach (L IN ITEMS Cxx Java Python Perl Bash Matlab) string (TOUPPER "${L}" U) basis_get_project_property (USES_${U}_UTILITIES PROPERTY PROJECT_USES_${U}_UTILITIES) if (USES_${U}_UTILITIES) list (FIND DOXYGEN_INPUT "${BASIS_MODULE_PATH}/Utilities.dox" IDX) if (IDX EQUAL -1) list (APPEND DOXYGEN_INPUT "${BASIS_MODULE_PATH}/Utilities.dox") endif () list (APPEND DOXYGEN_INPUT "${BASIS_MODULE_PATH}/${L}Utilities.dox") endif () endforeach () endif () # include path - Disabled as this increases the runtime of Doxygen but # generally the source of third-party packages are not # really referenced. Only the source files of this # project have to be considered. This code is kept as it # might be used again at a later point once it is figured # how Doxygen can be only rerun if necessary. #basis_get_project_property (INCLUDE_DIRS PROPERTY PROJECT_INCLUDE_DIRS) #foreach (D IN LISTS INCLUDE_DIRS) # list (FIND DOXYGEN_INPUT "${D}" IDX) # if (IDX EQUAL -1) # list (APPEND DOXYGEN_INCLUDE_PATH "${D}") # endif () #endforeach () #basis_list_to_delimited_string ( # DOXYGEN_INCLUDE_PATH "\"\nINCLUDE_PATH += \"" ${DOXYGEN_INCLUDE_PATH} #) #set (DOXYGEN_INCLUDE_PATH "\"${DOXYGEN_INCLUDE_PATH}\"") # make string from DOXYGEN_INPUT - after include path was set basis_list_to_delimited_string ( DOXYGEN_INPUT "\"\nINPUT += \"" ${DOXYGEN_INPUT} ) set (DOXYGEN_INPUT "\"${DOXYGEN_INPUT}\"") # preprocessor definitions basis_list_to_delimited_string ( DOXYGEN_PREDEFINED "\"\nPREDEFINED += \"" ${DOXYGEN_PREDEFINED} ) set (DOXYGEN_PREDEFINED "\"${DOXYGEN_PREDEFINED}\"") # outputs if (NOT DOXYGEN_OUTPUT_DIRECTORY) set (DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME_L}") endif () if (DOXYGEN_TAGFILE MATCHES "^(None|NONE|none)$") set (DOXYGEN_TAGFILE) else () set (DOXYGEN_TAGFILE "${DOXYGEN_OUTPUT_DIRECTORY}/Doxytags.${TARGET_NAME_L}") endif () if (NOT DOXYGEN_OUTPUT) set (DOXYGEN_OUTPUT html) endif () foreach (F IN ITEMS HTML XML RTF LATEX MAN) set (DOXYGEN_GENERATE_${F} NO) endforeach () foreach (f IN LISTS DOXYGEN_OUTPUT) if (NOT f MATCHES "^(html|xml)$") message (FATAL_ERROR "Invalid/Unsupported Doxygen output format: ${f}") endif () string (TOUPPER "${f}" F) set (DOXYGEN_GENERATE_${F} YES) # enable generation of this output set (DOXYGEN_${F}_OUTPUT "${f}") # relative output directory endforeach () # input filters if (NOT DOXYGEN_INPUT_FILTER) basis_get_target_uid (DOXYFILTER "basis.doxyfilter") if (TARGET "${DOXYFILTER}") basis_get_target_location (DOXYGEN_INPUT_FILTER ${DOXYFILTER} ABSOLUTE) else () basis_get_target_uid (DOXYFILTER "doxyfilter") if (TARGET "${DOXYFILTER}") basis_get_target_location (DOXYGEN_INPUT_FILTER ${DOXYFILTER} ABSOLUTE) endif () endif () else () set (DOXYFILTER) endif () if (DOXYGEN_INPUT_FILTER) if (WIN32) # Doxygen on Windows (XP, 32-bit) (at least up to version 1.8.0) seems # to have a problem of not calling filters which have a space character # in their file path correctly. The doxyfilter.bat Batch program is used # as a wrapper for the actual filter which is part of the BASIS build. # As this file is in the working directory of Doxygen, it can be # referenced relative to this working directory, i.e., without file paths. # The Batch program itself then calls the actual Doxygen filter with proper # quotes to ensure that spaces in the file path are handled correctly. # The file extension .bat shall distinguish this wrapper script from the actual # doxyfilter.cmd which is generated by BASIS on Windows. configure_file ("${BASIS_MODULE_PATH}/doxyfilter.bat.in" "${DOXYGEN_OUTPUT_DIRECTORY}/doxyfilter.bat" @ONLY) set (DOXYGEN_INPUT_FILTER "doxyfilter.bat") endif () endif () basis_list_to_delimited_string ( DOXYGEN_FILTER_PATTERNS "\"\nFILTER_PATTERNS += \"" ${DOXYGEN_FILTER_PATTERNS} ) if (DOXYGEN_FILTER_PATTERNS) set (DOXYGEN_FILTER_PATTERNS "\"${DOXYGEN_FILTER_PATTERNS}\"") endif () # exclude patterns list (APPEND DOXYGEN_EXCLUDE_PATTERNS "cmake_install.cmake") list (APPEND DOXYGEN_EXCLUDE_PATTERNS "CTestTestfile.cmake") basis_list_to_delimited_string ( DOXYGEN_EXCLUDE_PATTERNS "\"\nEXCLUDE_PATTERNS += \"" ${DOXYGEN_EXCLUDE_PATTERNS} ) set (DOXYGEN_EXCLUDE_PATTERNS "\"${DOXYGEN_EXCLUDE_PATTERNS}\"") # section for man pages if (NOT DOXYGEN_MAN_SECTION) set (DOXYGEN_MAN_SECTION 3) endif () # other settings if (NOT DOXYGEN_COLS_IN_ALPHA_INDEX OR DOXYGEN_COLS_IN_ALPHA_INDEX MATCHES "[^0-9]") set (DOXYGEN_COLS_IN_ALPHA_INDEX 1) endif () basis_list_to_delimited_string (DOXYGEN_IGNORE_PREFIX " " ${DOXYGEN_IGNORE_PREFIX}) # click & jump in emacs and Visual Studio if (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)") set (DOXYGEN_WARN_FORMAT "\"$file($line) : $text \"") else () set (DOXYGEN_WARN_FORMAT "\"$file:$line: $text \"") endif () # installation directories set (BASIS_INSTALL_${TARGET_NAME_U}_DIR "" CACHE PATH "Installation directory for Doxygen ${TARGET_NAME} target.") mark_as_advanced (BASIS_INSTALL_${TARGET_NAME_U}_DIR) foreach (f IN LISTS DOXYGEN_OUTPUT) string (TOUPPER "${f}" F) if (BASIS_INSTALL_${TARGET_NAME_U}_DIR) set (DOXYGEN_${F}_DESTINATION "${BASIS_INSTALL_${TARGET_NAME_U}_DIR}") # user setting endif () if (NOT DOXYGEN_${F}_DESTINATION) if (DOXYGEN_DESTINATION) set (DOXYGEN_${F}_DESTINATION "${DOXYGEN_DESTINATION}") # common destination elseif (f MATCHES "man") if (INSTALL_MAN_DIR) set (DOXYGEN_MAN_DESTINATION "${INSTALL_MAN_DIR}/man${DOXYGEN_MAN_SECTION}") # default for manual pages endif () elseif (NOT f MATCHES "html") # do not install excludes by default set (DOXYGEN_${F}_DESTINATION "${INSTALL_DOC_DIR}") # default destination endif () endif () endforeach () # determine tool to generate pdf documentation, see USE_PDFLATEX in Doxyfile.in find_package (LATEX QUIET) if (PDFLATEX_COMPILER) set (DOXYGEN_USE_PDFLATEX YES) else () set (DOXYGEN_USE_PDFLATEX NO) message (STATUS "pdflatex not found. For higher quality PDFs make sure pdflatex is installed and found on the PATH.") endif () # use default custom HTML files if available and none explicitly specified if (NOT DOXYGEN_HTML_EXTRA_STYLESHEET) if (EXISTS "${PROJECT_DOCRES_DIR}/doxygen_extra.css.in") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOCRES_DIR}/doxygen_extra.css.in") elseif (EXISTS "${PROJECT_DOCRES_DIR}/doxygen_extra.css") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOCRES_DIR}/doxygen_extra.css") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen_extra.css.in") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOC_DIR}/doxygen_extra.css.in") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen_extra.css") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOC_DIR}/doxygen_extra.css") elseif (EXISTS "${PROJECT_DOCRES_DIR}/doxygen.css.in") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOCRES_DIR}/doxygen.css.in") elseif (EXISTS "${PROJECT_DOCRES_DIR}/doxygen.css") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOCRES_DIR}/doxygen.css") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen.css.in") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOC_DIR}/doxygen.css.in") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen.css") set (DOXYGEN_HTML_EXTRA_STYLESHEET "${PROJECT_DOC_DIR}/doxygen.css") endif () endif () if (DOXYGEN_HTML_HEADER_IS_DEFAULT AND NOT DOXYGEN_HTML_EXTRA_STYLESHEET) set (DOXYGEN_HTML_EXTRA_STYLESHEET "${BASIS_MODULE_PATH}/doxygen_extra.css.in") endif () if (NOT DOXYGEN_HTML_HEADER) if (EXISTS "${PROJECT_DOCRES_DIR}/doxygen_header.html.in") set (DOXYGEN_HTML_HEADER "${PROJECT_DOCRES_DIR}/doxygen_header.html.in") elseif (EXISTS "${PROJECT_DOCRES_DIR}/doxygen_header.html") set (DOXYGEN_HTML_HEADER "${PROJECT_DOCRES_DIR}/doxygen_header.html") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen_header.html.in") set (DOXYGEN_HTML_HEADER "${PROJECT_DOC_DIR}/doxygen_header.html.in") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen_header.html") set (DOXYGEN_HTML_HEADER "${PROJECT_DOC_DIR}/doxygen_header.html") endif () endif () if (NOT DOXYGEN_HTML_FOOTER) if (EXISTS "${PROJECT_DOCRES_DIR}/doxygen_footer.html.in") set (DOXYGEN_HTML_FOOTER "${PROJECT_DOCRES_DIR}/doxygen_footer.html.in") elseif (EXISTS "${PROJECT_DOCRES_DIR}/doxygen_footer.html") set (DOXYGEN_HTML_FOOTER "${PROJECT_DOCRES_DIR}/doxygen_footer.html") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen_footer.html.in") set (DOXYGEN_HTML_FOOTER "${PROJECT_DOC_DIR}/doxygen_footer.html.in") elseif (EXISTS "${PROJECT_DOC_DIR}/doxygen_footer.html") set (DOXYGEN_HTML_FOOTER "${PROJECT_DOC_DIR}/doxygen_footer.html") endif () endif () # configure/copy custom HTML ressource files if (DOXYGEN_GENERATE_HTML) set (DOXYGEN_HTML_EXTRA_STYLESHEET_NAME "doxygen_extra.css") set (OUTPUT_HTML_EXTRA_STYLESHEET "${DOXYGEN_OUTPUT_DIRECTORY}/${DOXYGEN_HTML_EXTRA_STYLESHEET_NAME}") set (OUTPUT_HTML_HEADER "${DOXYGEN_OUTPUT_DIRECTORY}/doxygen_header.html") set (OUTPUT_HTML_FOOTER "${DOXYGEN_OUTPUT_DIRECTORY}/doxygen_footer.html") foreach (res IN ITEMS EXTRA_STYLESHEET HEADER FOOTER) if (EXISTS "${DOXYGEN_HTML_${res}}") if (DOXYGEN_HTML_${res} MATCHES "\\.in$") configure_file (${DOXYGEN_HTML_${res}} "${OUTPUT_HTML_${res}}" @ONLY) elseif (DOXYGEN_HTML_${res}) configure_file (${DOXYGEN_HTML_${res}} "${OUTPUT_HTML_${res}}" COPYONLY) else () set (OUTPUT_HTML_${res}) endif () endif () endforeach () set (DOXYGEN_HTML_EXTRA_STYLESHEET "${OUTPUT_HTML_EXTRA_STYLESHEET}") set (DOXYGEN_HTML_HEADER "${OUTPUT_HTML_HEADER}") set (DOXYGEN_HTML_FOOTER "${OUTPUT_HTML_FOOTER}") else () set (DOXYGEN_HTML_EXTRA_STYLESHEET) set (DOXYGEN_HTML_FOOTER) set (DOXYGEN_HTML_HEADER) endif () if (DOXYGEN_PROVIDER_LOGO) list (APPEND DOXYGEN_HTML_EXTRA_FILES "${DOXYGEN_PROVIDER_LOGO}") endif() if (DOXYGEN_DIVISION_LOGO) list (APPEND DOXYGEN_HTML_EXTRA_FILES "${DOXYGEN_DIVISION_LOGO}") endif() if (DOXYGEN_HTML_EXTRA_FILES) basis_list_to_delimited_string ( DOXYGEN_HTML_EXTRA_FILES "\"\nHTML_EXTRA_FILES += \"" ${DOXYGEN_HTML_EXTRA_FILES} ) endif () # list of enabled Doxygen comment sections basis_join ("${DOXYGEN_ENABLED_SECTIONS}" " " DOXYGEN_ENABLED_SECTIONS) # configure Doxygen configuration file set (DOXYFILE "${DOXYGEN_OUTPUT_DIRECTORY}/Doxyfile.${TARGET_NAME_L}") configure_file ("${DOXYGEN_DOXYFILE}" "${DOXYFILE}" @ONLY) # add build target set (OPTALL) if (BUILD_DOCUMENTATION AND BASIS_ALL_DOC) set (OPTALL "ALL") endif () file (MAKE_DIRECTORY "${DOXYGEN_OUTPUT_DIRECTORY}") add_custom_target ( ${TARGET_UID} ${OPTALL} "${DOXYGEN_EXECUTABLE}" "${DOXYFILE}" WORKING_DIRECTORY "${DOXYGEN_OUTPUT_DIRECTORY}" COMMENT "Building documentation ${TARGET_UID}..." ) # memorize certain settings which might be useful to know by other functions # in particular, in case of the use of the XML output by other documentation # build tools such as Sphinx, the function that wants to make use of this # output can check if the Doxygen target has been configured properly and # further requires to know the location of the XML output set_target_properties ( ${TARGET_UID} PROPERTIES BASIS_TYPE Doxygen OUTPUT_DIRECTORY "${DOXYGEN_OUTPUT_DIRECTORY}" DOXYFILE "${DOXYGEN_DOXYFILE}" TAGFILE "${DOXYGEN_TAGFILE}" OUTPUT "${DOXYGEN_OUTPUT}" ) foreach (f IN LISTS DOXYGEN_OUTPUT) string (TOUPPER "${f}" F) set_target_properties ( ${TARGET_UID} PROPERTIES ${F}_INSTALL_DIRECTORY "${DOXYGEN_${F}_DESTINATION}" ${F}_OUTPUT_DIRECTORY "${DOXYGEN_OUTPUT_DIRECTORY}/${DOXYGEN_${F}_OUTPUT}" ) set_property ( DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${DOXYGEN_OUTPUT_DIRECTORY}/${DOXYGEN_${F}_OUTPUT}" ) endforeach () if (DOXYGEN_TAGFILE) set_property ( DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${DOXYGEN_TAGFILE}" ) endif () # The Doxygen filter, if a build target of this project, has to be build # before the documentation can be generated. if (TARGET "${DOXYFILTER}") add_dependencies (${TARGET_UID} ${DOXYFILTER}) endif () # The public header files shall be configured/copied before. if (TARGET headers) add_dependencies (${TARGET_UID} headers) endif () # The documentation shall be build after all other executable and library # targets have been build. For example, a .py.in script file shall first # be "build", i.e., configured before the documentation is being generated # from the configured .py file. basis_get_project_property (TARGETS PROPERTY TARGETS) foreach (_UID ${TARGETS}) get_target_property (BASIS_TYPE ${_UID} "BASIS_TYPE") if (BASIS_TYPE MATCHES "SCRIPT|EXECUTABLE|LIBRARY") add_dependencies (${TARGET_UID} ${_UID}) endif () endforeach () # add general "doc" target if (NOT DOXYGEN_EXCLUDE_FROM_DOC) if (NOT TARGET doc) add_custom_target (doc) endif () add_dependencies (doc ${TARGET_UID}) endif () # install documentation install ( CODE " set (HTML_DESTINATION \"${DOXYGEN_HTML_DESTINATION}\") set (MAN_DESTINATION \"${DOXYGEN_MAN_DESTINATION}\") function (install_doxydoc FMT) string (TOUPPER \"\${FMT}\" FMT_U) set (CMAKE_INSTALL_PREFIX \"\${\${FMT_U}_DESTINATION}\") if (NOT CMAKE_INSTALL_PREFIX) return () elseif (NOT IS_ABSOLUTE \"\${CMAKE_INSTALL_PREFIX}\") set (CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}/\${CMAKE_INSTALL_PREFIX}\") endif () set (EXT) set (DIR \"\${FMT}\") if (FMT MATCHES \".pdf\") set (EXT \".pdf\") set (DIR \"latex\") elseif (FMT MATCHES \".rtf\") set (EXT \".rtf\") elseif (FMT MATCHES \"man\") set (EXT \".?\") endif () file ( GLOB_RECURSE FILES RELATIVE \"${DOXYGEN_OUTPUT_DIRECTORY}/\${DIR}\" \"${DOXYGEN_OUTPUT_DIRECTORY}/\${DIR}/*\${EXT}\" ) foreach (F IN LISTS FILES) execute_process ( COMMAND \"${CMAKE_COMMAND}\" -E compare_files \"${DOXYGEN_OUTPUT_DIRECTORY}/\${DIR}/\${F}\" \"\${CMAKE_INSTALL_PREFIX}/\${F}\" RESULT_VARIABLE RC OUTPUT_QUIET ERROR_QUIET ) if (RC EQUAL 0) message (STATUS \"Up-to-date: \${CMAKE_INSTALL_PREFIX}/\${F}\") else () message (STATUS \"Installing: \${CMAKE_INSTALL_PREFIX}/\${F}\") execute_process ( COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different \"${DOXYGEN_OUTPUT_DIRECTORY}/\${DIR}/\${F}\" \"\${CMAKE_INSTALL_PREFIX}/\${F}\" RESULT_VARIABLE RC OUTPUT_QUIET ERROR_QUIET ) if (RC EQUAL 0) list (APPEND CMAKE_INSTALL_MANIFEST_FILES \"\${CMAKE_INSTALL_PREFIX}/\${F}\") else () message (STATUS \"Failed to install \${CMAKE_INSTALL_PREFIX}/\${F}\") endif () endif () endforeach () if (FMT MATCHES \"html\" AND EXISTS \"${DOXYGEN_TAGFILE}\") get_filename_component (DOXYGEN_TAGFILE_NAME \"${DOXYGEN_TAGFILE}\" NAME) execute_process ( COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different \"${DOXYGEN_TAGFILE}\" \"\${CMAKE_INSTALL_PREFIX}/\${DOXYGEN_TAGFILE_NAME}\" ) list (APPEND CMAKE_INSTALL_MANIFEST_FILES \"\${CMAKE_INSTALL_PREFIX}/\${DOXYGEN_TAGFILE_NAME}\") endif () endfunction () foreach (FMT IN ITEMS html pdf rtf man) install_doxydoc (\${FMT}) endforeach () " ) # done message (STATUS "Adding documentation ${TARGET_UID}... - done") endfunction () # ---------------------------------------------------------------------------- ## @brief Add documentation target to be generated by Sphinx (sphinx-build). # # This function adds a build target to generate documentation from # <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> # (.rst files) using <a href="http://sphinx.pocoo.org/">Sphinx</a>. # # @param [in] TARGET_NAME Name of the documentation target. # @param [in] ARGN List of arguments. The valid arguments are: # @par # <table border="0"> # <tr> # @tp @b EXCLUDE_FROM_DOC @endtp # <td>By default, the specified target is build as part of the global # @c doc target. If this option is given, however, the added # documentation will not be build as part of this target.</td> # </tr> # <tr> # @tp @b BUILDER(S) builder... @endtp # <td>Sphinx builders to use. For each named builder, a build target # named <TARGET_NAME>_<builder> is added.</td> # </tr> # <tr> # @tp @b DEFAULT_BUILDER builder @endtp # <td>Default Sphinx builder to associated with the @c TARGET_NAME # build target. Defaults to the first builder named by @c BUILDERS.</td> # </tr> # <tr> # @tp @b AUTHOR(S) name @endtp # <td>Names of authors who wrote this documentation. # (default: @c PROJECT_AUTHORS)</td> # </tr> # <tr> # @tp @b COPYRIGHT text @endtp # <td>Copyright statement for generated files. (default: @c PROJECT_COPYRIGHT)</td> # </tr> # <tr> # @tp @b COMPONENT component @endtp # <td>Name of the component this documentation belongs to. # Defaults to @c BASIS_RUNTIME_COMPONENT.</td> # </tr> # <tr> # @tp @b DESTINATION dir @endtp # <td>Installation directory prefix. Used whenever there is no specific # destination specified for a particular Sphinx builder. Defaults to # @c BASIS_INSTALL_<TARGET>_DIR in case of HTML output if set. # Otherwise, the generated HTML files are not installed.</td> # </tr> # <tr> # @tp @b <BUILDER>_DESTINATION dir @endtp # <td>Installation directory for files generated by the specific builder.<td> # </tr> # <tr> # @tp @b EXTENSIONS ext... @endtp # <td>Names of Sphinx extensions to enable.</td> # </tr> # <tr> # @tp @b BREATHE target... @endtp # <td>Adds a project for the breathe extension which allows the # inclusion of in-source code documentation extracted by Doxygen. # For this to work, the specified Doxygen target has to be # configured with the XML output enabled.</td> # </tr> # <tr> # @tp @b DOXYLINK target... @endtp # <td>Adds a role for the doxylink Sphinx extension which allows to cross-reference # generated HTML API documentation generated by Doxygen.</td> # </tr> # <tr> # @tp @b DOXYLINK_URL url @endtp # <td>URL to Doxygen documentation. Use DOXYLINK_PREFIX and/or DOXYLINK_SUFFIX # instead if you use multiple Doxygen targets, where the target name is # part of the URL.</td> # </tr> # <tr> # @tp @b DOXYLINK_PREFIX url @endtp # <td>Prefix to use for links to Doxygen generated documentation pages # as generated by the doxylink Sphinx extension. If this prefix does # not start with a protocol such as http:// or https://, it is prefixed # to the default path determined by this function relative to the build # or installed Doxygen documentation.</td> # </tr> # <tr> # @tp @b DOXYLINK_SUFFIX suffix @endtp # <td>Suffix for links to Doxygen generated documentation pages as generated # by the doxylink Sphinx extension.</td> # </tr> # <tr> # @tp @b DOXYDOC target... @endtp # <td>Alias for both @c BREATHE and @c DOXYLINK options.</td> # </tr> # <tr> # @tp @b CONFIG_FILE file @endtp # <td>Sphinx configuration file. Defaults to @c BASIS_SPHINX_CONFIG.</td> # </tr> # <tr> # @tp @b SOURCE_DIRECTORY @endtp # <td>Root directory of Sphinx source files. # Defaults to the current source directory or, if a subdirectory # named @c TARGET_NAME in lowercase only exists, to this subdirectory.</td> # </tr> # <tr> # @tp @b OUTPUT_NAME @endtp # <td>Output name for generated documentation such as PDF document or MAN page. # Defaults to @c PROJECT_NAME.</td> # </tr> # <tr> # @tp @b OUTPUT_DIRECTORY @endtp # <td>Root output directory for generated files. Defaults to the binary # directory corresponding to the set @c SOURCE_DIRECTORY.</td> # </tr> # <tr> # @tp @b TAG tag @endtp # <td>Tag argument of <tt>sphinx-build</tt>.</td> # </tr> # <tr> # @tp @b TEMPLATES_PATH @endtp # <td>Path to template files. Defaults to <tt>SOURCE_DIRECTORY/templates/</tt>.</td> # </tr> # <tr> # @tp @b MASTER_DOC name @endtp # <td>Name of master document. Defaults to <tt>index</tt>.</td> # </tr> # <tr> # @tp @b EXCLUDE_PATTERN pattern @endtp # <td>A glob-style pattern that should be excluded when looking for source files. # Specify this option more than once to specify multiple exclude patterns. # They are matched against the source file names relative to the source directory, # using slashes as directory separators on all platforms.</td> # </tr> # <tr> # @tp @b HTML_TITLE title @endtp # <td>Title of HTML web site.</td> # </tr> # <tr> # @tp @b HTML_THEME theme @endtp # <td>Name of HTML theme. Defaults to the @c sbia theme included with BASIS.</td> # </tr> # <tr> # @tp @b HTML_THEME_PATH dir @endtp # <td>Directory of HTML theme. Defaults to @c BASIS_SPHINX_HTML_THEME_PATH.</td> # </tr> # <tr> # @tp @b HTML_LOGO file @endtp # <td>Logo to display in sidebar of HTML pages.</td> # </tr> # <tr> # @tp @b HTML_FAVICON file @endtp # <td>Favorite square icon often displayed by browsers in the tab bar. # Should be a @c .ico file.</td> # </tr> # <tr> # @tp @b HTML_STATIC_PATH dir @endtp # <td>Directory for static files of HTML pages. Defaults to <tt>SOURCE_DIRECTORY/static/</tt>.</td> # </tr> # <tr> # @tp @b HTML_STYLE css @endtp # <td>The style sheet to use for HTML pages. A file of that name must exist either in Sphinx' # default static/ path or the specified @c HTML_STATIC_PATH. Default is the stylesheet # given by the selected theme. If you only want to add or override a few things compared # to the theme’s stylesheet, use CSS \@import to import the theme’s stylesheet.</td> # </tr> # <tr> # @tp @b HTML_SIDEBARS name... @endtp # <td>Names of HTML template files for sidebar(s). Defaults to none if not specified. # Valid default templates are @c localtoc, @c globaltoc, @c searchbox, @c relations, # @c sourcelink. See <a href="http://sphinx.pocoo.org/config.html#confval-html_sidebars"> # Shinx documentation of html_sidebars option</a>. Custom templates can be used as # well by copying the template <tt>.html</tt> file to the @c TEMPLATES_PATH directory.</td> # </tr> # <tr> # @tp @b NO_HTML_DOMAIN_INDICES @endtp # <td>Set Sphinx configuration option @c html_domain_indices to @c False. (Default: @c True)</td> # </tr> # <tr> # @tp @b NO_HTML_MODINDEX @endtp # <td>Set Sphinx configuration option @c html_use_modindex to @c False. (Default: @c True)</td> # </tr> # <tr> # @tp @b NO_HTML_INDEX @endtp # <td>Set Sphinx configuration option @c html_use_index to @c False. (Default: @c True)</td> # </tr> # <tr> # @tp @b LATEX_MASTER_DOC name @endtp # <td>Name of master document for LaTeX builder. Defaults to <tt>MASTER_DOC</tt>.</td> # </tr> # <tr> # @tp @b LATEX_TITLE title @endtp # <td>Title for LaTeX/PDF output. Defaults to title of <tt>index.rst</tt>.</td> # </tr> # <tr> # @tp @b LATEX_LOGO file @endtp # <td>Logo to display above title in generated LaTeX/PDF output.</td> # </tr> # <tr> # @tp @b LATEX_DOCUMENT_CLASS howto|manual @endtp # <td>Document class to use by @c latex builder.</td> # </tr> # <tr> # @tp @b LATEX_SHOW_URLS @endtp # <td>See Sphinx documentation of the # <a href="http://sphinx.pocoo.org/config.html#confval-latex_show_urls">latex_show_urls</a> option.</td> # </tr> # <tr> # @tp @b LATEX_SHOW_PAGEREFS @endtp # <td>See Sphinx documentation of the # <a href="">latex_show_pagerefs</a> option.</td> # </tr> # <tr> # @tp @b MAN_SECTION num @endtp # <td>Section number for manual pages generated by @c man builder.</td> # </tr> # </table> # # @sa basis_add_doc() function (basis_add_sphinx_doc TARGET_NAME) # check target name basis_check_target_name ("${TARGET_NAME}") basis_make_target_uid (TARGET_UID "${TARGET_NAME}") string (TOLOWER "${TARGET_NAME}" TARGET_NAME_L) string (TOUPPER "${TARGET_NAME}" TARGET_NAME_U) # verbose output message (STATUS "Adding documentation ${TARGET_UID}...") # parse arguments set (ONE_ARG_OPTIONS COMPONENT DEFAUL_BUILDER DESTINATION HTML_DESTINATION MAN_DESTINATION TEXINFO_DESTINATION CONFIG_FILE SOURCE_DIRECTORY OUTPUT_DIRECTORY OUTPUT_NAME TAG COPYRIGHT MASTER_DOC HTML_TITLE HTML_THEME HTML_LOGO HTML_FAVICON HTML_THEME_PATH HTML_STYLE LATEX_MASTER_DOC LATEX_TITLE LATEX_LOGO LATEX_DOCUMENT_CLASS LATEX_SHOW_URLS LATEX_SHOW_PAGEREFS MAN_SECTION DOXYLINK_URL DOXYLINK_PREFIX DOXYLINK_SUFFIX ) # note that additional multiple value arguments are parsed later on below # this is necessary b/c all unparsed arguments are considered to be options # of the used HTML theme CMAKE_PARSE_ARGUMENTS (SPHINX "EXCLUDE_FROM_DOC;NO_HTML_DOMAIN_INDICES;NO_HTML_MODINDEX;NO_HTML_INDEX" "${ONE_ARG_OPTIONS}" "" ${ARGN} ) # source directory if (NOT SPHINX_SOURCE_DIRECTORY) if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_NAME}") set (SPHINX_SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_NAME}") else () set (SPHINX_SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") endif () elseif (NOT IS_ABSOLUTE "${SPHINX_SOURCE_DIRECTORY}") get_filename_component (SPHINX_SOURCE_DIRECTORY "${SPHINX_SOURCE_DIRECTORY}" ABSOLUTE) endif () # component if (NOT SPHINX_COMPONENT) set (SPHINX_COMPONENT "${BASIS_RUNTIME_COMPONENT}") endif () if (NOT SPHINX_COMPONENT) set (SPHINX_COMPONENT "Unspecified") endif () # find Sphinx find_package (Sphinx COMPONENTS build QUIET) if (NOT Sphinx-build_EXECUTABLE) if (BUILD_DOCUMENTATION) message (FATAL_ERROR "Command sphinx-build not found! Either install Sphinx and/or set Sphinx-build_EXECUTABLE or disable BUILD_DOCUMENTATION.") endif () message (STATUS "Command sphinx-build not found. Generation of ${TARGET_UID} documentation disabled.") message (STATUS "Adding documentation ${TARGET_UID}... - skipped") return () endif () if (DEFINED Sphinx_VERSION_MAJOR AND Sphinx_VERSION_MAJOR LESS 1) if (BUILD_DOCUMENTATION) message (FATAL_ERROR "Found sphinx-build is too old (v${Sphinx_VERSION_STRING})! Please install a more recent version and/or set Sphinx-build_EXECUTABLE to a newer version or disable BUILD_DOCUMENTATION.") endif () message (STATUS "Command sphinx-build is too old (v${Sphinx_VERSION_STRING}). Generation of ${TARGET_UID} documentation disabled.") message (STATUS "Adding documentation ${TARGET_UID}... - skipped") return () endif () # parse remaining arguments set (SPHINX_HTML_THEME_OPTIONS) set (SPHINX_BUILDERS) set (SPHINX_AUTHORS) set (SPHINX_EXTENSIONS) set (SPHINX_BREATHE_TARGETS) set (SPHINX_DOXYLINK_TARGETS) set (SPHINX_HTML_SIDEBARS) set (SPHINX_TEMPLATES_PATH) set (SPHINX_HTML_STATIC_PATH) set (SPHINX_EXCLUDE_PATTERNS) set (SPHINX_DEPENDS) set (OPTION_NAME) set (OPTION_VALUE) set (OPTION_PATTERN "(authors?|builders?|extensions|breathe|doxylink|doxydoc|html_sidebars|templates_path|html_static_path|exclude_pattern)") foreach (ARG IN LISTS SPHINX_UNPARSED_ARGUMENTS) if (NOT OPTION_NAME OR ARG MATCHES "^[A-Z_]+$") # SPHINX_HTML_THEME_OPTIONS if (OPTION_NAME AND NOT OPTION_NAME MATCHES "^${OPTION_PATTERN}$") if (NOT OPTION_VALUE) message (FATAL_ERROR "Option ${OPTION_NAME} is missing an argument!") endif () list (LENGTH OPTION_VALUE NUM) if (NUM GREATER 1) basis_list_to_delimited_string (OPTION_VALUE ", " NOAUTOQUOTE ${OPTION_VALUE}) set (OPTION_VALUE "[${OPTION_VALUE}]") endif () list (APPEND SPHINX_HTML_THEME_OPTIONS "'${OPTION_NAME}': ${OPTION_VALUE}") endif () # name of next option set (OPTION_NAME "${ARG}") set (OPTION_VALUE) string (TOLOWER "${OPTION_NAME}" OPTION_NAME) # BUILDER option elseif (OPTION_NAME MATCHES "^builders?$") if (ARG MATCHES "html dirhtml singlehtml pdf latex man text texinfo linkcheck") message (FATAL_ERROR "Invalid/Unsupported Sphinx builder: ${ARG}") endif () list (APPEND SPHINX_BUILDERS "${ARG}") # AUTHORS option elseif (OPTION_NAME MATCHES "^authors?$") list (APPEND SPHINX_AUTHORS "'${ARG}'") # EXTENSIONS option elseif (OPTION_NAME MATCHES "^extensions$") # built-in extension if (ARG MATCHES "^(autodoc|autosummary|doctest|intersphinx|pngmath|jsmath|mathjax|graphvis|inheritance_graph|ifconfig|coverage|todo|extlinks|viewcode)$") set (ARG "sphinx.ext.${CMAKE_MATCH_0}") # map originial name of extensions included with BASIS elseif (BASIS_SPHINX_EXTENSIONS_PATH AND ARG MATCHES "^sphinxcontrib.(doxylink)$") set (ARG "${CMAKE_MATCH_1}") endif () list (APPEND SPHINX_EXTENSIONS "'${ARG}'") # DOXYDOC elseif (OPTION_NAME MATCHES "^doxydoc$") list (APPEND SPHINX_BREATHE_TARGETS "${ARG}") list (APPEND SPHINX_DOXYLINK_TARGETS "${ARG}") # BREATHE elseif (OPTION_NAME MATCHES "^breathe$") list (APPEND SPHINX_BREATHE_TARGETS "${ARG}") # DOXYLINK elseif (OPTION_NAME MATCHES "^doxylink$") list (APPEND SPHINX_DOXYLINK_TARGETS "${ARG}") # HTML_SIDEBARS elseif (OPTION_NAME MATCHES "^html_sidebars$") if (NOT ARG MATCHES "\\.html?$") set (ARG "${ARG}.html") endif () list (APPEND SPHINX_HTML_SIDEBARS "'${ARG}'") # TEMPLATES_PATH elseif (OPTION_NAME MATCHES "^templates_path$") if (NOT IS_ABSOLUTE "${ARG}") set (ARG "${SPHINX_SOURCE_DIRECTORY}/${ARG}") endif () list (APPEND SPHINX_TEMPLATES_PATH "'${ARG}'") # HTML_STATIC_PATH elseif (OPTION_NAME MATCHES "^html_static_path$") if (NOT IS_ABSOLUTE "${ARG}") set (ARG "${SPHINX_SOURCE_DIRECTORY}/${ARG}") endif () list (APPEND SPHINX_HTML_STATIC_PATH "'${ARG}'") # EXCLUDE_PATTERN elseif (OPTION_NAME MATCHES "^exclude_pattern$") list (APPEND SPHINX_EXCLUDE_PATTERNS "'${ARG}'") # value of theme option else () if (ARG MATCHES "^(TRUE|FALSE)$") string (TOLOWER "${ARG}" "${ARG}") endif () if (NOT ARG MATCHES "^\\[.*\\]$|^{.*}$") set (ARG "'${ARG}'") endif () list (APPEND OPTION_VALUE "${ARG}") endif () endforeach () # append parsed option setting to SPHINX_HTML_THEME_OPTIONS if (OPTION_NAME AND NOT OPTION_NAME MATCHES "^${OPTION_PATTERN}$") if (NOT OPTION_VALUE) message (FATAL_ERROR "Option ${OPTION_NAME} is missing an argument!") endif () list (LENGTH OPTION_VALUE NUM) if (NUM GREATER 1) basis_list_to_delimited_string (OPTION_VALUE ", " NOAUTOQUOTE ${OPTION_VALUE}) set (OPTION_VALUE "[${OPTION_VALUE}]") endif () list (APPEND SPHINX_HTML_THEME_OPTIONS "'${OPTION_NAME}': ${OPTION_VALUE}") endif () # authors if (NOT SPHINX_AUTHORS) foreach (AUTHOR IN LISTS PROJECT_AUTHORS) list (APPEND SPHINX_AUTHORS "'${AUTHOR}'") endforeach () endif () if (NOT SPHINX_COPYRIGHT) set (SPHINX_COPYRIGHT "${PROJECT_COPYRIGHT}") endif () # default builders if (NOT SPHINX_BUILDERS) set (SPHINX_BUILDERS html dirhtml singlehtml man pdf texinfo text linkcheck) endif () if (SPHINX_DEFAULT_BUILDER) list (FIND SPHINX_BUILDERS "${SPHINX_DEFAULT_BUILDER}" IDX) if (IDX EQUAL -1) list (INSERT SPHINX_BUILDERS 0 "${SPHINX_DEFAULT_BUILDER}") endif () else () list (GET SPHINX_BUILDERS 0 SPHINX_DEFAULT_BUILDER) endif () # output directories if (NOT SPHINX_OUTPUT_NAME) set (SPHINX_OUTPUT_NAME "${PROJECT_NAME}") endif () if (NOT SPHINX_OUTPUT_DIRECTORY) if (IS_ABSOLUTE "${SPHINX_OUTPUT_NAME}") get_filename_component (SPHINX_OUTPUT_DIRECTORY "${SPHINX_OUTPUT_NAME}" PATH) else () basis_get_relative_path (SPHINX_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${SPHINX_SOURCE_DIRECTORY}") endif () endif () if (NOT IS_ABSOLUTE "${SPHINX_OUTPUT_DIRECTORY}") set (SPHINX_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${SPHINX_OUTPUT_DIRECTORY}") endif () foreach (b IN LISTS SPHINX_BUILDERS) string (TOUPPER "${b}" B) if (SPHINX_${B}_OUTPUT_DIRECTORY) if (NOT IS_ABSOLUTE "${SPHINX_${B}_OUTPUT_DIRECTORY}") set (SPHINX_${B}_OUTPUT_DIRECTORY "${SPHINX_OUTPUT_DIRECTORY}/${SPHINX_${B}_OUTPUT_DIRECTORY}") endif () else () set (SPHINX_${B}_OUTPUT_DIRECTORY "${SPHINX_OUTPUT_DIRECTORY}/${b}") endif () endforeach () if (IS_ABSOLUTE "${SPHINX_OUTPUT_NAME}") basis_get_relative_path (SPHINX_OUTPUT_NAME "${SPHINX_OUTPUT_DIRECTORY}" NAME_WE) endif () # configuration directory basis_get_relative_path (SPHINX_CONFIG_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${SPHINX_SOURCE_DIRECTORY}") set (SPHINX_CONFIG_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${SPHINX_CONFIG_DIRECTORY}") # build configuration if (NOT SPHINX_MASTER_DOC) set (SPHINX_MASTER_DOC "index") endif () if (NOT SPHINX_LATEX_MASTER_DOC) set (SPHINX_LATEX_MASTER_DOC "${SPHINX_MASTER_DOC}") endif () if (NOT SPHINX_TEMPLATES_PATH AND EXISTS "${SPHINX_SOURCE_DIRECTORY}/templates") set (SPHINX_TEMPLATES_PATH "'${SPHINX_SOURCE_DIRECTORY}/templates'") endif () if (NOT SPHINX_HTML_STATIC_PATH AND EXISTS "${SPHINX_SOURCE_DIRECTORY}/static") set (SPHINX_HTML_STATIC_PATH "'${SPHINX_SOURCE_DIRECTORY}/static'") endif () if (NOT SPHINX_HTML_THEME) set (SPHINX_HTML_THEME "${BASIS_SPHINX_HTML_THEME}") endif () if (NOT SPHINX_UNPARSED_ARGUMENTS AND SPHINX_HTML_THEME STREQUAL BASIS_SPHINX_HTML_THEME) set (SPHINX_UNPARSED_ARGUMENTS ${BASIS_SPHINX_HTML_THEME_OPTIONS}) endif () if (NOT SPHINX_LATEX_DOCUMENT_CLASS) set (SPHINX_LATEX_DOCUMENT_CLASS "howto") endif () if (NOT SPHINX_MAN_SECTION) set (SPHINX_MAN_SECTION 1) endif () # installation directories set (BASIS_INSTALL_${TARGET_NAME_U}_DIR "" CACHE PATH "Installation directory for documentation ${TARGET_NAME} target.") mark_as_advanced (BASIS_INSTALL_${TARGET_NAME_U}_DIR) foreach (b IN LISTS SPHINX_BUILDERS) string (TOUPPER "${b}" B) if (BASIS_INSTALL_${TARGET_NAME_U}_DIR) set (SPHINX_${B}_DESTINATION "${BASIS_INSTALL_${TARGET_NAME_U}_DIR}") # user setting endif () if (NOT SPHINX_${B}_DESTINATION) if (SPHINX_DESTINATION) set (SPHINX_${B}_DESTINATION "${DESTINATION}") # common destination elseif (b MATCHES "text") set (SPHINX_${B}_DESTINATION "${INSTALL_DOC_DIR}/${TARGET_NAME_L}") elseif (b MATCHES "man") if (INSTALL_MAN_DIR) set (SPHINX_${B}_DESTINATION "${INSTALL_MAN_DIR}/man${SPHINX_MAN_SECTION}") # default for manual pages endif () elseif (b MATCHES "texinfo") if (INSTALL_TEXINFO_DIR) set (SPHINX_${B}_DESTINATION "${INSTALL_TEXINFO_DIR}") # default for Texinfo files endif () elseif (NOT b MATCHES "html") # do not install excludes by default set (SPHINX_${B}_DESTINATION "${INSTALL_DOC_DIR}") # default location endif () endif () endforeach () if (SPHINX_HTML_DESTINATION) foreach (b IN LISTS SPHINX_BUILDERS) if (b MATCHES "(dir|single)html") string (TOUPPER "${b}" B) if (NOT SPHINX_${B}_DESTINATION) set (SPHINX_${B}_DESTINATION "${SPHINX_HTML_DESTINATION}") endif () endif () endforeach () endif () # enable required extension if (SPHINX_DOXYLINK_TARGETS) if (BASIS_SPHINX_EXTENSIONS_PATH) if (NOT SPHINX_EXTENSIONS MATCHES "(^|;)?doxylink(;|$)?") list (APPEND SPHINX_EXTENSIONS "'doxylink'") endif () else () if (NOT SPHINX_EXTENSIONS MATCHES "(^|;)?sphinxcontrib.doxylink(;|$)?") list (APPEND SPHINX_EXTENSIONS "'sphinxcontrib.doxylink'") endif () endif () endif () if (SPHINX_BREATHE_TARGETS AND NOT SPHINX_EXTENSIONS MATCHES "(^|;)?breathe(;|$)?") list (APPEND SPHINX_EXTENSIONS "'breathe'") endif () # doxylink configuration foreach (TARGET IN LISTS SPHINX_DOXYLINK_TARGETS) basis_get_target_uid (UID "${TARGET}") get_target_property (TYPE ${UID} BASIS_TYPE) if (NOT TYPE MATCHES "Doxygen") message (FATAL_ERROR "Invalid argument for DOXYLINK: Target ${UID} either unknown or it is not a Doxygen target!") endif () get_target_property (DOXYGEN_OUTPUT ${UID} OUTPUT) if (NOT DOXYGEN_OUTPUT MATCHES "html") message (FATAL_ERROR "Doxygen target ${UID} was not configured to generate HTML output! This output is required by the doxylink Sphinx extension.") endif () get_target_property (DOXYGEN_TAGFILE ${UID} TAGFILE) get_target_property (DOXYGEN_HTML_DIRECTORY ${UID} HTML_INSTALL_DIRECTORY) set (DOXYLINK_PATH) if (SPHINX_DOXYLINK_URL) set (DOXYLINK_PATH "${SPHINX_DOXYLINK_URL}") elseif (SPHINX_DOXYLINK_PREFIX MATCHES "^[a-z]://") set (DOXYLINK_PATH "${SPHINX_DOXYLINK_PREFIX}${TARGET}${SPHINX_DOXYLINK_SUFFIX}") else () set (DOXYLINK_BASE_DIR) if (DOXYGEN_HTML_DIRECTORY) if (SPHINX_DOXYLINK_BASE_DIR) set (DOXYLINK_BASE_DIR "${SPHINX_DOXYLINK_BASE_DIR}") elseif (SPHINX_HTML_INSTALL_DIRECTORY) set (DOXYLINK_BASE_DIR "${SPHINX_HTML_INSTALL_DIRECTORY}") endif () else () get_target_property (DOXYGEN_HTML_DIRECTORY ${UID} HTML_OUTPUT_DIRECTORY) if (SPHINX_DOXYLINK_BASE_DIR) set (DOXYLINK_BASE_DIR "${SPHINX_DOXYLINK_BASE_DIR}") else () set (DOXYLINK_BASE_DIR "${SPHINX_HTML_OUTPUT_DIRECTORY}") endif () endif () if (DOXYLINK_BASE_DIR) basis_get_relative_path (DOXYLINK_PATH "${DOXYLINK_BASE_DIR}" "${DOXYGEN_HTML_DIRECTORY}") else () set (DOXYLINK_PATH "${TARGET}") # safe fall back endif () set (DOXYLINK_PATH "${SPHINX_DOXYLINK_PREFIX}${DOXYLINK_PATH}${SPHINX_DOXYLINK_SUFFIX}") endif () list (APPEND SPHINX_DOXYLINK "'${TARGET}': ('${DOXYGEN_TAGFILE}', '${DOXYLINK_PATH}')") list (APPEND SPHINX_DEPENDS ${UID}) endforeach () # breathe configuration set (SPHINX_BREATHE_PROJECTS) set (SPHINX_BREATHE_DEFAULT_PROJECT) foreach (TARGET IN LISTS SPHINX_BREATHE_TARGETS) basis_get_target_uid (UID "${TARGET}") get_target_property (TYPE ${UID} BASIS_TYPE) if (NOT TYPE MATCHES "Doxygen") message (FATAL_ERROR "Invalid argument for BREATHE_PROJECTS: Target ${UID} either unknown or it is not a Doxygen target!") endif () get_target_property (DOXYGEN_OUTPUT ${UID} OUTPUT) if (NOT DOXYGEN_OUTPUT MATCHES "xml") message (FATAL_ERROR "Doxygen target ${UID} was not configured to generate XML output! This output is required by the Sphinx extension breathe.") endif () get_target_property (DOXYGEN_OUTPUT_DIRECTORY ${UID} XML_OUTPUT_DIRECTORY) list (APPEND SPHINX_BREATHE_PROJECTS "'${TARGET}': '${DOXYGEN_OUTPUT_DIRECTORY}'") if (NOT SPHINX_BREATHE_DEFAULT_PROJECT) set (SPHINX_BREATHE_DEFAULT_PROJECT "${TARGET}") endif () list (APPEND SPHINX_DEPENDS ${UID}) endforeach () # HTML output options if (SPHINX_NO_HTML_DOMAIN_INDICES) set (SPHINX_USE_DOMAIN_INDICES False) else () set (SPHINX_USE_DOMAIN_INDICES True) endif () if (SPHINX_NO_HTML_MODINDEX) set (SPHINX_USE_MODINDEX False) else () set (SPHINX_USE_MODINDEX True) endif () if (SPHINX_NO_HTML_INDEX) set (SPHINX_USE_INDEX False) else () set (SPHINX_USE_INDEX True) endif () # LaTeX output options if (NOT SPHINX_LATEX_SHOW_URLS) set (SPHINX_LATEX_SHOW_URLS "no") endif () if (SPHINX_LATEX_SHOW_PAGEREFS) set (SPHINX_LATEX_SHOW_PAGEREFS "True") else () set (SPHINX_LATEX_SHOW_PAGEREFS "False") endif () # turn html_logo, html_favicon, and latex_logo into absolute file path foreach (L IN ITEMS HTML_LOGO HTML_FAVICON LATEX_LOGO) if (SPHINX_${L} AND NOT IS_ABSOLUTE "${SPHINX_${L}}") if (EXISTS "${SPHINX_SOURCE_DIRECTORY}/${SPHINX_${L}}") set (SPHINX_${L} "${SPHINX_SOURCE_DIRECTORY}/${SPHINX_${L}}") elseif (L MATCHES "^HTML|^LATEX") foreach (D IN LISTS SPHINX_${CMAKE_MATCH_0}_STATIC_PATH) string (REGEX REPLACE "^'|'$" "" D "${D}") if (EXISTS "${D}/${SPHINX_${L}}") set (SPHINX_${L} "${D}/${SPHINX_${L}}") break () endif () endforeach () endif () endif () endforeach () # turn CMake lists into Python lists basis_list_to_delimited_string (SPHINX_EXTENSIONS ", " NOAUTOQUOTE ${SPHINX_EXTENSIONS}) basis_list_to_delimited_string (SPHINX_HTML_THEME_OPTIONS ", " NOAUTOQUOTE ${SPHINX_HTML_THEME_OPTIONS}) basis_list_to_delimited_string (SPHINX_AUTHORS ", " NOAUTOQUOTE ${SPHINX_AUTHORS}) basis_list_to_delimited_string (SPHINX_DOXYLINK ", " NOAUTOQUOTE ${SPHINX_DOXYLINK}) basis_list_to_delimited_string (SPHINX_BREATHE_PROJECTS ", " NOAUTOQUOTE ${SPHINX_BREATHE_PROJECTS}) basis_list_to_delimited_string (SPHINX_HTML_SIDEBARS ", " NOAUTOQUOTE ${SPHINX_HTML_SIDEBARS}) basis_list_to_delimited_string (SPHINX_TEMPLATES_PATH ", " NOAUTOQUOTE ${SPHINX_TEMPLATES_PATH}) basis_list_to_delimited_string (SPHINX_HTML_STATIC_PATH ", " NOAUTOQUOTE ${SPHINX_HTML_STATIC_PATH}) basis_list_to_delimited_string (SPHINX_EXCLUDE_PATTERNS ", " NOAUTOQUOTE ${SPHINX_EXCLUDE_PATTERNS}) # configuration file if (NOT SPHINX_CONFIG_FILE) set (SPHINX_CONFIG_FILE "${BASIS_SPHINX_CONFIG}") endif () get_filename_component (SPHINX_CONFIG_FILE "${SPHINX_CONFIG_FILE}" ABSOLUTE) if (EXISTS "${SPHINX_CONFIG_FILE}") configure_file ("${SPHINX_CONFIG_FILE}" "${SPHINX_CONFIG_DIRECTORY}/conf.py" @ONLY) elseif (EXISTS "${SPHINX_CONFIG_FILE}.in") configure_file ("${SPHINX_CONFIG_FILE}.in" "${SPHINX_CONFIG_DIRECTORY}/conf.py" @ONLY) else () message (FATAL_ERROR "Missing Sphinx configuration file ${SPHINX_CONFIG_FILE}!") endif () # add target to build documentation set (OPTIONS -a -N -n) if (NOT BASIS_VERBOSE) list (APPEND OPTIONS "-q") endif () foreach (TAG IN LISTS SPHINX_TAG) list (APPEND OPTIONS "-t" "${TAG}") endforeach () add_custom_target (${TARGET_UID}_all) # target to run all builders foreach (BUILDER IN LISTS SPHINX_BUILDERS) set (SPHINX_BUILDER "${BUILDER}") set (SPHINX_POST_COMMAND) if (BUILDER MATCHES "pdf|texinfo") if (UNIX) set (SPHINX_MAKE_COMMAND "make") if (BUILDER MATCHES "pdf") set (SPHINX_BUILDER "latex") configure_file ("${BASIS_MODULE_PATH}/sphinx_make.sh.in" "${SPHINX_CONFIG_DIRECTORY}/make.sh" @ONLY) set (SPHINX_MAKE_COMMAND "${SPHINX_CONFIG_DIRECTORY}/make.sh") execute_process (COMMAND chmod +x "${SPHINX_CONFIG_DIRECTORY}/make.sh") endif () set (SPHINX_POST_COMMAND COMMAND "${SPHINX_MAKE_COMMAND}" -C "${SPHINX_OUTPUT_DIRECTORY}/${SPHINX_BUILDER}") elseif (BUILDER MATCHES "pdf") message (WARNING "Target ${TARGET_UID} requires the execution of pdflatex which is currently" " only executed after sphinx-build on Unix platforms. On Windows, pdflatex" " must be executed manually in the directory\n\n\t${SPHINX_OUTPUT_DIRECTORY}/${SPHINX_BUILDER}") endif () endif () if (Sphinx_PYTHON_EXECUTABLE) add_custom_target ( ${TARGET_UID}_${BUILDER} "${Sphinx_PYTHON_EXECUTABLE}" ${Sphinx_PYTHON_OPTIONS} "${Sphinx-build_EXECUTABLE}" ${OPTIONS} -b ${SPHINX_BUILDER} -c "${SPHINX_CONFIG_DIRECTORY}" -d "${SPHINX_CONFIG_DIRECTORY}/doctrees" "${SPHINX_SOURCE_DIRECTORY}" "${SPHINX_OUTPUT_DIRECTORY}/${SPHINX_BUILDER}" ${SPHINX_POST_COMMAND} ${OPTDEPENDS} WORKING_DIRECTORY "${SPHINX_CONFIG_DIRECTORY}" COMMENT "Building documentation ${TARGET_UID} (${BUILDER})..." ) elseif (UNIX) add_custom_target ( ${TARGET_UID}_${BUILDER} "${Sphinx-build_EXECUTABLE}" ${OPTIONS} -b ${SPHINX_BUILDER} -c "${SPHINX_CONFIG_DIRECTORY}" -d "${SPHINX_CONFIG_DIRECTORY}/doctrees" "${SPHINX_SOURCE_DIRECTORY}" "${SPHINX_OUTPUT_DIRECTORY}/${SPHINX_BUILDER}" ${SPHINX_POST_COMMAND} ${OPTDEPENDS} WORKING_DIRECTORY "${SPHINX_CONFIG_DIRECTORY}" COMMENT "Building documentation ${TARGET_UID} (${BUILDER})..." ) else () message (FATAL_ERROR "Python executable required to run Sphinx could not be determined by FindSphinx.cmake!" " Set the advanced PYTHON_EXECUTABLE variable and try again.") endif () if (SPHINX_DEPENDS) add_dependencies (${TARGET_UID}_${BUILDER} ${SPHINX_DEPENDS}) endif () add_dependencies (${TARGET_UID}_all ${TARGET_UID}_${BUILDER}) # cleanup on "make clean" set_property ( DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${SPHINX_OUTPUT_DIRECTORY}" ) endforeach () # add general target which depends on default builder only if (BUILD_DOCUMENTATION AND BASIS_ALL_DOC) add_custom_target (${TARGET_UID} ALL) else () add_custom_target (${TARGET_UID}) endif () add_dependencies (${TARGET_UID} ${TARGET_UID}_${SPHINX_DEFAULT_BUILDER}) # add general "doc" target if (NOT SPHINX_EXCLUDE_FROM_DOC) if (NOT TARGET doc) add_custom_target (doc) endif () add_dependencies (doc ${TARGET_UID}_${SPHINX_DEFAULT_BUILDER}) endif () # memorize important target properties set_target_properties ( ${TARGET_UID} PROPERTIES BASIS_TYPE Sphinx BUILDERS "${SPHINX_BUILDERS}" SOURCE_DIRECTORY "${SPHINX_SOURCE_DIRECTORY}" OUTPUT_DIRECTORY "${SPHINX_OUTPUT_DIRECTORY}" CONFIG_DIRECTORY "${SPHINX_CONFIG_DIRECTORY}" ) foreach (b IN LISTS SPHINX_BUILDERS) string (TOUPPER ${b} B) set_target_properties (${TARGET_UID} PROPERTIES ${B}_INSTALL_DIRECTORY "${SPHINX_${B}_DESTINATION}") endforeach () # cleanup on "make clean" set_property ( DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${SPHINX_CONFIG_DIRECTORY}/doctrees" ) # install documentation install ( CODE " set (HTML_DESTINATION \"${SPHINX_HTML_DESTINATION}\") set (PDF_DESTINATION \"${SPHINX_PDF_DESTINATION}\") set (LATEX_DESTINATION \"${SPHINX_LATEX_DESTINATION}\") set (MAN_DESTINATION \"${SPHINX_MAN_DESTINATION}\") set (TEXINFO_DESTINATION \"${SPHINX_TEXINFO_DESTINATION}\") set (TEXT_DESTINATION \"${SPHINX_TEXT_DESTINATION}\") function (install_sphinx_doc BUILDER) if (BUILDER MATCHES \"pdf\") set (SPHINX_BUILDER \"latex\") else () set (SPHINX_BUILDER \"\${BUILDER}\") endif () string (TOUPPER \"\${BUILDER}\" BUILDER_U) set (CMAKE_INSTALL_PREFIX \"\${\${BUILDER_U}_DESTINATION}\") if (NOT CMAKE_INSTALL_PREFIX) return () elseif (NOT IS_ABSOLUTE \"\${CMAKE_INSTALL_PREFIX}\") set (CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}/\${CMAKE_INSTALL_PREFIX}\") endif () set (EXT) if (BUILDER MATCHES \"pdf\") set (EXT \".pdf\") elseif (BUILDER MATCHES \"man\") set (EXT \".?\") elseif (BUILDER MATCHES \"texinfo\") set (EXT \".info\") endif () file ( GLOB_RECURSE FILES RELATIVE \"${SPHINX_OUTPUT_DIRECTORY}/\${SPHINX_BUILDER}\" \"${SPHINX_OUTPUT_DIRECTORY}/\${SPHINX_BUILDER}/*\${EXT}\" ) foreach (F IN LISTS FILES) if (NOT F MATCHES \"\\\\.buildinfo\") set (RC 1) if (NOT BUILDER MATCHES \"texinfo\") execute_process ( COMMAND \"${CMAKE_COMMAND}\" -E compare_files \"${SPHINX_OUTPUT_DIRECTORY}/\${SPHINX_BUILDER}/\${F}\" \"\${CMAKE_INSTALL_PREFIX}/\${F}\" RESULT_VARIABLE RC OUTPUT_QUIET ERROR_QUIET ) endif () if (RC EQUAL 0) message (STATUS \"Up-to-date: \${CMAKE_INSTALL_PREFIX}/\${F}\") else () message (STATUS \"Installing: \${CMAKE_INSTALL_PREFIX}/\${F}\") if (BUILDER MATCHES \"texinfo\") if (EXISTS \"\${CMAKE_INSTALL_PREFIX}/dir\") execute_process ( COMMAND install-info \"${SPHINX_OUTPUT_DIRECTORY}/\${SPHINX_BUILDER}/\${F}\" \"\${CMAKE_INSTALL_PREFIX}/dir\" RESULT_VARIABLE RC OUTPUT_QUIET ERROR_QUIET ) else () execute_process ( COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different \"${SPHINX_OUTPUT_DIRECTORY}/\${SPHINX_BUILDER}/\${F}\" \"\${CMAKE_INSTALL_PREFIX}/dir\" RESULT_VARIABLE RC OUTPUT_QUIET ERROR_QUIET ) endif () else () execute_process ( COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different \"${SPHINX_OUTPUT_DIRECTORY}/\${SPHINX_BUILDER}/\${F}\" \"\${CMAKE_INSTALL_PREFIX}/\${F}\" RESULT_VARIABLE RC OUTPUT_QUIET ERROR_QUIET ) endif () if (RC EQUAL 0) # also remember .info files for deinstallation via install-info --delete list (APPEND CMAKE_INSTALL_MANIFEST_FILES \"\${CMAKE_INSTALL_PREFIX}/\${F}\") else () message (STATUS \"Failed to install \${CMAKE_INSTALL_PREFIX}/\${F}\") endif () endif () endif () endforeach () endfunction () set (BUILDERS \"${SPHINX_BUILDERS}\") set (HTML_INSTALLED FALSE) foreach (BUILDER IN LISTS BUILDERS) if ((BUILDER MATCHES \"html\" AND NOT HTML_INSTALLED) OR (BUILDER MATCHES \"texinfo|man\" AND UNIX) OR NOT BUILDER MATCHES \"html|texinfo|man|latex|linkcheck\") install_sphinx_doc (\${BUILDER}) if (BUILDER MATCHES \"html\") set (HTML_INSTALLED TRUE) endif () endif () endforeach () " ) # done message (STATUS "Adding documentation ${TARGET_UID}... - done") endfunction () # ============================================================================ # change log # ============================================================================ # ---------------------------------------------------------------------------- ## @brief Add target for generation of ChangeLog file. # # The ChangeLog is either generated from the Subversion or Git log depending # on which revision control system is used by the project. Moreover, the # project's source directory must be either a Subversion working copy or # the root of a Git repository, respectively. In case of Subversion, if the # command-line tool svn2cl(.sh) is installed, it is used to output a nicer # formatted change log. function (basis_add_changelog) _basis_make_target_uid (TARGET_UID changelog) option (BUILD_CHANGELOG "Request build and/or installation of the ChangeLog." OFF) mark_as_advanced (BUILD_CHANGELOG) set (CHANGELOG_FILE "${PROJECT_BINARY_DIR}/ChangeLog") message (STATUS "Adding ChangeLog...") if (NOT PROJECT_IS_MODULE AND BUILD_CHANGELOG) set (_ALL "ALL") else () set (_ALL) endif () set (DISABLE_BUILD_CHANGELOG FALSE) # -------------------------------------------------------------------------- # generate ChangeLog from Subversion history if (EXISTS "${PROJECT_SOURCE_DIR}/.svn") find_package (Subversion QUIET) if (Subversion_FOUND) if (_ALL) message ("Generation of ChangeLog enabled as part of ALL." " Be aware that the ChangeLog generation from the Subversion" " commit history can take several minutes and may require the" " input of your Subversion repository credentials during the" " build. If you would like to build the ChangeLog separate" " from the rest of the software package, disable the option" " BUILD_CHANGELOG. You can then build the changelog target" " separate from ALL.") endif () # using svn2cl command find_program ( SVN2CL_EXECUTABLE NAMES svn2cl svn2cl.sh DOC "The command line tool svn2cl." ) mark_as_advanced (SVN2CL_EXECUTABLE) if (SVN2CL_EXECUTABLE) add_custom_target ( ${TARGET_UID} ${_ALL} COMMAND "${SVN2CL_EXECUTABLE}" "--output=${CHANGELOG_FILE}" "--linelen=79" "--reparagraph" "--group-by-day" "--include-actions" "--separate-daylogs" "${PROJECT_SOURCE_DIR}" COMMAND "${CMAKE_COMMAND}" "-DCHANGELOG_FILE:FILE=${CHANGELOG_FILE}" -DINPUTFORMAT=SVN2CL -P "${BASIS_MODULE_PATH}/PostprocessChangeLog.cmake" WORKING_DIRECTORY "${PROJECT_BINARY_DIR}" COMMENT "Generating ChangeLog from Subversion log (using svn2cl)..." ) # otherwise, use svn log output directly else () add_custom_target ( ${TARGET_UID} ${_ALL} COMMAND "${CMAKE_COMMAND}" "-DCOMMAND=${Subversion_SVN_EXECUTABLE};log" "-DWORKING_DIRECTORY=${PROJECT_SOURCE_DIR}" "-DOUTPUT_FILE=${CHANGELOG_FILE}" -P "${BASIS_SCRIPT_EXECUTE_PROCESS}" COMMAND "${CMAKE_COMMAND}" "-DCHANGELOG_FILE:FILE=${CHANGELOG_FILE}" -DINPUTFORMAT=SVN -P "${BASIS_MODULE_PATH}/PostprocessChangeLog.cmake" COMMENT "Generating ChangeLog from Subversion log..." VERBATIM ) endif () else () if (BASIS_VERBOSE) message (STATUS "Project is SVN working copy but Subversion executable was not found." " Generation of ChangeLog disabled.") endif () set (DISABLE_BUILD_CHANGELOG TRUE) endif () # -------------------------------------------------------------------------- # generate ChangeLog from Git log elseif (EXISTS "${PROJECT_SOURCE_DIR}/.git") find_package (Git QUIET) if (GIT_FOUND) add_custom_target ( ${TARGET_UID} ${_ALL} COMMAND "${CMAKE_COMMAND}" "-DCOMMAND=${GIT_EXECUTABLE};log;--date-order;--date=short;--pretty=format:%ad\ \ %an%n%n%w(79,8,10)* %s%n%n%b%n" "-DWORKING_DIRECTORY=${PROJECT_SOURCE_DIR}" "-DOUTPUT_FILE=${CHANGELOG_FILE}" -P "${BASIS_SCRIPT_EXECUTE_PROCESS}" COMMAND "${CMAKE_COMMAND}" "-DCHANGELOG_FILE=${CHANGELOG_FILE}" -DINPUTFORMAT=GIT -P "${BASIS_MODULE_PATH}/PostprocessChangeLog.cmake" COMMENT "Generating ChangeLog from Git log..." VERBATIM ) else () if (BASIS_VERBOSE) message (STATUS "Project is Git repository but Git executable was not found." " Generation of ChangeLog disabled.") endif () set (DISABLE_BUILD_CHANGELOG TRUE) endif () # -------------------------------------------------------------------------- # neither SVN nor Git repository else () if (BASIS_VERBOSE) message (STATUS "Project source directory ${PROJECT_SOURCE_DIR} is neither" " SVN working copy nor Git repository. Generation of ChangeLog disabled.") endif () set (DISABLE_BUILD_CHANGELOG TRUE) endif () # -------------------------------------------------------------------------- # disable changelog target if (DISABLE_BUILD_CHANGELOG) set (BUILD_CHANGELOG OFF CACHE INTERNAL "" FORCE) message (STATUS "Adding ChangeLog... - skipped") return () endif () # -------------------------------------------------------------------------- # cleanup on "make clean" set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CHANGELOG_FILE}") # -------------------------------------------------------------------------- # install ChangeLog get_filename_component (CHANGELOG_NAME "${CHANGELOG_FILE}" NAME) if (PROJECT_IS_MODULE) set (CHANGELOG_NAME "${CHANGELOG_NAME}-${PROJECT_NAME}") endif () install ( FILES "${CHANGELOG_FILE}" DESTINATION "${TOPLEVEL_INSTALL_DOC_DIR}" COMPONENT "${BASIS_RUNTIME_COMPONENT}" RENAME "${CHANGELOG_NAME}" OPTIONAL ) message (STATUS "Adding ChangeLog... - done") endfunction ()