1 # CMake macros to use the GtkDoc documentation system
3 # See the GTK-Doc manual (help/manual/C/index.docbook) for an example of how to
8 # GTKDOC_FOUND ... set to 1
10 # GTKDOC_SCAN_EXE ... the location of the gtkdoc-scan executable
11 # GTKDOC_SCANGOBJ_EXE ... the location of the gtkdoc-scangobj executable
12 # GTKDOC_MKDB_EXE ... the location of the gtkdoc-mkdb executable
13 # GTKDOC_MKHTML_EXE ... the location of the gtkdoc-mkhtml executable
14 # GTKDOC_FIXXREF_EXE ... the location of the gtkdoc-fixxref executable
17 #=============================================================================
18 # Copyright 2009 Rich Wareham
19 # Copyright 2015 Lautsprecher Teufel GmbH
21 # This program is free software; you can redistribute it and/or modify
22 # it under the terms of the GNU General Public License as published by
23 # the Free Software Foundation; either version 2 of the License, or
24 # (at your option) any later version.
26 # This program is distributed in the hope that it will be useful,
27 # but WITHOUT ANY WARRANTY; without even the implied warranty of
28 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 # GNU General Public License for more details.
31 # You should have received a copy of the GNU General Public License
32 # along with this program. If not, see <http://www.gnu.org/licenses/>.
33 #=============================================================================
35 include(CMakeParseArguments)
39 set(GTKDOC_SCAN_EXE @bindir@/gtkdoc-scan)
40 set(GTKDOC_SCANGOBJ_EXE @bindir@/gtkdoc-scangobj)
41 set(GTKDOC_MKDB_EXE @bindir@/gtkdoc-mkdb)
42 set(GTKDOC_MKHTML_EXE @bindir@/gtkdoc-mkhtml)
43 set(GTKDOC_FIXXREF_EXE @bindir@/gtkdoc-fixxref)
45 get_filename_component(_this_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
46 find_file(GTKDOC_SCANGOBJ_WRAPPER GtkDocScanGObjWrapper.cmake PATH ${_this_dir})
50 # gtk_doc_add_module(doc_prefix
51 # SOURCE <sourcedir> [...]
53 # [LIBRARIES depend1...]
54 # [FIXXREFOPTS fixxrefoption1...]
55 # [IGNOREHEADERS header1...])
57 # Add a module with documentation to be processed with GTK-Doc.
59 # <sourcedir> must be the *full* path to the source directory.
61 # If omitted, xmlfile defaults to the auto generated ${doc_prefix}/${doc_prefix}-docs.xml.
63 # The `gtkdoc-scangobj` program is used to get introspection information for
64 # the module. You should pass the target(s) to be scanned as LIRARIES. This
65 # will try to set the correct compiler and link flags for the introspection
66 # build to use, and the correct LD_LIBRARY_PATH for it to run, and the correct
67 # dependencies for the doc target.
69 # You *can* also set the compile and link flags manually, using the 'CFLAGS'
70 # and 'LDFLAGS' options. The 'LDPATH' option controls the LD_LIBRARY_PATH. You
71 # can also manually add additional targets as dependencies of the
72 # documentation build with the DEPENDS option.
74 # This function a target named "doc-${doc_prefix}". You will need to manually
75 # add it to the ALL target if you want it to be built by default, you can do
76 # something like this:
78 # gtk_doc_add_module(doc-mymodule
79 # SOURCE ${CMAKE_SOURCE_DIR}/module ${CMAKE_BINARY_DIR}/module
81 # LIBRARY_DIRS ${GLIB_LIBRARY_DIRS} ${FOO_LIBRARY_DIRS}
82 # add_custom_target(all-documentation ALL)
83 # add_dependencies(all-documentation doc-mymodule)
85 function(gtk_doc_add_module _doc_prefix)
86 set(_one_value_args "XML")
87 set(_multi_value_args "FIXXREFOPTS" "IGNOREHEADERS" "LIBRARIES" "LIBRARY_DIRS" "SOURCE" "SUFFIXES"
88 "CFLAGS" "DEPENDS" "LDFLAGS" "LDPATH")
89 cmake_parse_arguments("GTK_DOC" "" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
91 if(NOT GTK_DOC_SOURCE)
92 message(FATAL_ERROR "No SOURCE specified for gtk_doc_add_module ${_doc_prefix}")
95 set(_xml_file ${GTK_DOC_XML})
97 set(_fixxrefopts ${GTK_DOC_FIXXREFOPTS})
98 set(_ignore_headers ${GTK_DOC_IGNOREHEADERS})
99 set(_libraries ${GTK_DOC_LIBRARIES})
100 set(_library_dirs ${GTK_DOC_LIBRARY_DIRS})
101 set(_suffixes ${GTK_DOC_SUFFIXES})
103 set(_extra_cflags ${GTK_DOC_CFLAGS})
104 set(_depends ${GTK_DOC_DEPENDS})
105 set(_extra_ldflags ${GTK_DOC_LDFLAGS})
106 set(_extra_ldpath ${GTK_DOC_LDPATH})
109 set(_doc_source_suffixes "")
110 foreach(_suffix ${_suffixes})
111 if(_doc_source_suffixes)
112 set(_doc_source_suffixes "${_doc_source_suffixes},${_suffix}")
113 else(_doc_source_suffixes)
114 set(_doc_source_suffixes "${_suffix}")
115 endif(_doc_source_suffixes)
118 set(_doc_source_suffixes "h")
121 # Parse the LIBRARIES option and collect compile and link flags for those
123 foreach(target ${_libraries})
124 _gtk_doc_get_cflags_for_target(_target_cflags ${target})
125 _gtk_doc_get_ldflags_for_target(_target_ldflags ${target} "${_libraries}")
126 list(APPEND _extra_cflags ${_target_cflags})
127 list(APPEND _extra_ldflags ${_target_ldflags})
128 list(APPEND _extra_ldpath $<TARGET_FILE_DIR:${target}>)
130 list(APPEND _depends ${target})
133 # Link directories can't be specified per target, only for every target
134 # under a given directory.
135 get_property(all_library_directories DIRECTORY PROPERTY LINK_DIRECTORIES)
136 foreach(library_dir ${all_library_directories})
137 list(APPEND _extra_ldflags ${CMAKE_LIBRARY_PATH_FLAG}${library_dir})
138 list(APPEND _extra_ldpath ${library_dir})
141 # a directory to store output.
142 set(_output_dir "${CMAKE_CURRENT_BINARY_DIR}/${_doc_prefix}")
143 set(_output_dir_stamp "${_output_dir}/dir.stamp")
145 # set default sgml file if not specified
146 set(_default_xml_file "${_output_dir}/${_doc_prefix}-docs.xml")
147 get_filename_component(_default_xml_file ${_default_xml_file} ABSOLUTE)
149 # a directory to store html output.
150 set(_output_html_dir "${_output_dir}/html")
151 set(_output_html_dir_stamp "${_output_dir}/html_dir.stamp")
154 set(_output_decl_list "${_output_dir}/${_doc_prefix}-decl-list.txt")
155 set(_output_decl "${_output_dir}/${_doc_prefix}-decl.txt")
156 set(_output_overrides "${_output_dir}/${_doc_prefix}-overrides.txt")
157 set(_output_sections "${_output_dir}/${_doc_prefix}-sections.txt")
158 set(_output_types "${_output_dir}/${_doc_prefix}.types")
160 set(_output_signals "${_output_dir}/${_doc_prefix}.signals")
162 set(_output_unused "${_output_dir}/${_doc_prefix}-unused.txt")
163 set(_output_undeclared "${_output_dir}/${_doc_prefix}-undeclared.txt")
164 set(_output_undocumented "${_output_dir}/${_doc_prefix}-undocumented.txt")
166 set(_output_xml_dir "${_output_dir}/xml")
167 set(_output_sgml_stamp "${_output_dir}/sgml.stamp")
169 set(_output_html_stamp "${_output_dir}/html.stamp")
171 # add a command to create output directory
173 OUTPUT "${_output_dir_stamp}" "${_output_dir}"
174 COMMAND ${CMAKE_COMMAND} -E make_directory "${_output_dir}"
175 COMMAND ${CMAKE_COMMAND} -E touch ${_output_dir_stamp}
178 set(_ignore_headers_opt "")
180 set(_ignore_headers_opt "--ignore-headers=")
181 foreach(_header ${_ignore_headers})
182 set(_ignore_headers_opt "${_ignore_headers_opt}${_header} ")
183 endforeach(_header ${_ignore_headers})
184 endif(_ignore_headers)
186 foreach(source_dir ${GTK_DOC_SOURCE})
187 set(_source_dirs_opt ${_source_dirs_opt} --source-dir=${source_dir})
190 # add a command to scan the input
193 "${_output_decl_list}"
195 "${_output_overrides}"
196 "${_output_sections}"
199 "${_output_dir_stamp}"
203 --module=${_doc_prefix}
204 ${_ignore_headers_opt}
208 WORKING_DIRECTORY ${_output_dir}
211 # add a command to scan the input via gtkdoc-scangobj
212 # This is such a disgusting hack!
218 COMMAND ${CMAKE_COMMAND}
219 -D "GTKDOC_SCANGOBJ_EXE:STRING=${GTKDOC_SCANGOBJ_EXE}"
220 -D "doc_prefix:STRING=${_doc_prefix}"
221 -D "output_types:STRING=${_output_types}"
222 -D "output_dir:STRING=${_output_dir}"
223 -D "EXTRA_CFLAGS:STRING=${_extra_cflags}"
224 -D "EXTRA_LDFLAGS:STRING=${_extra_ldflags}"
225 -D "EXTRA_LDPATH:STRING=${_extra_ldpath}"
226 -P ${GTKDOC_SCANGOBJ_WRAPPER}
227 WORKING_DIRECTORY "${_output_dir}"
230 set(_copy_xml_if_needed "")
232 get_filename_component(_xml_file ${_xml_file} ABSOLUTE)
233 set(_copy_xml_if_needed
234 COMMAND ${CMAKE_COMMAND} -E copy "${_xml_file}" "${_default_xml_file}")
237 set(_remove_xml_if_needed "")
239 set(_remove_xml_if_needed
240 COMMAND ${CMAKE_COMMAND} -E remove ${_default_xml_file})
243 # add a command to make the database
246 ${_output_sgml_stamp}
254 ${_remove_xml_if_needed}
255 COMMAND ${CMAKE_COMMAND} -E remove_directory ${_output_xml_dir}
256 COMMAND ${GTKDOC_MKDB_EXE}
257 --module=${_doc_prefix}
259 --source-suffixes=${_doc_source_suffixes}
261 --main-sgml-file=${_default_xml_file}
262 ${_copy_xml_if_needed}
263 WORKING_DIRECTORY "${_output_dir}"
266 # add a command to create html directory
268 OUTPUT "${_output_html_dir_stamp}" "${_output_html_dir}"
269 COMMAND ${CMAKE_COMMAND} -E make_directory ${_output_html_dir}
270 COMMAND ${CMAKE_COMMAND} -E touch ${_output_html_dir_stamp}
273 # add a command to output HTML
276 ${_output_html_stamp}
278 ${_output_html_dir_stamp}
279 ${_output_sgml_stamp}
282 ${_copy_xml_if_needed}
283 # The binary dir needs adding to --path in order for mkhtml to pick up
284 # any version.xml file there might be in there
286 cd ${_output_html_dir} && ${GTKDOC_MKHTML_EXE}
290 cd ${_output_dir} && ${GTKDOC_FIXXREF_EXE}
291 --module=${_doc_prefix}
292 --module-dir=${_output_html_dir}
295 "Generating HTML documentation for ${_doc_prefix} module with gtkdoc-mkhtml"
298 add_custom_target(doc-${_doc_prefix}
299 DEPENDS "${_output_html_stamp}")
300 endfunction(gtk_doc_add_module)
302 # These two functions reimplement some of the core logic of CMake, in order
303 # to generate compiler and linker flags from the relevant target properties.
304 # It sucks that we have to do this, but CMake's own code for this doesn't seem
305 # to be reusable -- there's no way to say "tell me the flags that you would
306 # pass to a linker for this target".
308 function(_gtk_doc_get_cflags_for_target result_var target)
309 get_target_property(target_definitions ${target} COMPILE_DEFINITIONS)
310 if(target_definitions)
311 list(APPEND cflags ${target_definitions})
314 get_target_property(target_options ${target} COMPILE_OPTIONS)
316 list(APPEND cflags ${target_options})
319 get_target_property(target_include_dirs ${target} INCLUDE_DIRECTORIES)
320 foreach(target_include_dir ${target_include_dirs})
321 list(APPEND cflags -I${target_include_dir})
324 list(REMOVE_DUPLICATES cflags)
327 set(${result_var} ${cflags} PARENT_SCOPE)
330 function(_gtk_doc_get_ldflags_for_target result_var target all_targets)
331 get_target_property(target_link_flags ${target} LINK_FLAGS)
332 if(target_link_flags)
333 list(APPEND ldflags ${target_link_flags})
336 get_target_property(target_link_libraries ${target} LINK_LIBRARIES)
337 foreach(target_library ${target_link_libraries})
338 # The IN_LIST operator is new in CMake 3.3, so I've tried to avoid using it.
339 list(FIND all_targets ${target_library} target_library_is_explicit_dependency)
340 if(NOT ${target_library_is_explicit_dependency} EQUAL -1)
341 # This target is part of the current project. We will add it to
342 # LDFLAGS explicitly, so don't try to add it with -l<target> as
343 # well. In fact, we can't do that, as the containing directory
344 # probably won't be in the linker search path, and we can't find
345 # that out and add it ourselves.
346 elseif(EXISTS ${target_library})
347 # Pass the filename directly to the linker.
348 list(APPEND ldflags "${target_library}")
350 # Pass -l<filename> to the linker.
351 list(APPEND ldflags "${CMAKE_LINK_LIBRARY_FLAG}${target_library}")
355 # Link in the actual target, as well.
356 list(APPEND ldflags $<TARGET_FILE:${target}>)
358 list(REMOVE_DUPLICATES ldflags)
361 set(${result_var} ${ldflags} PARENT_SCOPE)