|
|
|
|
@@ -1,6 +1,112 @@
|
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
""" Generate LVGL documentation using Doxygen and Sphinx.
|
|
|
|
|
""" build.py -- Generate LVGL documentation using Doxygen and Sphinx + Breathe.
|
|
|
|
|
|
|
|
|
|
Synopsis
|
|
|
|
|
--------
|
|
|
|
|
- $ python build.py html [ skip_api ] [ fresh_env ]
|
|
|
|
|
- $ python build.py latex [ skip_api ] [ fresh_env ]
|
|
|
|
|
- $ python build.py temp [ skip_api ]
|
|
|
|
|
- $ python build.py clean
|
|
|
|
|
- $ python build.py clean_temp
|
|
|
|
|
- $ python build.py clean_html
|
|
|
|
|
- $ python build.py clean_latex
|
|
|
|
|
|
|
|
|
|
Build Arguments and Clean Arguments can be used one at a time
|
|
|
|
|
or be freely mixed and combined.
|
|
|
|
|
|
|
|
|
|
Description
|
|
|
|
|
-----------
|
|
|
|
|
Source files are copied to a temporary directory and modified there before
|
|
|
|
|
doc generation occurs. If a full rebuild is being done (e.g. after a `clean`)
|
|
|
|
|
Doxygen is run on LVGL's source files to generate intermediate API information
|
|
|
|
|
in XML format, example documents are generated, API documents are generated
|
|
|
|
|
for Breathe's consumption, and API links are added to the end of some documents.
|
|
|
|
|
From there, Sphinx with Breathe extension uses the resulting set of source
|
|
|
|
|
files to generate the desired output.
|
|
|
|
|
|
|
|
|
|
It is only during this first build that the `skip_api` option has meaning.
|
|
|
|
|
After the first build, no further actions is taken regarding API pages since
|
|
|
|
|
they are not regenerated after the first build.
|
|
|
|
|
|
|
|
|
|
The temporary directory has a fixed location (overridable by
|
|
|
|
|
`LVGL_DOC_BUILD_TEMP_DIR` environment variable) and by default this
|
|
|
|
|
script attempts to rebuild only those documents whose path, name or
|
|
|
|
|
modification date has changed since the last build.
|
|
|
|
|
|
|
|
|
|
Caution:
|
|
|
|
|
|
|
|
|
|
The document build meant for end-user consumption should ONLY be done after a
|
|
|
|
|
`clean` unless you know that no API documentation and no code examples have changed.
|
|
|
|
|
|
|
|
|
|
A `sphinx-build` will do a full doc rebuild any time:
|
|
|
|
|
|
|
|
|
|
- the temporary directory doesn't exist or is empty (since the new files in
|
|
|
|
|
the temporary directory will have modification times after the generated
|
|
|
|
|
HTML or Latex files, even if nothing changed),
|
|
|
|
|
- the targeted output directory doesn't exist or is empty, or
|
|
|
|
|
- Sphinx determines that a full rebuild is necessary. This happens when:
|
|
|
|
|
- temporary directory (Sphinx's source-file path) has changed,
|
|
|
|
|
- any options on the `sphinx-build` command line have changed,
|
|
|
|
|
- `conf.py` modification date has changed, or
|
|
|
|
|
- `fresh_env` argument is included (runs `sphinx-build` with -E option).
|
|
|
|
|
|
|
|
|
|
Typical run time:
|
|
|
|
|
|
|
|
|
|
Full build: 22.5 min
|
|
|
|
|
skip_api : 1.9 min (applies to first build only)
|
|
|
|
|
|
|
|
|
|
Options
|
|
|
|
|
-------
|
|
|
|
|
help
|
|
|
|
|
Print usage note and exit with status 0.
|
|
|
|
|
|
|
|
|
|
html [ skip_api ] [ fresh_env ]
|
|
|
|
|
Build HTML output.
|
|
|
|
|
`skip_api` only has effect on first build after a `clean` or `clean_temp`.
|
|
|
|
|
|
|
|
|
|
latex [ skip_api ] [ fresh_env ]
|
|
|
|
|
Build Latex/PDF output (on hold pending removal of non-ASCII characters from input files).
|
|
|
|
|
`skip_api` only has effect on first build after a `clean` or `clean_temp`.
|
|
|
|
|
|
|
|
|
|
temp [ skip_api ]
|
|
|
|
|
Generate temporary directory contents (ready to build output formats).
|
|
|
|
|
If they already exist, they are removed and re-generated.
|
|
|
|
|
|
|
|
|
|
skip_api (with `html` and/or `latex` and/or `temp` options)
|
|
|
|
|
Skip API pages and links when temp directory contents are being generated
|
|
|
|
|
(saving about 91% of build time). Note: they are not thereafter regenerated
|
|
|
|
|
unless requested by `temp` argument or the temp directory does not exist.
|
|
|
|
|
This is intended to be used only during doc development to speed up
|
|
|
|
|
turn-around time between doc modifications and seeing final results.
|
|
|
|
|
|
|
|
|
|
fresh_env (with `html` and/or `latex` options)
|
|
|
|
|
Run `sphinx-build` with -E command-line argument, which makes it regenerate its
|
|
|
|
|
"environment" (memory of what was built previously, forcing a full rebuild).
|
|
|
|
|
|
|
|
|
|
clean
|
|
|
|
|
Remove all generated files.
|
|
|
|
|
|
|
|
|
|
clean_temp
|
|
|
|
|
Remove temporary directory.
|
|
|
|
|
|
|
|
|
|
clean_html
|
|
|
|
|
Remove HTML output directory.
|
|
|
|
|
|
|
|
|
|
clean_latex
|
|
|
|
|
Remove Latex output directory.
|
|
|
|
|
|
|
|
|
|
Unrecognized arguments print error message, usage note, and exit with status 1.
|
|
|
|
|
|
|
|
|
|
Python Package Requirements
|
|
|
|
|
---------------------------
|
|
|
|
|
The list of Python package requirements are in `requirements.txt`.
|
|
|
|
|
|
|
|
|
|
Install them by:
|
|
|
|
|
|
|
|
|
|
$ pip install -r requirements.txt
|
|
|
|
|
|
|
|
|
|
History
|
|
|
|
|
-------
|
|
|
|
|
The first version of this file (Apr 2021) discovered the name of
|
|
|
|
|
the current branch (e.g. 'master', 'release/v8.4', etc.) to support
|
|
|
|
|
different versions of the documentation by establishing the base URL
|
|
|
|
|
@@ -25,7 +131,7 @@ Since then its duties have grown to include:
|
|
|
|
|
- Supporting additional command-line options.
|
|
|
|
|
|
|
|
|
|
- Generating a temporary `./docs/lv_conf.h` for Doxygen to use
|
|
|
|
|
(config_builder.py).
|
|
|
|
|
(via config_builder.py).
|
|
|
|
|
|
|
|
|
|
- Supporting multiple execution platforms (which then required tokenizing
|
|
|
|
|
Doxygen's INPUT path in `Doxyfile` and re-writing portions that used
|
|
|
|
|
@@ -33,263 +139,84 @@ Since then its duties have grown to include:
|
|
|
|
|
|
|
|
|
|
- Adding translation and API links (requiring generating docs in a
|
|
|
|
|
temporary directory so that the links could be programmatically
|
|
|
|
|
added to each document before Sphinx was run).
|
|
|
|
|
added to each document before Sphinx was run). Note: translation link
|
|
|
|
|
are now done manually since they are only on the main landing page.
|
|
|
|
|
|
|
|
|
|
- Generating EXAMPLES page + sub-examples where applicable to individual
|
|
|
|
|
documents, e.g. to widget-, style-, layout-pages, etc.
|
|
|
|
|
documents, e.g. to widget-, style-, layout-pages, etc..
|
|
|
|
|
|
|
|
|
|
- Building PDF via latex (when working).
|
|
|
|
|
|
|
|
|
|
- Shifting doc-generation paradigm to behave more like `make`.
|
|
|
|
|
|
|
|
|
|
Command-Line Arguments
|
|
|
|
|
----------------------
|
|
|
|
|
Command-line arguments have been broken down to give the user the
|
|
|
|
|
ability to control each individual major variation in behavior of
|
|
|
|
|
this script. These were added to speed up long doc-development
|
|
|
|
|
tasks by shortening the turn-around time between doc modification
|
|
|
|
|
and seeing the final .html results in a local development environment.
|
|
|
|
|
Finally, this script can now be used in a way such that Sphinx will
|
|
|
|
|
only modify changed documents, and reduce an average ~22-minute
|
|
|
|
|
run time to a run time that is workable for rapidly repeating doc
|
|
|
|
|
generation to see Sphinx formatting results quickly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Normal Usage
|
|
|
|
|
------------
|
|
|
|
|
This is the way this script is used for normal (full) docs generation.
|
|
|
|
|
|
|
|
|
|
$ python build.py skip_latex
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Docs-Dev Initial Docs Generation Usage
|
|
|
|
|
--------------------------------------
|
|
|
|
|
1. Set `LVGL_FIXED_TEMP_DIR` environment variable to path to
|
|
|
|
|
the temporary directory you will use over and over during
|
|
|
|
|
document editing, without trailing directory separator.
|
|
|
|
|
Initially directory should not exist.
|
|
|
|
|
|
|
|
|
|
2. $ python build.py skip_latex preserve fixed_tmp_dir
|
|
|
|
|
|
|
|
|
|
This takes typically ~22 minutes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Docs-Dev Update-Only Generation Usage
|
|
|
|
|
-------------------------------------
|
|
|
|
|
After the above has been run through once, you can thereafter
|
|
|
|
|
run the following until docs-development task is complete.
|
|
|
|
|
|
|
|
|
|
$ python build.py skip_latex docs_dev update
|
|
|
|
|
|
|
|
|
|
Generation time depends on the number of `.rst` files that
|
|
|
|
|
have been updated:
|
|
|
|
|
|
|
|
|
|
+--------------+------------+---------------------------------+
|
|
|
|
|
| Docs Changed | Time | Typical Time to Browser Refresh |
|
|
|
|
|
+==============+============+=================================+
|
|
|
|
|
| 0 | 6 seconds | n/a |
|
|
|
|
|
+--------------+------------+---------------------------------+
|
|
|
|
|
| 1 | 19 seconds | 12 seconds |
|
|
|
|
|
+--------------+------------+---------------------------------+
|
|
|
|
|
| 5 | 28 seconds | 21 seconds |
|
|
|
|
|
+--------------+------------+---------------------------------+
|
|
|
|
|
| 20 | 59 seconds | 52 seconds |
|
|
|
|
|
+--------------+------------+---------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sphinx Doc-Regeneration Criteria
|
|
|
|
|
--------------------------------
|
|
|
|
|
Sphinx uses the following to determine what documents get updated:
|
|
|
|
|
|
|
|
|
|
- source-doc modification date
|
|
|
|
|
- Change the modification date and `sphinx-build` will re-build it.
|
|
|
|
|
|
|
|
|
|
- full (absolute) path to the source document, including its file name
|
|
|
|
|
- Change the path or filename and `sphinx-build` will re-build it.
|
|
|
|
|
|
|
|
|
|
- whether the -E option is on the `sphinx-build` command line
|
|
|
|
|
- -E forces `sphinx-build` to do a full re-build.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Argument Descriptions
|
|
|
|
|
---------------------
|
|
|
|
|
- skip_latex
|
|
|
|
|
The meaning of this argument has not changed: it simply skips
|
|
|
|
|
attempting to generate Latex and subsequent PDF generation.
|
|
|
|
|
- skip_api
|
|
|
|
|
Skips generating API pages (this saves about 70% of build time).
|
|
|
|
|
This is intended to be used only during doc development to speed up
|
|
|
|
|
turn-around time between doc modifications and seeing final results.
|
|
|
|
|
- no_fresh_env
|
|
|
|
|
Excludes -E command-line argument to `sphinx-build`, which, when present,
|
|
|
|
|
forces it to generate a whole new environment (memory of what was built
|
|
|
|
|
previously, forcing a full rebuild). "no_fresh_env" enables a rebuild
|
|
|
|
|
of only docs that got updated -- Sphinx's default behavior.
|
|
|
|
|
- preserve (previously "develop")
|
|
|
|
|
Leaves temporary directory intact for docs development purposes.
|
|
|
|
|
- fixed_tmp_dir
|
|
|
|
|
If (fixed_tmp_dir and 'LVGL_FIXED_TEMP_DIR' in `os.environ`),
|
|
|
|
|
then this script uses the value of that that environment variable
|
|
|
|
|
to populate `temp_directory` instead of the normal (randomly-named)
|
|
|
|
|
temporary directory. This is important when getting `sphinx-build`
|
|
|
|
|
to ONLY rebuild updated documents, since changing the directory
|
|
|
|
|
from which they are generated (normally the randomly-named temp
|
|
|
|
|
dir) will force Sphinx to do a full-rebuild because it remembers
|
|
|
|
|
the doc paths from which the build was last performed.
|
|
|
|
|
- skip_trans
|
|
|
|
|
Skips adding translation links. This allows direct copying of
|
|
|
|
|
`.rst` files to `temp_directory` when they are updated to save time
|
|
|
|
|
during re-build. Final build must not include this option so that
|
|
|
|
|
the translation links are added at the top of each intended page.
|
|
|
|
|
- no_copy
|
|
|
|
|
Skips copying ./docs/ directory tree to `temp_directory`.
|
|
|
|
|
This is only honored if:
|
|
|
|
|
- fixed_tmp_dir == True, and
|
|
|
|
|
- the doc files were previously copied to the temporary directory
|
|
|
|
|
and thus are already present there.
|
|
|
|
|
- docs_dev
|
|
|
|
|
This is a command-line shortcut to combining these command-line args:
|
|
|
|
|
- no_fresh_env
|
|
|
|
|
- preserve
|
|
|
|
|
- fixed_tmp_dir
|
|
|
|
|
- no_copy
|
|
|
|
|
- update
|
|
|
|
|
When no_copy is active, check modification dates on `.rst` files
|
|
|
|
|
and re-copy the updated `./docs/` files to the temporary directory
|
|
|
|
|
that have later modification dates, thus updating what Sphinx uses
|
|
|
|
|
as input.
|
|
|
|
|
Warning: this wipes out translation links and API-page links that
|
|
|
|
|
were added in the first pass, so should only be used for doc
|
|
|
|
|
development -- not for final doc generation.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# ****************************************************************************
|
|
|
|
|
# IMPORTANT: If you are getting a PDF-lexer error for an example, check
|
|
|
|
|
# for extra lines at the end of the file. Only a single empty line
|
|
|
|
|
# is allowed!!! Ask me how long it took me to figure this out.
|
|
|
|
|
# -- @kdschlosser
|
|
|
|
|
# ****************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run():
|
|
|
|
|
# Python Library Imports
|
|
|
|
|
# Python Library
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import subprocess
|
|
|
|
|
import shutil
|
|
|
|
|
import tempfile
|
|
|
|
|
import dirsync
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
# LVGL Custom Imports
|
|
|
|
|
import example_list as ex
|
|
|
|
|
# LVGL Custom
|
|
|
|
|
import example_list
|
|
|
|
|
import doc_builder
|
|
|
|
|
import config_builder
|
|
|
|
|
import add_translation
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Start.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
t1 = datetime.now()
|
|
|
|
|
print('Current time: ' + str(t1))
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Configuration
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# These are relative paths from the ./docs/ directory.
|
|
|
|
|
cfg_temp_dir = 'tmp'
|
|
|
|
|
cfg_output_dir = 'output'
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Process args.
|
|
|
|
|
#
|
|
|
|
|
# With argument `docs_dev`, Sphinx will generate docs from a fixed
|
|
|
|
|
# temporary directory that can be then used later using the same
|
|
|
|
|
# command line to get Sphinx to ONLY rebuild changed documents.
|
|
|
|
|
# This saves a huge amount of time during long document projects.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Set defaults.
|
|
|
|
|
clean = False
|
|
|
|
|
skip_latex = False
|
|
|
|
|
skip_api = False
|
|
|
|
|
fresh_sphinx_env = True
|
|
|
|
|
preserve = False
|
|
|
|
|
fixed_tmp_dir = False
|
|
|
|
|
skip_trans = False
|
|
|
|
|
no_copy = False
|
|
|
|
|
docs_dev = False
|
|
|
|
|
update = False
|
|
|
|
|
args = sys.argv[1:]
|
|
|
|
|
# Filename generated in `cfg_latex_output_dir` and copied to `cfg_pdf_output_dir`.
|
|
|
|
|
cfg_pdf_filename = 'LVGL.pdf'
|
|
|
|
|
|
|
|
|
|
for arg in args:
|
|
|
|
|
# We use chained `if-elif-else` instead of `match` for those on Linux
|
|
|
|
|
# systems that will not have the required version 3.10 of Python yet.
|
|
|
|
|
if arg == "clean":
|
|
|
|
|
clean = True
|
|
|
|
|
elif arg == "skip_latex":
|
|
|
|
|
skip_latex = True
|
|
|
|
|
elif arg == 'skip_api':
|
|
|
|
|
skip_api = True
|
|
|
|
|
elif arg == 'no_fresh_env':
|
|
|
|
|
fresh_sphinx_env = False
|
|
|
|
|
elif arg == 'preserve':
|
|
|
|
|
preserve = True
|
|
|
|
|
elif arg == 'fixed_tmp_dir':
|
|
|
|
|
fixed_tmp_dir = True
|
|
|
|
|
elif arg == 'skip_trans':
|
|
|
|
|
skip_trans = True
|
|
|
|
|
elif arg == 'no_copy':
|
|
|
|
|
no_copy = True
|
|
|
|
|
elif arg == 'docs_dev':
|
|
|
|
|
docs_dev = True
|
|
|
|
|
elif arg == 'update':
|
|
|
|
|
update = True
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Print usage note.
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
def print_usage_note():
|
|
|
|
|
print('Usage:')
|
|
|
|
|
print(' $ python build.py [optional_arg ...]')
|
|
|
|
|
print()
|
|
|
|
|
print(' where `optional_arg` can be any of these:')
|
|
|
|
|
print(' html [ skip_api ] [ fresh_env ]')
|
|
|
|
|
print(' latex [ skip_api ] [ fresh_env ]')
|
|
|
|
|
print(' temp [ skip_api ]')
|
|
|
|
|
print(' clean')
|
|
|
|
|
print(' clean_temp')
|
|
|
|
|
print(' clean_html')
|
|
|
|
|
print(' clean_latex')
|
|
|
|
|
print(' help')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Remove directory `tgt_dir`.
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
def remove_dir(tgt_dir):
|
|
|
|
|
if os.path.isdir(tgt_dir):
|
|
|
|
|
print(f'Removing {tgt_dir}...')
|
|
|
|
|
shutil.rmtree(tgt_dir)
|
|
|
|
|
else:
|
|
|
|
|
print(f'Argument [{arg}] not recognized.')
|
|
|
|
|
exit(1)
|
|
|
|
|
print(f'{tgt_dir} already removed...')
|
|
|
|
|
|
|
|
|
|
# Arg ramifications:
|
|
|
|
|
# docs_dev implies no_fresh_env, preserve, fixed_tmp_dir, and no_copy.
|
|
|
|
|
if docs_dev:
|
|
|
|
|
fresh_sphinx_env = False
|
|
|
|
|
preserve = True
|
|
|
|
|
fixed_tmp_dir = True
|
|
|
|
|
no_copy = True
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Due to the modifications that take place to the documentation files
|
|
|
|
|
# when the documentation builds it is better to copy the source files to a
|
|
|
|
|
# temporary folder and modify the copies. Not setting it up this way makes it
|
|
|
|
|
# a real headache when making alterations that need to be committed as the
|
|
|
|
|
# alterations trigger the files as changed. Also, this keeps maintenance
|
|
|
|
|
# effort to a minimum as adding a new language translation only needs to be
|
|
|
|
|
# done in 2 places (add_translation.py and ./docs/_ext/link_roles.py) rather
|
|
|
|
|
# than once for each .rst file.
|
|
|
|
|
#
|
|
|
|
|
# The html and PDF output locations are going to remain the same as they were.
|
|
|
|
|
# it's just the source documentation files that are going to be copied.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
if fixed_tmp_dir and 'LVGL_FIXED_TEMP_DIR' in os.environ:
|
|
|
|
|
temp_directory = os.environ['LVGL_FIXED_TEMP_DIR']
|
|
|
|
|
else:
|
|
|
|
|
temp_directory = tempfile.mkdtemp(suffix='.lvgl_docs')
|
|
|
|
|
|
|
|
|
|
print(f'Using temp directory: [{temp_directory}]')
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Set up paths.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
base_path = os.path.abspath(os.path.dirname(__file__))
|
|
|
|
|
project_path = os.path.abspath(os.path.join(base_path, '..'))
|
|
|
|
|
examples_path = os.path.join(project_path, 'examples')
|
|
|
|
|
lvgl_src_path = os.path.join(project_path, 'src')
|
|
|
|
|
latex_output_path = os.path.join(temp_directory, 'out_latex')
|
|
|
|
|
pdf_src_file = os.path.join(latex_output_path, 'LVGL.pdf')
|
|
|
|
|
pdf_dst_file = os.path.join(temp_directory, 'LVGL.pdf')
|
|
|
|
|
html_src_path = temp_directory
|
|
|
|
|
html_dst_path = os.path.join(project_path, 'out_html')
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Change to script directory for consistency.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
os.chdir(base_path)
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Provide a way to run an external command and abort build on error.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
def cmd(s, start_dir=None):
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Run external command and abort build on error.
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
def cmd(s, start_dir=None, exit_on_error=True):
|
|
|
|
|
if start_dir is None:
|
|
|
|
|
start_dir = os.getcwd()
|
|
|
|
|
|
|
|
|
|
@@ -301,10 +228,205 @@ def run():
|
|
|
|
|
result = os.system(s)
|
|
|
|
|
os.chdir(saved_dir)
|
|
|
|
|
|
|
|
|
|
if result != 0:
|
|
|
|
|
if result != 0 and exit_on_error:
|
|
|
|
|
print("Exiting build due to previous error.")
|
|
|
|
|
sys.exit(result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Build and return LVGL version string from `lv_version.h`. Updated to be
|
|
|
|
|
# multi-platform compatible and resilient to changes in file in compliance
|
|
|
|
|
# with C macro syntax.
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
def get_version(_verfile):
|
|
|
|
|
major = ''
|
|
|
|
|
minor = ''
|
|
|
|
|
|
|
|
|
|
with open(_verfile, 'r') as file:
|
|
|
|
|
major_re = re.compile(r'define\s+LVGL_VERSION_MAJOR\s+(\d+)')
|
|
|
|
|
minor_re = re.compile(r'define\s+LVGL_VERSION_MINOR\s+(\d+)')
|
|
|
|
|
|
|
|
|
|
for line in file.readlines():
|
|
|
|
|
# Skip if line not long enough to match.
|
|
|
|
|
if len(line) < 28:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
match = major_re.search(line)
|
|
|
|
|
if match is not None:
|
|
|
|
|
major = match[1]
|
|
|
|
|
else:
|
|
|
|
|
match = minor_re.search(line)
|
|
|
|
|
if match is not None:
|
|
|
|
|
minor = match[1]
|
|
|
|
|
# Exit early if we have both values.
|
|
|
|
|
if len(major) > 0 and len(minor) > 0:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
return f'{major}.{minor}'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Provide answer to question: Can we have reasonable confidence that
|
|
|
|
|
# the contents of `temp_directory` already exists?
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
def temp_dir_contents_exists(_tmpdir):
|
|
|
|
|
result = False
|
|
|
|
|
c1 = os.path.isdir(_tmpdir)
|
|
|
|
|
|
|
|
|
|
if c1:
|
|
|
|
|
temp_path = os.path.join(_tmpdir, 'CHANGELOG.rst')
|
|
|
|
|
c2 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, 'CODING_STYLE.rst')
|
|
|
|
|
c3 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, 'CONTRIBUTING.rst')
|
|
|
|
|
c4 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, '_ext')
|
|
|
|
|
c5 = os.path.isdir(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, '_static')
|
|
|
|
|
c6 = os.path.isdir(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, 'details')
|
|
|
|
|
c7 = os.path.isdir(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, 'intro')
|
|
|
|
|
c8 = os.path.isdir(temp_path)
|
|
|
|
|
temp_path = os.path.join(_tmpdir, 'examples')
|
|
|
|
|
c9 = os.path.isdir(temp_path)
|
|
|
|
|
result = c2 and c3 and c4 and c5 and c6 and c7 and c8 and c9
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
# Perform doc-build function(s) requested.
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
def run():
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Process args.
|
|
|
|
|
#
|
|
|
|
|
# With argument `docs_dev`, Sphinx will generate docs from a fixed
|
|
|
|
|
# temporary directory that can be then used later using the same
|
|
|
|
|
# command line to get Sphinx to ONLY rebuild changed documents.
|
|
|
|
|
# This saves a huge amount of time during long document projects.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Set defaults.
|
|
|
|
|
clean_temp = False
|
|
|
|
|
clean_html = False
|
|
|
|
|
clean_latex = False
|
|
|
|
|
clean_all = False
|
|
|
|
|
build_html = False
|
|
|
|
|
build_latex = False
|
|
|
|
|
build_temp = False
|
|
|
|
|
skip_api = False
|
|
|
|
|
fresh_sphinx_env = False
|
|
|
|
|
args = sys.argv[1:]
|
|
|
|
|
|
|
|
|
|
# No args means print usage note and exit with status 0.
|
|
|
|
|
if len(args) == 0:
|
|
|
|
|
print_usage_note()
|
|
|
|
|
exit(0)
|
|
|
|
|
|
|
|
|
|
# Some args are present. Interpret them in loop here.
|
|
|
|
|
# Unrecognized arg means print error, print usage note, exit with status 1.
|
|
|
|
|
for arg in args:
|
|
|
|
|
# We use chained `if-elif-else` instead of `match` for those on Linux
|
|
|
|
|
# systems that will not have the required version 3.10 of Python yet.
|
|
|
|
|
if arg == 'help':
|
|
|
|
|
print_usage_note()
|
|
|
|
|
exit(0)
|
|
|
|
|
elif arg == "temp":
|
|
|
|
|
build_temp = True
|
|
|
|
|
elif arg == "html":
|
|
|
|
|
build_html = True
|
|
|
|
|
elif arg == "latex":
|
|
|
|
|
build_latex = True
|
|
|
|
|
elif arg == 'skip_api':
|
|
|
|
|
skip_api = True
|
|
|
|
|
elif arg == 'fresh_env':
|
|
|
|
|
fresh_sphinx_env = True
|
|
|
|
|
elif arg == "clean":
|
|
|
|
|
clean_all = True
|
|
|
|
|
clean_temp = True
|
|
|
|
|
clean_html = True
|
|
|
|
|
clean_latex = True
|
|
|
|
|
elif arg == "clean_temp":
|
|
|
|
|
clean_temp = True
|
|
|
|
|
elif arg == "clean_html":
|
|
|
|
|
clean_html = True
|
|
|
|
|
elif arg == "clean_latex":
|
|
|
|
|
clean_latex = True
|
|
|
|
|
else:
|
|
|
|
|
print(f'Argument [{arg}] not recognized.')
|
|
|
|
|
print()
|
|
|
|
|
print_usage_note()
|
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Start.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
t0 = datetime.now()
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Set up paths.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
base_path = os.path.abspath(os.path.dirname(__file__))
|
|
|
|
|
project_path = os.path.abspath(os.path.join(base_path, '..'))
|
|
|
|
|
examples_path = os.path.join(project_path, 'examples')
|
|
|
|
|
lvgl_src_path = os.path.join(project_path, 'src')
|
|
|
|
|
output_path = os.path.join(base_path, cfg_output_dir)
|
|
|
|
|
html_output_path = os.path.join(output_path, 'html')
|
|
|
|
|
latex_output_path = os.path.join(output_path, 'latex')
|
|
|
|
|
pdf_src_file = os.path.join(latex_output_path, cfg_pdf_filename)
|
|
|
|
|
pdf_dst_file = os.path.join(base_path, cfg_pdf_filename)
|
|
|
|
|
version_source_path = os.path.join(project_path, 'lv_version.h')
|
|
|
|
|
|
|
|
|
|
# Establish temporary directory. The presence of environment variable
|
|
|
|
|
# `LVGL_DOC_BUILD_TEMP_DIR` overrides default in `cfg_temp_dir`.
|
|
|
|
|
#
|
|
|
|
|
# Temporary directory is used as Sphinx source directory -- some source
|
|
|
|
|
# files are edited, some are fully generated. Adding translation
|
|
|
|
|
# links can be done with by adding temp in:
|
|
|
|
|
# - ./docs/add_translation.py, and
|
|
|
|
|
# - ./docs/_ext/link_roles.py.
|
|
|
|
|
# Currently, translation-link editing is being suppressed since there
|
|
|
|
|
# is only 1 file that gets the link: top-level landing page.
|
|
|
|
|
if 'LVGL_DOC_BUILD_TEMP_DIR' in os.environ:
|
|
|
|
|
temp_directory = os.environ['LVGL_DOC_BUILD_TEMP_DIR']
|
|
|
|
|
else:
|
|
|
|
|
temp_directory = os.path.join(base_path, cfg_temp_dir)
|
|
|
|
|
|
|
|
|
|
html_src_path = temp_directory
|
|
|
|
|
print(f'Temporary directory: [{temp_directory}]')
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Change to script directory for consistency.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
os.chdir(base_path)
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Clean? If so, clean (like `make clean`), but do not exit.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
some_cleaning_to_be_done = clean_temp or clean_html or clean_latex or clean_all \
|
|
|
|
|
or (os.path.isdir(temp_directory) and build_temp)
|
|
|
|
|
|
|
|
|
|
if some_cleaning_to_be_done:
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Cleaning...")
|
|
|
|
|
print("****************")
|
|
|
|
|
|
|
|
|
|
if clean_temp:
|
|
|
|
|
remove_dir(temp_directory)
|
|
|
|
|
|
|
|
|
|
if clean_html:
|
|
|
|
|
remove_dir(html_output_path)
|
|
|
|
|
|
|
|
|
|
if clean_latex:
|
|
|
|
|
remove_dir(latex_output_path)
|
|
|
|
|
|
|
|
|
|
if clean_all:
|
|
|
|
|
remove_dir(output_path)
|
|
|
|
|
|
|
|
|
|
if os.path.isdir(temp_directory) and build_temp:
|
|
|
|
|
remove_dir(temp_directory)
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Populate LVGL_URLPATH and LVGL_GITCOMMIT environment variables:
|
|
|
|
|
# - LVGL_URLPATH <= 'master' or '8.4' '9.2' etc.
|
|
|
|
|
@@ -361,107 +483,74 @@ def run():
|
|
|
|
|
os.environ['LVGL_URLPATH'] = branch
|
|
|
|
|
os.environ['LVGL_GITCOMMIT'] = branch
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Start doc-build process.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
print("")
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Building")
|
|
|
|
|
print("****************")
|
|
|
|
|
|
|
|
|
|
# Remove all previous output files if 'clean' on command line.
|
|
|
|
|
if clean:
|
|
|
|
|
print('Removing previous output files...')
|
|
|
|
|
# The below commented-out code below is being preserved
|
|
|
|
|
# for docs-generation development purposes.
|
|
|
|
|
|
|
|
|
|
# api_path = os.path.join(temp_directory, 'API')
|
|
|
|
|
# xml_path = os.path.join(temp_directory, 'xml')
|
|
|
|
|
# doxy_path = os.path.join(temp_directory, 'doxygen_html')
|
|
|
|
|
|
|
|
|
|
# if os.path.exists(api_path):
|
|
|
|
|
# shutil.rmtree(api_path)
|
|
|
|
|
|
|
|
|
|
# lang = 'en'
|
|
|
|
|
# if os.path.exists(lang):
|
|
|
|
|
# shutil.rmtree(lang)
|
|
|
|
|
|
|
|
|
|
if os.path.exists(html_dst_path):
|
|
|
|
|
shutil.rmtree(html_dst_path)
|
|
|
|
|
|
|
|
|
|
# if os.path.exists(xml_path):
|
|
|
|
|
# shutil.rmtree(xml_path)
|
|
|
|
|
#
|
|
|
|
|
# if os.path.exists(doxy_path):
|
|
|
|
|
# shutil.rmtree(doxy_path)
|
|
|
|
|
|
|
|
|
|
# os.mkdir(api_path)
|
|
|
|
|
# os.mkdir(lang)
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Build local lv_conf.h from lv_conf_template.h for this build only.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
config_builder.run()
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Provide answer to question: Can we have reasonable confidence that
|
|
|
|
|
# the contents of `temp_directory` already exists?
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
def temp_dir_contents_exists():
|
|
|
|
|
result = False
|
|
|
|
|
c1 = os.path.exists(temp_directory)
|
|
|
|
|
|
|
|
|
|
if c1:
|
|
|
|
|
temp_path = os.path.join(temp_directory, 'CHANGELOG.rst')
|
|
|
|
|
c2 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, 'CODING_STYLE.rst')
|
|
|
|
|
c3 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, 'CONTRIBUTING.rst')
|
|
|
|
|
c4 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, '_ext')
|
|
|
|
|
c5 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, '_static')
|
|
|
|
|
c6 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, 'details')
|
|
|
|
|
c7 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, 'intro')
|
|
|
|
|
c8 = os.path.exists(temp_path)
|
|
|
|
|
temp_path = os.path.join(temp_directory, 'examples')
|
|
|
|
|
c9 = os.path.exists(temp_path)
|
|
|
|
|
result = c2 and c3 and c4 and c5 and c6 and c7 and c8 and c9
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Copy files to 'temp_directory' where they will be edited (translation
|
|
|
|
|
# link and API links) before being used to generate new docs.
|
|
|
|
|
# link(s) and API links) before being used to generate new docs.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
doc_files_copied = False
|
|
|
|
|
if no_copy and fixed_tmp_dir and temp_dir_contents_exists():
|
|
|
|
|
if update:
|
|
|
|
|
exclude_list = ['lv_conf.h']
|
|
|
|
|
# dirsync `exclude_list` = list of regex patterns to exclude.
|
|
|
|
|
exclude_list = [r'lv_conf\.h', r'^tmp.*', r'^output.*']
|
|
|
|
|
|
|
|
|
|
if temp_dir_contents_exists(temp_directory):
|
|
|
|
|
# We are just doing an update of the temp_directory contents.
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Updating temp directory...")
|
|
|
|
|
print("****************")
|
|
|
|
|
|
|
|
|
|
exclude_list.append(r'examples.*')
|
|
|
|
|
options = {
|
|
|
|
|
'verbose': True,
|
|
|
|
|
'create': True,
|
|
|
|
|
'verbose': True, # Report files copied.
|
|
|
|
|
'create': True, # Create directories if they don't exist.
|
|
|
|
|
'twoway': False, # False means data flow only src => tgt.
|
|
|
|
|
'purge': False, # False means DO NOT remove orphan files/dirs in tgt dir (preserving examples/ dir).
|
|
|
|
|
'exclude': exclude_list
|
|
|
|
|
}
|
|
|
|
|
dirsync.sync('.', temp_directory, 'update', **options)
|
|
|
|
|
else:
|
|
|
|
|
print("Skipping copying ./docs/ directory as requested.")
|
|
|
|
|
else:
|
|
|
|
|
shutil.copytree('.', temp_directory, dirs_exist_ok=True)
|
|
|
|
|
shutil.copytree(examples_path, os.path.join(temp_directory, 'examples'), dirs_exist_ok=True)
|
|
|
|
|
doc_files_copied = True
|
|
|
|
|
# action == 'sync' means copy files even when they do not already exist in tgt dir.
|
|
|
|
|
# action == 'update' means DO NOT copy files when they do not already exist in tgt dir.
|
|
|
|
|
dirsync.sync('.', temp_directory, 'sync', **options)
|
|
|
|
|
dirsync.sync(examples_path, os.path.join(temp_directory, 'examples'), 'sync', **options)
|
|
|
|
|
elif build_temp or build_html or build_latex:
|
|
|
|
|
# We are having to create the temp_directory contents by copying.
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Building temp directory...")
|
|
|
|
|
print("****************")
|
|
|
|
|
|
|
|
|
|
copy_method = 1
|
|
|
|
|
|
|
|
|
|
# Both of these methods work.
|
|
|
|
|
if copy_method == 0:
|
|
|
|
|
# --------- Method 0:
|
|
|
|
|
ignore_func = shutil.ignore_patterns('tmp*', 'output*')
|
|
|
|
|
print('Copying docs...')
|
|
|
|
|
shutil.copytree('.', temp_directory, ignore=ignore_func, dirs_exist_ok=True)
|
|
|
|
|
print('Copying examples...')
|
|
|
|
|
shutil.copytree(examples_path, os.path.join(temp_directory, 'examples'), dirs_exist_ok=True)
|
|
|
|
|
else:
|
|
|
|
|
# --------- Method 1:
|
|
|
|
|
options = {
|
|
|
|
|
'create': True, # Create directories if they don't exist.
|
|
|
|
|
'exclude': exclude_list
|
|
|
|
|
}
|
|
|
|
|
# action == 'sync' means copy files even when they do not already exist in tgt dir.
|
|
|
|
|
# action == 'update' means DO NOT copy files when they do not already exist in tgt dir.
|
|
|
|
|
print('Copying docs...')
|
|
|
|
|
dirsync.sync('.', temp_directory, 'sync', **options)
|
|
|
|
|
print('Copying examples...')
|
|
|
|
|
dirsync.sync(examples_path, os.path.join(temp_directory, 'examples'), 'sync', **options)
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------
|
|
|
|
|
# Build Example docs, Doxygen output, API docs, and API links.
|
|
|
|
|
# -----------------------------------------------------------------
|
|
|
|
|
t1 = datetime.now()
|
|
|
|
|
|
|
|
|
|
# Build local lv_conf.h from lv_conf_template.h for this build only.
|
|
|
|
|
config_builder.run()
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Replace tokens in Doxyfile in 'temp_directory' with data from this run.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
if doc_files_copied:
|
|
|
|
|
with open(os.path.join(temp_directory, 'Doxyfile'), 'rb') as f:
|
|
|
|
|
data = f.read().decode('utf-8')
|
|
|
|
|
|
|
|
|
|
data = data.replace('#*#*LV_CONF_PATH*#*#', os.path.join(base_path, 'lv_conf.h'))
|
|
|
|
|
data = data.replace('*#*#SRC#*#*', '"{0}"'.format(lvgl_src_path))
|
|
|
|
|
data = data.replace('<<LV_CONF_PATH>>', os.path.join(base_path, 'lv_conf.h'))
|
|
|
|
|
data = data.replace('<<SRC>>', '"{0}"'.format(lvgl_src_path))
|
|
|
|
|
|
|
|
|
|
with open(os.path.join(temp_directory, 'Doxyfile'), 'wb') as f:
|
|
|
|
|
f.write(data.encode('utf-8'))
|
|
|
|
|
@@ -471,13 +560,15 @@ def run():
|
|
|
|
|
# in individual documents where applicable.
|
|
|
|
|
# -----------------------------------------------------------------
|
|
|
|
|
print("Generating examples...")
|
|
|
|
|
ex.exec(temp_directory)
|
|
|
|
|
example_list.exec(temp_directory)
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------
|
|
|
|
|
# Add translation links.
|
|
|
|
|
# This is being skipped in favor of a manually-placed
|
|
|
|
|
# translation link at the top of `./docs/index.rst`.
|
|
|
|
|
# -----------------------------------------------------------------
|
|
|
|
|
if skip_trans:
|
|
|
|
|
print("Skipping translation links as requested.")
|
|
|
|
|
if True:
|
|
|
|
|
print("Skipping adding translation links.")
|
|
|
|
|
else:
|
|
|
|
|
print("Adding translation links...")
|
|
|
|
|
add_translation.exec(temp_directory)
|
|
|
|
|
@@ -491,9 +582,11 @@ def run():
|
|
|
|
|
print("Running Doxygen...")
|
|
|
|
|
cmd('doxygen Doxyfile', temp_directory)
|
|
|
|
|
|
|
|
|
|
print("API page and link processing...")
|
|
|
|
|
doc_builder.EMIT_WARNINGS = False
|
|
|
|
|
|
|
|
|
|
# Create .RST files for API pages.
|
|
|
|
|
# Create .RST files for API pages, plus
|
|
|
|
|
# add API hyperlinks to .RST files in the directories in passed array.
|
|
|
|
|
doc_builder.run(
|
|
|
|
|
project_path,
|
|
|
|
|
temp_directory,
|
|
|
|
|
@@ -518,18 +611,26 @@ def run():
|
|
|
|
|
os.path.join(temp_directory, 'details', 'integration', 'renderers'),
|
|
|
|
|
os.path.join(temp_directory, 'details', 'libs'),
|
|
|
|
|
os.path.join(temp_directory, 'details', 'main-components'),
|
|
|
|
|
# Note: details/main-components/display omitted intentionally,
|
|
|
|
|
# since API links for those .RST files have been added manually.
|
|
|
|
|
os.path.join(temp_directory, 'details', 'other-components'),
|
|
|
|
|
os.path.join(temp_directory, 'details', 'widgets')
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
print('Reading Doxygen output...')
|
|
|
|
|
t2 = datetime.now()
|
|
|
|
|
print('Example/API processing run time: ' + str(t2 - t1))
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# BUILD PDF
|
|
|
|
|
# Build PDF
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
if skip_latex:
|
|
|
|
|
print("Skipping latex build as requested.")
|
|
|
|
|
if not build_latex:
|
|
|
|
|
print("Skipping Latex build.")
|
|
|
|
|
else:
|
|
|
|
|
t1 = datetime.now()
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Building Latex output...")
|
|
|
|
|
print("****************")
|
|
|
|
|
|
|
|
|
|
# Remove PDF link so PDF does not have a link to itself.
|
|
|
|
|
index_path = os.path.join(temp_directory, 'index.rst')
|
|
|
|
|
|
|
|
|
|
@@ -548,14 +649,17 @@ def run():
|
|
|
|
|
# PDF download link in the PDF
|
|
|
|
|
# cmd("cp -f " + lang +"/latex/LVGL.pdf LVGL.pdf | true")
|
|
|
|
|
src = temp_directory
|
|
|
|
|
dst = latex_output_path
|
|
|
|
|
dst = output_path
|
|
|
|
|
cpu = os.cpu_count()
|
|
|
|
|
cmd_line = f'sphinx-build -b latex "{src}" "{dst}" -j {cpu}'
|
|
|
|
|
cmd_line = f'sphinx-build -M latex "{src}" "{dst}" -j {cpu}'
|
|
|
|
|
cmd(cmd_line)
|
|
|
|
|
|
|
|
|
|
# Generate PDF.
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Building PDF...")
|
|
|
|
|
print("****************")
|
|
|
|
|
cmd_line = 'latexmk -pdf "LVGL.tex"'
|
|
|
|
|
cmd(cmd_line, latex_output_path)
|
|
|
|
|
cmd(cmd_line, latex_output_path, True)
|
|
|
|
|
|
|
|
|
|
# Copy the result PDF to the main directory to make
|
|
|
|
|
# it available for the HTML build.
|
|
|
|
|
@@ -567,37 +671,20 @@ def run():
|
|
|
|
|
with open(index_path, 'wb') as f:
|
|
|
|
|
f.write(index_data.encode('utf-8'))
|
|
|
|
|
|
|
|
|
|
t2 = datetime.now()
|
|
|
|
|
print('PDF : ' + pdf_dst_file)
|
|
|
|
|
print('Latex gen run time: ' + str(t2 - t1))
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# BUILD HTML
|
|
|
|
|
# Build HTML
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# This version of get_version() works correctly under both Linux and Windows.
|
|
|
|
|
# Updated to be resilient to changes in `lv_version.h` compliant with C macro syntax.
|
|
|
|
|
def get_version():
|
|
|
|
|
path = os.path.join(project_path, 'lv_version.h')
|
|
|
|
|
major = ''
|
|
|
|
|
minor = ''
|
|
|
|
|
|
|
|
|
|
with open(path, 'r') as file:
|
|
|
|
|
major_re = re.compile(r'define\s+LVGL_VERSION_MAJOR\s+(\d+)')
|
|
|
|
|
minor_re = re.compile(r'define\s+LVGL_VERSION_MINOR\s+(\d+)')
|
|
|
|
|
|
|
|
|
|
for line in file.readlines():
|
|
|
|
|
# Skip if line not long enough to match.
|
|
|
|
|
if len(line) < 28:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
match = major_re.search(line)
|
|
|
|
|
if match is not None:
|
|
|
|
|
major = match[1]
|
|
|
|
|
if not build_html:
|
|
|
|
|
print("Skipping HTML build.")
|
|
|
|
|
else:
|
|
|
|
|
match = minor_re.search(line)
|
|
|
|
|
if match is not None:
|
|
|
|
|
minor = match[1]
|
|
|
|
|
# Exit early if we have both values.
|
|
|
|
|
if len(major) > 0 and len(minor) > 0:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
return f'{major}.{minor}'
|
|
|
|
|
t1 = datetime.now()
|
|
|
|
|
print("****************")
|
|
|
|
|
print("Building HTML output...")
|
|
|
|
|
print("****************")
|
|
|
|
|
|
|
|
|
|
# Note: While it can be done (e.g. if one needs to set a stop point
|
|
|
|
|
# in Sphinx code for development purposes), it is NOT a good idea to
|
|
|
|
|
@@ -618,44 +705,31 @@ def run():
|
|
|
|
|
print("Regenerating only updated files...")
|
|
|
|
|
env_opt = ''
|
|
|
|
|
|
|
|
|
|
ver = get_version()
|
|
|
|
|
ver = get_version(version_source_path)
|
|
|
|
|
src = html_src_path
|
|
|
|
|
dst = html_dst_path
|
|
|
|
|
dst = output_path
|
|
|
|
|
cpu = os.cpu_count()
|
|
|
|
|
cmd_line = f'sphinx-build -b html "{src}" "{dst}" -D version="{ver}" {env_opt} -j {cpu}'
|
|
|
|
|
t2 = datetime.now()
|
|
|
|
|
print('Current time: ' + str(t2))
|
|
|
|
|
cmd_line = f'sphinx-build -M html "{src}" "{dst}" -D version="{ver}" {env_opt} -j {cpu}'
|
|
|
|
|
cmd(cmd_line)
|
|
|
|
|
t3 = datetime.now()
|
|
|
|
|
print('Current time: ' + str(t3))
|
|
|
|
|
print('Sphinx run time: ' + str(t3 - t2))
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Cleanup.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
if preserve:
|
|
|
|
|
print('Temp directory: ', temp_directory)
|
|
|
|
|
else:
|
|
|
|
|
print('Removing temporary files...', temp_directory)
|
|
|
|
|
if os.path.exists(temp_directory):
|
|
|
|
|
shutil.rmtree(temp_directory)
|
|
|
|
|
t2 = datetime.now()
|
|
|
|
|
print('HTML gen time : ' + str(t2 - t1))
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Remove temporary `lv_conf.h` created for this build.
|
|
|
|
|
# Do this even when `lv_conf.h` was not generated in case a prior run got interrupted.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
config_builder.cleanup()
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
# Indicate results.
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
|
t4 = datetime.now()
|
|
|
|
|
print('Total run time: ' + str(t4 - t1))
|
|
|
|
|
print('Output path: ', html_dst_path)
|
|
|
|
|
t_end = datetime.now()
|
|
|
|
|
print('Total run time: ' + str(t_end - t0))
|
|
|
|
|
print()
|
|
|
|
|
print('Note: warnings about `/details/index.rst` and `/intro/index.rst`')
|
|
|
|
|
print(' "not being in any toctree" are expected and intentional.')
|
|
|
|
|
print()
|
|
|
|
|
print('Finished.')
|
|
|
|
|
print('Done.')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|