[{"id":28425,"web_url":"https://patchwork.libcamera.org/comment/28425/","msgid":"<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>","date":"2024-01-09T14:28:07","subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Dan\n  I really like the split!\n\nOn Fri, Jan 05, 2024 at 04:41:03PM +0000, Daniel Scally via libcamera-devel wrote:\n> The API reference pages generated by Doxygen are comprehensive, but\n> therefore quite overwhelming for application developers who will\n> likely never need to use the majority of the library's objects. To\n> reduce the complexity of the documentation, split it into two runs of\n> doxygen.\n>\n> In the first run of doxygen we pass a specific list of source files\n> to parse, which is built from the File arrays in Meson's build files.\n> This ensures that we only generate the documentation for code from\n> those files.\n>\n> In the second run allow doxygen to generate documentation for all of\n> the library's objects as it currently does. This set will now be\n> output into build/Documentation/internal-api-html.\n>\n> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n> ---\n> Changes in v2:\n>\n> \t- Formatting fixes (Jacopo)\n> \t- Phraseology (Laurent)\n> \t- Switched to passing specific files to parse to doxygen rather than\n> \t  relying on \\internal to remove other docu-comments.\n>\n>  Documentation/Doxyfile-internal.in     | 21 +++++++\n>  Documentation/Doxyfile-public.in       |  5 ++\n>  Documentation/Doxyfile.in              | 26 ++-------\n>  Documentation/meson.build              | 76 +++++++++++++++++++++++---\n>  include/libcamera/base/meson.build     |  7 +++\n>  include/libcamera/internal/meson.build |  7 +++\n>  include/libcamera/meson.build          | 10 ++++\n>  meson.build                            |  8 +++\n>  src/libcamera/base/class.cpp           |  1 +\n>  src/libcamera/base/meson.build         |  7 +++\n>  src/libcamera/camera.cpp               |  7 +++\n>  src/libcamera/camera_manager.cpp       |  1 +\n>  src/libcamera/framebuffer.cpp          |  6 +-\n>  src/libcamera/meson.build              |  7 +++\n>  src/libcamera/request.cpp              |  1 +\n>  15 files changed, 160 insertions(+), 30 deletions(-)\n>  create mode 100644 Documentation/Doxyfile-internal.in\n>  create mode 100644 Documentation/Doxyfile-public.in\n>\n> diff --git a/Documentation/Doxyfile-internal.in b/Documentation/Doxyfile-internal.in\n> new file mode 100644\n> index 00000000..7b3cce49\n> --- /dev/null\n> +++ b/Documentation/Doxyfile-internal.in\n> @@ -0,0 +1,21 @@\n> +# SPDX-License-Identifier: CC-BY-SA-4.0\n> +\n> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> +                         \"@TOP_SRCDIR@/include/libcamera\" \\\n> +                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n> +                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n> +                         \"@TOP_SRCDIR@/src/libcamera\" \\\n> +                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n> +                         \"@TOP_BUILDDIR@/src/libcamera\"\n> +\n> +EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n\nI'm still a bit puzzled on why we don't document Span<>, but this was\nalready here\n\n> +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n> +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n> +                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n> +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n> +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n> +                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n> +                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n> +                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n> +                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n> +                         @TOP_BUILDDIR@/src/libcamera/proxy/\n> diff --git a/Documentation/Doxyfile-public.in b/Documentation/Doxyfile-public.in\n> new file mode 100644\n> index 00000000..cdbc03a0\n> --- /dev/null\n> +++ b/Documentation/Doxyfile-public.in\n> @@ -0,0 +1,5 @@\n> +# SPDX-License-Identifier: CC-BY-SA-4.0\n> +\n> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> +                         \"@INPUT@\" \\\n> +                         \"@TOP_BUILDDIR@/src/libcamera/version.cpp\"\n> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> index 48fea8bc..a271c7bc 100644\n> --- a/Documentation/Doxyfile.in\n> +++ b/Documentation/Doxyfile.in\n> @@ -21,14 +21,6 @@ CASE_SENSE_NAMES       = YES\n>\n>  QUIET                  = YES\n>\n> -INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> -                         \"@TOP_SRCDIR@/include/libcamera\" \\\n> -                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n> -                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n> -                         \"@TOP_SRCDIR@/src/libcamera\" \\\n> -                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n> -                         \"@TOP_BUILDDIR@/src/libcamera\"\n> -\n>  FILE_PATTERNS          = *.c \\\n>                           *.cpp \\\n>                           *.h \\\n> @@ -36,17 +28,8 @@ FILE_PATTERNS          = *.c \\\n>\n>  RECURSIVE              = YES\n>\n> -EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n> -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n> -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n> -                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n> -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n> -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n> -                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n> -                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n> -                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n> -                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n> -                         @TOP_BUILDDIR@/src/libcamera/proxy/\n> +@INCLUDE_PATH          = @TOP_BUILDDIR@/Documentation\n> +@INCLUDE               = @INCLUDE_FILE@\n>\n>  EXCLUDE_PATTERNS       = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \\\n>                           @TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \\\n> @@ -70,7 +53,10 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n>\n>  EXCLUDE_SYMLINKS       = YES\n>\n> -HTML_OUTPUT            = api-html\n> +HIDE_UNDOC_CLASSES     = @HIDE_UNDOC_CLASSES@\n> +HIDE_UNDOC_MEMBERS     = @HIDE_UNDOC_MEMBERS@\n> +HTML_OUTPUT            = @HTML_OUTPUT@\n> +INTERNAL_DOCS          = @INTERNAL_DOCS@\n>\n>  GENERATE_LATEX         = NO\n>\n> diff --git a/Documentation/meson.build b/Documentation/meson.build\n> index 7a58fec8..afaad751 100644\n> --- a/Documentation/meson.build\n> +++ b/Documentation/meson.build\n> @@ -23,12 +23,7 @@ if doxygen.found() and dot.found()\n>\n>      cdata.set('PREDEFINED', ' \\\\\\n\\t\\t\\t '.join(doxygen_predefined))\n>\n> -    doxyfile = configure_file(input : 'Doxyfile.in',\n> -                              output : 'Doxyfile',\n> -                              configuration : cdata)\n> -\n> -    doxygen_input = [\n> -        doxyfile,\n> +    global_doxygen_input = [\n>          libcamera_base_headers,\n>          libcamera_base_sources,\n>          libcamera_internal_headers,\n> @@ -41,16 +36,79 @@ if doxygen.found() and dot.found()\n>      ]\n>\n>      if is_variable('ipu3_ipa_sources')\n> -        doxygen_input += [ipu3_ipa_sources]\n> +        global_doxygen_input += [ipu3_ipa_sources]\n>      endif\n>\n> +    # We need to generate two \"include\" files for the final Doxyfile which\n> +    # define a set of source files to use in the documentation parsing. We\n> +    # collected a list of the public sources in doxygen_public_sources, so we\n> +    # pass that to the doxyfiles so that Doxyfile-public refers only to those\n> +    # files. Although INPUT is sent to both, Doxyfile-internal.in doesn't refer\n> +    # to it and just hardcodes the directories to parse.\n\nThanks, this is quite clear now!\n\n> +    cdata.set('INPUT', '\" \\\\\\n\\t\\t\\t \"'.join(doxygen_public_sources))\n> +    doxyfile_include_public = configure_file(input : 'Doxyfile-public.in',\n> +                                             output : 'Doxyfile-include-public',\n> +                                             configuration : cdata)\n> +    doxyfile_include_internal = configure_file(input : 'Doxyfile-internal.in',\n> +                                               output : 'Doxyfile-include-internal',\n> +                                               configuration : cdata)\n> +\n> +    # We run doxygen twice - the first run excludes internal API objects as it\n> +    # is intended to document the public API only. A second run covers all of\n> +    # the library's objects for libcamera developers. To achieve this we need to\n> +    # flag as \\internal some of the comments for objects which we wish to hide,\n> +    # and remove the auto generated documents via HIDE_UNDOC_CLASSES and\n> +    # HIDE_UNDOC_MEMBERS.\n> +\n> +    cdata_public = configuration_data()\n> +    cdata_public.merge_from(cdata)\n> +    cdata_public.set('HIDE_UNDOC_CLASSES', 'YES')\n> +    cdata_public.set('HIDE_UNDOC_MEMBERS', 'YES')\n> +    cdata_public.set('HTML_OUTPUT', 'api-html')\n> +    cdata_public.set('INCLUDE_FILE', 'Doxyfile-include-public')\n> +    cdata_public.set('INTERNAL_DOCS', 'NO')\n> +\n> +    doxyfile_public = configure_file(input : 'Doxyfile.in',\n> +                                     output : 'Doxyfile-public',\n> +                                     configuration : cdata_public)\n> +\n> +    public_doxygen_input = global_doxygen_input\n> +    public_doxygen_input += doxyfile_public\n> +\n>      custom_target('doxygen',\n> -                  input : doxygen_input,\n> +                  input : public_doxygen_input,\n>                    output : 'api-html',\n> -                  command : [doxygen, doxyfile],\n> +                  command : [doxygen, doxyfile_public],\n>                    install : true,\n>                    install_dir : doc_install_dir,\n>                    install_tag : 'doc')\n> +\n> +    # This is the internal documentation, so _don't_ hide undocumented classes\n> +    # as we want everything to show up and warnings to be generated if any\n> +    # documentation is missing.\n> +\n> +    cdata_internal = configuration_data()\n> +    cdata_internal.merge_from(cdata)\n> +    cdata_internal.set('HIDE_UNDOC_CLASSES', 'NO')\n> +    cdata_internal.set('HIDE_UNDOC_MEMBERS', 'NO')\n> +    cdata_internal.set('HTML_OUTPUT', 'internal-api-html')\n> +    cdata_internal.set('INCLUDE_FILE', 'Doxyfile-include-internal')\n> +    cdata_internal.set('INTERNAL_DOCS', 'YES')\n> +\n> +    doxyfile_internal = configure_file(input : 'Doxyfile.in',\n> +                                       output : 'Doxyfile-internal',\n> +                                       configuration : cdata_internal)\n> +\n> +    internal_doxygen_input = global_doxygen_input\n> +    internal_doxygen_input += doxyfile_internal\n> +\n> +    custom_target('doxygen-internal',\n> +                  input : internal_doxygen_input,\n> +                  output : 'internal-api-html',\n> +                  command : [doxygen, doxyfile_internal],\n> +                  install : true,\n> +                  install_dir : doc_install_dir,\n> +                  install_tag : 'doc-internal')\n>  endif\n>\n>  #\n> diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\n> index f24f47de..82277f46 100644\n> --- a/include/libcamera/base/meson.build\n> +++ b/include/libcamera/base/meson.build\n> @@ -38,3 +38,10 @@ libcamera_base_headers = [\n>\n>  install_headers(libcamera_base_public_headers,\n>                  subdir : libcamera_base_include_dir)\n> +\n> +foreach lbph : libcamera_base_public_headers\n> +\tdoxygen_public_sources += '/'.join(\n> +\t\tmeson.project_source_root(),\n> +\t\t'@0@'.format(lbph)\n> +\t)\n> +endforeach\n> diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build\n> index 4d59cb2a..4af36884 100644\n> --- a/include/libcamera/internal/meson.build\n> +++ b/include/libcamera/internal/meson.build\n> @@ -58,4 +58,11 @@ libcamera_internal_headers = [\n>      libcamera_internal_headers_publically_undocumented\n>  ]\n>\n> +foreach lph : libcamera_internal_headers_publically_documented\n> +\tdoxygen_public_sources += '/'.join(\n> +\t\tmeson.project_source_root(),\n> +\t\t'@0@'.format(lph)\n> +\t)\n> +endforeach\n> +\n>  subdir('converter')\n> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> index bab858a3..25e2f8a4 100644\n> --- a/include/libcamera/meson.build\n> +++ b/include/libcamera/meson.build\n> @@ -26,6 +26,13 @@ subdir('ipa')\n>  install_headers(libcamera_public_headers,\n>                  subdir : libcamera_include_dir)\n>\n> +foreach lph : libcamera_public_headers\n> +\tdoxygen_public_sources += '/'.join(\n> +\t\tmeson.project_source_root(),\n> +\t\t'@0@'.format(lph)\n> +\t)\n> +endforeach\n> +\n>  #\n>  # Generate headers from templates.\n>  #\n> @@ -85,6 +92,7 @@ foreach mode, entry : controls_map\n>                                                  '-r', ranges_file, '@INPUT@'],\n>                                       install : true,\n>                                       install_dir : libcamera_headers_install_dir)\n> +    doxygen_public_sources += control_headers.get(-1).full_path()\n>  endforeach\n>\n>  libcamera_public_headers += control_headers\n> @@ -101,6 +109,7 @@ formats_h = custom_target('formats_h',\n>                            install : true,\n>                            install_dir : libcamera_headers_install_dir)\n>  libcamera_public_headers += formats_h\n> +doxygen_public_sources += formats_h.full_path()\n>\n>  # libcamera.h\n>  libcamera_h = custom_target('gen-header',\n> @@ -111,6 +120,7 @@ libcamera_h = custom_target('gen-header',\n>                              install_dir : libcamera_headers_install_dir)\n>\n>  libcamera_public_headers += libcamera_h\n> +doxygen_public_sources += libcamera_h.full_path()\n>\n>  # version.h\n>  version = libcamera_version.split('.')\n> diff --git a/meson.build b/meson.build\n> index e49de4c2..cca1883e 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -231,6 +231,14 @@ endif\n>  # Utilities are parsed first to provide support for other components.\n>  subdir('utils')\n>\n> +# To support auto-generation of documentation We need an array of the paths to\n\ns/We/we\n\n> +# public headers and source files so that we can tell doxygen which files to\n> +# look at later. Unfortunately the inclusion of custom targets in some of the\n> +# existing arrays precludes using them directly and you cannot generate File\n> +# objects from generated files, so we need to collect paths to relevant files\n> +# within an array.\n> +doxygen_public_sources = []\n> +\n>  subdir('include')\n>  subdir('src')\n>\n> diff --git a/src/libcamera/base/class.cpp b/src/libcamera/base/class.cpp\n> index 9c2d9f21..70fd5cd5 100644\n> --- a/src/libcamera/base/class.cpp\n> +++ b/src/libcamera/base/class.cpp\n> @@ -184,6 +184,7 @@ Extensible::Extensible(std::unique_ptr<Extensible::Private> d)\n>   */\n>\n>  /**\n> + * \\internal\n>   * \\class Extensible::Private\n>   * \\brief Base class for private data managed through a d-pointer\n>   */\n> diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\n> index 523c5885..ae949a51 100644\n> --- a/src/libcamera/base/meson.build\n> +++ b/src/libcamera/base/meson.build\n> @@ -30,6 +30,13 @@ libcamera_base_sources = [\n>  \tlibcamera_base_internal_sources\n>  ]\n>\n> +foreach lbps : libcamera_base_public_sources\n> +\tdoxygen_public_sources += '/'.join(\n> +\t\tmeson.project_source_root(),\n> +\t\t'@0@'.format(lbps)\n> +\t)\n> +endforeach\n> +\n>  libdw = dependency('libdw', required : false)\n>  libunwind = dependency('libunwind', required : false)\n>\n> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n> index 0ad1a4b5..ed46f853 100644\n> --- a/src/libcamera/camera.cpp\n> +++ b/src/libcamera/camera.cpp\n> @@ -560,6 +560,13 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF\n>   */\n>\n>  /**\n> + * \\internal\n> + * \\file libcamera\\internal\\camera.h\n> + * \\brief Internal Camera device handling\n> + */\n> +\n> +/**\n> + * \\internal\n>   * \\class Camera::Private\n>   * \\brief Base class for camera private data\n>   *\n> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n> index 355f3ada..61d45256 100644\n> --- a/src/libcamera/camera_manager.cpp\n> +++ b/src/libcamera/camera_manager.cpp\n> @@ -23,6 +23,7 @@\n>   */\n>\n>  /**\n> + * \\internal\n>   * \\file libcamera/internal/camera_manager.h\n>   * \\brief Internal camera manager support\n>   */\n\nThat's weird, I don't see CameraManager::Private::addCamera() and\nCameraManager::Private::removeCamera() being documented. It was not\ndocumented even before this commit though :/\n\n> diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp\n> index 5a7f3c0b..db450e11 100644\n> --- a/src/libcamera/framebuffer.cpp\n> +++ b/src/libcamera/framebuffer.cpp\n> @@ -16,7 +16,10 @@\n>  /**\n>   * \\file libcamera/framebuffer.h\n>   * \\brief Frame buffer handling\n> - *\n> + */\n> +\n> +/**\n> + * \\internal\n>   * \\file libcamera/internal/framebuffer.h\n>   * \\brief Internal frame buffer handling support\n>   */\n> @@ -105,6 +108,7 @@ LOG_DEFINE_CATEGORY(Buffer)\n>   */\n>\n>  /**\n> + * \\internal\n>   * \\class FrameBuffer::Private\n>   * \\brief Base class for FrameBuffer private data\n>   *\n> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> index 676470c1..413e14db 100644\n> --- a/src/libcamera/meson.build\n> +++ b/src/libcamera/meson.build\n> @@ -59,6 +59,13 @@ libcamera_sources = [\n>  \tlibcamera_internal_sources\n>  ]\n>\n> +foreach lps : libcamera_public_sources\n> +\tdoxygen_public_sources += '/'.join(\n> +\t\tmeson.project_source_root(),\n> +\t\t'@0@'.format(lps)\n> +\t)\n> +endforeach\n> +\n>  libcamera_sources += libcamera_public_headers\n>  libcamera_sources += libcamera_generated_ipa_headers\n>  libcamera_sources += libcamera_tracepoint_header\n> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\n> index 949c556f..930d8c92 100644\n> --- a/src/libcamera/request.cpp\n> +++ b/src/libcamera/request.cpp\n> @@ -33,6 +33,7 @@ namespace libcamera {\n>  LOG_DEFINE_CATEGORY(Request)\n>\n>  /**\n> + * \\internal\n>   * \\class Request::Private\n>   * \\brief Request private data\n>   *\n\nSo we should remember to mark every classes that derives a private\nimplementation from Extensible to mark it as \\internal. I think it's\nfine, and I like the patch  a lot!\n\nWith the few above points clarified\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nThanks\n   j\n\n> --\n> 2.34.1\n>","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 9F409BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  9 Jan 2024 14:28:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E517162B32;\n\tTue,  9 Jan 2024 15:28:11 +0100 (CET)","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 3AEB562B30\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Jan 2024 15:28:10 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2001:b07:5d2e:52c9:cc1e:e404:491f:e6ea])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0F88E552;\n\tTue,  9 Jan 2024 15:27:05 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1704810491;\n\tbh=NY1EoHa+x/iEh85CICkXmpkaMJdRCfnv+P2OpqAu9wk=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=mK6XXbw34s3HVT64IRAPBAIOlnu7BmnaGZ4hZKUaQGRGp3srZfDkE0CLwVDG9Q7gj\n\tHEX5v3tO7sRECmwAUgPPSnw7CPBthZNhDWrRiFHdInBPq+VOoLf/hZ3xn+1K8ymA8b\n\toEpS8Z6OwfalrjpwQTned6A/4i32I2anM5i6COHW1w5ZFUQYQ3C8wh8KawUIOSXBFP\n\tNGtixjlaJ5VbNARUN/AdJpwSR0/+rcLjXvZIeZXQRfUycLymN+DkBXGYoLHrKacD4T\n\tGmgL/p7rLC1exz1Y3uyB2Vkd4Hd7i4qlj+1TRLvrn+OvtE+QHdMI0Gb+Uq+j35V3mU\n\te2BzuD+rszvCQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1704810426;\n\tbh=NY1EoHa+x/iEh85CICkXmpkaMJdRCfnv+P2OpqAu9wk=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=LMNn3KCl8Gacafm9bnqf9gkkRNWQ4P8ZZaqhEoikJpCXn6iDT6fIiHRbjemCcvV6q\n\tCtrDO49hu1Oz2QDJabOnwPJr6sDfwDgdx8jdUCv63EnnZzhGKaDBKqXyHWjFbILWZz\n\tYshZZ2zPeJNSWgeJkvTYhvqUK2gowwoRtMG7xgPc="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"LMNn3KCl\"; dkim-atps=neutral","Date":"Tue, 9 Jan 2024 15:28:07 +0100","To":"Daniel Scally <dan.scally@ideasonboard.com>","Message-ID":"<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>","References":"<20240105164104.78398-1-dan.scally@ideasonboard.com>\n\t<20240105164104.78398-5-dan.scally@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20240105164104.78398-5-dan.scally@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","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>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28441,"web_url":"https://patchwork.libcamera.org/comment/28441/","msgid":"<170483813334.1166171.2088897607589779707@ping.linuxembedded.co.uk>","date":"2024-01-09T22:08:53","subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jacopo Mondi via libcamera-devel (2024-01-09 14:28:07)\n> Hi Dan\n>   I really like the split!\n> \n> On Fri, Jan 05, 2024 at 04:41:03PM +0000, Daniel Scally via libcamera-devel wrote:\n> > The API reference pages generated by Doxygen are comprehensive, but\n> > therefore quite overwhelming for application developers who will\n> > likely never need to use the majority of the library's objects. To\n> > reduce the complexity of the documentation, split it into two runs of\n> > doxygen.\n> >\n> > In the first run of doxygen we pass a specific list of source files\n> > to parse, which is built from the File arrays in Meson's build files.\n> > This ensures that we only generate the documentation for code from\n> > those files.\n> >\n> > In the second run allow doxygen to generate documentation for all of\n> > the library's objects as it currently does. This set will now be\n> > output into build/Documentation/internal-api-html.\n> >\n> > Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n> > ---\n> > Changes in v2:\n> >\n> >       - Formatting fixes (Jacopo)\n> >       - Phraseology (Laurent)\n> >       - Switched to passing specific files to parse to doxygen rather than\n> >         relying on \\internal to remove other docu-comments.\n> >\n> >  Documentation/Doxyfile-internal.in     | 21 +++++++\n> >  Documentation/Doxyfile-public.in       |  5 ++\n> >  Documentation/Doxyfile.in              | 26 ++-------\n> >  Documentation/meson.build              | 76 +++++++++++++++++++++++---\n> >  include/libcamera/base/meson.build     |  7 +++\n> >  include/libcamera/internal/meson.build |  7 +++\n> >  include/libcamera/meson.build          | 10 ++++\n> >  meson.build                            |  8 +++\n> >  src/libcamera/base/class.cpp           |  1 +\n> >  src/libcamera/base/meson.build         |  7 +++\n> >  src/libcamera/camera.cpp               |  7 +++\n> >  src/libcamera/camera_manager.cpp       |  1 +\n> >  src/libcamera/framebuffer.cpp          |  6 +-\n> >  src/libcamera/meson.build              |  7 +++\n> >  src/libcamera/request.cpp              |  1 +\n> >  15 files changed, 160 insertions(+), 30 deletions(-)\n> >  create mode 100644 Documentation/Doxyfile-internal.in\n> >  create mode 100644 Documentation/Doxyfile-public.in\n> >\n> > diff --git a/Documentation/Doxyfile-internal.in b/Documentation/Doxyfile-internal.in\n> > new file mode 100644\n> > index 00000000..7b3cce49\n> > --- /dev/null\n> > +++ b/Documentation/Doxyfile-internal.in\n> > @@ -0,0 +1,21 @@\n> > +# SPDX-License-Identifier: CC-BY-SA-4.0\n> > +\n> > +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> > +                         \"@TOP_SRCDIR@/include/libcamera\" \\\n> > +                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n> > +                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n> > +                         \"@TOP_SRCDIR@/src/libcamera\" \\\n> > +                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n> > +                         \"@TOP_BUILDDIR@/src/libcamera\"\n> > +\n> > +EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n> \n> I'm still a bit puzzled on why we don't document Span<>, but this was\n> already here\n\nPresumably this is expected to be covered by the C++ definition of a\nSpan. It's supposed to be a 'like for like' implementation. (or as close\nas possible I think).\n\nPerhaps somewhere we should document that fact. In the 'long future'\n(when we can support C++20 - I would expect we'd convert to use\nstd::span in place of libcamera::Span.\n\n> > +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n> > +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n> > +                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n> > +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n> > +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n> > +                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n> > +                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n> > +                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n> > +                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n> > +                         @TOP_BUILDDIR@/src/libcamera/proxy/\n> > diff --git a/Documentation/Doxyfile-public.in b/Documentation/Doxyfile-public.in\n> > new file mode 100644\n> > index 00000000..cdbc03a0\n> > --- /dev/null\n> > +++ b/Documentation/Doxyfile-public.in\n> > @@ -0,0 +1,5 @@\n> > +# SPDX-License-Identifier: CC-BY-SA-4.0\n> > +\n> > +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> > +                         \"@INPUT@\" \\\n> > +                         \"@TOP_BUILDDIR@/src/libcamera/version.cpp\"\n> > diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> > index 48fea8bc..a271c7bc 100644\n> > --- a/Documentation/Doxyfile.in\n> > +++ b/Documentation/Doxyfile.in\n> > @@ -21,14 +21,6 @@ CASE_SENSE_NAMES       = YES\n> >\n> >  QUIET                  = YES\n> >\n> > -INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n> > -                         \"@TOP_SRCDIR@/include/libcamera\" \\\n> > -                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n> > -                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n> > -                         \"@TOP_SRCDIR@/src/libcamera\" \\\n> > -                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n> > -                         \"@TOP_BUILDDIR@/src/libcamera\"\n> > -\n> >  FILE_PATTERNS          = *.c \\\n> >                           *.cpp \\\n> >                           *.h \\\n> > @@ -36,17 +28,8 @@ FILE_PATTERNS          = *.c \\\n> >\n> >  RECURSIVE              = YES\n> >\n> > -EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n> > -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n> > -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n> > -                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n> > -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n> > -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n> > -                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n> > -                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n> > -                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n> > -                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n> > -                         @TOP_BUILDDIR@/src/libcamera/proxy/\n> > +@INCLUDE_PATH          = @TOP_BUILDDIR@/Documentation\n> > +@INCLUDE               = @INCLUDE_FILE@\n> >\n> >  EXCLUDE_PATTERNS       = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \\\n> >                           @TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \\\n> > @@ -70,7 +53,10 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n> >\n> >  EXCLUDE_SYMLINKS       = YES\n> >\n> > -HTML_OUTPUT            = api-html\n> > +HIDE_UNDOC_CLASSES     = @HIDE_UNDOC_CLASSES@\n> > +HIDE_UNDOC_MEMBERS     = @HIDE_UNDOC_MEMBERS@\n> > +HTML_OUTPUT            = @HTML_OUTPUT@\n> > +INTERNAL_DOCS          = @INTERNAL_DOCS@\n> >\n> >  GENERATE_LATEX         = NO\n> >\n> > diff --git a/Documentation/meson.build b/Documentation/meson.build\n> > index 7a58fec8..afaad751 100644\n> > --- a/Documentation/meson.build\n> > +++ b/Documentation/meson.build\n> > @@ -23,12 +23,7 @@ if doxygen.found() and dot.found()\n> >\n> >      cdata.set('PREDEFINED', ' \\\\\\n\\t\\t\\t '.join(doxygen_predefined))\n> >\n> > -    doxyfile = configure_file(input : 'Doxyfile.in',\n> > -                              output : 'Doxyfile',\n> > -                              configuration : cdata)\n> > -\n> > -    doxygen_input = [\n> > -        doxyfile,\n> > +    global_doxygen_input = [\n> >          libcamera_base_headers,\n> >          libcamera_base_sources,\n> >          libcamera_internal_headers,\n> > @@ -41,16 +36,79 @@ if doxygen.found() and dot.found()\n> >      ]\n> >\n> >      if is_variable('ipu3_ipa_sources')\n> > -        doxygen_input += [ipu3_ipa_sources]\n> > +        global_doxygen_input += [ipu3_ipa_sources]\n> >      endif\n> >\n> > +    # We need to generate two \"include\" files for the final Doxyfile which\n> > +    # define a set of source files to use in the documentation parsing. We\n> > +    # collected a list of the public sources in doxygen_public_sources, so we\n> > +    # pass that to the doxyfiles so that Doxyfile-public refers only to those\n> > +    # files. Although INPUT is sent to both, Doxyfile-internal.in doesn't refer\n> > +    # to it and just hardcodes the directories to parse.\n> \n> Thanks, this is quite clear now!\n> \n> > +    cdata.set('INPUT', '\" \\\\\\n\\t\\t\\t \"'.join(doxygen_public_sources))\n> > +    doxyfile_include_public = configure_file(input : 'Doxyfile-public.in',\n> > +                                             output : 'Doxyfile-include-public',\n> > +                                             configuration : cdata)\n> > +    doxyfile_include_internal = configure_file(input : 'Doxyfile-internal.in',\n> > +                                               output : 'Doxyfile-include-internal',\n> > +                                               configuration : cdata)\n> > +\n> > +    # We run doxygen twice - the first run excludes internal API objects as it\n> > +    # is intended to document the public API only. A second run covers all of\n> > +    # the library's objects for libcamera developers. To achieve this we need to\n> > +    # flag as \\internal some of the comments for objects which we wish to hide,\n> > +    # and remove the auto generated documents via HIDE_UNDOC_CLASSES and\n> > +    # HIDE_UNDOC_MEMBERS.\n> > +\n> > +    cdata_public = configuration_data()\n> > +    cdata_public.merge_from(cdata)\n> > +    cdata_public.set('HIDE_UNDOC_CLASSES', 'YES')\n> > +    cdata_public.set('HIDE_UNDOC_MEMBERS', 'YES')\n> > +    cdata_public.set('HTML_OUTPUT', 'api-html')\n> > +    cdata_public.set('INCLUDE_FILE', 'Doxyfile-include-public')\n> > +    cdata_public.set('INTERNAL_DOCS', 'NO')\n> > +\n> > +    doxyfile_public = configure_file(input : 'Doxyfile.in',\n> > +                                     output : 'Doxyfile-public',\n> > +                                     configuration : cdata_public)\n> > +\n> > +    public_doxygen_input = global_doxygen_input\n> > +    public_doxygen_input += doxyfile_public\n> > +\n> >      custom_target('doxygen',\n> > -                  input : doxygen_input,\n> > +                  input : public_doxygen_input,\n> >                    output : 'api-html',\n> > -                  command : [doxygen, doxyfile],\n> > +                  command : [doxygen, doxyfile_public],\n> >                    install : true,\n> >                    install_dir : doc_install_dir,\n> >                    install_tag : 'doc')\n> > +\n> > +    # This is the internal documentation, so _don't_ hide undocumented classes\n> > +    # as we want everything to show up and warnings to be generated if any\n> > +    # documentation is missing.\n> > +\n> > +    cdata_internal = configuration_data()\n> > +    cdata_internal.merge_from(cdata)\n> > +    cdata_internal.set('HIDE_UNDOC_CLASSES', 'NO')\n> > +    cdata_internal.set('HIDE_UNDOC_MEMBERS', 'NO')\n> > +    cdata_internal.set('HTML_OUTPUT', 'internal-api-html')\n> > +    cdata_internal.set('INCLUDE_FILE', 'Doxyfile-include-internal')\n> > +    cdata_internal.set('INTERNAL_DOCS', 'YES')\n> > +\n> > +    doxyfile_internal = configure_file(input : 'Doxyfile.in',\n> > +                                       output : 'Doxyfile-internal',\n> > +                                       configuration : cdata_internal)\n> > +\n> > +    internal_doxygen_input = global_doxygen_input\n> > +    internal_doxygen_input += doxyfile_internal\n> > +\n> > +    custom_target('doxygen-internal',\n> > +                  input : internal_doxygen_input,\n> > +                  output : 'internal-api-html',\n> > +                  command : [doxygen, doxyfile_internal],\n> > +                  install : true,\n> > +                  install_dir : doc_install_dir,\n> > +                  install_tag : 'doc-internal')\n> >  endif\n> >\n> >  #\n> > diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\n> > index f24f47de..82277f46 100644\n> > --- a/include/libcamera/base/meson.build\n> > +++ b/include/libcamera/base/meson.build\n> > @@ -38,3 +38,10 @@ libcamera_base_headers = [\n> >\n> >  install_headers(libcamera_base_public_headers,\n> >                  subdir : libcamera_base_include_dir)\n> > +\n> > +foreach lbph : libcamera_base_public_headers\n> > +     doxygen_public_sources += '/'.join(\n> > +             meson.project_source_root(),\n> > +             '@0@'.format(lbph)\n> > +     )\n> > +endforeach\n> > diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build\n> > index 4d59cb2a..4af36884 100644\n> > --- a/include/libcamera/internal/meson.build\n> > +++ b/include/libcamera/internal/meson.build\n> > @@ -58,4 +58,11 @@ libcamera_internal_headers = [\n> >      libcamera_internal_headers_publically_undocumented\n> >  ]\n> >\n> > +foreach lph : libcamera_internal_headers_publically_documented\n\nI think I saw a suggestion somewhere to drop _publically anyway, but\notherwise I think the correct spelling is 'publicly'.\n\n\n> > +     doxygen_public_sources += '/'.join(\n> > +             meson.project_source_root(),\n> > +             '@0@'.format(lph)\n> > +     )\n> > +endforeach\n> > +\n> >  subdir('converter')\n> > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > index bab858a3..25e2f8a4 100644\n> > --- a/include/libcamera/meson.build\n> > +++ b/include/libcamera/meson.build\n> > @@ -26,6 +26,13 @@ subdir('ipa')\n> >  install_headers(libcamera_public_headers,\n> >                  subdir : libcamera_include_dir)\n> >\n> > +foreach lph : libcamera_public_headers\n> > +     doxygen_public_sources += '/'.join(\n> > +             meson.project_source_root(),\n> > +             '@0@'.format(lph)\n> > +     )\n\nI'm surprised meson doesn't have better helpers for this.\nIt might be worth a check through with meson to see if there's a cleaner\nway to handle this. But otherwise, if this is the only way to get the\nfully qualified paths if that's what's needed...\n\n> > +endforeach\n> > +\n> >  #\n> >  # Generate headers from templates.\n> >  #\n> > @@ -85,6 +92,7 @@ foreach mode, entry : controls_map\n> >                                                  '-r', ranges_file, '@INPUT@'],\n> >                                       install : true,\n> >                                       install_dir : libcamera_headers_install_dir)\n> > +    doxygen_public_sources += control_headers.get(-1).full_path()\n\nWhat's going on here? (Why a .get(-1) ?)\n\n> >  endforeach\n> >\n> >  libcamera_public_headers += control_headers\n> > @@ -101,6 +109,7 @@ formats_h = custom_target('formats_h',\n> >                            install : true,\n> >                            install_dir : libcamera_headers_install_dir)\n> >  libcamera_public_headers += formats_h\n> > +doxygen_public_sources += formats_h.full_path()\n> >\n> >  # libcamera.h\n> >  libcamera_h = custom_target('gen-header',\n> > @@ -111,6 +120,7 @@ libcamera_h = custom_target('gen-header',\n> >                              install_dir : libcamera_headers_install_dir)\n> >\n> >  libcamera_public_headers += libcamera_h\n> > +doxygen_public_sources += libcamera_h.full_path()\n> >\n> >  # version.h\n> >  version = libcamera_version.split('.')\n> > diff --git a/meson.build b/meson.build\n> > index e49de4c2..cca1883e 100644\n> > --- a/meson.build\n> > +++ b/meson.build\n> > @@ -231,6 +231,14 @@ endif\n> >  # Utilities are parsed first to provide support for other components.\n> >  subdir('utils')\n> >\n> > +# To support auto-generation of documentation We need an array of the paths to\n> \n> s/We/we\n> \n> > +# public headers and source files so that we can tell doxygen which files to\n> > +# look at later. Unfortunately the inclusion of custom targets in some of the\n> > +# existing arrays precludes using them directly and you cannot generate File\n> > +# objects from generated files, so we need to collect paths to relevant files\n> > +# within an array.\n> > +doxygen_public_sources = []\n\nAha, that might have answered my question above.\n\n> > +\n> >  subdir('include')\n> >  subdir('src')\n> >\n> > diff --git a/src/libcamera/base/class.cpp b/src/libcamera/base/class.cpp\n> > index 9c2d9f21..70fd5cd5 100644\n> > --- a/src/libcamera/base/class.cpp\n> > +++ b/src/libcamera/base/class.cpp\n> > @@ -184,6 +184,7 @@ Extensible::Extensible(std::unique_ptr<Extensible::Private> d)\n> >   */\n> >\n> >  /**\n> > + * \\internal\n> >   * \\class Extensible::Private\n> >   * \\brief Base class for private data managed through a d-pointer\n> >   */\n> > diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\n> > index 523c5885..ae949a51 100644\n> > --- a/src/libcamera/base/meson.build\n> > +++ b/src/libcamera/base/meson.build\n> > @@ -30,6 +30,13 @@ libcamera_base_sources = [\n> >       libcamera_base_internal_sources\n> >  ]\n> >\n> > +foreach lbps : libcamera_base_public_sources\n> > +     doxygen_public_sources += '/'.join(\n> > +             meson.project_source_root(),\n> > +             '@0@'.format(lbps)\n> > +     )\n> > +endforeach\n> > +\n> >  libdw = dependency('libdw', required : false)\n> >  libunwind = dependency('libunwind', required : false)\n> >\n> > diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n> > index 0ad1a4b5..ed46f853 100644\n> > --- a/src/libcamera/camera.cpp\n> > +++ b/src/libcamera/camera.cpp\n> > @@ -560,6 +560,13 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF\n> >   */\n> >\n> >  /**\n> > + * \\internal\n> > + * \\file libcamera\\internal\\camera.h\n> > + * \\brief Internal Camera device handling\n> > + */\n> > +\n> > +/**\n> > + * \\internal\n> >   * \\class Camera::Private\n> >   * \\brief Base class for camera private data\n> >   *\n> > diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n> > index 355f3ada..61d45256 100644\n> > --- a/src/libcamera/camera_manager.cpp\n> > +++ b/src/libcamera/camera_manager.cpp\n> > @@ -23,6 +23,7 @@\n> >   */\n> >\n> >  /**\n> > + * \\internal\n> >   * \\file libcamera/internal/camera_manager.h\n> >   * \\brief Internal camera manager support\n> >   */\n> \n> That's weird, I don't see CameraManager::Private::addCamera() and\n> CameraManager::Private::removeCamera() being documented. It was not\n> documented even before this commit though :/\n> \n> > diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp\n> > index 5a7f3c0b..db450e11 100644\n> > --- a/src/libcamera/framebuffer.cpp\n> > +++ b/src/libcamera/framebuffer.cpp\n> > @@ -16,7 +16,10 @@\n> >  /**\n> >   * \\file libcamera/framebuffer.h\n> >   * \\brief Frame buffer handling\n> > - *\n> > + */\n> > +\n> > +/**\n> > + * \\internal\n> >   * \\file libcamera/internal/framebuffer.h\n> >   * \\brief Internal frame buffer handling support\n> >   */\n> > @@ -105,6 +108,7 @@ LOG_DEFINE_CATEGORY(Buffer)\n> >   */\n> >\n> >  /**\n> > + * \\internal\n> >   * \\class FrameBuffer::Private\n> >   * \\brief Base class for FrameBuffer private data\n> >   *\n> > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> > index 676470c1..413e14db 100644\n> > --- a/src/libcamera/meson.build\n> > +++ b/src/libcamera/meson.build\n> > @@ -59,6 +59,13 @@ libcamera_sources = [\n> >       libcamera_internal_sources\n> >  ]\n> >\n> > +foreach lps : libcamera_public_sources\n> > +     doxygen_public_sources += '/'.join(\n> > +             meson.project_source_root(),\n> > +             '@0@'.format(lps)\n> > +     )\n> > +endforeach\n> > +\n> >  libcamera_sources += libcamera_public_headers\n> >  libcamera_sources += libcamera_generated_ipa_headers\n> >  libcamera_sources += libcamera_tracepoint_header\n> > diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\n> > index 949c556f..930d8c92 100644\n> > --- a/src/libcamera/request.cpp\n> > +++ b/src/libcamera/request.cpp\n> > @@ -33,6 +33,7 @@ namespace libcamera {\n> >  LOG_DEFINE_CATEGORY(Request)\n> >\n> >  /**\n> > + * \\internal\n> >   * \\class Request::Private\n> >   * \\brief Request private data\n> >   *\n> \n> So we should remember to mark every classes that derives a private\n> implementation from Extensible to mark it as \\internal. I think it's\n> fine, and I like the patch  a lot!\n> \n\nLikewise, I suspect we can try to come up with a checkstyle reminder\nsometime.\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> With the few above points clarified\n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> \n> Thanks\n>    j\n> \n> > --\n> > 2.34.1\n> >","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 43971C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  9 Jan 2024 22:08:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4D91862B5E;\n\tTue,  9 Jan 2024 23:08:57 +0100 (CET)","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 038E161D76\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Jan 2024 23:08:55 +0100 (CET)","from pendragon.ideasonboard.com\n\t(aztw-30-b2-v4wan-166917-cust845.vm26.cable.virginm.net\n\t[82.37.23.78])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 771D7922;\n\tTue,  9 Jan 2024 23:07:51 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1704838137;\n\tbh=mOIt+IN7ueUAaYcnvYxU5LW1cveYLwlNptbIEsbAavw=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=PK51wQtITJPcUB20ePinYbxZxhQHjUrqE8xh5icH6MZoJEv1Xb6G+EtXM+0V3GYL9\n\tzXaHXw/sj1148JunEuGHNxH+NcBokxZcowiD/jKLxAaC6TDOttSGkQpPfnTl8CPItE\n\tJXVepfCYc0x5bxQbBKP579+/rGHJR0jlmAIvjk3OIYiJ08hum3OoJ+CJiCrLNYHTVC\n\toZJxSg9tPvyoq0SsG2iykeShV9mW4zeQYlEfmDtzdkZCt3g41N9S2uWKBfhwgm2Vmo\n\tNXU0K+4amJ9ELO0z2Pys6cFF8p0AJI0yxNn2i55yXXh3nrLaUKkxnAsmGZJu9hsKVb\n\t9b4tvn3z8u8dw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1704838071;\n\tbh=mOIt+IN7ueUAaYcnvYxU5LW1cveYLwlNptbIEsbAavw=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=m9O6eELrJ/BGKE6w0fK6nS5iAMLsVG1KTDzPnzfefj4TgNz3fzGSs2L2Cbdj9hRMD\n\tSrQhrUldSNihHNaqwmdsInS88O4OwybiOcAcGn85xXXT70hacBJEIqb4s6tEEoVWcD\n\tcHrIO1wfKpX+0Me2bWiofTK9VaIRFvV4YmzMSURE="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"m9O6eELr\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>","References":"<20240105164104.78398-1-dan.scally@ideasonboard.com>\n\t<20240105164104.78398-5-dan.scally@ideasonboard.com>\n\t<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>","To":"Daniel Scally <dan.scally@ideasonboard.com>,\n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tJacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Date":"Tue, 09 Jan 2024 22:08:53 +0000","Message-ID":"<170483813334.1166171.2088897607589779707@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","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>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28444,"web_url":"https://patchwork.libcamera.org/comment/28444/","msgid":"<6fdea8b0-279b-4d94-9afd-f91df37961fc@ideasonboard.com>","date":"2024-01-10T08:49:26","subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","submitter":{"id":156,"url":"https://patchwork.libcamera.org/api/people/156/","name":"Dan Scally","email":"dan.scally@ideasonboard.com"},"content":"Morning Kieran\n\nOn 09/01/2024 22:08, Kieran Bingham wrote:\n> Quoting Jacopo Mondi via libcamera-devel (2024-01-09 14:28:07)\n>> Hi Dan\n>>    I really like the split!\n>>\n>> On Fri, Jan 05, 2024 at 04:41:03PM +0000, Daniel Scally via libcamera-devel wrote:\n>>> The API reference pages generated by Doxygen are comprehensive, but\n>>> therefore quite overwhelming for application developers who will\n>>> likely never need to use the majority of the library's objects. To\n>>> reduce the complexity of the documentation, split it into two runs of\n>>> doxygen.\n>>>\n>>> In the first run of doxygen we pass a specific list of source files\n>>> to parse, which is built from the File arrays in Meson's build files.\n>>> This ensures that we only generate the documentation for code from\n>>> those files.\n>>>\n>>> In the second run allow doxygen to generate documentation for all of\n>>> the library's objects as it currently does. This set will now be\n>>> output into build/Documentation/internal-api-html.\n>>>\n>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n>>> ---\n>>> Changes in v2:\n>>>\n>>>        - Formatting fixes (Jacopo)\n>>>        - Phraseology (Laurent)\n>>>        - Switched to passing specific files to parse to doxygen rather than\n>>>          relying on \\internal to remove other docu-comments.\n>>>\n>>>   Documentation/Doxyfile-internal.in     | 21 +++++++\n>>>   Documentation/Doxyfile-public.in       |  5 ++\n>>>   Documentation/Doxyfile.in              | 26 ++-------\n>>>   Documentation/meson.build              | 76 +++++++++++++++++++++++---\n>>>   include/libcamera/base/meson.build     |  7 +++\n>>>   include/libcamera/internal/meson.build |  7 +++\n>>>   include/libcamera/meson.build          | 10 ++++\n>>>   meson.build                            |  8 +++\n>>>   src/libcamera/base/class.cpp           |  1 +\n>>>   src/libcamera/base/meson.build         |  7 +++\n>>>   src/libcamera/camera.cpp               |  7 +++\n>>>   src/libcamera/camera_manager.cpp       |  1 +\n>>>   src/libcamera/framebuffer.cpp          |  6 +-\n>>>   src/libcamera/meson.build              |  7 +++\n>>>   src/libcamera/request.cpp              |  1 +\n>>>   15 files changed, 160 insertions(+), 30 deletions(-)\n>>>   create mode 100644 Documentation/Doxyfile-internal.in\n>>>   create mode 100644 Documentation/Doxyfile-public.in\n>>>\n>>> diff --git a/Documentation/Doxyfile-internal.in b/Documentation/Doxyfile-internal.in\n>>> new file mode 100644\n>>> index 00000000..7b3cce49\n>>> --- /dev/null\n>>> +++ b/Documentation/Doxyfile-internal.in\n>>> @@ -0,0 +1,21 @@\n>>> +# SPDX-License-Identifier: CC-BY-SA-4.0\n>>> +\n>>> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n>>> +                         \"@TOP_SRCDIR@/include/libcamera\" \\\n>>> +                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n>>> +                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n>>> +                         \"@TOP_SRCDIR@/src/libcamera\" \\\n>>> +                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n>>> +                         \"@TOP_BUILDDIR@/src/libcamera\"\n>>> +\n>>> +EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n>> I'm still a bit puzzled on why we don't document Span<>, but this was\n>> already here\n> Presumably this is expected to be covered by the C++ definition of a\n> Span. It's supposed to be a 'like for like' implementation. (or as close\n> as possible I think).\n>\n> Perhaps somewhere we should document that fact. In the 'long future'\n> (when we can support C++20 - I would expect we'd convert to use\n> std::span in place of libcamera::Span.\n>\n>>> +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n>>> +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n>>> +                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n>>> +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n>>> +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n>>> +                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n>>> +                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n>>> +                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n>>> +                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n>>> +                         @TOP_BUILDDIR@/src/libcamera/proxy/\n>>> diff --git a/Documentation/Doxyfile-public.in b/Documentation/Doxyfile-public.in\n>>> new file mode 100644\n>>> index 00000000..cdbc03a0\n>>> --- /dev/null\n>>> +++ b/Documentation/Doxyfile-public.in\n>>> @@ -0,0 +1,5 @@\n>>> +# SPDX-License-Identifier: CC-BY-SA-4.0\n>>> +\n>>> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n>>> +                         \"@INPUT@\" \\\n>>> +                         \"@TOP_BUILDDIR@/src/libcamera/version.cpp\"\n>>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n>>> index 48fea8bc..a271c7bc 100644\n>>> --- a/Documentation/Doxyfile.in\n>>> +++ b/Documentation/Doxyfile.in\n>>> @@ -21,14 +21,6 @@ CASE_SENSE_NAMES       = YES\n>>>\n>>>   QUIET                  = YES\n>>>\n>>> -INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n>>> -                         \"@TOP_SRCDIR@/include/libcamera\" \\\n>>> -                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n>>> -                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n>>> -                         \"@TOP_SRCDIR@/src/libcamera\" \\\n>>> -                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n>>> -                         \"@TOP_BUILDDIR@/src/libcamera\"\n>>> -\n>>>   FILE_PATTERNS          = *.c \\\n>>>                            *.cpp \\\n>>>                            *.h \\\n>>> @@ -36,17 +28,8 @@ FILE_PATTERNS          = *.c \\\n>>>\n>>>   RECURSIVE              = YES\n>>>\n>>> -EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n>>> -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n>>> -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n>>> -                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n>>> -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n>>> -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n>>> -                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n>>> -                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n>>> -                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n>>> -                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n>>> -                         @TOP_BUILDDIR@/src/libcamera/proxy/\n>>> +@INCLUDE_PATH          = @TOP_BUILDDIR@/Documentation\n>>> +@INCLUDE               = @INCLUDE_FILE@\n>>>\n>>>   EXCLUDE_PATTERNS       = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \\\n>>>                            @TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \\\n>>> @@ -70,7 +53,10 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n>>>\n>>>   EXCLUDE_SYMLINKS       = YES\n>>>\n>>> -HTML_OUTPUT            = api-html\n>>> +HIDE_UNDOC_CLASSES     = @HIDE_UNDOC_CLASSES@\n>>> +HIDE_UNDOC_MEMBERS     = @HIDE_UNDOC_MEMBERS@\n>>> +HTML_OUTPUT            = @HTML_OUTPUT@\n>>> +INTERNAL_DOCS          = @INTERNAL_DOCS@\n>>>\n>>>   GENERATE_LATEX         = NO\n>>>\n>>> diff --git a/Documentation/meson.build b/Documentation/meson.build\n>>> index 7a58fec8..afaad751 100644\n>>> --- a/Documentation/meson.build\n>>> +++ b/Documentation/meson.build\n>>> @@ -23,12 +23,7 @@ if doxygen.found() and dot.found()\n>>>\n>>>       cdata.set('PREDEFINED', ' \\\\\\n\\t\\t\\t '.join(doxygen_predefined))\n>>>\n>>> -    doxyfile = configure_file(input : 'Doxyfile.in',\n>>> -                              output : 'Doxyfile',\n>>> -                              configuration : cdata)\n>>> -\n>>> -    doxygen_input = [\n>>> -        doxyfile,\n>>> +    global_doxygen_input = [\n>>>           libcamera_base_headers,\n>>>           libcamera_base_sources,\n>>>           libcamera_internal_headers,\n>>> @@ -41,16 +36,79 @@ if doxygen.found() and dot.found()\n>>>       ]\n>>>\n>>>       if is_variable('ipu3_ipa_sources')\n>>> -        doxygen_input += [ipu3_ipa_sources]\n>>> +        global_doxygen_input += [ipu3_ipa_sources]\n>>>       endif\n>>>\n>>> +    # We need to generate two \"include\" files for the final Doxyfile which\n>>> +    # define a set of source files to use in the documentation parsing. We\n>>> +    # collected a list of the public sources in doxygen_public_sources, so we\n>>> +    # pass that to the doxyfiles so that Doxyfile-public refers only to those\n>>> +    # files. Although INPUT is sent to both, Doxyfile-internal.in doesn't refer\n>>> +    # to it and just hardcodes the directories to parse.\n>> Thanks, this is quite clear now!\n>>\n>>> +    cdata.set('INPUT', '\" \\\\\\n\\t\\t\\t \"'.join(doxygen_public_sources))\n>>> +    doxyfile_include_public = configure_file(input : 'Doxyfile-public.in',\n>>> +                                             output : 'Doxyfile-include-public',\n>>> +                                             configuration : cdata)\n>>> +    doxyfile_include_internal = configure_file(input : 'Doxyfile-internal.in',\n>>> +                                               output : 'Doxyfile-include-internal',\n>>> +                                               configuration : cdata)\n>>> +\n>>> +    # We run doxygen twice - the first run excludes internal API objects as it\n>>> +    # is intended to document the public API only. A second run covers all of\n>>> +    # the library's objects for libcamera developers. To achieve this we need to\n>>> +    # flag as \\internal some of the comments for objects which we wish to hide,\n>>> +    # and remove the auto generated documents via HIDE_UNDOC_CLASSES and\n>>> +    # HIDE_UNDOC_MEMBERS.\n>>> +\n>>> +    cdata_public = configuration_data()\n>>> +    cdata_public.merge_from(cdata)\n>>> +    cdata_public.set('HIDE_UNDOC_CLASSES', 'YES')\n>>> +    cdata_public.set('HIDE_UNDOC_MEMBERS', 'YES')\n>>> +    cdata_public.set('HTML_OUTPUT', 'api-html')\n>>> +    cdata_public.set('INCLUDE_FILE', 'Doxyfile-include-public')\n>>> +    cdata_public.set('INTERNAL_DOCS', 'NO')\n>>> +\n>>> +    doxyfile_public = configure_file(input : 'Doxyfile.in',\n>>> +                                     output : 'Doxyfile-public',\n>>> +                                     configuration : cdata_public)\n>>> +\n>>> +    public_doxygen_input = global_doxygen_input\n>>> +    public_doxygen_input += doxyfile_public\n>>> +\n>>>       custom_target('doxygen',\n>>> -                  input : doxygen_input,\n>>> +                  input : public_doxygen_input,\n>>>                     output : 'api-html',\n>>> -                  command : [doxygen, doxyfile],\n>>> +                  command : [doxygen, doxyfile_public],\n>>>                     install : true,\n>>>                     install_dir : doc_install_dir,\n>>>                     install_tag : 'doc')\n>>> +\n>>> +    # This is the internal documentation, so _don't_ hide undocumented classes\n>>> +    # as we want everything to show up and warnings to be generated if any\n>>> +    # documentation is missing.\n>>> +\n>>> +    cdata_internal = configuration_data()\n>>> +    cdata_internal.merge_from(cdata)\n>>> +    cdata_internal.set('HIDE_UNDOC_CLASSES', 'NO')\n>>> +    cdata_internal.set('HIDE_UNDOC_MEMBERS', 'NO')\n>>> +    cdata_internal.set('HTML_OUTPUT', 'internal-api-html')\n>>> +    cdata_internal.set('INCLUDE_FILE', 'Doxyfile-include-internal')\n>>> +    cdata_internal.set('INTERNAL_DOCS', 'YES')\n>>> +\n>>> +    doxyfile_internal = configure_file(input : 'Doxyfile.in',\n>>> +                                       output : 'Doxyfile-internal',\n>>> +                                       configuration : cdata_internal)\n>>> +\n>>> +    internal_doxygen_input = global_doxygen_input\n>>> +    internal_doxygen_input += doxyfile_internal\n>>> +\n>>> +    custom_target('doxygen-internal',\n>>> +                  input : internal_doxygen_input,\n>>> +                  output : 'internal-api-html',\n>>> +                  command : [doxygen, doxyfile_internal],\n>>> +                  install : true,\n>>> +                  install_dir : doc_install_dir,\n>>> +                  install_tag : 'doc-internal')\n>>>   endif\n>>>\n>>>   #\n>>> diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\n>>> index f24f47de..82277f46 100644\n>>> --- a/include/libcamera/base/meson.build\n>>> +++ b/include/libcamera/base/meson.build\n>>> @@ -38,3 +38,10 @@ libcamera_base_headers = [\n>>>\n>>>   install_headers(libcamera_base_public_headers,\n>>>                   subdir : libcamera_base_include_dir)\n>>> +\n>>> +foreach lbph : libcamera_base_public_headers\n>>> +     doxygen_public_sources += '/'.join(\n>>> +             meson.project_source_root(),\n>>> +             '@0@'.format(lbph)\n>>> +     )\n>>> +endforeach\n>>> diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build\n>>> index 4d59cb2a..4af36884 100644\n>>> --- a/include/libcamera/internal/meson.build\n>>> +++ b/include/libcamera/internal/meson.build\n>>> @@ -58,4 +58,11 @@ libcamera_internal_headers = [\n>>>       libcamera_internal_headers_publically_undocumented\n>>>   ]\n>>>\n>>> +foreach lph : libcamera_internal_headers_publically_documented\n> I think I saw a suggestion somewhere to drop _publically anyway, but\n> otherwise I think the correct spelling is 'publicly'.\nDerp - thanks!\n>\n>>> +     doxygen_public_sources += '/'.join(\n>>> +             meson.project_source_root(),\n>>> +             '@0@'.format(lph)\n>>> +     )\n>>> +endforeach\n>>> +\n>>>   subdir('converter')\n>>> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n>>> index bab858a3..25e2f8a4 100644\n>>> --- a/include/libcamera/meson.build\n>>> +++ b/include/libcamera/meson.build\n>>> @@ -26,6 +26,13 @@ subdir('ipa')\n>>>   install_headers(libcamera_public_headers,\n>>>                   subdir : libcamera_include_dir)\n>>>\n>>> +foreach lph : libcamera_public_headers\n>>> +     doxygen_public_sources += '/'.join(\n>>> +             meson.project_source_root(),\n>>> +             '@0@'.format(lph)\n>>> +     )\n> I'm surprised meson doesn't have better helpers for this.\n> It might be worth a check through with meson to see if there's a cleaner\n> way to handle this. But otherwise, if this is the only way to get the\n> fully qualified paths if that's what's needed...\n\n\nIt does; File.full_path() [1], but the problem is that it wasn't added until Meson 1.4.0 and Laurent \nwas concerned that's too recent - quite reasonably, apparently, since my Ubuntu meson package only \ngives me 0.61.2. This method is apparently available back to 0.54.0\n\n\n[1] https://mesonbuild.com/Reference-manual_returned_file.html\n\n>\n>>> +endforeach\n>>> +\n>>>   #\n>>>   # Generate headers from templates.\n>>>   #\n>>> @@ -85,6 +92,7 @@ foreach mode, entry : controls_map\n>>>                                                   '-r', ranges_file, '@INPUT@'],\n>>>                                        install : true,\n>>>                                        install_dir : libcamera_headers_install_dir)\n>>> +    doxygen_public_sources += control_headers.get(-1).full_path()\n> What's going on here? (Why a .get(-1) ?)\n\n\nWe're within a foreach loop that adds a CustomTarget to the control_headers array, but doesn't \ncreate a new variable for it, so to use it I'm just fetching the last entry from the array. A fuller \ncontext for that change would be:\n\n\n     control_headers += custom_target(header + '_h',\n                                      input : input_files,\n                                      output : outfile,\n                                      command : [gen_controls, '-o', '@OUTPUT@',\n                                                 '--mode', mode, '-t', template_file,\n                                                 '-r', ranges_file, '@INPUT@'],\n                                      install : true,\n                                      install_dir : libcamera_headers_install_dir)\n     doxygen_public_sources += control_headers.get(-1).full_path()\n\n\nAlternatively I could create a local variable for the custom target and use that, like so:\n\n\n     ct = custom_target(header + '_h',\n                        input : input_files,\n                        output : outfile,\n                        command : [gen_controls, '-o', '@OUTPUT@',\n                                   '--mode', mode, '-t', template_file,\n                                   '-r', ranges_file, '@INPUT@'],\n                        install : true,\n                        install_dir : libcamera_headers_install_dir)\n     control_headers += ct\n     doxygen_public_sources += ct.full_path()\n\n\nBut it didn't seem worth it.\n\n\n\n>\n>>>   endforeach\n>>>\n>>>   libcamera_public_headers += control_headers\n>>> @@ -101,6 +109,7 @@ formats_h = custom_target('formats_h',\n>>>                             install : true,\n>>>                             install_dir : libcamera_headers_install_dir)\n>>>   libcamera_public_headers += formats_h\n>>> +doxygen_public_sources += formats_h.full_path()\n>>>\n>>>   # libcamera.h\n>>>   libcamera_h = custom_target('gen-header',\n>>> @@ -111,6 +120,7 @@ libcamera_h = custom_target('gen-header',\n>>>                               install_dir : libcamera_headers_install_dir)\n>>>\n>>>   libcamera_public_headers += libcamera_h\n>>> +doxygen_public_sources += libcamera_h.full_path()\n>>>\n>>>   # version.h\n>>>   version = libcamera_version.split('.')\n>>> diff --git a/meson.build b/meson.build\n>>> index e49de4c2..cca1883e 100644\n>>> --- a/meson.build\n>>> +++ b/meson.build\n>>> @@ -231,6 +231,14 @@ endif\n>>>   # Utilities are parsed first to provide support for other components.\n>>>   subdir('utils')\n>>>\n>>> +# To support auto-generation of documentation We need an array of the paths to\n>> s/We/we\n>>\n>>> +# public headers and source files so that we can tell doxygen which files to\n>>> +# look at later. Unfortunately the inclusion of custom targets in some of the\n>>> +# existing arrays precludes using them directly and you cannot generate File\n>>> +# objects from generated files, so we need to collect paths to relevant files\n>>> +# within an array.\n>>> +doxygen_public_sources = []\n> Aha, that might have answered my question above.\n>\n>>> +\n>>>   subdir('include')\n>>>   subdir('src')\n>>>\n>>> diff --git a/src/libcamera/base/class.cpp b/src/libcamera/base/class.cpp\n>>> index 9c2d9f21..70fd5cd5 100644\n>>> --- a/src/libcamera/base/class.cpp\n>>> +++ b/src/libcamera/base/class.cpp\n>>> @@ -184,6 +184,7 @@ Extensible::Extensible(std::unique_ptr<Extensible::Private> d)\n>>>    */\n>>>\n>>>   /**\n>>> + * \\internal\n>>>    * \\class Extensible::Private\n>>>    * \\brief Base class for private data managed through a d-pointer\n>>>    */\n>>> diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\n>>> index 523c5885..ae949a51 100644\n>>> --- a/src/libcamera/base/meson.build\n>>> +++ b/src/libcamera/base/meson.build\n>>> @@ -30,6 +30,13 @@ libcamera_base_sources = [\n>>>        libcamera_base_internal_sources\n>>>   ]\n>>>\n>>> +foreach lbps : libcamera_base_public_sources\n>>> +     doxygen_public_sources += '/'.join(\n>>> +             meson.project_source_root(),\n>>> +             '@0@'.format(lbps)\n>>> +     )\n>>> +endforeach\n>>> +\n>>>   libdw = dependency('libdw', required : false)\n>>>   libunwind = dependency('libunwind', required : false)\n>>>\n>>> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n>>> index 0ad1a4b5..ed46f853 100644\n>>> --- a/src/libcamera/camera.cpp\n>>> +++ b/src/libcamera/camera.cpp\n>>> @@ -560,6 +560,13 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF\n>>>    */\n>>>\n>>>   /**\n>>> + * \\internal\n>>> + * \\file libcamera\\internal\\camera.h\n>>> + * \\brief Internal Camera device handling\n>>> + */\n>>> +\n>>> +/**\n>>> + * \\internal\n>>>    * \\class Camera::Private\n>>>    * \\brief Base class for camera private data\n>>>    *\n>>> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n>>> index 355f3ada..61d45256 100644\n>>> --- a/src/libcamera/camera_manager.cpp\n>>> +++ b/src/libcamera/camera_manager.cpp\n>>> @@ -23,6 +23,7 @@\n>>>    */\n>>>\n>>>   /**\n>>> + * \\internal\n>>>    * \\file libcamera/internal/camera_manager.h\n>>>    * \\brief Internal camera manager support\n>>>    */\n>> That's weird, I don't see CameraManager::Private::addCamera() and\n>> CameraManager::Private::removeCamera() being documented. It was not\n>> documented even before this commit though :/\n>>\n>>> diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp\n>>> index 5a7f3c0b..db450e11 100644\n>>> --- a/src/libcamera/framebuffer.cpp\n>>> +++ b/src/libcamera/framebuffer.cpp\n>>> @@ -16,7 +16,10 @@\n>>>   /**\n>>>    * \\file libcamera/framebuffer.h\n>>>    * \\brief Frame buffer handling\n>>> - *\n>>> + */\n>>> +\n>>> +/**\n>>> + * \\internal\n>>>    * \\file libcamera/internal/framebuffer.h\n>>>    * \\brief Internal frame buffer handling support\n>>>    */\n>>> @@ -105,6 +108,7 @@ LOG_DEFINE_CATEGORY(Buffer)\n>>>    */\n>>>\n>>>   /**\n>>> + * \\internal\n>>>    * \\class FrameBuffer::Private\n>>>    * \\brief Base class for FrameBuffer private data\n>>>    *\n>>> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n>>> index 676470c1..413e14db 100644\n>>> --- a/src/libcamera/meson.build\n>>> +++ b/src/libcamera/meson.build\n>>> @@ -59,6 +59,13 @@ libcamera_sources = [\n>>>        libcamera_internal_sources\n>>>   ]\n>>>\n>>> +foreach lps : libcamera_public_sources\n>>> +     doxygen_public_sources += '/'.join(\n>>> +             meson.project_source_root(),\n>>> +             '@0@'.format(lps)\n>>> +     )\n>>> +endforeach\n>>> +\n>>>   libcamera_sources += libcamera_public_headers\n>>>   libcamera_sources += libcamera_generated_ipa_headers\n>>>   libcamera_sources += libcamera_tracepoint_header\n>>> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\n>>> index 949c556f..930d8c92 100644\n>>> --- a/src/libcamera/request.cpp\n>>> +++ b/src/libcamera/request.cpp\n>>> @@ -33,6 +33,7 @@ namespace libcamera {\n>>>   LOG_DEFINE_CATEGORY(Request)\n>>>\n>>>   /**\n>>> + * \\internal\n>>>    * \\class Request::Private\n>>>    * \\brief Request private data\n>>>    *\n>> So we should remember to mark every classes that derives a private\n>> implementation from Extensible to mark it as \\internal. I think it's\n>> fine, and I like the patch  a lot!\n>>\n> Likewise, I suspect we can try to come up with a checkstyle reminder\n> sometime.\nYeah I was going to take a look at that when time allowed\n>\n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n\nThanks!\n\n>\n>> With the few above points clarified\n>> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>>\n>> Thanks\n>>     j\n>>\n>>> --\n>>> 2.34.1\n>>>","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 3E1FDBEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 10 Jan 2024 08:49:31 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 93F6562B5F;\n\tWed, 10 Jan 2024 09:49:30 +0100 (CET)","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 0648261D5B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 10 Jan 2024 09:49:29 +0100 (CET)","from [192.168.0.43]\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 3427EC67;\n\tWed, 10 Jan 2024 09:48:25 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1704876570;\n\tbh=8StU50sBWDWW19OdO05ZzgYygYvX1abR4APUVCijlwU=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=i+VYNjzCc8L/ZBXCxhkU7XbC283ccsSAgz4DlVSksw47Em5wqS2Qo/xaEHkuIlUuA\n\twDuff3AXueSLyuXUXDXcWGmBGGQzt/NUrecNLCtz5x85VlAC9fvrIjSS3ywJ7aJhH7\n\tqsk4HtWmxhDAkp3xE1WUkfHNAlFobTT/XSNHwCa/KzvJ1/Sh6ZSP9WD6PEHwqfi311\n\t+eeJPZbUEUBh2fBjVg5WKFHBhyxFJu60XhBUMFaJ6R34V3hyTV3x4xWTU9YRj7SaEn\n\tzvutwADxgjYi+Ul9rxSVhhcGJ/C3BXgxNt04/161/hMDE9qnVsDge6hM2DBrKubwKY\n\tWbSpL/aufGRWw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1704876505;\n\tbh=8StU50sBWDWW19OdO05ZzgYygYvX1abR4APUVCijlwU=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=U+5WOTGslS11dixG2eaAQHbX4WtivWSl0oSdjOD7Nu6JJgvy8bDp0ndeiNBAcRnOw\n\t2oiYBPu4F6zxJa0SLA5zccuQDTdie1k8InN6E6MlaWpCU9JUnPxhzoeXiKftCBp4gT\n\tOVtZBK+E98Yv92Ixa5zdBAcImodTzbyp2rv+Lhl0="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"U+5WOTGs\"; dkim-atps=neutral","Message-ID":"<6fdea8b0-279b-4d94-9afd-f91df37961fc@ideasonboard.com>","Date":"Wed, 10 Jan 2024 08:49:26 +0000","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Content-Language":"en-US","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tJacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","References":"<20240105164104.78398-1-dan.scally@ideasonboard.com>\n\t<20240105164104.78398-5-dan.scally@ideasonboard.com>\n\t<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>\n\t<170483813334.1166171.2088897607589779707@ping.linuxembedded.co.uk>","Autocrypt":"addr=dan.scally@ideasonboard.com; keydata=\n\t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","In-Reply-To":"<170483813334.1166171.2088897607589779707@ping.linuxembedded.co.uk>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","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>","From":"Dan Scally via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Dan Scally <dan.scally@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28449,"web_url":"https://patchwork.libcamera.org/comment/28449/","msgid":"<83d94802-c9fd-47bb-ac28-b0488b1581f9@ideasonboard.com>","date":"2024-01-12T10:57:45","subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","submitter":{"id":156,"url":"https://patchwork.libcamera.org/api/people/156/","name":"Dan Scally","email":"dan.scally@ideasonboard.com"},"content":"Hi Jacopo\n\nOn 09/01/2024 14:28, Jacopo Mondi wrote:\n> Hi Dan\n>    I really like the split!\n>\n> On Fri, Jan 05, 2024 at 04:41:03PM +0000, Daniel Scally via libcamera-devel wrote:\n>> The API reference pages generated by Doxygen are comprehensive, but\n>> therefore quite overwhelming for application developers who will\n>> likely never need to use the majority of the library's objects. To\n>> reduce the complexity of the documentation, split it into two runs of\n>> doxygen.\n>>\n>> In the first run of doxygen we pass a specific list of source files\n>> to parse, which is built from the File arrays in Meson's build files.\n>> This ensures that we only generate the documentation for code from\n>> those files.\n>>\n>> In the second run allow doxygen to generate documentation for all of\n>> the library's objects as it currently does. This set will now be\n>> output into build/Documentation/internal-api-html.\n>>\n>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n>> ---\n>> Changes in v2:\n>>\n>> \t- Formatting fixes (Jacopo)\n>> \t- Phraseology (Laurent)\n>> \t- Switched to passing specific files to parse to doxygen rather than\n>> \t  relying on \\internal to remove other docu-comments.\n>>\n>>   Documentation/Doxyfile-internal.in     | 21 +++++++\n>>   Documentation/Doxyfile-public.in       |  5 ++\n>>   Documentation/Doxyfile.in              | 26 ++-------\n>>   Documentation/meson.build              | 76 +++++++++++++++++++++++---\n>>   include/libcamera/base/meson.build     |  7 +++\n>>   include/libcamera/internal/meson.build |  7 +++\n>>   include/libcamera/meson.build          | 10 ++++\n>>   meson.build                            |  8 +++\n>>   src/libcamera/base/class.cpp           |  1 +\n>>   src/libcamera/base/meson.build         |  7 +++\n>>   src/libcamera/camera.cpp               |  7 +++\n>>   src/libcamera/camera_manager.cpp       |  1 +\n>>   src/libcamera/framebuffer.cpp          |  6 +-\n>>   src/libcamera/meson.build              |  7 +++\n>>   src/libcamera/request.cpp              |  1 +\n>>   15 files changed, 160 insertions(+), 30 deletions(-)\n>>   create mode 100644 Documentation/Doxyfile-internal.in\n>>   create mode 100644 Documentation/Doxyfile-public.in\n>>\n>> diff --git a/Documentation/Doxyfile-internal.in b/Documentation/Doxyfile-internal.in\n>> new file mode 100644\n>> index 00000000..7b3cce49\n>> --- /dev/null\n>> +++ b/Documentation/Doxyfile-internal.in\n>> @@ -0,0 +1,21 @@\n>> +# SPDX-License-Identifier: CC-BY-SA-4.0\n>> +\n>> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n>> +                         \"@TOP_SRCDIR@/include/libcamera\" \\\n>> +                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n>> +                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n>> +                         \"@TOP_SRCDIR@/src/libcamera\" \\\n>> +                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n>> +                         \"@TOP_BUILDDIR@/src/libcamera\"\n>> +\n>> +EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n> I'm still a bit puzzled on why we don't document Span<>, but this was\n> already here\n>\n>> +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n>> +                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n>> +                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n>> +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n>> +                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n>> +                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n>> +                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n>> +                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n>> +                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n>> +                         @TOP_BUILDDIR@/src/libcamera/proxy/\n>> diff --git a/Documentation/Doxyfile-public.in b/Documentation/Doxyfile-public.in\n>> new file mode 100644\n>> index 00000000..cdbc03a0\n>> --- /dev/null\n>> +++ b/Documentation/Doxyfile-public.in\n>> @@ -0,0 +1,5 @@\n>> +# SPDX-License-Identifier: CC-BY-SA-4.0\n>> +\n>> +INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n>> +                         \"@INPUT@\" \\\n>> +                         \"@TOP_BUILDDIR@/src/libcamera/version.cpp\"\n>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n>> index 48fea8bc..a271c7bc 100644\n>> --- a/Documentation/Doxyfile.in\n>> +++ b/Documentation/Doxyfile.in\n>> @@ -21,14 +21,6 @@ CASE_SENSE_NAMES       = YES\n>>\n>>   QUIET                  = YES\n>>\n>> -INPUT                  = \"@TOP_SRCDIR@/Documentation\" \\\n>> -                         \"@TOP_SRCDIR@/include/libcamera\" \\\n>> -                         \"@TOP_SRCDIR@/src/ipa/ipu3\" \\\n>> -                         \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n>> -                         \"@TOP_SRCDIR@/src/libcamera\" \\\n>> -                         \"@TOP_BUILDDIR@/include/libcamera\" \\\n>> -                         \"@TOP_BUILDDIR@/src/libcamera\"\n>> -\n>>   FILE_PATTERNS          = *.c \\\n>>                            *.cpp \\\n>>                            *.h \\\n>> @@ -36,17 +28,8 @@ FILE_PATTERNS          = *.c \\\n>>\n>>   RECURSIVE              = YES\n>>\n>> -EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \\\n>> -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_sysfs.h \\\n>> -                         @TOP_SRCDIR@/include/libcamera/internal/device_enumerator_udev.h \\\n>> -                         @TOP_SRCDIR@/include/libcamera/internal/ipc_pipe_unixsocket.h \\\n>> -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \\\n>> -                         @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \\\n>> -                         @TOP_SRCDIR@/src/libcamera/ipc_pipe_unixsocket.cpp \\\n>> -                         @TOP_SRCDIR@/src/libcamera/pipeline/ \\\n>> -                         @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \\\n>> -                         @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \\\n>> -                         @TOP_BUILDDIR@/src/libcamera/proxy/\n>> +@INCLUDE_PATH          = @TOP_BUILDDIR@/Documentation\n>> +@INCLUDE               = @INCLUDE_FILE@\n>>\n>>   EXCLUDE_PATTERNS       = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \\\n>>                            @TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \\\n>> @@ -70,7 +53,10 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n>>\n>>   EXCLUDE_SYMLINKS       = YES\n>>\n>> -HTML_OUTPUT            = api-html\n>> +HIDE_UNDOC_CLASSES     = @HIDE_UNDOC_CLASSES@\n>> +HIDE_UNDOC_MEMBERS     = @HIDE_UNDOC_MEMBERS@\n>> +HTML_OUTPUT            = @HTML_OUTPUT@\n>> +INTERNAL_DOCS          = @INTERNAL_DOCS@\n>>\n>>   GENERATE_LATEX         = NO\n>>\n>> diff --git a/Documentation/meson.build b/Documentation/meson.build\n>> index 7a58fec8..afaad751 100644\n>> --- a/Documentation/meson.build\n>> +++ b/Documentation/meson.build\n>> @@ -23,12 +23,7 @@ if doxygen.found() and dot.found()\n>>\n>>       cdata.set('PREDEFINED', ' \\\\\\n\\t\\t\\t '.join(doxygen_predefined))\n>>\n>> -    doxyfile = configure_file(input : 'Doxyfile.in',\n>> -                              output : 'Doxyfile',\n>> -                              configuration : cdata)\n>> -\n>> -    doxygen_input = [\n>> -        doxyfile,\n>> +    global_doxygen_input = [\n>>           libcamera_base_headers,\n>>           libcamera_base_sources,\n>>           libcamera_internal_headers,\n>> @@ -41,16 +36,79 @@ if doxygen.found() and dot.found()\n>>       ]\n>>\n>>       if is_variable('ipu3_ipa_sources')\n>> -        doxygen_input += [ipu3_ipa_sources]\n>> +        global_doxygen_input += [ipu3_ipa_sources]\n>>       endif\n>>\n>> +    # We need to generate two \"include\" files for the final Doxyfile which\n>> +    # define a set of source files to use in the documentation parsing. We\n>> +    # collected a list of the public sources in doxygen_public_sources, so we\n>> +    # pass that to the doxyfiles so that Doxyfile-public refers only to those\n>> +    # files. Although INPUT is sent to both, Doxyfile-internal.in doesn't refer\n>> +    # to it and just hardcodes the directories to parse.\n> Thanks, this is quite clear now!\n>\n>> +    cdata.set('INPUT', '\" \\\\\\n\\t\\t\\t \"'.join(doxygen_public_sources))\n>> +    doxyfile_include_public = configure_file(input : 'Doxyfile-public.in',\n>> +                                             output : 'Doxyfile-include-public',\n>> +                                             configuration : cdata)\n>> +    doxyfile_include_internal = configure_file(input : 'Doxyfile-internal.in',\n>> +                                               output : 'Doxyfile-include-internal',\n>> +                                               configuration : cdata)\n>> +\n>> +    # We run doxygen twice - the first run excludes internal API objects as it\n>> +    # is intended to document the public API only. A second run covers all of\n>> +    # the library's objects for libcamera developers. To achieve this we need to\n>> +    # flag as \\internal some of the comments for objects which we wish to hide,\n>> +    # and remove the auto generated documents via HIDE_UNDOC_CLASSES and\n>> +    # HIDE_UNDOC_MEMBERS.\n>> +\n>> +    cdata_public = configuration_data()\n>> +    cdata_public.merge_from(cdata)\n>> +    cdata_public.set('HIDE_UNDOC_CLASSES', 'YES')\n>> +    cdata_public.set('HIDE_UNDOC_MEMBERS', 'YES')\n>> +    cdata_public.set('HTML_OUTPUT', 'api-html')\n>> +    cdata_public.set('INCLUDE_FILE', 'Doxyfile-include-public')\n>> +    cdata_public.set('INTERNAL_DOCS', 'NO')\n>> +\n>> +    doxyfile_public = configure_file(input : 'Doxyfile.in',\n>> +                                     output : 'Doxyfile-public',\n>> +                                     configuration : cdata_public)\n>> +\n>> +    public_doxygen_input = global_doxygen_input\n>> +    public_doxygen_input += doxyfile_public\n>> +\n>>       custom_target('doxygen',\n>> -                  input : doxygen_input,\n>> +                  input : public_doxygen_input,\n>>                     output : 'api-html',\n>> -                  command : [doxygen, doxyfile],\n>> +                  command : [doxygen, doxyfile_public],\n>>                     install : true,\n>>                     install_dir : doc_install_dir,\n>>                     install_tag : 'doc')\n>> +\n>> +    # This is the internal documentation, so _don't_ hide undocumented classes\n>> +    # as we want everything to show up and warnings to be generated if any\n>> +    # documentation is missing.\n>> +\n>> +    cdata_internal = configuration_data()\n>> +    cdata_internal.merge_from(cdata)\n>> +    cdata_internal.set('HIDE_UNDOC_CLASSES', 'NO')\n>> +    cdata_internal.set('HIDE_UNDOC_MEMBERS', 'NO')\n>> +    cdata_internal.set('HTML_OUTPUT', 'internal-api-html')\n>> +    cdata_internal.set('INCLUDE_FILE', 'Doxyfile-include-internal')\n>> +    cdata_internal.set('INTERNAL_DOCS', 'YES')\n>> +\n>> +    doxyfile_internal = configure_file(input : 'Doxyfile.in',\n>> +                                       output : 'Doxyfile-internal',\n>> +                                       configuration : cdata_internal)\n>> +\n>> +    internal_doxygen_input = global_doxygen_input\n>> +    internal_doxygen_input += doxyfile_internal\n>> +\n>> +    custom_target('doxygen-internal',\n>> +                  input : internal_doxygen_input,\n>> +                  output : 'internal-api-html',\n>> +                  command : [doxygen, doxyfile_internal],\n>> +                  install : true,\n>> +                  install_dir : doc_install_dir,\n>> +                  install_tag : 'doc-internal')\n>>   endif\n>>\n>>   #\n>> diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\n>> index f24f47de..82277f46 100644\n>> --- a/include/libcamera/base/meson.build\n>> +++ b/include/libcamera/base/meson.build\n>> @@ -38,3 +38,10 @@ libcamera_base_headers = [\n>>\n>>   install_headers(libcamera_base_public_headers,\n>>                   subdir : libcamera_base_include_dir)\n>> +\n>> +foreach lbph : libcamera_base_public_headers\n>> +\tdoxygen_public_sources += '/'.join(\n>> +\t\tmeson.project_source_root(),\n>> +\t\t'@0@'.format(lbph)\n>> +\t)\n>> +endforeach\n>> diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build\n>> index 4d59cb2a..4af36884 100644\n>> --- a/include/libcamera/internal/meson.build\n>> +++ b/include/libcamera/internal/meson.build\n>> @@ -58,4 +58,11 @@ libcamera_internal_headers = [\n>>       libcamera_internal_headers_publically_undocumented\n>>   ]\n>>\n>> +foreach lph : libcamera_internal_headers_publically_documented\n>> +\tdoxygen_public_sources += '/'.join(\n>> +\t\tmeson.project_source_root(),\n>> +\t\t'@0@'.format(lph)\n>> +\t)\n>> +endforeach\n>> +\n>>   subdir('converter')\n>> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n>> index bab858a3..25e2f8a4 100644\n>> --- a/include/libcamera/meson.build\n>> +++ b/include/libcamera/meson.build\n>> @@ -26,6 +26,13 @@ subdir('ipa')\n>>   install_headers(libcamera_public_headers,\n>>                   subdir : libcamera_include_dir)\n>>\n>> +foreach lph : libcamera_public_headers\n>> +\tdoxygen_public_sources += '/'.join(\n>> +\t\tmeson.project_source_root(),\n>> +\t\t'@0@'.format(lph)\n>> +\t)\n>> +endforeach\n>> +\n>>   #\n>>   # Generate headers from templates.\n>>   #\n>> @@ -85,6 +92,7 @@ foreach mode, entry : controls_map\n>>                                                   '-r', ranges_file, '@INPUT@'],\n>>                                        install : true,\n>>                                        install_dir : libcamera_headers_install_dir)\n>> +    doxygen_public_sources += control_headers.get(-1).full_path()\n>>   endforeach\n>>\n>>   libcamera_public_headers += control_headers\n>> @@ -101,6 +109,7 @@ formats_h = custom_target('formats_h',\n>>                             install : true,\n>>                             install_dir : libcamera_headers_install_dir)\n>>   libcamera_public_headers += formats_h\n>> +doxygen_public_sources += formats_h.full_path()\n>>\n>>   # libcamera.h\n>>   libcamera_h = custom_target('gen-header',\n>> @@ -111,6 +120,7 @@ libcamera_h = custom_target('gen-header',\n>>                               install_dir : libcamera_headers_install_dir)\n>>\n>>   libcamera_public_headers += libcamera_h\n>> +doxygen_public_sources += libcamera_h.full_path()\n>>\n>>   # version.h\n>>   version = libcamera_version.split('.')\n>> diff --git a/meson.build b/meson.build\n>> index e49de4c2..cca1883e 100644\n>> --- a/meson.build\n>> +++ b/meson.build\n>> @@ -231,6 +231,14 @@ endif\n>>   # Utilities are parsed first to provide support for other components.\n>>   subdir('utils')\n>>\n>> +# To support auto-generation of documentation We need an array of the paths to\n> s/We/we\n>\n>> +# public headers and source files so that we can tell doxygen which files to\n>> +# look at later. Unfortunately the inclusion of custom targets in some of the\n>> +# existing arrays precludes using them directly and you cannot generate File\n>> +# objects from generated files, so we need to collect paths to relevant files\n>> +# within an array.\n>> +doxygen_public_sources = []\n>> +\n>>   subdir('include')\n>>   subdir('src')\n>>\n>> diff --git a/src/libcamera/base/class.cpp b/src/libcamera/base/class.cpp\n>> index 9c2d9f21..70fd5cd5 100644\n>> --- a/src/libcamera/base/class.cpp\n>> +++ b/src/libcamera/base/class.cpp\n>> @@ -184,6 +184,7 @@ Extensible::Extensible(std::unique_ptr<Extensible::Private> d)\n>>    */\n>>\n>>   /**\n>> + * \\internal\n>>    * \\class Extensible::Private\n>>    * \\brief Base class for private data managed through a d-pointer\n>>    */\n>> diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\n>> index 523c5885..ae949a51 100644\n>> --- a/src/libcamera/base/meson.build\n>> +++ b/src/libcamera/base/meson.build\n>> @@ -30,6 +30,13 @@ libcamera_base_sources = [\n>>   \tlibcamera_base_internal_sources\n>>   ]\n>>\n>> +foreach lbps : libcamera_base_public_sources\n>> +\tdoxygen_public_sources += '/'.join(\n>> +\t\tmeson.project_source_root(),\n>> +\t\t'@0@'.format(lbps)\n>> +\t)\n>> +endforeach\n>> +\n>>   libdw = dependency('libdw', required : false)\n>>   libunwind = dependency('libunwind', required : false)\n>>\n>> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n>> index 0ad1a4b5..ed46f853 100644\n>> --- a/src/libcamera/camera.cpp\n>> +++ b/src/libcamera/camera.cpp\n>> @@ -560,6 +560,13 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF\n>>    */\n>>\n>>   /**\n>> + * \\internal\n>> + * \\file libcamera\\internal\\camera.h\n>> + * \\brief Internal Camera device handling\n>> + */\n>> +\n>> +/**\n>> + * \\internal\n>>    * \\class Camera::Private\n>>    * \\brief Base class for camera private data\n>>    *\n>> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n>> index 355f3ada..61d45256 100644\n>> --- a/src/libcamera/camera_manager.cpp\n>> +++ b/src/libcamera/camera_manager.cpp\n>> @@ -23,6 +23,7 @@\n>>    */\n>>\n>>   /**\n>> + * \\internal\n>>    * \\file libcamera/internal/camera_manager.h\n>>    * \\brief Internal camera manager support\n>>    */\n> That's weird, I don't see CameraManager::Private::addCamera() and\n> CameraManager::Private::removeCamera() being documented. It was not\n> documented even before this commit though :/\n\n\nTurns out CameraManager::Private is actually explicitly excluded at the symbol level in \nDocumentation/Doxyfile.in, so that's why. So; probably unecessary to flag these...but perhaps for \nconsistency's sake it's best to follow the rule that any public class deriving a private from \n::Extensible needs flagging.\n\n>\n>> diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp\n>> index 5a7f3c0b..db450e11 100644\n>> --- a/src/libcamera/framebuffer.cpp\n>> +++ b/src/libcamera/framebuffer.cpp\n>> @@ -16,7 +16,10 @@\n>>   /**\n>>    * \\file libcamera/framebuffer.h\n>>    * \\brief Frame buffer handling\n>> - *\n>> + */\n>> +\n>> +/**\n>> + * \\internal\n>>    * \\file libcamera/internal/framebuffer.h\n>>    * \\brief Internal frame buffer handling support\n>>    */\n>> @@ -105,6 +108,7 @@ LOG_DEFINE_CATEGORY(Buffer)\n>>    */\n>>\n>>   /**\n>> + * \\internal\n>>    * \\class FrameBuffer::Private\n>>    * \\brief Base class for FrameBuffer private data\n>>    *\n>> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n>> index 676470c1..413e14db 100644\n>> --- a/src/libcamera/meson.build\n>> +++ b/src/libcamera/meson.build\n>> @@ -59,6 +59,13 @@ libcamera_sources = [\n>>   \tlibcamera_internal_sources\n>>   ]\n>>\n>> +foreach lps : libcamera_public_sources\n>> +\tdoxygen_public_sources += '/'.join(\n>> +\t\tmeson.project_source_root(),\n>> +\t\t'@0@'.format(lps)\n>> +\t)\n>> +endforeach\n>> +\n>>   libcamera_sources += libcamera_public_headers\n>>   libcamera_sources += libcamera_generated_ipa_headers\n>>   libcamera_sources += libcamera_tracepoint_header\n>> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\n>> index 949c556f..930d8c92 100644\n>> --- a/src/libcamera/request.cpp\n>> +++ b/src/libcamera/request.cpp\n>> @@ -33,6 +33,7 @@ namespace libcamera {\n>>   LOG_DEFINE_CATEGORY(Request)\n>>\n>>   /**\n>> + * \\internal\n>>    * \\class Request::Private\n>>    * \\brief Request private data\n>>    *\n> So we should remember to mark every classes that derives a private\n> implementation from Extensible to mark it as \\internal. I think it's\n> fine, and I like the patch  a lot!\n>\n> With the few above points clarified\n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>\n> Thanks\n>     j\n>\n>> --\n>> 2.34.1\n>>","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 22D3DBEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 12 Jan 2024 10:57:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5B48C628B7;\n\tFri, 12 Jan 2024 11:57:49 +0100 (CET)","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 D0D24628B1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 12 Jan 2024 11:57:48 +0100 (CET)","from [192.168.0.43]\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9D95FE62;\n\tFri, 12 Jan 2024 11:56:42 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1705057069;\n\tbh=TztBSU1osgp8C69r6bMENRbu34NmvrfkM0yp2RfEpVI=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=nOCRCfMjDRRPBEay8hfQG5CXR/MqW1kSXqVkUPoARnIDGN4LZkvB8eCxEwGJirDaY\n\tOlAJb1Xu3hcXEL1R8UfcapaB3Zm+zA3SPNn6m9GgxifoI6d6cskMJaZ+Cn9gLYEeDA\n\tRKv0cEGg21uU0GZUFlHr22uqnOok5YXCgegbbAuK2Jx1/rZ0a30Gg9Ps+KMdbEzfgF\n\tXJrzT+rtVVbQWQhIqf7hXDmqWvofeETpEx/SxOdK+/N0Jg7tPU1vr2UWh7eojBzjjh\n\t7Jvli7WO+fYdYAKz3q7LxtTzDK7JFVmf74TmXrxNeCOBfX51lX+zDqs/02qaY13H0M\n\tu9N9mbONRAsGg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1705057002;\n\tbh=TztBSU1osgp8C69r6bMENRbu34NmvrfkM0yp2RfEpVI=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=oqYDB+1V5spJwjOIlzmExepiKt/CZfQgXDhRX0wcnA4JFZ8BlIF3dzKHpr2ZgjJuX\n\tlGTET9CbWJK5eK+FzZuTEZpheRZLI8FfRsasaJCXr+1r20i1YS6eQsyS/weYfNMC1A\n\tqtkvqyLAdYPyHiEU0C3yE5mUplgwo/+WbKqQPA7M="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"oqYDB+1V\"; dkim-atps=neutral","Message-ID":"<83d94802-c9fd-47bb-ac28-b0488b1581f9@ideasonboard.com>","Date":"Fri, 12 Jan 2024 10:57:45 +0000","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Content-Language":"en-US","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","References":"<20240105164104.78398-1-dan.scally@ideasonboard.com>\n\t<20240105164104.78398-5-dan.scally@ideasonboard.com>\n\t<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>","Autocrypt":"addr=dan.scally@ideasonboard.com; keydata=\n\t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","In-Reply-To":"<hdgsgjeqfxdf3bl3f62ikmz76l2hiseuunrog2iyioxjljoexf@rjilowmjaj6d>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH v2 4/5] libcamera: Documentation:\n\tSplit public/private documentation","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>","From":"Dan Scally via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Dan Scally <dan.scally@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]