Patch Detail
Show a patch.
GET /api/1.1/patches/24335/?format=api
{ "id": 24335, "url": "https://patchwork.libcamera.org/api/1.1/patches/24335/?format=api", "web_url": "https://patchwork.libcamera.org/patch/24335/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20250911230115.25335-7-laurent.pinchart@ideasonboard.com>", "date": "2025-09-11T23:01:07", "name": "[v2,06/10] Documentation: Install API documentation within HTML directory", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "c2555cc8abf5281477edf693fb42b405d3ed45b1", "submitter": { "id": 2, "url": "https://patchwork.libcamera.org/api/1.1/people/2/?format=api", "name": "Laurent Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/24335/mbox/", "series": [ { "id": 5435, "url": "https://patchwork.libcamera.org/api/1.1/series/5435/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5435", "date": "2025-09-11T23:01:01", "name": "Documentation theming update", "version": 2, "mbox": "https://patchwork.libcamera.org/series/5435/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/24335/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/24335/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 25EEDC324E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 11 Sep 2025 23:01:59 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2486969380;\n\tFri, 12 Sep 2025 01:01:58 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CC4B06936E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Sep 2025 01:01:52 +0200 (CEST)", "from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id B79CC4579\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Sep 2025 01:00:37 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"wSCAK5Ow\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1757631637;\n\tbh=T3oHH2BBgxsWfdixafQQNiR67XuNBweueWURidmbNs8=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=wSCAK5OwNKVi3LTO4YIftNltjkb9aE2vM94rRsN7WcbafXIg4VRB8wkeAZEEktFNP\n\tSt8/S3yjV5Dm8B5jlhnPM073q/AvCD6uCZ/Mwlegus1GtuH9FRLBhT4XOPXbkdFHi3\n\tQz65C7l8P5p/WmBhHCr8suW/NX+XDtSq2Z5MwxDo=", "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Subject": "[PATCH v2 06/10] Documentation: Install API documentation within\n\tHTML directory", "Date": "Fri, 12 Sep 2025 02:01:07 +0300", "Message-ID": "<20250911230115.25335-7-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.49.1", "In-Reply-To": "<20250911230115.25335-1-laurent.pinchart@ideasonboard.com>", "References": "<20250911230115.25335-1-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "The libcamera documentation is made of high-level documentation and\nguides, written as ReStructuredText and compiled to HTML by Sphinx, and\nAPI reference documentation, written as comments in the code and\ncompiled to HTML by Doxygen.\n\nDue to meson limitations that make it difficult to place output files in\nsubdirectories, the compilation process produces an html/ directory for\nthe Sphinx documentation, and api-html/ and internal-api-html/\ndirectories for the Doxygen documentation. When deploying the\ndocumentation to the libcamera.org website, the api-html and\ninternal-api-html/ directories are moved within html/ to make the\ndocumentation self-contained.\n\nThe Sphinx and Doxygen documentation link to each other. The links are\ngenerated using relative paths, based on the directory hierarchy on the\nwebsite. This makes them broken when navigating the documentation in the\nbuild tree or in the directory where libcamera is installed.\n\nFix this by standardizing on the directories hierarchy of the website in\nthe build and install directories:\n\n- For the build directory, we can't easily build the Doxygen\n documentation in a subdirectory of the Sphinx documentation due to\n limitations of meson. Keep the existing output directories, and\n replace the html/api-html/ and html/internal-api-html/ placeholder\n directories with symlinks to the Doxygen output directories. This is\n handled by a small custom Sphinx extension.\n\n- For the install directory, install the Doxygen documentation to\n html/api-html/ and html/internal-api-html/. This overwrites the\n placeholders.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\nChanges since v1:\n\n- Split from \"[PATCH 4/6] documentation: Include API docs in the sphinx\n documentation\"\n- Avoid copying the doxygen documentation\n- Use a sphinx extension to generate symlinks\n---\n Documentation/conf.py.in | 26 +++++----\n Documentation/extensions/doxygen-link.py | 73 ++++++++++++++++++++++++\n Documentation/meson.build | 19 ++++--\n 3 files changed, 104 insertions(+), 14 deletions(-)\n create mode 100644 Documentation/extensions/doxygen-link.py", "diff": "diff --git a/Documentation/conf.py.in b/Documentation/conf.py.in\nindex 34fa3956f49e..5e0a7cff2984 100644\n--- a/Documentation/conf.py.in\n+++ b/Documentation/conf.py.in\n@@ -9,14 +9,8 @@\n \n # -- Path setup --------------------------------------------------------------\n \n-# If extensions (or modules to document with autodoc) are in another directory,\n-# add these directories to sys.path here. If the directory is relative to the\n-# documentation root, use os.path.abspath to make it absolute, like shown here.\n-#\n-# import os\n-# import sys\n-# sys.path.insert(0, os.path.abspath('.'))\n-\n+import sys\n+sys.path.insert(0, \"@CURRENT_SRCDIR@/extensions\")\n \n # -- Project information -----------------------------------------------------\n \n@@ -39,6 +33,7 @@ author = 'The libcamera documentation authors'\n extensions = [\n 'sphinx.ext.graphviz',\n 'sphinxcontrib.doxylink',\n+ 'doxygen-link',\n ]\n \n graphviz_output_format = 'svg'\n@@ -75,14 +70,25 @@ pygments_style = None\n doxylink = {\n 'doxy-pub': (\n '@TOP_BUILDDIR@/Documentation/api-html/tagfile.xml',\n- '../api-html/',\n+ 'api-html/',\n ),\n 'doxy-int': (\n '@TOP_BUILDDIR@/Documentation/internal-api-html/tagfile.xml',\n- '../internal-api-html/',\n+ 'internal-api-html/',\n ),\n }\n \n+doxygen_links = [\n+ [\n+ '@TOP_BUILDDIR@/Documentation/html/api-html',\n+ '@TOP_BUILDDIR@/Documentation/api-html',\n+ ],\n+ [\n+ '@TOP_BUILDDIR@/Documentation/html/internal-api-html',\n+ '@TOP_BUILDDIR@/Documentation/internal-api-html',\n+ ],\n+]\n+\n # -- Options for HTML output -------------------------------------------------\n \n # The theme to use for HTML and HTML Help pages. See the documentation for\ndiff --git a/Documentation/extensions/doxygen-link.py b/Documentation/extensions/doxygen-link.py\nnew file mode 100644\nindex 000000000000..8b94a4dd7f0b\n--- /dev/null\n+++ b/Documentation/extensions/doxygen-link.py\n@@ -0,0 +1,73 @@\n+# SPDX-License-Identifier: GPL-2.0-or-later\n+# Copyright (C) 2025, Ideas on Board Oy\n+\n+import contextlib\n+import os\n+import shutil\n+from pathlib import Path\n+from sphinx.util import logging\n+\n+__version__ = \"0.0.0\"\n+\n+logger = logging.getLogger(__name__)\n+\n+\n+def on_config_inited(app, config):\n+ entries = []\n+\n+ outdir = Path(app.outdir).absolute()\n+\n+ for index, items in enumerate(config.doxygen_links):\n+ err_msg_prefix = f'Config variable `doxygen_links` contains invalid entry {index} (`{items}`)'\n+\n+ if len(items) != 2:\n+ raise ValueError(f'{err_msg_prefix}: expected (path, target)')\n+\n+ path = Path(items[0]).absolute()\n+ target = Path(items[1]).relative_to(path.parent, walk_up=True)\n+\n+ if not path.is_relative_to(outdir):\n+ raise ValueError(f'{err_msg_prefix}: path `{items[0]}` is outside of output directory `{outdir}`')\n+\n+ entries.append([path, target])\n+\n+ config.doxygen_links = entries\n+\n+\n+def on_builder_inited(app):\n+ # Remove the symlinks if they exist, to avoid overwriting the index.html\n+ # generated by Doxygen with the placeholder index from Sphinx.\n+\n+ for path, target in app.config.doxygen_links:\n+ if path.is_symlink():\n+ logger.info(f'Removing existing symlink {path}')\n+ os.unlink(path)\n+\n+\n+def on_build_finished(app, exc):\n+ # Create the symlinks. Remove any existing placeholder directory\n+ # recursively first.\n+\n+ if exc:\n+ return\n+\n+ for path, target in app.config.doxygen_links:\n+ logger.info(f'Creating symlink {path} -> {target}')\n+\n+ if path.is_dir():\n+ shutil.rmtree(path)\n+\n+ os.symlink(target, path)\n+\n+\n+def setup(app):\n+ app.add_config_value('doxygen_links', [], 'env', frozenset({list, tuple}))\n+ app.connect('config-inited', on_config_inited)\n+ app.connect('builder-inited', on_builder_inited)\n+ app.connect('build-finished', on_build_finished)\n+\n+ return {\n+ \"version\": __version__,\n+ \"parallel_read_safe\": True,\n+ \"parallel_write_safe\": True,\n+ }\ndiff --git a/Documentation/meson.build b/Documentation/meson.build\nindex f73407432fff..82d76b257b8c 100644\n--- a/Documentation/meson.build\n+++ b/Documentation/meson.build\n@@ -12,6 +12,7 @@ dot = find_program('dot', required : get_option('documentation'))\n if doxygen.found() and dot.found()\n cdata = configuration_data()\n cdata.set('VERSION', 'v@0@'.format(libcamera_git_version))\n+ cdata.set('CURRENT_SRCDIR', meson.current_source_dir())\n cdata.set('TOP_SRCDIR', meson.project_source_root())\n cdata.set('TOP_BUILDDIR', meson.project_build_root())\n cdata.set('OUTPUT_DIR', meson.current_build_dir())\n@@ -89,7 +90,7 @@ if doxygen.found() and dot.found()\n output : 'api-html',\n command : [doxygen, doxyfile],\n install : true,\n- install_dir : doc_install_dir,\n+ install_dir : doc_install_dir / 'html',\n install_tag : 'doc')\n \n # This is the internal documentation, which hard-codes a list of directories\n@@ -109,7 +110,7 @@ if doxygen.found() and dot.found()\n output : 'internal-api-html',\n command : [doxygen, doxyfile],\n install : true,\n- install_dir : doc_install_dir,\n+ install_dir : doc_install_dir / 'html',\n install_tag : 'doc-internal')\n endif\n \n@@ -149,7 +150,11 @@ if sphinx.found()\n fs = import('fs')\n sphinx_conf_dir = fs.parent(sphinx_conf)\n \n+ sphinx_env = environment()\n+ sphinx_env.set('PYTHONDONTWRITEBYTECODE', '1')\n+\n docs_sources = [\n+ 'api-html/index.rst',\n 'camera-sensor-model.rst',\n 'code-of-conduct.rst',\n 'coding-style.rst',\n@@ -164,6 +169,7 @@ if sphinx.found()\n 'guides/pipeline-handler.rst',\n 'guides/tracing.rst',\n 'index.rst',\n+ 'internal-api-html/index.rst',\n 'introduction.rst',\n 'lens_driver_requirements.rst',\n 'libcamera_architecture.rst',\n@@ -183,10 +189,14 @@ if sphinx.found()\n input : docs_sources,\n output : 'html',\n build_by_default : true,\n+ depend_files : [\n+ 'extensions/doxygen-link.py',\n+ ],\n depends : [\n doxygen_public,\n doxygen_internal,\n ],\n+ env : sphinx_env,\n install : true,\n install_dir : doc_install_dir,\n install_tag : 'doc')\n@@ -195,7 +205,8 @@ if sphinx.found()\n command : [sphinx, '-W', '-b', 'linkcheck',\n '-c', sphinx_conf_dir,\n meson.current_source_dir(), '@OUTPUT@'],\n- build_always_stale : true,\n input : docs_sources,\n- output : 'linkcheck')\n+ output : 'linkcheck',\n+ build_always_stale : true,\n+ env : sphinx_env)\n endif\n", "prefixes": [ "v2", "06/10" ] }