]> git.saurik.com Git - apt.git/blobdiff - CMake/Documentation.cmake
test: Substitute GNU commands for other commands where available
[apt.git] / CMake / Documentation.cmake
index 98e07176b3cf87104c1890a4afde870397b98e54..f3bbfdc6b857dbba0c16895f65c861f79ab80d4c 100644 (file)
@@ -1,4 +1,7 @@
-# Copyright (C) 2009, 2016 Julian Andres Klode <jak@debian.org>.
+# po4a/docbook documentation support for CMake
+# - see documentation of add_docbook()
+#
+# Copyright (C) 2016 Julian Andres Klode <jak@debian.org>.
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation files
 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 # SOFTWARE.
 
-function(add_docbook target sourcefiles installdest)
-    foreach(file ${sourcefiles})
-        get_filename_component(relfile ${file} NAME)
-        string(REPLACE ".dbk" "" manual ${relfile})
-        get_filename_component(absolute ${file} ABSOLUTE)
-
-        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${manual}.html/
-            COMMAND xsltproc --nonet --novalid --xinclude
-                             --stringparam base.dir ${CMAKE_CURRENT_BINARY_DIR}/${manual}.html/
-                             --path ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/${CURRENT_VENDOR}/
-                             --path ${CMAKE_CURRENT_SOURCE_DIR}/
-                             ${CMAKE_CURRENT_SOURCE_DIR}/docbook-html-style.xsl
-                             ${absolute}
-            WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-            DEPENDS ${file}
-        )
-        set(commands ${commands} ${CMAKE_CURRENT_BINARY_DIR}/${manual}.html)
-        if (NOT ${installdest} EQUAL "" )
-        install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${manual}.html
-            DESTINATION ${installdest})
-        endif()
-    endforeach(file ${sourcefiles})
 
-    add_custom_target(${target} ALL DEPENDS ${commands})
+find_path(DOCBOOK_XSL manpages/docbook.xsl
+         # Debian
+         /usr/share/xml/docbook/stylesheet/docbook-xsl
+         /usr/share/xml/docbook/stylesheet/nwalsh
+         # OpenSUSE
+         /usr/share/xml/docbook/stylesheet/nwalsh/current
+         # Arch
+          /usr/share/xml/docbook/xsl-stylesheets
+         # Fedora
+         /usr/share/sgml/docbook/xsl-stylesheets
+         # Fink
+         ${CMAKE_INSTALL_PREFIX}/share/xml/xsl/docbook-xsl
+         # FreeBSD
+         ${CMAKE_INSTALL_PREFIX}/share/xsl/docbook/
+         NO_DEFAULT_PATH)
+
+if(NOT DOCBOOK_XSL)
+    message(FATAL_ERROR "Could not find docbook xsl")
+endif()
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docbook-text-style.xsl.cmake.in
+                ${CMAKE_CURRENT_BINARY_DIR}/docbook-text-style.xsl)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docbook-html-style.xsl.cmake.in
+                ${CMAKE_CURRENT_BINARY_DIR}/docbook-html-style.xsl)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/manpage-style.xsl.cmake.in
+                ${CMAKE_CURRENT_BINARY_DIR}/manpage-style.xsl)
+
+
+# Split up a string of the form DOCUMENT[.DOCUMENT][.LANGUAGE][.SECTION].EXTENSION
+#
+# There might be up to two parts in the document name. The language must be
+# a two char language code like de, or a 5 char code of the form de_DE.
+function(po4a_components doc lang sec ext translated_full_document)
+    get_filename_component(name ${translated_full_document} NAME)
+    string(REPLACE "." ";" name "${name}")          # Make it a list
+
+    list(GET name 0 _doc)   # First element is always the document
+    list(GET name 1 _lang)  # Second *might* be a language
+    list(GET name -2 _sec)  # Second-last *might* be a section
+    list(GET name -1 _ext)  # Last element is always the file type
+
+    # If the language code is neither a file type, nor a section, nor a language
+    # assume it is part of the file name and use the next component as the lang.
+    if(_lang AND NOT _lang MATCHES "^(xml|dbk|[0-9]|[a-z][a-z]|[a-z][a-z]_[A-Z][A-Z])$")
+        set(_doc "${_doc}.${_lang}")
+        list(GET name 2 _lang)
+    endif()
+    # If no language is present, we get a section; both not present => type
+    if(_lang MATCHES "xml|dbk|[0-9]")
+        set(_lang "")
+    endif()
+    if(NOT _sec MATCHES "^[0-9]$")        # A (manpage) section must be a number
+        set(_sec "")
+    endif()
+
+    set(${doc} ${_doc} PARENT_SCOPE)
+    set(${lang} ${_lang} PARENT_SCOPE)
+    set(${sec} ${_sec} PARENT_SCOPE)
+    set(${ext} ${_ext} PARENT_SCOPE)
 endfunction()
 
 
-function(add_po4a type master po target deps)
-    add_custom_command(OUTPUT ${target}
-        COMMAND po4a-translate --keep 0 -f ${type} -m ${master}
-                               -p ${po} -l ${target}
-        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        DEPENDS ${deps} ${master} ${po})
+# Process one document
+function(po4a_one stamp_out out full_document language deps)
+    path_join(full_path "${CMAKE_CURRENT_SOURCE_DIR}" "${full_document}")
+    po4a_components(document _ section ext "${full_document}")
+
+    # Calculate target file name
+    set(dest "${language}/${document}.${language}")
+    if(section)
+        set(dest "${dest}.${section}")
+    endif()
+
+    # po4a might drop files not translated enough, so build a stamp file
+    set(stamp ${CMAKE_CURRENT_BINARY_DIR}/${dest}.po4a-stamp)
+    add_custom_command(
+        OUTPUT ${stamp}
+        COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${language}
+        COMMAND po4a --previous --no-backups
+                     --package-name='${PROJECT_NAME}-doc'
+                     --package-version='${PACKAGE_VERSION}'
+                     --msgid-bugs-address='${PACKAGE_MAIL}'
+                     --translate-only ${dest}.${ext}
+                     --srcdir ${CMAKE_CURRENT_SOURCE_DIR}
+                     --destdir ${CMAKE_CURRENT_BINARY_DIR}
+                      ${CMAKE_CURRENT_SOURCE_DIR}/po4a.conf
+        COMMAND ${CMAKE_COMMAND} -E touch ${stamp}
+        COMMENT "Generating ${dest}.${ext} (or dropping it)"
+        DEPENDS ${full_document} ${deps} po/${language}.po
+    )
+    # Return result
+    set(${stamp_out} ${stamp} PARENT_SCOPE)
+    set(${out} ${CMAKE_CURRENT_BINARY_DIR}/${dest}.${ext} PARENT_SCOPE)
 endfunction()
 
+function(xsltproc_one)
+    set(generated "")
+    set(options HTML TEXT MANPAGE)
+    set(oneValueArgs STAMP STAMP_OUT FULL_DOCUMENT)
+    set(multiValueArgs INSTALL DEPENDS)
+    cmake_parse_arguments(DOC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-# Macro for XML man pages.
-function(add_xml_manpages target manpages translations entities)
-    foreach(manpage ${manpages})
-        string(LENGTH ${manpage} manpage_length)
-        math(EXPR manpage_length ${manpage_length}-1)
-        string(SUBSTRING ${manpage} ${manpage_length} 1 section)
-
-        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${manpage}
-                COMMAND xsltproc --path ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/${CURRENT_VENDOR}/
-                                 --path ${CMAKE_CURRENT_SOURCE_DIR}/
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/manpage-style.xsl
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/${manpage}.xml
-            WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${manpage}.xml
-            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/manpage-style.xsl
-        )
+    po4a_components(document language section ext "${DOC_FULL_DOCUMENT}")
+
+    # Default parameters
+    set(params
+        --nonet
+        --xinclude
+        --stringparam chunk.quietly yes
+        --stringparam man.output.quietly yes
+        --path ${PROJECT_SOURCE_DIR}/vendor/${CURRENT_VENDOR}/
+        --path ${CMAKE_CURRENT_SOURCE_DIR}/
+    )
+
+    # Parameters if localized
+    if(language)
+        list(APPEND params -stringparam l10n.gentext.default.language ${language})
+    endif()
+
+    path_join(full_input_path ${CMAKE_CURRENT_SOURCE_DIR} ${DOC_FULL_DOCUMENT})
+
+    if (DOC_MANPAGE)
+        if (language)
+        set(manpage_output "${CMAKE_CURRENT_BINARY_DIR}/${language}/${document}.${section}")
+        else()
+        set(manpage_output "${CMAKE_CURRENT_BINARY_DIR}/${document}.${section}")
+        endif()
+        set(manpage_stylesheet "${CMAKE_CURRENT_BINARY_DIR}/manpage-style.xsl")
+        set(manpage_params)
 
+        install(FILES ${manpage_output}
+                DESTINATION ${CMAKE_INSTALL_MANDIR}/${language}/man${section}
+                OPTIONAL)
+    endif()
+    if (DOC_HTML)
+        if (language)
+        set(html_output "${CMAKE_CURRENT_BINARY_DIR}/${language}/${document}.${language}.html")
+        else()
+        set(html_output "${CMAKE_CURRENT_BINARY_DIR}/${document}.html")
+        endif()
+        set(html_params --stringparam base.dir ${html_output})
+        set(html_stylesheet "${CMAKE_CURRENT_BINARY_DIR}/docbook-html-style.xsl")
+        install(DIRECTORY ${html_output}
+                DESTINATION ${DOC_INSTALL}
+                OPTIONAL)
 
-        set(commands ${commands} ${CMAKE_CURRENT_BINARY_DIR}/${manpage})
+    endif()
+    if (DOC_TEXT)
+        if (language)
+        set(text_output "${CMAKE_CURRENT_BINARY_DIR}/${language}/${document}.${language}.text")
+        else()
+        set(text_output "${CMAKE_CURRENT_BINARY_DIR}/${document}.text")
+        endif()
+        set(text_params --stringparam base.dir ${text_output})
+        set(text_stylesheet "${CMAKE_CURRENT_BINARY_DIR}/docbook-text-style.xsl")
 
-        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${manpage}
-                DESTINATION ${CMAKE_INSTALL_MANDIR}/man${section})
+        file(RELATIVE_PATH text_output_relative ${CMAKE_CURRENT_BINARY_DIR} ${text_output})
 
-        # Add the translations for the manpage.
-        foreach(translation ${translations})
-            set(entities)
-            # transdir = shortcut to the output directory for translations.
-            set(transdir ${CMAKE_CURRENT_BINARY_DIR}/${translation})
+        add_custom_command(OUTPUT ${text_output}.w3m-stamp
+                            COMMAND ${PROJECT_SOURCE_DIR}/CMake/run_if_exists.sh
+                                    --stdout ${text_output}
+                                    ${text_output}.html
+                                    env LC_ALL=C.UTF-8 w3m -cols 78 -dump
+                                    -o display_charset=UTF-8
+                                    -no-graph -T text/html ${text_output}.html
+                            COMMAND ${CMAKE_COMMAND} -E touch ${text_output}.w3m-stamp
+                            COMMENT "Generating ${text_output_relative} (if not dropped by po4a)"
+                            DEPENDS "${text_output}.html.xsltproc-stamp"
+                            )
+        list(APPEND generated ${text_output}.w3m-stamp)
 
-            add_po4a(docbook ${manpage}.xml po/${translation}.po
-                             ${transdir}/${manpage}.xml "${ent_cmds}")
+        install(FILES ${text_output}
+                DESTINATION ${DOC_INSTALL}
+                OPTIONAL)
+        set(text_output "${text_output}.html")
+    endif()
 
+    foreach(type in manpage html text)
+        if (NOT ${type}_output)
+            continue()
+        endif()
 
-            add_custom_command(OUTPUT ${transdir}/${manpage}
-                COMMAND xsltproc --path ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/${CURRENT_VENDOR}/
-                                 --path ${CMAKE_CURRENT_SOURCE_DIR}/
-                                 --stringparam l10n.gentext.default.language ${translation}
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/manpage-style.xsl
-                                 ${transdir}/${manpage}.xml
-                WORKING_DIRECTORY ${transdir}
-                DEPENDS ${transdir}/${manpage}.xml
-                DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/manpage-style.xsl)
+        set(output ${${type}_output})
+        set(stylesheet ${${type}_stylesheet})
+        set(type_params ${${type}_params})
+        file(RELATIVE_PATH output_relative ${CMAKE_CURRENT_BINARY_DIR} ${output})
 
-            set(nls-cmd ${nls-cmd} ${transdir}/${manpage})
-            install(FILES ${transdir}/${manpage}
-                    DESTINATION ${CMAKE_INSTALL_MANDIR}/${translation}/man${section})
+        add_custom_command(OUTPUT ${output}.xsltproc-stamp
+                COMMAND ${PROJECT_SOURCE_DIR}/CMake/run_if_exists.sh
+                        ${full_input_path}
+                        xsltproc ${params} ${type_params} -o ${output}
+                                 ${stylesheet}
+                                 ${full_input_path}
+                COMMAND ${CMAKE_COMMAND} -E touch ${output}.xsltproc-stamp
+                COMMENT "Generating ${output_relative} (if not dropped by po4a)"
+                DEPENDS ${DOC_STAMP} ${DOC_DEPENDS})
 
-        endforeach(translation ${translations})
-    endforeach(manpage ${manpages})
+        list(APPEND generated ${output}.xsltproc-stamp)
+    endforeach()
 
-    add_custom_target(${target} ALL DEPENDS ${commands})
-    # Sort the list of the translations.
-    list(SORT nls-cmd)
-    add_custom_target(nls-${target} ALL DEPENDS ${nls-cmd})
+    set(${DOC_STAMP_OUT} ${generated} PARENT_SCOPE)
 endfunction()
 
 
-function(add_manpages target manpages translations)
-    foreach(man ${manpages})
-        string(LENGTH ${man} manpage_length)
-        math(EXPR manpage_length ${manpage_length}-1)
-        string(SUBSTRING ${man} ${manpage_length} 1 section)
-        install(FILES ${man} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${section})
-
-        if (USE_NLS)
-            foreach(translation ${translations})
-                set(transdir ${CMAKE_CURRENT_BINARY_DIR}/${translation})
-                add_po4a(man ${man} po/${translation}.po ${transdir}/${man} "")
-                install(FILES ${transdir}/${man}
-                        DESTINATION ${CMAKE_INSTALL_MANDIR}/${translation}/man${section})
-                set(files ${files} ${transdir}/${man})
-            endforeach(translation ${translations})
-        endif()
-    endforeach(man ${manpages})
-    add_custom_target(${target} ALL DEPENDS ${files})
+# add_docbook(Name [ALL] [HTML] [TEXT] [MANPAGE]
+#             [INSTALL install dir]
+#             [DEPENDS depend ...]
+#             [DOCUMENTS documents ...]
+#             [LINGUAS lingua ...])
+#
+# Generate a target called name with all the documents being converted to
+# the chosen output formats and translated to the chosen languages using po4a.
+#
+# For the translation support, the po4a.conf must be written so that
+# translations for a document guide.xml are written to LANG/guide.LANG.xml,
+# and for a manual page man.5.xml to a file called LANG/man.LANG.5.xml.
+#
+# The guide and manual page names may also contain a second component separated
+# by a dot, it must however not be a valid language code.
+#
+# Note that po4a might chose not to generate a translated manual page for a
+# given language if the translation rate is not high enough. We deal with this
+# by creating stamp files.
+function(add_docbook target)
+    set(generated "")
+    set(options HTML TEXT MANPAGE ALL)
+    set(oneValueArgs)
+    set(multiValueArgs INSTALL DOCUMENTS LINGUAS DEPENDS)
+    cmake_parse_arguments(DOC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    if (DOC_HTML)
+        list(APPEND formats HTML)
+    endif()
+    if (DOC_TEXT)
+        list(APPEND formats TEXT)
+    endif()
+    if (DOC_MANPAGE)
+        list(APPEND formats MANPAGE)
+    endif()
+
+    foreach(document ${DOC_DOCUMENTS})
+        foreach(lang ${DOC_LINGUAS})
+            po4a_one(po4a_stamp po4a_out ${document} "${lang}" "${DOC_DEPENDS}")
+            xsltproc_one(STAMP_OUT xslt_stamp
+                         STAMP ${po4a_stamp}
+                         FULL_DOCUMENT ${po4a_out}
+                         INSTALL ${DOC_INSTALL}
+                         ${formats})
+
+            list(APPEND stamps ${xslt_stamp})
+        endforeach()
+            xsltproc_one(STAMP_OUT xslt_stamp
+                         STAMP ${document}
+                         FULL_DOCUMENT ${document}
+                         INSTALL ${DOC_INSTALL}
+                         ${formats})
+
+            list(APPEND stamps ${xslt_stamp})
+    endforeach()
+
+    if (DOC_ALL)
+        add_custom_target(${target} ALL DEPENDS ${stamps})
+    else()
+        add_custom_target(${target} DEPENDS ${stamps})
+    endif()
+endfunction()
+
+# Add an update-po4a target
+function(add_update_po4a target pot header)
+    set(WRITE_HEADER "")
+
+    if (header)
+        set(WRITE_HEADER
+            COMMAND sed -n "/^\#$/,$p" ${pot} > ${pot}.headerfree
+            COMMAND cat ${header} ${pot}.headerfree > ${pot}
+            COMMAND rm ${pot}.headerfree
+        )
+    endif()
+    add_custom_target(${target}
+        COMMAND po4a --previous --no-backups --force --no-translations
+                --msgmerge-opt --add-location=file
+                --porefs noline,wrap
+                --package-name=${PROJECT_NAME}-doc --package-version=${PACKAGE_VERSION}
+                --msgid-bugs-address=${PACKAGE_MAIL} po4a.conf
+        ${WRITE_HEADER}
+        VERBATIM
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+    )
 endfunction()