1 # Generate the FreeBSD documentation
2 #
3 # Copyright (c) 2020-2021, The FreeBSD Documentation Project
4 # Copyright (c) 2020-2021, Sergio Carlavilla <carlavilla@FreeBSD.org>
5 #
6 # Targets intended for use on the command line
7 #
8 # all (default) - generate the books TOC and compile all the documentation
9 # clean - removes generated files
10 # run - serves the built documentation site for local browsing
11 # pdf - build PDF versions of the articles and books.
12 # html - build HTML versions of the articles and books for
13 # offline use
14 #
15 # The run target uses hugo's built-in webserver to make the documentation site
16 # available for local browsing. The documentation should have been built prior
17 # to attempting to use the `run` target. By default, hugo will start its
18 # webserver on port 1313.
19
20 MAINTAINER=carlavilla@FreeBSD.org
21
22 # List of languages without book translations
23 ARTICLEONLY_LANGS= bd da ko tr
24 # List of languages without article translations
25 BOOKONLY_LANGS= mn
26
27 # List of all languages we have content for
28 ALL_LANGUAGES= bd da de el en es fr hu it ja ko mn nl pl pt-br ru tr zh-cn zh-tw
29
30 LOCALBASE?= /usr/local
31
32 .if ${OS} == "FreeBSD" || ${OS} == "Darwin"
33 PYTHON_CMD = ${LOCALBASE}/bin/python3
34 RUBY_CMD = ${LOCALBASE}/bin/ruby
35 HUGO_CMD = ${LOCALBASE}/bin/hugo
36 .elif ${OS} == "Linux"
37 PYTHON_CMD = /usr/bin/python3
38 RUBY_CMD = /usr/bin/ruby
39 HUGO_CMD = /usr/bin/hugo
40 .else
41 @echo "Unsupported Platfom, stopping make"
42 exit 0
43 .endif
44
45 HUGO_ARGS?= --verbose --minify
46 ASCIIDOCTOR_CMD= ${LOCALBASE}/bin/asciidoctor
47 ASCIIDOCTORPDF_CMD= ${LOCALBASE}/bin/asciidoctor-pdf
48 ROUGE_CMD= ${LOCALBASE}/bin/rougify
49 .if !exists(${ASCIIDOCTOR_CMD}) || !exists(${ASCIIDOCTORPDF_CMD}) || !exists({ROUGE_CMD})
50 @echo "Please install asciidoctor, asciidoctor-pdf, or rouge via rubygem"
51 exit 0
52 .endif
53 SED_CMD = /usr/bin/sed
54 .if defined(DOC_LANG) && !empty(DOC_LANG)
55 LANGUAGES= ${DOC_LANG:S/,/ /g}
56 .if ${LANGUAGES:Men} == "" && ${.TARGETS:Mpdf*} == "" && ${.TARGETS:Mhtml*} == ""
57 .warning "Warning: cannot skip 'en'; adding it back"
58 LANGUAGES+= en
59 .endif
60 .else
61 LANGUAGES= ${ALL_LANGUAGES}
62 .endif
63
64 RUBYLIB = ../shared/lib
65 .export RUBYLIB
66
67 RUN_DEPENDS= ${PYTHON_CMD} \
68 ${HUGO_CMD} \
69 ${LOCALBASE}/bin/asciidoctor \
70 ${LOCALBASE}/bin/asciidoctor-pdf \
71 ${LOCALBASE}/bin/rougify
72
73 .ifndef HOSTNAME
74 . ifdef BIND
75 .HOST=$(BIND)
76 . else
77 .HOST=localhost
78 . endif
79 .else
80 .HOST=$(HOSTNAME)
81 .endif
82
83 # Strip the languages with only articles from the list of languages we
84 # will use to build books.
85 BOOK_LANGS= ${LANGUAGES}
86 .for a in ${ARTICLEONLY_LANGS}
87 BOOK_LANGS:= ${BOOK_LANGS:N${a}}
88 .endfor
89
90 # Strip the languages with only books from the list of languages we
91 # will use to build articles.
92 ARTICLE_LANGS= ${LANGUAGES}
93 .for a in ${BOOKONLY_LANGS}
94 ARTICLE_LANGS:= ${ARTICLE_LANGS:N${a}}
95 .endfor
96
97 # Take the list of all languages, and take out the ones we have been
98 # asked for. We'll feed this to hugo.
99 SKIP_LANGS=
100 .for a in ${ALL_LANGUAGES}
101 .if ${LANGUAGES:M${a}} == ""
102 SKIP_LANGS+= ${a}
103 .endif
104 .endfor
105
106 .ORDER: all run
107
108 .ORDER: requirements
109 .ORDER: starting-message generate-books-toc
110 .ORDER: starting-message build
111 .ORDER: generate-books-toc build
112
113 all: requirements starting-message generate-books-toc generate-pgpkeys-txt build
114 run: requirements starting-message generate-books-toc generate-pgpkeys-txt run-local
115
116 # clean does not call pdf-clean as that is a subset of hugo-clean
117 clean: hugo-clean pgp-clean toc-clean
118
119 requirements:
120 .for dep in ${RUN_DEPENDS}
121 .if !exists(${dep})
122 @(echo ${dep} not found, please run 'pkg install docproj python3'; exit 1)
123 .endif
124 .endfor
125
126 starting-message: .PHONY
127 @echo ---------------------------------------------------------------
128 @echo Building the documentation
129 @echo included languages: ${LANGUAGES}
130 @echo excluded languages: ${SKIP_LANGS}
131 @echo ---------------------------------------------------------------
132
133 generate-books-toc: .PHONY
134 .if !empty(BOOK_LANGS)
135 ${PYTHON_CMD} ./tools/books-toc-parts-creator.py -l ${BOOK_LANGS}
136 ${PYTHON_CMD} ./tools/books-toc-creator.py -l ${BOOK_LANGS}
137 ${PYTHON_CMD} ./tools/books-toc-figures-creator.py -l ${BOOK_LANGS}
138 ${PYTHON_CMD} ./tools/books-toc-tables-creator.py -l ${BOOK_LANGS}
139 ${PYTHON_CMD} ./tools/books-toc-examples-creator.py -l ${BOOK_LANGS}
140 .endif
141
142 generate-pgpkeys-txt: static/pgpkeys/pgpkeys.txt
143
144 static/pgpkeys/pgpkeys.txt: static/pgpkeys/*key
145 ${RUBY_CMD} ./tools/global-pgpkeys-creator.rb
146
147 run-local: .PHONY
148 HUGO_DISABLELANGUAGES="${SKIP_LANGS}" ${HUGO_CMD} server \
149 ${HUGO_ARGS} -D $(BIND:D--bind=$(BIND)) --baseURL="http://$(.HOST):1313"
150
151 build: .PHONY
152 HUGO_DISABLELANGUAGES="${SKIP_LANGS}" ${HUGO_CMD} ${HUGO_ARGS}
153
154 toc-clean: .PHONY
155 .if !empty(BOOK_LANGS)
156 rm -f $$(${PYTHON_CMD} ./tools/books-toc-parts-creator.py -l ${BOOK_LANGS} -o)
157 rm -f $$(${PYTHON_CMD} ./tools/books-toc-creator.py -l ${BOOK_LANGS} -o)
158 rm -f $$(${PYTHON_CMD} ./tools/books-toc-figures-creator.py -l ${BOOK_LANGS} -o)
159 rm -f $$(${PYTHON_CMD} ./tools/books-toc-tables-creator.py -l ${BOOK_LANGS} -o)
160 rm -f $$(${PYTHON_CMD} ./tools/books-toc-examples-creator.py -l ${BOOK_LANGS} -o)
161 .endif
162
163 pgp-clean: .PHONY
164 rm -f static/pgpkeys/pgpkeys.txt
165
166 hugo-clean: .PHONY
167 rm -rf resources public
168
169 #
170 # PDF targets
171 # Use DOC_LANG to choose the language, e.g., make DOC_LANG="en fr" pdf-books
172 #
173 pdf: pdf-articles pdf-books
174
175 pdf-books-target:
176 .for _lang in ${BOOK_LANGS}
177 TMP+= ${.CURDIR}/content/${_lang}/books/*/
178 .endfor
179 BOOKSDIR != echo ${TMP}
180
181 pdf-articles-target:
182 .for _lang in ${ARTICLE_LANGS}
183 TTMP += ${.CURDIR}/content/${_lang}/articles/*/
184 .endfor
185 ARTICLESDIR != echo ${TTMP}
186
187 pdf-books: pdf-books-target generate-books-toc
188
189 # Books build
190 #
191 # Notes:
192 # pdf-theme=default-with-fallback-font is
193 # used instead of pdf-theme=./themes/default-pdf-theme.yml because
194 # it allows ja, ru, tr, zh-* fonts to be embedded and rendering is
195 # better for other languages.
196 #
197 # asciidoctor-pdf-cjk and/or specific themes should be used for cjk
198 # fonts
199 .for _curpdf in ${BOOKSDIR}
200 @mkdir -p ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}
201 .if exists(${_curpdf}book.adoc)
202 ${ASCIIDOCTORPDF_CMD} \
203 -r ./shared/lib/man-macro.rb \
204 -r ./shared/lib/man-macro.rb \
205 -r ./shared/lib/git-macro.rb \
206 -r ./shared/lib/packages-macro.rb \
207 -r ./shared/lib/inter-document-references-macro.rb \
208 -r ./shared/lib/sectnumoffset-treeprocessor.rb \
209 --doctype=book \
210 -a skip-front-matter \
211 -a pdf-theme=default-with-fallback-font \
212 -o ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}book.pdf \
213 ${_curpdf}book.adoc
214 .else
215 # some books use _index.adoc as main document
216 ${ASCIIDOCTORPDF_CMD} \
217 -r ./shared/lib/man-macro.rb \
218 -r ./shared/lib/man-macro.rb \
219 -r ./shared/lib/git-macro.rb \
220 -r ./shared/lib/packages-macro.rb \
221 -r ./shared/lib/inter-document-references-macro.rb \
222 -r ./shared/lib/sectnumoffset-treeprocessor.rb \
223 --doctype=book \
224 -a skip-front-matter \
225 -a pdf-theme=default-with-fallback-font \
226 -o ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}book.pdf \
227 ${_curpdf}_index.adoc
228 .endif
229 .endfor
230
231 pdf-articles: pdf-articles-target
232
233 # Articles build
234 .for _curpdf in ${ARTICLESDIR}
235 @mkdir -p ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}
236 ${ASCIIDOCTORPDF_CMD} \
237 -r ./shared/lib/man-macro.rb \
238 -r ./shared/lib/man-macro.rb \
239 -r ./shared/lib/git-macro.rb \
240 -r ./shared/lib/packages-macro.rb \
241 -r ./shared/lib/inter-document-references-macro.rb \
242 -r ./shared/lib/sectnumoffset-treeprocessor.rb \
243 --doctype=article \
244 -a skip-front-matter \
245 -a pdf-theme=default-with-fallback-font \
246 -o ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}article.pdf \
247 ${_curpdf}_index.adoc
248 .if exists(${.CURDIR}/static/source/articles/${_curpdf:H:T})
249 cp -R ${.CURDIR}/static/source/articles/${_curpdf:H:T}/ \
250 ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}
251 .endif
252 .endfor
253
254 pdf-clean: pdf-articles-clean pdf-books-clean
255
256 pdf-books-clean: pdf-books-target toc-clean
257 .for _curpdf in ${BOOKSDIR}
258 rm -f ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}book.pdf
259 .endfor
260 .for _lang in ${BOOK_LANGS}
261 rm -fr ${.CURDIR}/public/${_lang}/books
262 -rmdir ${.CURDIR}/public/${_lang}
263 .endfor
264 -rmdir ${.CURDIR}/public/
265
266 #
267 # HTML targets
268 # Use DOC_LANG to choose the language, e.g., make DOC_LANG="en fr" html-books
269 #
270 html: html-articles html-books
271
272 html-books-target:
273 .for _lang in ${BOOK_LANGS}
274 TMPH += ${.CURDIR}/content/${_lang}/books/*/
275 .endfor
276 BOOKSDIR != echo ${TMPH}
277
278 html-articles-target:
279 .for _lang in ${ARTICLE_LANGS}
280 TTMPH += ${.CURDIR}/content/${_lang}/articles/*/
281 .endfor
282 ARTICLESDIR != echo ${TTMPH}
283
284 html-books: html-books-target generate-books-toc
285
286 # Books build
287 #
288 .for _curhtml in ${BOOKSDIR}
289 @mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}
290 .if exists(${_curhtml}book.adoc)
291 ${ASCIIDOCTOR_CMD} \
292 -B ${.CURDIR}/ \
293 -r ./shared/lib/man-macro.rb \
294 -r ./shared/lib/man-macro.rb \
295 -r ./shared/lib/git-macro.rb \
296 -r ./shared/lib/packages-macro.rb \
297 -r ./shared/lib/inter-document-references-macro.rb \
298 -r ./shared/lib/sectnumoffset-treeprocessor.rb \
299 --doctype=book \
300 -a skip-front-matter \
301 -a linkcss -a copycss=${.CURDIR}/themes/beastie/static/css/docbook.css -a stylesheet=docbook.css -a stylesdir=../../css \
302 -a iconfont-remote! -a iconfont-name=font-awesome-min \
303 -o ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}book.html \
304 ${_curhtml}book.adoc
305 .if exists(${.CURDIR}/static/images/books/${_curhtml:H:T})
306 @mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/images/books/
307 cp -R ${.CURDIR}/static/images/books/${_curhtml:H:T}/ \
308 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/images/books/${_curhtml:H:T}/
309 ${SED_CMD} -i '' -e "s|../../../../images|../../images|g" \
310 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}book.html
311 .endif
312 .else
313 # some books use _index.adoc as main document
314 ${ASCIIDOCTOR_CMD} \
315 -B ${.CURDIR}/ \
316 -r ./shared/lib/man-macro.rb \
317 -r ./shared/lib/man-macro.rb \
318 -r ./shared/lib/git-macro.rb \
319 -r ./shared/lib/packages-macro.rb \
320 -r ./shared/lib/inter-document-references-macro.rb \
321 -r ./shared/lib/sectnumoffset-treeprocessor.rb \
322 --doctype=book \
323 -a skip-front-matter \
324 -a linkcss -a copycss=${.CURDIR}/themes/beastie/static/css/docbook.css -a stylesheet=docbook.css -a stylesdir=../../css \
325 -a iconfont-remote! -a iconfont-name=font-awesome-min \
326 -o ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}book.html \
327 ${_curhtml}_index.adoc
328 .if exists(${.CURDIR}/static/images/books/${_curhtml:H:T})
329 @mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/images/books/
330 cp -R ${.CURDIR}/static/images/books/${_curhtml:H:T}/ \
331 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/images/books/${_curhtml:H:T}/
332 ${SED_CMD} -i '' -e "s|../../../../images|../../images|g" \
333 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}book.html
334 .endif
335 .endif
336 .if !exists(${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/fonts/)
337 mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/fonts/
338 cp -R ${.CURDIR}/themes/beastie/static/fonts/ \
339 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/fonts/
340 cp ${.CURDIR}/themes/beastie/static/css/font-awesome-min.css \
341 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/css/
342 .endif
343 .endfor
344
345 html-articles: html-articles-target
346
347 # Articles build
348 .for _curhtml in ${ARTICLESDIR}
349 @mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}
350 ${ASCIIDOCTOR_CMD} \
351 -B ${.CURDIR}/ \
352 -r ./shared/lib/man-macro.rb \
353 -r ./shared/lib/man-macro.rb \
354 -r ./shared/lib/git-macro.rb \
355 -r ./shared/lib/packages-macro.rb \
356 -r ./shared/lib/inter-document-references-macro.rb \
357 -r ./shared/lib/sectnumoffset-treeprocessor.rb \
358 --doctype=article \
359 -a skip-front-matter \
360 -a linkcss -a copycss=${.CURDIR}/themes/beastie/static/css/docbook.css -a stylesheet=docbook.css -a stylesdir=../../css \
361 -a iconfont-remote! -a iconfont-name=font-awesome-min \
362 -o ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}article.html \
363 ${_curhtml}_index.adoc
364 .if exists(${.CURDIR}/static/source/articles/${_curhtml:H:T})
365 cp -R ${.CURDIR}/static/source/articles/${_curhtml:H:T}/ \
366 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}
367 .endif
368 .if exists(${.CURDIR}/static/images/articles/${_curhtml:H:T})
369 @mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/images/articles/
370 cp -R ${.CURDIR}/static/images/articles/${_curhtml:H:T}/ \
371 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/images/articles/${_curhtml:H:T}/
372 ${SED_CMD} -i '' -e "s|../../../images|../../images|g" \
373 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}article.html
374 .endif
375 .if !exists(${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/fonts/)
376 mkdir -p ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/fonts/
377 cp -R ${.CURDIR}/themes/beastie/static/fonts/ \
378 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/fonts/
379 cp ${.CURDIR}/themes/beastie/static/css/font-awesome-min.css \
380 ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||:H:H:H}/css/
381 .endif
382 .endfor
383
384 html-clean: html-resources-clean html-articles-clean html-books-clean
385
386 html-resources-clean:
387 .for _lang in ${LANGUAGES}
388 rm -fr ${.CURDIR}/public/${_lang}/css
389 rm -fr ${.CURDIR}/public/${_lang}/fonts
390 rm -fr ${.CURDIR}/public/${_lang}/images
391 .endfor
392
393 html-books-clean: html-books-target toc-clean
394 .for _curhtml in ${BOOKSDIR}
395 rm -f ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}book.html ${_curhtml}toc*.adoc
396 -rmdir ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}
397 .endfor
398 .for _lang in ${BOOK_LANGS}
399 rm -fr ${.CURDIR}/public/${_lang}/books
400 rm -fr ${.CURDIR}/public/${_lang}/images/books
401 -rmdir ${.CURDIR}/public/${_lang}
402 .endfor
403 -rmdir ${.CURDIR}/public
404
405 html-articles-clean: html-articles-target
406 .for _curhtml in ${ARTICLESDIR}
407 rm -f ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}article.html
408 -rmdir ${.CURDIR}/public${_curhtml:S|^${.CURDIR}/content||}
409 .endfor
410 .for _lang in ${ARTICLE_LANGS}
411 rm -fr ${.CURDIR}/public/${_lang}/articles
412 rm -fr ${.CURDIR}/public/${_lang}/images/articles
413 -rmdir ${.CURDIR}/public/${_lang}
414 .endfor
415 -rmdir ${.CURDIR}/public
416
417 pdf-articles-clean: pdf-articles-target
418 .for _curpdf in ${ARTICLESDIR}
419 rm -f ${.CURDIR}/public${_curpdf:S|^${.CURDIR}/content||}article.pdf
420 .endfor
421 .for _lang in ${ARTICLE_LANGS}
422 rm -fr ${.CURDIR}/public/${_lang}/articles
423 .if !exists(${.CURDIR}/public/${_lang}/books)
424 rm -fr ${.CURDIR}/public/${_lang}
425 .endif
426 .endfor
427 -rmdir ${.CURDIR}/public
428