Всем привет!
Наверное, каждого, кто хотя бы раз сталкивался с CMake, посещала мысль: почему документация на официальном сайте лежит в виде большущего одностраничного документа, использование которого доставляет больше неудобств, чем должно приносить пользы? Оказывается, нужно выполнить всего несколько шагов, чтобы получить удобную документацию с деревом категорий, списком подразделов и адекватным форматированием всей информации. Подробности сего действа под катом.
Как это работает
В основе всего процесса лежит незаметный и малоизвестный факт: документация для CMake распространяется в нескольких форматах: HTML, txt и DocBook v4.5. Основой для первых двух является документация в формате DocBook – это обычный XML со строгим набором тэгов, который, как вы уже догадались, можно преобразовать с помощью XSLT в совершенно любое представление. Формат этот достаточно популярный и конвертеры в разные форматы help-документов уже написаны, нам же остаётся только применить один из них. Так как CMake создан для кроссплатформенности, документацию для него будем делать также кроссплатформенную. Для этого лучше всего подходит формат Web help. Желающие могут поэкспериментировать со своими форматами в качестве домашней работы.
Ингредиенты
- Apache Ant
- Набор DocBook XSLT шаблонов
- Java
- Saxon — XSLT Java преобразователь
- Xerces — XML Java парсер
Далее по тексту путь docbook-xsl будет указывать в папку, куда вы извлекли набор DocBook XSLT шаблонов.
DocBook webhelp шаблон
Каждый docbook-конвертер разрабатывается отдельно, в связи с этим, некоторые из них поддерживаются, другие уже давно не обновляются. На наше счастье, webhelp-конвертер достаточно популярен и имеет хорошую документацию по его использованию, которую можно найти в папке docbook-xsl/webhelp/docs.
Подготовительные шаги для решения нашей задачи:
- Прописать пути к 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
- Проверить конвертацию docbook-документа модуля webhelp, выполнив следующую команду в папке docbook-xsl/webhelp:
ant webhelp -Doutput-dir=test-help
Если вы всё сделали правильно, то результат работы команды должен быть примерно таким:
Вывод ant webhelpd: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.
- Создадим рабочую папку и скопируем туда файл cmake.docbook, который обычно находится в установленном CMake в папке: doc/CMake-2.8.
- Создадим в рабочей папке файл 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 скорректируйте в соответствие с вашим окружением.
- Запускаем генерацию:
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 формат – удобное дерево со списком разделов и подразделов.
Про применение CMake в геймдеве на платформах Win32, Mac OS X, iOS и Android мы расскажем в одной из следующих статей. Там своих интересностей выше крыши.
Автор: Dipp