Собираем удобную документацию для CMake

в 6:03, , рубрики: Без рубрики

Всем привет!

Наверное, каждого, кто хотя бы раз сталкивался с CMake, посещала мысль: почему документация на официальном сайте лежит в виде большущего одностраничного документа, использование которого доставляет больше неудобств, чем должно приносить пользы? Оказывается, нужно выполнить всего несколько шагов, чтобы получить удобную документацию с деревом категорий, списком подразделов и адекватным форматированием всей информации. Подробности сего действа под катом.

Как это работает

В основе всего процесса лежит незаметный и малоизвестный факт: документация для CMake распространяется в нескольких форматах: HTML, txt и DocBook v4.5. Основой для первых двух является документация в формате DocBook – это обычный XML со строгим набором тэгов, который, как вы уже догадались, можно преобразовать с помощью XSLT в совершенно любое представление. Формат этот достаточно популярный и конвертеры в разные форматы help-документов уже написаны, нам же остаётся только применить один из них. Так как CMake создан для кроссплатформенности, документацию для него будем делать также кроссплатформенную. Для этого лучше всего подходит формат Web help. Желающие могут поэкспериментировать со своими форматами в качестве домашней работы.

Ингредиенты

Далее по тексту путь docbook-xsl будет указывать в папку, куда вы извлекли набор DocBook XSLT шаблонов.

DocBook webhelp шаблон

Каждый docbook-конвертер разрабатывается отдельно, в связи с этим, некоторые из них поддерживаются, другие уже давно не обновляются. На наше счастье, webhelp-конвертер достаточно популярен и имеет хорошую документацию по его использованию, которую можно найти в папке docbook-xsl/webhelp/docs.

Подготовительные шаги для решения нашей задачи:

  1. Прописать пути к Saxon и Xerces в файле docbook-xsl/webhelp/build.properties:
    # Modify the following so that they point to your local
    # copy of the jars indicated:
    # * Saxon 6.5 jar
    # * Xerces 2: xercesImpl.jar
    # * xml-commons: xml-apis.jar
    xslt-processor-classpath=d:/projects/CMake/doc/saxon6-5-5/saxon.jar
    xercesImpl.jar=d:/projects/CMake/doc/xerces-2_11_0/xercesImpl.jar
    xml-apis.jar=d:/projects/CMake/doc/xerces-2_11_0/xml-apis.jar
    

  2. Проверить конвертацию docbook-документа модуля webhelp, выполнив следующую команду в папке docbook-xsl/webhelp:
    ant webhelp -Doutput-dir=test-help
    

    Если вы всё сделали правильно, то результат работы команды должен быть примерно таким:

    Вывод ant webhelp
    d:projectsCMakedocdocbook-xsl-1.78.1webhelp>ant webhelp -Doutput-dir=test-help
    Unable to locate tools.jar. Expected to find it in C:Program FilesJavajre7libtools.jar
    Buildfile: d:projectsCMakedocdocbook-xsl-1.78.1webhelpbuild.xml
    
    validate:
    
    clean:
    
    chunk:
        [mkdir] Created dir: d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-help
         [xslt] Processing d:projectsCMakedocdocbook-xsl-1.78.1webhelpdocsrcreadme.xml to d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-helpnull1481456544
         [xslt] Loading stylesheet d:projectsCMakedocdocbook-xsl-1.78.1profilingprofile.xsl
         [xslt] Processing d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-helpnull1481456544 to d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-helpnull884696268
         [xslt] Loading stylesheet d:projectsCMakedocdocbook-xsl-1.78.1webhelpxslwebhelp.xsl
         [xslt] language: en
         [xslt] Writing test-help/ch01.html for chapter
         [xslt] Writing test-help/ch02s01.html for section
         [xslt] Writing test-help/ch02s02s01.html for section
         [xslt] Writing test-help/ch02s02.html for section
         [xslt] Writing test-help/ch02s03.html for section
         [xslt] Writing test-help/ch02s04.html for section
         [xslt] Writing test-help/ch02s05.html for section
         [xslt] Writing test-help/ch02.html for chapter
         [xslt] Writing test-help/ch03s01.html for section
         [xslt] Writing test-help/ch03s02s01.html for section
         [xslt] Writing test-help/ch03s02.html for section
         [xslt] Writing test-help/ch03.html for chapter
         [xslt] Writing test-help/ch04.html for chapter
         [xslt] Writing test-help/ch05s01.html for section
         [xslt] Writing test-help/ch05s02.html for section
         [xslt] Writing test-help/ch05.html for chapter
         [xslt] Writing test-help/ix01.html for index
         [xslt] Writing test-help/index.html for book
         [xslt] Writing test-help/search/l10n.js
         [copy] Copying 96 files to d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-help
         [copy] Copying 1 file to d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-help
    
    index:
         [copy] Copying 1 file to d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-helpsearch
         [copy] Copied 1 empty directory to 1 empty directory under d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-helpsearch
         [copy] Copying 4 files to d:projectsCMakedocdocbook-xsl-1.78.1webhelptest-helpsearch
         [echo] Indexing html files in test-help
         [java] Stemming enabled
         [java] The created index files are located in test-helpsearch
         [java] Indexed the contents in 828 milliseconds
    
    webhelp:
    
    BUILD SUCCESSFUL
    Total time: 35 seconds
    

    В папке docbook-xsl/webhelp/test-help должна появиться сгенерированная документация по модулю webhelp.

CMake документация

Так как DocBook->webhelp конвертер построен на основе Apache Ant, и разработчики конвертера использовали некоторые его полезные возможности, мы можем создать удобное окружение для генерации любой документации из DocBook в формат webhelp.

  1. Создадим рабочую папку и скопируем туда файл cmake.docbook, который обычно находится в установленном CMake в папке: doc/CMake-2.8.
  2. Создадим в рабочей папке файл build.xml следующего содержания:
    <project default="help" name="cmake-doc">
    	<property name="input-xml" value="cmake.docbook"/>
    	<import file="d:/projects/CMake/doc/docbook-xsl-1.78.1/webhelp/build.xml"/>
    </project>
    

    Путь в атрибуте file скорректируйте в соответствие с вашим окружением.

  3. Запускаем генерацию:
    ant webhelp
    

    И… Получаем явно не SUCCESSFUL, а ошибку с адским коллстэком.

    Скрытый текст

    d:projectsCMakedoccmake_doc>ant webhelp
    Unable to locate tools.jar. Expected to find it in C:Program FilesJavajre7libtools.jar
    Buildfile: d:projectsCMakedoccmake_docbuild.xml
    
    validate:
    
    clean:
       [delete] Deleting directory d:projectsCMakedoccmake_docdocs
    
    chunk:
        [mkdir] Created dir: d:projectsCMakedoccmake_docdocs
         [xslt] Processing d:projectsCMakedoccmake_doccmake.docbook to d:projectsCMakedoccmake_docdocsnull2096887678
         [xslt] Loading stylesheet d:projectsCMakedocdocbook-xsl-1.78.1profilingprofile.xsl
         [xslt] : Error! No more DTM IDs are available
         [xslt] Failed to process d:projectsCMakedoccmake_doccmake.docbook
    
    BUILD FAILED
    d:projectsCMakedocdocbook-xsl-1.78.1webhelpbuild.xml:36: javax.xml.transform.TransformerException: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
            at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(Unknown Source)
            at org.apache.tools.ant.taskdefs.optional.TraXLiaison.transform(TraXLiaison.java:195)
            at org.apache.tools.ant.taskdefs.XSLTProcess.process(XSLTProcess.java:850)
            at org.apache.tools.ant.taskdefs.XSLTProcess.execute(XSLTProcess.java:388)
            at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
            at org.apache.tools.ant.Task.perform(Task.java:348)
            at org.apache.tools.ant.Target.execute(Target.java:435)
            at org.apache.tools.ant.Target.performTasks(Target.java:456)
            at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1393)
            at org.apache.tools.ant.Project.executeTarget(Project.java:1364)
            at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
            at org.apache.tools.ant.Project.executeTargets(Project.java:1248)
            at org.apache.tools.ant.Main.runBuild(Main.java:851)
            at org.apache.tools.ant.Main.startAnt(Main.java:235)
            at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
            at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
    Caused by: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
            at com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault.addDTM(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.getResultTreeFrag(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter.getResultTreeFrag(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.dom.MultiDOM.getResultTreeFrag(Unknown Source)
            at profile.template$dot$1()
            at profile.applyTemplates1()
            at profile.template$dot$1()
            at profile.applyTemplates1()
            at profile.template$dot$1()
            at profile.applyTemplates1()
            at profile.applyTemplates1()
            at profile.template$dot$16()
            at profile.applyTemplates()
            at profile.transform()
            at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(Unknown Source)
            ... 22 more
    ---------
    com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
            at com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault.addDTM(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.getResultTreeFrag(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter.getResultTreeFrag(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.dom.MultiDOM.getResultTreeFrag(Unknown Source)
            at profile.template$dot$1()
            at profile.applyTemplates1()
            at profile.template$dot$1()
            at profile.applyTemplates1()
            at profile.template$dot$1()
            at profile.applyTemplates1()
            at profile.applyTemplates1()
            at profile.template$dot$16()
            at profile.applyTemplates()
            at profile.transform()
            at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(Unknown Source)
            at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(Unknown Source)
            at org.apache.tools.ant.taskdefs.optional.TraXLiaison.transform(TraXLiaison.java:195)
            at org.apache.tools.ant.taskdefs.XSLTProcess.process(XSLTProcess.java:850)
            at org.apache.tools.ant.taskdefs.XSLTProcess.execute(XSLTProcess.java:388)
            at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
            at org.apache.tools.ant.Task.perform(Task.java:348)
            at org.apache.tools.ant.Target.execute(Target.java:435)
            at org.apache.tools.ant.Target.performTasks(Target.java:456)
            at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1393)
            at org.apache.tools.ant.Project.executeTarget(Project.java:1364)
            at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
            at org.apache.tools.ant.Project.executeTargets(Project.java:1248)
            at org.apache.tools.ant.Main.runBuild(Main.java:851)
            at org.apache.tools.ant.Main.startAnt(Main.java:235)
            at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
            at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
    
    Total time: 16 seconds
    

WTF? // FIXME

Возникает мысль, что причиной ошибки является гораздо больший размер docbook-файла из CMake, чем тот, что используется в качестве теста webhelp-конвертера, на что косвенно указывает эта строчка в логе:

     [xslt] : Error! No more DTM IDs are available

После гугления подобной ошибки видим, что она относится к Xalan (XML-парсер, используемый Xerces'ом) и вроде как решена, но по факту проблемы имеются. Проверяем актуальность нужных компонентов – всё ок. Проверив cmake.docbook, никаких вопросов тоже не возникло: вполне себе корректный DocBook v4.5.
Приходим к выводу, что Xalan+Xerces работают некорректно на файлах большого объема, но мы-то понимаем, что XSLT-преобразователей в мире огромная куча, и большинство из них работают с куда большими объемами без проблем. Итак, копаем в сторону подключения другого XSLT-трансформера.

Помедитировав над файлом docbook-xsl/webhelp/build.xml, можно увидеть, что там есть два XSLT шага, но у них есть одно интересное различие – один из них использует Xerces XSLT-преобразователь, а другой — Saxon:

<xslt
	  in="${input-xml}"
	    out="${xincluded-profiled.xml}"
	    style="${ant.file.dir}/../profiling/profile.xsl"
            classpath="${xercesImpl.jar}"> <!-- путь к xercesImpl.jar, который мы задали в build.properties -->
...
</xslt>

<xslt
	  in="${xincluded-profiled.xml}"
	  out="${dummy.html}"
	  style="${stylesheet-path}"
	  scanincludeddirectories="false"
	  classpath="${xslt-processor-classpath}"> <!-- путь к Saxon.jar, который мы задали в build.properties -->
...
</xslt>

Причины такого подхода трудно понять, но возможно это наш шанс на решение проблемы! Прописываем другой XSLT-преобразователь в первый шаг:

<xslt
	  in="${input-xml}"
	    out="${xincluded-profiled.xml}"
	    style="${ant.file.dir}/../profiling/profile.xsl"
            classpath="${xslt-processor-classpath}"> <!-- теперь здесь путь к Saxon.jar -->
...
</xslt>

Запускаем генерацию и… Получаем заветные строчки в конце лога:

ant webhelp
...
BUILD SUCCESSFUL
Total time: 2 minutes 33 seconds

После завершения, в папке docs появится вся документация на CMake в отличном формате. Вам остаётся лишь открыть index.html и начать работу.

Заключение

При желании документацию можно выложить на веб-сервер или общую шару и тянуть оттуда всей командой.

Сравнение оригинального формата и Web help

Оригинал – описание всех команд на одной html странице (обратите внимание на размер скрола).
Собираем удобную документацию для CMake

Web help формат – удобное дерево со списком разделов и подразделов.
Собираем удобную документацию для CMake

Про применение CMake в геймдеве на платформах Win32, Mac OS X, iOS и Android мы расскажем в одной из следующих статей. Там своих интересностей выше крыши.

Автор: Dipp

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js