diff --git a/docs/Doxyfile b/docs/Doxyfile index e92435f922..92fbecf9e2 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -815,11 +815,11 @@ INPUT_ENCODING = UTF-8 # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. -FILE_PATTERNS = lv*.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ +FILE_PATTERNS = lv*.h \ + lv*.hh \ + lv*.hxx \ + lv*.hpp \ + lv*.h++ # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. diff --git a/docs/api_doc_builder.py b/docs/api_doc_builder.py index 708c95cad4..7557305d48 100644 --- a/docs/api_doc_builder.py +++ b/docs/api_doc_builder.py @@ -7,6 +7,46 @@ Uses doxygen_xml.py module to: - Prep and run Doxygen - make Doxygen XML output available, and - make Doxygen-documented symbols from the C code available. + +Because these 3 files are acceptable in a C project: + +1. ./path/to/one/aaa.c +2. ./path/to/one/aaa.h +3. ./path/to/one/aaa.cpp +4. ./path/to/one/aaa.hpp +5. ./path/to/another/aaa.h + +we see that: + +- duplicate filename stems ('aaa' above) are acceptable, and +- they must not only be differentiated by their extensions, but also by their path. + +On the other hand, Sphinx link reference names for :ref:`link_ref_name` link +references must be unique throughout a document project. Since API pages are +generated from C source files, to make this effective, they must include: + +A. at least part of the path, +B. filename stem, and +C. extension + +in the link reference names. Prior to 11-Aug-2025, link reference names were formed +using ONLY the filename stem. This created a conflict when an example of #4 above +appeared in the LVGL code, and caused a doc-build failure because the API-page link +reference names to #2 and #4 were identical, and Sphinx (correctly) does not allow +that. So after 11-Aug-2025, these link reference names are now differentiated all 3 +of A, B and C above. + +.. note:: + + Since they are generated and dealt with programmatically, using the full path + [below the docs source directory] will not be a problem. Even though it makes + the names long, they never have to be hand-typed. + +Likewise, API-page ``.rst`` filename stems also need to be unique within the directory +they are in, so the stems must contain the C source file's filename stem plus the +extension in them, in order to be unique in that directory, since they *must* end in +``.rst``. + """ import os import re @@ -16,6 +56,17 @@ from announce import * old_html_files = {} EMIT_WARNINGS = True rst_section_line_char = '=' +on_windows = (( os.name == 'nt' )) +# `doxy_src_file_ext_list` must +# - match the extensions in the Doxyfile FILE_PATTERNS list, and +# - be in lower case. +doxy_src_file_ext_list = [ + '.h', + '.hh', + '.hxx', + '.hpp', + '.h++' +] # Multi-line match ``API + newline + \*\*\* + whitespace``. # NB: the ``\s*`` at the end forces the regex to match the whitespace @@ -34,7 +85,7 @@ _re_api_startswith = re.compile(r'(?mi)^\s*\.\.\s+API\s+startswith:\s*([\w,\s]+) _re_multi_line_comma_sep = re.compile(r'(?m)[,\s]+') # Regex to identify editor-added hyperlinks: :ref:`lv_obj_h` -_re_editor_added_hyperlink = re.compile(r'^\s*:ref:`(\w+)`') +_re_editor_added_hyperlink = re.compile(r'^\s*:ref:`([\w/\.]+)`') # Separator to mark place where this script added hyperlinks. _auto_gen_sep = '.. Autogenerated' @@ -140,7 +191,15 @@ def _conditionally_add_hyperlink(obj, genned_link_set: set, exclude_set: set): :return: """ if obj.file_name is not None: - link_name = os.path.basename(obj.file_name).replace('.', '_') + # The link name should look like this: draw/sw/blend/lv_draw_sw_blend.h + # including when running under Windows. + # `obj.file_name` contains a path that looks like this: + # '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend.h' + # Note: we can't use 'lvgl/src' because there is no guarantee + # that the user's LVGL repo directory will be called that. + src_root = '/src/' + i = obj.file_name.index(src_root) + len(src_root) + link_name = obj.file_name[i:] if link_name not in genned_link_set: if link_name not in exclude_set: genned_link_set.add(link_name) @@ -191,7 +250,7 @@ def _add_exact_matches(symbols: [str], genned_link_set, editor_link_set): def _hyperlink_sort_value(init_value: str): - if init_value.endswith('_h'): + if init_value.endswith('.h'): result = init_value[:-2] else: result = init_value @@ -544,6 +603,12 @@ def _add_hyperlinks_to_eligible_files(intermediate_dir: str, f.write(data.encode('utf-8')) +def _extended_stem_from_path(path: str) -> str: + filename = os.path.basename(path) + stem, ext = os.path.splitext(filename) + return stem + '_' + ext[1:] # Remove leading '.' from ext. + + def _create_rst_files_for_dir(src_root_dir_len: int, src_dir_bep: str, elig_h_files: [str], @@ -558,14 +623,40 @@ def _create_rst_files_for_dir(src_root_dir_len: int, - add reference "sub_dir_name/index" in `index.rst`. :param src_root_dir_len: Length of source-root path string, used with `out_root_dir` to build paths + Example: 17 :param src_dir_bep: Directory currently *being processed* - :param elig_h_files: Eligible `.h` files directly contained in `src_dir_bep` - :param elig_sub_dirs: List of sub-dirs that contained eligible `.h` files + Example: '/path/to/lvgl/src/draw/sw/blend' + :param elig_h_files: Eligible `.h*` files directly contained in `src_dir_bep` + Example: [] or + [ + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_private.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_al88.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888_premultiplied.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_i1.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_l8.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565_swapped.h', + '/path/to/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.h' + ] + :param elig_sub_dirs: List of sub-dirs that contained eligible `.h*` files + Example: [] or + [ + '/path/to/lvgl/src/draw/sw/blend/arm2d', + '/path/to/lvgl/src/draw/sw/blend/helium', + '/path/to/lvgl/src/draw/sw/blend/neon' + ] :param out_root_dir: Root of output directory, used with to build paths. + Example: '/path/to/lvgl/src/docs/intermediate/API' :return: n/a """ indent = ' ' + # Keep only sub-path under 'lvgl/src/'. + # Example: 'draw/sw/blend' sub_path = src_dir_bep[src_root_dir_len:] + # Build full path to output directory for 'index.rst' file. + # Example: '/path/to/lvgl/src/docs/intermediate/API/draw/sw/blend' out_dir = str(os.path.join(out_root_dir, sub_path)) # Ensure dir exists. Multiple dirs MAY have to be created @@ -591,9 +682,8 @@ def _create_rst_files_for_dir(src_root_dir_len: int, # One entry per `.rst` file for h_file in elig_h_files: - filename = os.path.basename(h_file) - stem = os.path.splitext(filename)[0] - f.write(indent + stem + '\n') + extended_stem = _extended_stem_from_path(h_file) + f.write(indent + extended_stem + '\n') # One entry per eligible subdirectory. for sub_dir in elig_sub_dirs: @@ -603,14 +693,28 @@ def _create_rst_files_for_dir(src_root_dir_len: int, # One .rst file per h_file for h_file in elig_h_files: filename = os.path.basename(h_file) - stem = os.path.splitext(filename)[0] - rst_file = os.path.join(out_dir, stem + '.rst') - html_file = os.path.join(sub_path, stem + '.html') - old_html_files[stem] = html_file + extended_stem = _extended_stem_from_path(h_file) + rst_file = os.path.join(out_dir, extended_stem + '.rst') + html_file = os.path.join(sub_path, extended_stem + '.html') + old_html_files[extended_stem] = html_file with open(rst_file, 'w') as f: # Sphinx link target. - f.write(f'.. _{stem}_h:\n\n') + # The link name should look like this: draw/sw/blend/lv_draw_sw_blend.h + # including when running under Windows. + if on_windows: + link_name_path = sub_path.replace(os.sep, '/') + else: + link_name_path = sub_path + + if len(link_name_path) > 0: + link_name = link_name_path + '/' + filename + else: + link_name = filename + + line = f'.. _{link_name}:\n\n' + + f.write(line) # Doc title. section_line = (rst_section_line_char * len(filename)) + '\n' f.write(section_line) @@ -631,7 +735,7 @@ def _recursively_create_api_rst_files(depth: int, recursively for subdirectories below it. ("bep" = being processed.) Eligible - An input file (e.g. `.h` or `.c`) file is eligible if Doxygen generated + An input file (e.g. `.h*`) file is eligible if Doxygen generated documentation for it. The combination of these configuration items in the Doxyfile: @@ -646,12 +750,12 @@ def _recursively_create_api_rst_files(depth: int, file depends upon whether any eligible files were recursively found within it. And that isn't known until this function finishes (recursively) processing a directory and returns the number of - eligible `.h` files found in its subdirectory tree. Thus, the steps + eligible `.h*` files found in its subdirectory tree. Thus, the steps taken within are: - - Discover all eligible `.h` files directly contained in `src_dir_bep`. + - Discover all eligible `.h*` files directly contained in `src_dir_bep`. - Recursively do the same for each subdirectory, adding the returned - count of eligible `.h` files to the sum (`elig_h_file_count`). + count of eligible `.h*` files to the sum (`elig_h_file_count`). - If `elig_h_file_count > 0`: - call _create_rst_files_for_dir() to generate appropriate `.rst` files for this directory. @@ -665,9 +769,9 @@ def _recursively_create_api_rst_files(depth: int, :param src_root_len: Length of source-root path :param src_dir_bep: Source directory *being processed* :param out_root_dir: Output root directory (used to build output paths) - :return: Number of `.h` files encountered (so caller knows + :return: Number of `.h*` files encountered (so caller knows whether that directory recursively held any - eligible `.h` files, to know whether to include + eligible `.h*` files, to know whether to include "subdir/index" in caller's local `index.rst` file). """ elig_h_files = [] @@ -686,7 +790,10 @@ def _recursively_create_api_rst_files(depth: int, if os.path.isdir(path_bep): sub_dirs.append(path_bep) # Add to sub-dir list. else: - if dir_item.lower().endswith('.h'): + _, ext = os.path.splitext(dir_item) + # `ext` is converted to lower case so that any incidental case change + # in the extension on Windows will not break this algorithm. + if ext.lower() in doxy_src_file_ext_list: eligible = (dir_item in doxygen_xml.files) if eligible: elig_h_files.append(path_bep) # Add file to list. @@ -711,7 +818,7 @@ def _recursively_create_api_rst_files(depth: int, elig_sub_dirs.sort() elig_h_files.sort() - # Create index.rst plus .RST files for any .H file directly in in dir. + # Create index.rst plus .RST files for any .H* file directly in in dir. _create_rst_files_for_dir(src_root_len, src_dir_bep, elig_h_files, @@ -723,9 +830,9 @@ def _recursively_create_api_rst_files(depth: int, def create_api_rst_files(src_root_dir: str, out_root_dir: str): """ - Create `.rst` files for API pages based on the `.h` files found + Create `.rst` files for API pages based on the `.h*` files found in a tree-walk of `a_src_root` and the current contents of the - `doxygen_xml.files` dictionary (used to filter out `.h` files that + `doxygen_xml.files` dictionary (used to filter out `.h*` files that Doxygen generated no documentation for). Output the `.rst` files into `out_root_dir` mirroring the `a_src_root` directory structure. diff --git a/docs/build.py b/docs/build.py index 57b6bd3e02..dd761c9ea4 100755 --- a/docs/build.py +++ b/docs/build.py @@ -743,7 +743,7 @@ def run(args): if debugging_breathe: from sphinx.cmd.build import main as sphinx_build # Don't allow parallel processing while debugging (the '-j' arg is removed). - sphinx_args = ['-M', 'html', f'{src}', f'{dst}', '-D', f'version={ver}'] + sphinx_args = ['-M', 'html', f'{src}', f'{dst}'] if len(env_opt) > 0: sphinx_args.append(f'{env_opt}') diff --git a/docs/doxygen_xml.py b/docs/doxygen_xml.py index 9df4e52217..b3ca02a453 100644 --- a/docs/doxygen_xml.py +++ b/docs/doxygen_xml.py @@ -1606,6 +1606,7 @@ class DoxygenXml(object): 'LV_ATTRIBUTE_FAST_MEM=', 'LV_ATTRIBUTE_EXTERN_DATA=', 'LV_FORMAT_ATTRIBUTE(fmt,va)=', + 'FASTGLTF_EXPORT=', ] cfg.set('PREDEFINED', predefined_symbols) @@ -1631,9 +1632,14 @@ class DoxygenXml(object): full_path = os.path.join(lvgl_src_dir, osal_dir, osal_h) exclude_paths.append(full_path) + # Exclude as a workaround for Breathe parsing problems. full_path = os.path.join(lvgl_src_dir, 'core', 'lv_obj_property.h') exclude_paths.append(full_path) + # Exclude GLTF templates that Breathe appears to not know how to parse. + full_path = os.path.join(lvgl_src_dir, 'libs', 'gltf', 'fastgltf', 'lv_fastgltf.hpp') + exclude_paths.append(full_path) + cfg.set('EXCLUDE', exclude_paths) # Include TAGFILES if requested. diff --git a/docs/make.bat b/docs/make.bat index f1dfedcf59..73034f0d2f 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -38,9 +38,10 @@ if "%SPHINXOPTS%" == "" ( rem python ./src/lvgl_version.py >_version_temp.txt rem set /p VER=<_version_temp.txt rem del _version_temp.txt - for /F %%v in ('python lvgl_version.py') do set VER=%%v + for /F %%v in ('python src\lvgl_version.py') do set VER=%%v echo VERSION [!VER!] - set SPHINXOPTS=-D version="!VER!" -j 4 + rem set SPHINXOPTS=-D version="!VER!" -j 4 + set SPHINXOPTS=-j 4 set VER= ) diff --git a/docs/src/details/auxiliary-modules/test.rst b/docs/src/details/auxiliary-modules/test.rst index f47fd9affb..5cebbe472f 100644 --- a/docs/src/details/auxiliary-modules/test.rst +++ b/docs/src/details/auxiliary-modules/test.rst @@ -117,7 +117,8 @@ by getting the Y coordinate of a child. int32_t y_end = lv_obj_get_y(child); if(y_start + 100 != y_end) fail(); -Please refer to :ref:`lv_test_indev_h` for the list of supported input device emulation functions. +Please refer to :ref:`others/test/lv_test_indev.h` for the list of supported input +device emulation functions. Screenshot Comparison --------------------- diff --git a/docs/src/details/integration/adding-lvgl-to-your-project/connecting_lvgl.rst b/docs/src/details/integration/adding-lvgl-to-your-project/connecting_lvgl.rst index 6aa6c082a1..3f2e6336a9 100644 --- a/docs/src/details/integration/adding-lvgl-to-your-project/connecting_lvgl.rst +++ b/docs/src/details/integration/adding-lvgl-to-your-project/connecting_lvgl.rst @@ -159,4 +159,5 @@ See :ref:`indev_creation` to see how to do this. API *** -:ref:`lv_tick_h` + +.. API startswith: lv_tick_ diff --git a/docs/src/details/integration/renderers/arm2d.rst b/docs/src/details/integration/renderers/arm2d.rst index 2492fed744..898b89d869 100644 --- a/docs/src/details/integration/renderers/arm2d.rst +++ b/docs/src/details/integration/renderers/arm2d.rst @@ -65,6 +65,6 @@ Examples API *** -:ref:`lv_draw_sw_arm2d_h` +:ref:`draw/sw/arm2d/lv_draw_sw_arm2d.h` -:ref:`lv_blend_arm2d_h` +:ref:`draw/sw/blend/arm2d/lv_blend_arm2d.h` diff --git a/docs/src/details/integration/renderers/espressif_ppa.rst b/docs/src/details/integration/renderers/espressif_ppa.rst index 58160d9a92..ea998e56b6 100644 --- a/docs/src/details/integration/renderers/espressif_ppa.rst +++ b/docs/src/details/integration/renderers/espressif_ppa.rst @@ -5,4 +5,4 @@ Espressif Pixel Processing Accelerator API *** -:ref:`lv_draw_ppa_h` +.. API startswith: lv_draw_ppa_ diff --git a/docs/src/details/integration/renderers/nema_gfx.rst b/docs/src/details/integration/renderers/nema_gfx.rst index a1230bed98..a236d9ec89 100644 --- a/docs/src/details/integration/renderers/nema_gfx.rst +++ b/docs/src/details/integration/renderers/nema_gfx.rst @@ -109,6 +109,6 @@ See the LVGL :ref:`DMA2D support `. API *** -:ref:`lv_draw_nema_gfx_h` +.. API startswith: lv_draw_nema_ -:ref:`lv_draw_nema_gfx_utils_h` +.. API startswith: lv_nemagfx_ diff --git a/docs/src/details/integration/renderers/nxp_g2d.rst b/docs/src/details/integration/renderers/nxp_g2d.rst index b7a0730f76..70793f8eeb 100644 --- a/docs/src/details/integration/renderers/nxp_g2d.rst +++ b/docs/src/details/integration/renderers/nxp_g2d.rst @@ -5,4 +5,4 @@ NXP G2D GPU API *** -:ref:`lv_draw_g2d_h` +.. API startswith: lv_draw_g2d_ diff --git a/docs/src/details/integration/renderers/nxp_pxp.rst b/docs/src/details/integration/renderers/nxp_pxp.rst index c95fd4e76c..bca3854435 100644 --- a/docs/src/details/integration/renderers/nxp_pxp.rst +++ b/docs/src/details/integration/renderers/nxp_pxp.rst @@ -5,6 +5,6 @@ NXP PXP GPU API *** -:ref:`lv_draw_pxp_h` +.. API startswith: lv_draw_pxp_ -:ref:`lv_pxp_cfg_h` +.. API startswith: lv_pxp_ diff --git a/docs/src/details/integration/renderers/nxp_vglite_gpu.rst b/docs/src/details/integration/renderers/nxp_vglite_gpu.rst index de5aade189..bc71475789 100644 --- a/docs/src/details/integration/renderers/nxp_vglite_gpu.rst +++ b/docs/src/details/integration/renderers/nxp_vglite_gpu.rst @@ -5,4 +5,4 @@ NXP VGLite GPU API *** -:ref:`lv_draw_vglite_h` +.. API startswith: lv_draw_vglite_ diff --git a/docs/src/details/integration/renderers/sdl.rst b/docs/src/details/integration/renderers/sdl.rst index 82730640fa..3d6bf1cd92 100644 --- a/docs/src/details/integration/renderers/sdl.rst +++ b/docs/src/details/integration/renderers/sdl.rst @@ -5,5 +5,5 @@ SDL Renderer API *** -:ref:`lv_draw_sdl_h` +.. API startswith: lv_draw_sdl_ diff --git a/docs/src/details/integration/renderers/stm32_dma2d.rst b/docs/src/details/integration/renderers/stm32_dma2d.rst index 0d5fe00d99..b253ede927 100644 --- a/docs/src/details/integration/renderers/stm32_dma2d.rst +++ b/docs/src/details/integration/renderers/stm32_dma2d.rst @@ -5,5 +5,5 @@ STM32 DMA2D GPU API *** -:ref:`lv_draw_dma2d_h` +.. API startswith: lv_draw_dma2d_ diff --git a/docs/src/details/integration/renderers/vg_lite.rst b/docs/src/details/integration/renderers/vg_lite.rst index 3e5df714cb..2fcebac30e 100644 --- a/docs/src/details/integration/renderers/vg_lite.rst +++ b/docs/src/details/integration/renderers/vg_lite.rst @@ -73,14 +73,13 @@ For detailed instructions, see :ref:`vg_lite_tvg`. API *** -:ref:`lv_draw_vglite_h` +.. API startswith: lv_draw_vglite_ -:ref:`lv_vglite_buf_h` +.. API equals: vglite_set_buf -:ref:`lv_vglite_matrix_h` +.. API equals: vglite_set_translation_matrix -:ref:`lv_vglite_path_h` - -:ref:`lv_vglite_utils_h` +.. API equals: vglite_create_rect_path_data +.. API equals: vglite_get_color diff --git a/docs/src/details/libs/lfs.rst b/docs/src/details/libs/lfs.rst index 92ca803124..53b9386d06 100644 --- a/docs/src/details/libs/lfs.rst +++ b/docs/src/details/libs/lfs.rst @@ -62,7 +62,7 @@ Example API *** -:ref:`lv_fsdrv_h` +:ref:`libs/fsdrv/lv_fsdrv.h` See also: `lvgl/src/libs/fsdrv/lv_fs_littlefs.c `__ diff --git a/docs/src/details/libs/libjpeg_turbo.rst b/docs/src/details/libs/libjpeg_turbo.rst index 153bc2f72c..87705b91b5 100644 --- a/docs/src/details/libs/libjpeg_turbo.rst +++ b/docs/src/details/libs/libjpeg_turbo.rst @@ -76,5 +76,5 @@ Example API *** -:ref:`lv_libjpeg_turbo_h` +:ref:`libs/libjpeg_turbo/lv_libjpeg_turbo.h` diff --git a/docs/src/details/libs/rle.rst b/docs/src/details/libs/rle.rst index a13060890b..589267e8aa 100644 --- a/docs/src/details/libs/rle.rst +++ b/docs/src/details/libs/rle.rst @@ -101,4 +101,4 @@ the output to ``./output/cogwheel.bin``. API *** -:ref:`lv_rle_h` +:ref:`libs/rle/lv_rle.h` diff --git a/docs/src/details/main-modules/display/index.rst b/docs/src/details/main-modules/display/index.rst index a5e97c5e28..304058e3a1 100644 --- a/docs/src/details/main-modules/display/index.rst +++ b/docs/src/details/main-modules/display/index.rst @@ -26,4 +26,4 @@ Display (lv_display) API *** -:ref:`lv_display_h` +:ref:`display/lv_display.h`