1# =======================================
2# Macros and functions related to doxygen
3#
4# =======================================
5
6# ---------------------------------------------
7# For a given component (numerics, kernel ...)
8# get the list of directories containing
9# sources to be used to generate doxygen doc.
10# Result is saved in CACHE variable DOXY_INPUTS
11# This variables is unique and stands for all
12# components!
13# ---------------------------------------------
14macro(update_doxygen_inputs COMP)
15  # Scan all dirs of current component and append
16  # them to DOXY_INPUTS/
17  # Do not include dirs matching 'test' and dirs listed
18  # in <COMP>_EXCLUDE_DOXY.
19  foreach(_dir IN LISTS ${COMP}_DIRS)
20    list(FIND ${COMP}_EXCLUDE_DOXY ${_dir} check_dir)
21    if(NOT ${_dir} MATCHES test AND ${check_dir} EQUAL -1)
22      list(APPEND DOXY_INPUTS ${CMAKE_CURRENT_SOURCE_DIR}/${_dir})
23    endif()
24  endforeach()
25  if(DOXY_INPUTS)
26    list(REMOVE_DUPLICATES DOXY_INPUTS)
27  endif()
28  # convert cmake list to a single string
29  foreach(_dir ${DOXY_INPUTS})
30    set(_INPUTS "${_INPUTS} ${_dir}")
31  endforeach()
32
33  # Save doxy_inputs to cache.
34  set(${COMP}_DOXYGEN_INPUTS ${_INPUTS} CACHE INTERNAL "List of inputs (directories) used by doxygen to generate doc for <COMP>.")
35endmacro()
36
37
38# --------------------------------------------------
39# Prepare config and targets for
40# documentaition (xml-->rst-->sphinx)
41#
42# For a given component (numerics, kernel ...)
43# generate rst files (for sphinx/breathe)
44# from xml outputs (doxygen).
45#
46# ---------------------------------------------
47function(doxy2rst_sphinx COMPONENT)
48
49  set(multiValueArgs HEADERS)
50  cmake_parse_arguments(component "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
51
52
53  # --- Target : create rst files from xml outputs (doxygen) ---
54  # run : make doxy2rst
55  # depends : xml4rst
56  #
57  # Call python script to create rst files that can be parsed by sphinx/breathe
58  # to create documentation.
59
60  # output path, required to generate conf.py (breathe part)
61  # This is the place where xml files created by doxygen
62  # will be generated, for a later use by sphinx.
63  set(DOXYGEN_4_RST ${DOXYGEN_OUTPUT}/xml4rst CACHE INTERNAL "doxy (xml) output path")
64
65  # Doxygen conf for xml outputs for breathe. It might be different
66  # from the one used for xml outputs for swig.
67  set(DOXY_QUIET "YES")
68  set(DOXY_WARNINGS "NO")
69  set(GENERATE_HTML NO)
70  set(GENERATE_XML YES)
71  set(EXTRACT_ALL NO)
72  set(EXTRACT_PRIVATE NO)
73  set(XML_OUTPUT xml4rst/${COMPONENT})
74  file(MAKE_DIRECTORY ${DOXYGEN_4_RST}/${COMPONENT})
75  # Set config file name
76  set(DOXY_CONFIG_XML "${CMAKE_BINARY_DIR}/docs/config/${COMPONENT}doxy-xml.config")
77
78  # Get list of inputs
79  set(DOXYGEN_INPUTS ${${COMPONENT}_DOXYGEN_INPUTS})
80
81  configure_file(${CMAKE_SOURCE_DIR}/docs/config/doxyxml2sphinx.config.in ${DOXY_CONFIG_XML} @ONLY)
82
83  # Create a new target used to create doxygen outputs (xml).
84  # Required for documentation and/or for serialization.
85  add_custom_target(${COMPONENT}-doxy2xml
86    COMMAND ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG_XML}
87    OUTPUT_FILE ${DOXYGEN_OUTPUT}/${COMPONENT}doxy4rst.log ERROR_FILE ${DOXYGEN_OUTPUT}/${COMPONENT}doxy4rst.log
88    COMMENT "Generate xml/doxygen files for ${COMPONENT} (conf: ${DOXY_CONFIG_XML}).")
89
90  if(WITH_${COMPONENT}_DOCUMENTATION)
91    # Path where rst files will be generated.
92    set(SPHINX_DIR "${CMAKE_BINARY_DIR}/docs/sphinx")
93
94    # Create a new target used to create sphinx inputs (rst) from doxygen outputs (xml).
95    # It calls a python function defined in gendoctools (create_breathe_files)
96    add_custom_target(${COMPONENT}-xml2rst
97      COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_BINARY_DIR}/share ${PYTHON_EXECUTABLE} -c
98      "from gendoctools.cpp2rst import create_breathe_files as f; f('${component_HEADERS}', '${CMAKE_SOURCE_DIR}', '${COMPONENT}', '${SPHINX_DIR}','${DOXY_CONFIG_XML}')"
99        VERBATIM
100        DEPENDS ${COMPONENT}-doxy2xml
101        )
102
103      add_custom_command(TARGET  ${COMPONENT}-xml2rst POST_BUILD
104        COMMENT "${COMPONENT} : rst (c++ API) files have been generated in ${SPHINX_DIR}/reference/cpp.")
105    endif()
106endfunction()
107
108# --------------------------------------
109# Call this macro when configuration
110# process is done for all components.
111#
112# It will :
113#  - create doxygen configs
114# (for breathe, docstrings and so on)
115#  - create targets related to
116#   documentation
117#    --> make doxygen-html to generate html doxygen doc from sources
118#    --> make doxypng2sphinx to convert doxygen diagrams (class ...) to rst files
119# --------------------------------------
120macro(finalize_doc)
121  if(WITH_DOCUMENTATION)
122
123    # --- Target : html documentation from doxygen ---
124    # run : make doxygen-html
125    #  verbose mode : always off, since warnings
126    # may be obtained with 'doxygen_warnings' target.
127    # == set configuration file for doxygen doc from sources ==
128    #  - Results in binary_dir/docs/
129    #  - input config from config/doxy.config
130    #  - only html output
131    # 'inputs' are updated by each component, during call to update_doxygen_inputs macro.
132    # Doc will be built when 'make doxygen' is called.
133    # config file name
134    set(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/config/doxy.config" CACHE INTERNAL "Doxygen configuration file : used to produce html (doxygen only) and xml files for sphinx (breathe).")
135    # The generation of the config and the creation of the target will be done later,
136    # after the update of inputs by each component, with macro 'finalize_doc'
137    set(DOXY_QUIET "YES")
138    set(DOXY_WARNINGS "NO")
139    set(GENERATE_HTML YES)
140    set(GENERATE_XML NO)
141    set(EXTRACT_ALL NO)
142    if(USE_DEVEL_DOXYGEN) # OFF  by default. Activate to extract all.
143      set(EXTRACT_ALL YES)
144    endif()
145    # Build list of all dirs taken into accound by doxygen to build
146    # doc, from each component own list.
147    set(DOXYGEN_INPUTS)
148    foreach(COMP IN LISTS COMPONENTS)
149      set(DOXYGEN_INPUTS "${DOXYGEN_INPUTS} ${${COMP}_DOXYGEN_INPUTS}")
150    endforeach()
151    configure_file(${CMAKE_SOURCE_DIR}/docs/config/doxy.config.in ${DOXY_CONFIG} @ONLY)
152
153    # A new target to create  html files (doxygen) from code sources.
154    # One target for all components.
155    add_custom_target(doxygen-html
156      COMMAND ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG}
157      COMMENT "Run doxygen ${DOXY_CONFIG} ...")
158
159    add_custom_command(TARGET doxygen-html POST_BUILD
160      COMMENT "Doxygen documentation has been built in : \n - ${DOXYGEN_OUTPUT} (xml) \n - ${DOC_ROOT_DIR}/html/doxygen (html).")
161
162    # --- Target : create class diagrams from doxygen outputs, for sphinx. ---
163    # run : make doxypng2sphinx
164    # depends : doxygen-html
165    # Call a python function defined in gendoctools (find_doxygen_diagrams)
166    add_custom_target(doxypng2sphinx
167      COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_BINARY_DIR}/share ${PYTHON_EXECUTABLE} -c
168      "from gendoctools.generate_api import find_doxygen_diagrams as f; f('${CMAKE_BINARY_DIR}/docs/build/html/doxygen', '${CMAKE_BINARY_DIR}/docs/sphinx/reference')"
169      VERBATIM
170      DEPENDS doxygen-html
171      COMMENT "Browse doxygen outputs (graphs ...)")
172
173    add_custom_command(TARGET doxypng2sphinx POST_BUILD
174      COMMENT "Done. Generate class_diagrams.rst file in ${CMAKE_BINARY_DIR}/docs/sphinx/reference")
175
176    add_dependencies(html doxypng2sphinx)
177
178    foreach(COMP ${COMPONENTS})
179      add_dependencies(html ${COMP}-xml2rst)
180    endforeach()
181
182    # --- Generates conf.py, to describe sphinx setup ---
183    # !! Should be call after doxygen setup
184    # to have a correct DOXYGEN_INPUT value.
185    configure_file (
186      "${CMAKE_SOURCE_DIR}/docs/sphinx/conf.py.in"
187      "${CMAKE_BINARY_DIR}/docs/sphinx/conf.py" @ONLY)
188
189  endif()
190endmacro()
191
192
193
194function(docstrings2rst module_path module_name)
195  set(pymodule_name ${SICONOS_SWIG_ROOT_DIR}/${module_path}/${module_name}.py)
196
197  message("Start setup for generation of rst files from python docstrings for ${pymodule_name}")
198  # A target to postprocess latex forms in docstrings into
199  # something readable by sphinx.
200  # Calls a python function defined in gendoctools (replace_latex)
201  add_custom_target(${module_name}_replace_latex
202    COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_BINARY_DIR}/share ${PYTHON_EXECUTABLE} -c
203    "from gendoctools.common import replace_latex as f; f('${pymodule_name}', '${SICONOS_SWIG_ROOT_DIR}/tmp_${COMPONENT}/')"
204    VERBATIM
205    DEPENDS ${SWIG_MODULE_${module_name}_REAL_NAME}
206    COMMENT "Insert latex into docstrings.")
207
208  # Path where rst files (docstrings --> rst) will be written.
209  set(SPHINX_OUTPUT_DIR ${CMAKE_BINARY_DIR}/docs/sphinx/)
210  # python modules for previous components are required to apidoc (e.g. kernel.py for control).
211  # So we get this last comp and add a dependency.
212  list(APPEND PROCESSED_PYTHON_MODULES ${SWIG_MODULE_${module_name}_REAL_NAME})
213  list(REMOVE_DUPLICATES PROCESSED_PYTHON_MODULES)
214  set(PROCESSED_PYTHON_MODULES ${PROCESSED_PYTHON_MODULES} CACHE INTERNAL "python modules for siconos")
215
216  # A new target to convert python/swig docstrings (swig outputs) into rst files (sphinx inputs)
217  # Calls a python function defined in gendoctools (module_docstrings2rst)
218  # --> make <comp>_autodoc
219  add_custom_target(${module_name}_autodoc
220    COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_BINARY_DIR}/share:${CMAKE_BINARY_DIR}/wrap ${PYTHON_EXECUTABLE} -c
221    "from gendoctools.python2rst import docstrings2rst as f; f('${COMPONENT}', '${module_path}', '${module_name}', '${SPHINX_OUTPUT_DIR}', '${SICONOS_SWIG_ROOT_DIR}')"
222    VERBATIM
223    DEPENDS ${module_name}_replace_latex
224    COMMENT "Create rst files from python docstrings for module siconos.${module_name}")
225
226  # Create dependency between autodoc target and siconos python modules.
227  foreach(dep IN LISTS PROCESSED_PYTHON_MODULES)
228    add_dependencies(${module_name}_autodoc ${dep})
229  endforeach()
230
231  # rst_api needs autodoc.
232  add_dependencies(rst_api ${module_name}_autodoc)
233
234endfunction()
235
236