]>
Commit | Line | Data |
---|---|---|
1 | # po4a/docbook documentation support for CMake | |
2 | # - see documentation of add_docbook() | |
3 | # | |
4 | # Copyright (C) 2016 Julian Andres Klode <jak@debian.org>. | |
5 | # | |
6 | # Permission is hereby granted, free of charge, to any person | |
7 | # obtaining a copy of this software and associated documentation files | |
8 | # (the "Software"), to deal in the Software without restriction, | |
9 | # including without limitation the rights to use, copy, modify, merge, | |
10 | # publish, distribute, sublicense, and/or sell copies of the Software, | |
11 | # and to permit persons to whom the Software is furnished to do so, | |
12 | # subject to the following conditions: | |
13 | # | |
14 | # The above copyright notice and this permission notice shall be | |
15 | # included in all copies or substantial portions of the Software. | |
16 | # | |
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
21 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
22 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
23 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
24 | # SOFTWARE. | |
25 | ||
26 | ||
27 | find_path(DOCBOOK_XSL manpages/docbook.xsl | |
28 | # Debian | |
29 | /usr/share/xml/docbook/stylesheet/docbook-xsl | |
30 | /usr/share/xml/docbook/stylesheet/nwalsh | |
31 | # OpenSUSE | |
32 | /usr/share/xml/docbook/stylesheet/nwalsh/current | |
33 | # Arch | |
34 | /usr/share/xml/docbook/xsl-stylesheets | |
35 | # Fedora | |
36 | /usr/share/sgml/docbook/xsl-stylesheets | |
37 | # Fink | |
38 | ${CMAKE_INSTALL_PREFIX}/share/xml/xsl/docbook-xsl | |
39 | # FreeBSD | |
40 | ${CMAKE_INSTALL_PREFIX}/share/xsl/docbook/ | |
41 | NO_DEFAULT_PATH) | |
42 | ||
43 | if(NOT DOCBOOK_XSL) | |
44 | message(FATAL_ERROR "Could not find docbook xsl") | |
45 | endif() | |
46 | ||
47 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docbook-text-style.xsl.cmake.in | |
48 | ${CMAKE_CURRENT_BINARY_DIR}/docbook-text-style.xsl) | |
49 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docbook-html-style.xsl.cmake.in | |
50 | ${CMAKE_CURRENT_BINARY_DIR}/docbook-html-style.xsl) | |
51 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/manpage-style.xsl.cmake.in | |
52 | ${CMAKE_CURRENT_BINARY_DIR}/manpage-style.xsl) | |
53 | ||
54 | ||
55 | # Split up a string of the form DOCUMENT[.DOCUMENT][.LANGUAGE][.SECTION].EXTENSION | |
56 | # | |
57 | # There might be up to two parts in the document name. The language must be | |
58 | # a two char language code like de, or a 5 char code of the form de_DE. | |
59 | function(po4a_components doc lang sec ext translated_full_document) | |
60 | get_filename_component(name ${translated_full_document} NAME) | |
61 | string(REPLACE "." ";" name "${name}") # Make it a list | |
62 | ||
63 | list(GET name 0 _doc) # First element is always the document | |
64 | list(GET name 1 _lang) # Second *might* be a language | |
65 | list(GET name -2 _sec) # Second-last *might* be a section | |
66 | list(GET name -1 _ext) # Last element is always the file type | |
67 | ||
68 | # If the language code is neither a file type, nor a section, nor a language | |
69 | # assume it is part of the file name and use the next component as the lang. | |
70 | if(_lang AND NOT _lang MATCHES "^(xml|dbk|[0-9]|[a-z][a-z]|[a-z][a-z]_[A-Z][A-Z])$") | |
71 | set(_doc "${_doc}.${_lang}") | |
72 | list(GET name 2 _lang) | |
73 | endif() | |
74 | # If no language is present, we get a section; both not present => type | |
75 | if(_lang MATCHES "xml|dbk|[0-9]") | |
76 | set(_lang "") | |
77 | endif() | |
78 | if(NOT _sec MATCHES "^[0-9]$") # A (manpage) section must be a number | |
79 | set(_sec "") | |
80 | endif() | |
81 | ||
82 | set(${doc} ${_doc} PARENT_SCOPE) | |
83 | set(${lang} ${_lang} PARENT_SCOPE) | |
84 | set(${sec} ${_sec} PARENT_SCOPE) | |
85 | set(${ext} ${_ext} PARENT_SCOPE) | |
86 | endfunction() | |
87 | ||
88 | ||
89 | # Process one document | |
90 | function(po4a_one stamp_out out full_document language deps) | |
91 | path_join(full_path "${CMAKE_CURRENT_SOURCE_DIR}" "${full_document}") | |
92 | po4a_components(document _ section ext "${full_document}") | |
93 | ||
94 | # Calculate target file name | |
95 | set(dest "${language}/${document}.${language}") | |
96 | if(section) | |
97 | set(dest "${dest}.${section}") | |
98 | endif() | |
99 | ||
100 | # po4a might drop files not translated enough, so build a stamp file | |
101 | set(stamp ${CMAKE_CURRENT_BINARY_DIR}/${dest}.po4a-stamp) | |
102 | add_custom_command( | |
103 | OUTPUT ${stamp} | |
104 | COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${language} | |
105 | COMMAND po4a --previous --no-backups | |
106 | --package-name='${PROJECT_NAME}-doc' | |
107 | --package-version='${PACKAGE_VERSION}' | |
108 | --msgid-bugs-address='${PACKAGE_MAIL}' | |
109 | --translate-only ${dest}.${ext} | |
110 | --srcdir ${CMAKE_CURRENT_SOURCE_DIR} | |
111 | --destdir ${CMAKE_CURRENT_BINARY_DIR} | |
112 | ${CMAKE_CURRENT_SOURCE_DIR}/po4a.conf | |
113 | COMMAND ${CMAKE_COMMAND} -E touch ${stamp} | |
114 | COMMENT "Generating ${dest}.${ext} (or dropping it)" | |
115 | DEPENDS ${full_document} ${deps} po/${language}.po | |
116 | ) | |
117 | # Return result | |
118 | set(${stamp_out} ${stamp} PARENT_SCOPE) | |
119 | set(${out} ${CMAKE_CURRENT_BINARY_DIR}/${dest}.${ext} PARENT_SCOPE) | |
120 | endfunction() | |
121 | ||
122 | function(xsltproc_one) | |
123 | set(generated "") | |
124 | set(options HTML TEXT MANPAGE) | |
125 | set(oneValueArgs STAMP STAMP_OUT FULL_DOCUMENT) | |
126 | set(multiValueArgs INSTALL DEPENDS) | |
127 | cmake_parse_arguments(DOC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | |
128 | ||
129 | po4a_components(document language section ext "${DOC_FULL_DOCUMENT}") | |
130 | ||
131 | # Default parameters | |
132 | set(params | |
133 | --nonet | |
134 | --xinclude | |
135 | --stringparam chunk.quietly yes | |
136 | --stringparam man.output.quietly yes | |
137 | --path ${PROJECT_SOURCE_DIR}/vendor/${CURRENT_VENDOR}/ | |
138 | --path ${CMAKE_CURRENT_SOURCE_DIR}/ | |
139 | ) | |
140 | ||
141 | # Parameters if localized | |
142 | if(language) | |
143 | list(APPEND params -stringparam l10n.gentext.default.language ${language}) | |
144 | endif() | |
145 | ||
146 | path_join(full_input_path ${CMAKE_CURRENT_SOURCE_DIR} ${DOC_FULL_DOCUMENT}) | |
147 | ||
148 | if (DOC_MANPAGE) | |
149 | if (language) | |
150 | set(manpage_output "${CMAKE_CURRENT_BINARY_DIR}/${language}/${document}.${section}") | |
151 | else() | |
152 | set(manpage_output "${CMAKE_CURRENT_BINARY_DIR}/${document}.${section}") | |
153 | endif() | |
154 | set(manpage_stylesheet "${CMAKE_CURRENT_BINARY_DIR}/manpage-style.xsl") | |
155 | set(manpage_params) | |
156 | ||
157 | install(FILES ${manpage_output} | |
158 | DESTINATION ${CMAKE_INSTALL_MANDIR}/${language}/man${section} | |
159 | OPTIONAL) | |
160 | endif() | |
161 | if (DOC_HTML) | |
162 | if (language) | |
163 | set(html_output "${CMAKE_CURRENT_BINARY_DIR}/${language}/${document}.${language}.html") | |
164 | else() | |
165 | set(html_output "${CMAKE_CURRENT_BINARY_DIR}/${document}.html") | |
166 | endif() | |
167 | set(html_params --stringparam base.dir ${html_output}) | |
168 | set(html_stylesheet "${CMAKE_CURRENT_BINARY_DIR}/docbook-html-style.xsl") | |
169 | install(DIRECTORY ${html_output} | |
170 | DESTINATION ${DOC_INSTALL} | |
171 | OPTIONAL) | |
172 | ||
173 | endif() | |
174 | if (DOC_TEXT) | |
175 | if (language) | |
176 | set(text_output "${CMAKE_CURRENT_BINARY_DIR}/${language}/${document}.${language}.text") | |
177 | else() | |
178 | set(text_output "${CMAKE_CURRENT_BINARY_DIR}/${document}.text") | |
179 | endif() | |
180 | set(text_params --stringparam base.dir ${text_output}) | |
181 | set(text_stylesheet "${CMAKE_CURRENT_BINARY_DIR}/docbook-text-style.xsl") | |
182 | ||
183 | file(RELATIVE_PATH text_output_relative ${CMAKE_CURRENT_BINARY_DIR} ${text_output}) | |
184 | ||
185 | add_custom_command(OUTPUT ${text_output}.w3m-stamp | |
186 | COMMAND ${PROJECT_SOURCE_DIR}/CMake/run_if_exists.sh | |
187 | --stdout ${text_output} | |
188 | ${text_output}.html | |
189 | env LC_ALL=C.UTF-8 w3m -cols 78 -dump | |
190 | -o display_charset=UTF-8 | |
191 | -no-graph -T text/html ${text_output}.html | |
192 | COMMAND ${CMAKE_COMMAND} -E touch ${text_output}.w3m-stamp | |
193 | COMMENT "Generating ${text_output_relative} (if not dropped by po4a)" | |
194 | DEPENDS "${text_output}.html.xsltproc-stamp" | |
195 | ) | |
196 | list(APPEND generated ${text_output}.w3m-stamp) | |
197 | ||
198 | install(FILES ${text_output} | |
199 | DESTINATION ${DOC_INSTALL} | |
200 | OPTIONAL) | |
201 | set(text_output "${text_output}.html") | |
202 | endif() | |
203 | ||
204 | foreach(type in manpage html text) | |
205 | if (NOT ${type}_output) | |
206 | continue() | |
207 | endif() | |
208 | ||
209 | set(output ${${type}_output}) | |
210 | set(stylesheet ${${type}_stylesheet}) | |
211 | set(type_params ${${type}_params}) | |
212 | file(RELATIVE_PATH output_relative ${CMAKE_CURRENT_BINARY_DIR} ${output}) | |
213 | ||
214 | add_custom_command(OUTPUT ${output}.xsltproc-stamp | |
215 | COMMAND ${PROJECT_SOURCE_DIR}/CMake/run_if_exists.sh | |
216 | ${full_input_path} | |
217 | xsltproc ${params} ${type_params} -o ${output} | |
218 | ${stylesheet} | |
219 | ${full_input_path} | |
220 | COMMAND ${CMAKE_COMMAND} -E touch ${output}.xsltproc-stamp | |
221 | COMMENT "Generating ${output_relative} (if not dropped by po4a)" | |
222 | DEPENDS ${DOC_STAMP} ${DOC_DEPENDS}) | |
223 | ||
224 | list(APPEND generated ${output}.xsltproc-stamp) | |
225 | endforeach() | |
226 | ||
227 | set(${DOC_STAMP_OUT} ${generated} PARENT_SCOPE) | |
228 | endfunction() | |
229 | ||
230 | ||
231 | # add_docbook(Name [ALL] [HTML] [TEXT] [MANPAGE] | |
232 | # [INSTALL install dir] | |
233 | # [DEPENDS depend ...] | |
234 | # [DOCUMENTS documents ...] | |
235 | # [LINGUAS lingua ...]) | |
236 | # | |
237 | # Generate a target called name with all the documents being converted to | |
238 | # the chosen output formats and translated to the chosen languages using po4a. | |
239 | # | |
240 | # For the translation support, the po4a.conf must be written so that | |
241 | # translations for a document guide.xml are written to LANG/guide.LANG.xml, | |
242 | # and for a manual page man.5.xml to a file called LANG/man.LANG.5.xml. | |
243 | # | |
244 | # The guide and manual page names may also contain a second component separated | |
245 | # by a dot, it must however not be a valid language code. | |
246 | # | |
247 | # Note that po4a might chose not to generate a translated manual page for a | |
248 | # given language if the translation rate is not high enough. We deal with this | |
249 | # by creating stamp files. | |
250 | function(add_docbook target) | |
251 | set(generated "") | |
252 | set(options HTML TEXT MANPAGE ALL) | |
253 | set(oneValueArgs) | |
254 | set(multiValueArgs INSTALL DOCUMENTS LINGUAS DEPENDS) | |
255 | cmake_parse_arguments(DOC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | |
256 | ||
257 | if (DOC_HTML) | |
258 | list(APPEND formats HTML) | |
259 | endif() | |
260 | if (DOC_TEXT) | |
261 | list(APPEND formats TEXT) | |
262 | endif() | |
263 | if (DOC_MANPAGE) | |
264 | list(APPEND formats MANPAGE) | |
265 | endif() | |
266 | ||
267 | foreach(document ${DOC_DOCUMENTS}) | |
268 | foreach(lang ${DOC_LINGUAS}) | |
269 | po4a_one(po4a_stamp po4a_out ${document} "${lang}" "${DOC_DEPENDS}") | |
270 | xsltproc_one(STAMP_OUT xslt_stamp | |
271 | STAMP ${po4a_stamp} | |
272 | FULL_DOCUMENT ${po4a_out} | |
273 | INSTALL ${DOC_INSTALL} | |
274 | ${formats}) | |
275 | ||
276 | list(APPEND stamps ${xslt_stamp}) | |
277 | endforeach() | |
278 | xsltproc_one(STAMP_OUT xslt_stamp | |
279 | STAMP ${document} | |
280 | FULL_DOCUMENT ${document} | |
281 | INSTALL ${DOC_INSTALL} | |
282 | ${formats}) | |
283 | ||
284 | list(APPEND stamps ${xslt_stamp}) | |
285 | endforeach() | |
286 | ||
287 | if (DOC_ALL) | |
288 | add_custom_target(${target} ALL DEPENDS ${stamps}) | |
289 | else() | |
290 | add_custom_target(${target} DEPENDS ${stamps}) | |
291 | endif() | |
292 | endfunction() | |
293 | ||
294 | # Add an update-po4a target | |
295 | function(add_update_po4a target pot header) | |
296 | set(WRITE_HEADER "") | |
297 | ||
298 | if (header) | |
299 | set(WRITE_HEADER | |
300 | COMMAND sed -n "/^\#$/,$p" ${pot} > ${pot}.headerfree | |
301 | COMMAND cat ${header} ${pot}.headerfree > ${pot} | |
302 | COMMAND rm ${pot}.headerfree | |
303 | ) | |
304 | endif() | |
305 | add_custom_target(${target} | |
306 | COMMAND po4a --previous --no-backups --force --no-translations | |
307 | --msgmerge-opt --add-location=file | |
308 | --porefs noline,wrap | |
309 | --package-name=${PROJECT_NAME}-doc --package-version=${PACKAGE_VERSION} | |
310 | --msgid-bugs-address=${PACKAGE_MAIL} po4a.conf | |
311 | ${WRITE_HEADER} | |
312 | VERBATIM | |
313 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | |
314 | ) | |
315 | endfunction() |