summaryrefslogtreecommitdiff
path: root/cmake/modules/GtkDoc.cmake
blob: 3937874bf600e7f93893679adaecbfa8b5ef22bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# GtkDoc.cmake
#
# Macros to support develper documentation build from sources with gtk-doc.
#
# Note that every target and dependency should be defined before the macro is
# called, because it uses information from those targets.
#
# add_gtkdoc(_module _namespace _deprecated_guards _srcdirsvar _depsvar _ignoreheadersvar)
#    Adds rules to build developer documentation using gtk-doc for some part.
#    Arguments:
#       _module - the module name, like 'camel'; it expects ${_part}-docs.sgml.in in the CMAKE_CURRENT_SOURCE_DIR
#       _namespace - namespace for symbols
#       _deprecated_guards - define name, which guards deprecated symbols
#       _srcdirsvar - variable with dirs where the source files are located
#       _depsvar - a variable with dependencies (targets)
#       _ignoreheadersvar - a variable with a set of header files to ignore
#
# It also adds custom target gtkdoc-rebuild-${_module}-sgml to rebuild the sgml.in
# file based on the current sources.

option(ENABLE_GTK_DOC "Use gtk-doc to build documentation" True)

if(NOT ENABLE_GTK_DOC)
  return()
endif()

find_program(GTKDOC_SCAN gtkdoc-scan)
find_program(GTKDOC_SCANGOBJ gtkdoc-scangobj)
find_program(GTKDOC_MKDB gtkdoc-mkdb)
find_program(GTKDOC_MKHTML gtkdoc-mkhtml)
find_program(GTKDOC_FIXXREF gtkdoc-fixxref)

if(NOT (GTKDOC_SCAN AND GTKDOC_MKDB AND GTKDOC_MKHTML AND GTKDOC_FIXXREF))
  message(FATAL_ERROR "Cannot find all gtk-doc binaries, install them or use -DENABLE_GTK_DOC=OFF  instead")
  return()
endif()

if(NOT TARGET gtkdocs)
  add_custom_target(gtkdocs ALL)
endif()

if(NOT TARGET gtkdoc-rebuild-sgmls)
  add_custom_target(gtkdoc-rebuild-sgmls)
endif()

macro(add_gtkdoc _module _namespace _deprecated_guards _srcdirsvar _depsvar _ignoreheadersvar)
  configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/${_module}-docs.sgml.in
    ${CMAKE_CURRENT_BINARY_DIR}/${_module}-docs.sgml
    @ONLY)

  set(OUTPUT_DOCDIR ${SHARE_INSTALL_DIR}/gtk-doc/html/${_module})

  set(_filedeps)
  set(_srcdirs)
  foreach(_srcdir ${${_srcdirsvar}})
    set(_srcdirs ${_srcdirs} --source-dir="${_srcdir}")
    file(GLOB _files ${_srcdir}/*.h* ${_srcdir}/*.c*)
    list(APPEND _filedeps ${_files})
  endforeach()

  if(APPLE)
    if(NOT DEFINED ENV{XML_CATALOG_FILES})
      message(FATAL_ERROR "On OSX, please run \'export XML_CATALOG_FILES=/usr/local/etc/xml/catalog\' first; else the gtk entities cannot be located.")
    endif()
  endif()

  set(_scangobj_deps)
  set(_scangobj_cflags_list)
  set(_scangobj_cflags "")
  set(_scangobj_ldflags "")
  set(_scangobj_ld_lib_dirs "")

  foreach(opt IN LISTS ${_depsvar})
    if(TARGET ${opt})
      set(_target_type)
      get_target_property(_target_type ${opt} TYPE)
      if((_target_type STREQUAL "STATIC_LIBRARY") OR (_target_type STREQUAL "SHARED_LIBRARY") OR (_target_type STREQUAL "MODULE_LIBRARY"))
        set(_compile_options)
        set(_link_libraries)

        get_target_property(_compile_options ${opt} COMPILE_OPTIONS)
        get_target_property(_link_libraries ${opt} LINK_LIBRARIES)

        list(APPEND _scangobj_cflags_list ${_compile_options})
        list(APPEND _scangobj_deps ${_link_libraries})

        unset(_compile_options)
        unset(_link_libraries)
      endif()
      unset(_target_type)
    endif()

    list(APPEND _scangobj_deps ${opt})
  endforeach()

  # Add it as the last, thus in-tree headers have precedence
  list(APPEND _scangobj_cflags_list -I${INCLUDE_INSTALL_DIR})

  if(_scangobj_deps)
    list(REMOVE_DUPLICATES _scangobj_deps)
  endif()
  if(_scangobj_cflags_list)
    list(REMOVE_DUPLICATES _scangobj_cflags_list)
  endif()

  foreach(opt IN LISTS _scangobj_cflags_list)
    set(_scangobj_cflags "${_scangobj_cflags} ${opt}")
  endforeach()

  foreach(opt IN LISTS _scangobj_deps)
    if(TARGET ${opt})
      set(_target_type)
      get_target_property(_target_type ${opt} TYPE)
      if((_target_type STREQUAL "STATIC_LIBRARY") OR (_target_type STREQUAL "SHARED_LIBRARY") OR (_target_type STREQUAL "MODULE_LIBRARY"))
        set(_output_name "")
        get_target_property(_output_name ${opt} OUTPUT_NAME)
        if(NOT _output_name)
          set(_output_name ${opt})
        endif()
        set(_scangobj_ldflags "${_scangobj_ldflags} -L$<TARGET_FILE_DIR:${opt}> -l${_output_name}")

        if(_target_type STREQUAL "SHARED_LIBRARY" OR (_target_type STREQUAL "MODULE_LIBRARY"))
          set(_scangobj_ld_lib_dirs "${_scangobj_ld_lib_dirs}:$<TARGET_FILE_DIR:${opt}>")
        endif()
        unset(_output_name)
      endif()
      unset(_target_type)
    endif()
  endforeach()

  # Add extra flags from LDFLAGS environment variable
  set(_scangobj_ldflags "${_scangobj_ldflags} ${CMAKE_SHARED_LINKER_FLAGS}")

  foreach(opt IN LISTS _scangobj_deps)
    if(NOT TARGET ${opt})
      set(_scangobj_ldflags "${_scangobj_ldflags} ${opt}")
    endif()
  endforeach()

  # Add it as the last, thus in-tree libs have precedence
  set(_scangobj_ldflags "${_scangobj_ldflags} -L${LIB_INSTALL_DIR}")

  set(_scangobj_prefix ${CMAKE_COMMAND} -E env LD_LIBRARY_PATH="${_scangobj_ld_lib_dirs}:${LIB_INSTALL_DIR}:$ENV{LD_LIBRARY_PATH}")

#  if(NOT (_scangobj_cflags STREQUAL ""))
#    set(_scangobj_cflags --cflags "${_scangobj_cflags}")
#  endif()

#  if(NOT (_scangobj_ldflags STREQUAL ""))
#    set(_scangobj_ldflags "--ldflags ${_scangobj_ldflags}")
#  endif()

  add_custom_command(OUTPUT html/index.html
    COMMAND ${GTKDOC_SCAN}
      --module=${_module}
      --deprecated-guards="${_deprecated_guards}"
      --ignore-headers="${${_ignoreheadersvar}}"
      --rebuild-sections
      --rebuild-types
      ${_srcdirs}

    COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}" ${_scangobj_prefix} ${GTKDOC_SCANGOBJ}
      --module=${_module}
      --cflags=${_scangobj_cflags}
      --ldflags=${_scangobj_ldflags}

    COMMAND ${GTKDOC_MKDB}
      --module=${_module}
      --name-space=${_namespace}
      --main-sgml-file="${CMAKE_CURRENT_BINARY_DIR}/${_module}-docs.sgml"
      --sgml-mode
      --output-format=xml
      ${_srcdirs}

    COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/html"

    COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/html" ${GTKDOC_MKHTML} --path=.. ${_module} ../${_module}-docs.sgml

    COMMAND ${GTKDOC_FIXXREF}
      --module=${_module}
      --module-dir=html
      --extra-dir=..
      --html-dir="${OUTPUT_DOCDIR}"

    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${_module}-docs.sgml"
      ${_filedeps}
    COMMENT "Generating ${_module} documentation"
  )

  add_custom_target(gtkdoc-${_module}
    DEPENDS html/index.html
  )

  if(${_depsvar})
    add_dependencies(gtkdoc-${_module} ${${_depsvar}})
  endif(${_depsvar})

  add_dependencies(gtkdocs gtkdoc-${_module})

  install(
    DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
    DESTINATION ${OUTPUT_DOCDIR}
  )

  # ***************************************
  # sgml.in file rebuild, unconditional
  # ***************************************
  add_custom_target(gtkdoc-rebuild-${_module}-sgml
    COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/tmp"
    COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/tmp"

    COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/tmp"
      ${GTKDOC_SCAN}
      --module=${_module}
      --deprecated-guards="${_deprecated_guards}"
      --ignore-headers="${_ignore_headers}"
      --rebuild-sections
      --rebuild-types
      ${_srcdirs}

    COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}" ${_scangobj_prefix} ${GTKDOC_SCANGOBJ}
      --module=${_module}
      ${_scangobj_cflags}
      ${_scangobj_ldflags}

    COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/tmp"
      ${GTKDOC_MKDB}
      --module=${_module}
      --name-space=${_namespace}
      --main-sgml-file="${CMAKE_CURRENT_BINARY_DIR}/tmp/${_module}-docs.sgml"
      --sgml-mode
      --output-format=xml
      ${_srcdirs}

    COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/tmp/${_module}-docs.sgml ${CMAKE_CURRENT_SOURCE_DIR}/${_module}-docs.sgml.in

    COMMAND ${CMAKE_COMMAND} -E echo "File '${CMAKE_CURRENT_SOURCE_DIR}/${_module}-docs.sgml.in' overwritten, make sure you replace generated strings with proper content before committing."
  )

  add_dependencies(gtkdoc-rebuild-sgmls gtkdoc-rebuild-${_module}-sgml)

  unset(_scangobj_prefix)
  unset(_scangobj_deps)
  unset(_scangobj_cflags_list)
  unset(_scangobj_cflags)
  unset(_scangobj_ldflags)
  unset(_scangobj_ld_lib_dirs)
endmacro()