On 11/6/2026 4:21 AM, Alex Bennée wrote:
> We've had various versions of this diagram for a while so I thought it
> would be worth adding to the developer docs. I chose plantuml as it
> has a plugin for sphinx that we can use and supports sequence diagrams
> which could be useful for documenting other features in the code base.
> 
> Signed-off-by: Alex Bennée <[email protected]>
> 
> ---
> vRFC
>   - I've bundled all the plumbing together in this commit but it can
>   be split up if we want to go forward.
> ---
>  docs/conf.py                    | 22 +++++++++++++++
>  docs/devel/index-process.rst    | 47 +++++++++++++++++++++++++++++++++
>  docs/meson.build                |  3 ++-
>  docs/requirements.txt           |  1 +
>  configure                       |  6 +++++
>  pythondeps.toml                 |  1 +
>  tests/lcitool/mappings.yml      |  3 +++
>  tests/lcitool/projects/qemu.yml |  1 +
>  8 files changed, 83 insertions(+), 1 deletion(-)
> 
> diff --git a/docs/conf.py b/docs/conf.py
> index 914bae67d9c..9fc7be362ba 100644
> --- a/docs/conf.py
> +++ b/docs/conf.py
> @@ -66,8 +66,11 @@
>      'qapi_domain',
>      'qapidoc',
>      'qmp_lexer',
> +    'sphinxcontrib.plantuml',
>  ]
>  
> +plantuml_output_format = 'svg'
> +
>  # Add any paths that contain templates here, relative to this directory.
>  templates_path = [os.path.join(qemu_docdir, '_templates')]
>  
> @@ -345,3 +348,22 @@
>  qapidoc_srctree = os.path.join(qemu_docdir, '..')
>  dbusdoc_srctree = os.path.join(qemu_docdir, '..')
>  dbus_index_common_prefix = ["org.qemu."]
> +
> +
> +def setup(app):
> +    import docutils.nodes
> +    import sphinxcontrib.plantuml
> +
> +    # We manually setup the plantuml extension so we can skip nodes with
> +    # diagrams when generating the text based output.
> +
> +    def skip_node(self, node):
> +        raise docutils.nodes.SkipNode
> +
> +    app.setup_extension('sphinxcontrib.plantuml')
> +    app.add_node(
> +        sphinxcontrib.plantuml.plantuml,
> +        override=True,
> +        man=(skip_node, None),
> +        text=(skip_node, None),
> +    )
> diff --git a/docs/devel/index-process.rst b/docs/devel/index-process.rst
> index ce0f4e73197..1c13dd3f7b5 100644
> --- a/docs/devel/index-process.rst
> +++ b/docs/devel/index-process.rst
> @@ -5,6 +5,53 @@ QEMU Community Processes
>  
>  Notes about how to interact with the community and how and where to submit 
> patches.
>  
> +.. uml::
> +   :caption: QEMU Patch Review and Acceptance Flow
> +
> +   @startuml
> +   skinparam roundCorner 8
> +   skinparam shadowing false
> +   skinparam defaultFontName monospace
> +   skinparam sequenceMessageAlign center
> +
> +   actor "Developer" as dev
> +   participant "QEMU Community\n(qemu-devel)" as list
> +   actor "Subsystem\nMaintainer" as sub
> +   actor "QEMU\nMaintainer" as top
> +
> +   dev -> dev: Develop & test feature
> +
> +   loop Needs revision (v1, v2, ... vn)
> +       dev -> list: Post patch series to list
> +       note over list: Code review on list
> +
> +       opt Review comments
> +           list -> dev: Feedback & change requests
> +           dev -> dev: Incorporate feedback
> +       end
> +       opt Review tags
> +           list -> dev: Tags (Reviewed-by, Acked-by, ...)
> +           dev -> dev: Apply tags
> +       end
> +
> +       dev -> dev: Prepare n+1
> +   end
> +
> +   group Patch acceptance & release
> +       list -> sub: Maintainer accepts some or all patches
> +       note over sub: Incorporates patches\nfrom other developers
> +       sub -> sub: Add Maintainer Sign-off
> +       sub -> sub: GIT branch foo/next
> +       sub -> list: Sign & Submit Pull Request
> +       list -> top: Pull Request delivered to list
> +       note over top: Pull Requests from\nother maintainers
> +       top -> top: Test and Merge Pull Reqs
> +       top -> top: qemu.git master
> +       top -> top: Tag Release
> +       top -> list: QEMU Release
> +   end
> +   @enduml
> +
>  .. toctree::
>     :maxdepth: 2
>  
> diff --git a/docs/meson.build b/docs/meson.build
> index 4d8cc545fcc..600d3283299 100644
> --- a/docs/meson.build
> +++ b/docs/meson.build
> @@ -1,9 +1,10 @@
>  sphinx_build = find_program(fs.parent(python.full_path()) / 'sphinx-build',
>                              required: get_option('docs'))
> +plantuml = find_program('plantuml', required: get_option('docs'))
>  
>  # Check if tools are available to build documentation.
>  build_docs = false
> -if sphinx_build.found()
> +if sphinx_build.found() and plantuml.found()
>    SPHINX_ARGS = ['env', 'CONFDIR=' + qemu_confdir, sphinx_build, '-q']
>    # If we're making warnings fatal, apply this to Sphinx runs as well
>    if get_option('werror')
> diff --git a/docs/requirements.txt b/docs/requirements.txt
> index 509d56bd1e8..1cafcbaa38f 100644
> --- a/docs/requirements.txt
> +++ b/docs/requirements.txt
> @@ -3,3 +3,4 @@
>  
>  sphinx==7.2.6
>  sphinx_rtd_theme==2.0.0
> +sphinxcontrib-plantuml==0.30
> diff --git a/configure b/configure
> index 42dffed28f0..b0dedde65dd 100755
> --- a/configure
> +++ b/configure
> @@ -1020,6 +1020,12 @@ if test "$docs" != "disabled" ; then
>          fi
>          echo "Sphinx not found/usable, disabling docs."
>          docs=disabled
> +    elif ! has plantuml; then
> +        if test "$docs" = "enabled" ; then
> +            error_exit "plantuml not found"
> +        fi
> +        echo "plantuml not found, disabling docs."
> +        docs=disabled
>      else
>          docs=enabled
>      fi
> diff --git a/pythondeps.toml b/pythondeps.toml
> index c9a697046c6..c21d127ec93 100644
> --- a/pythondeps.toml
> +++ b/pythondeps.toml
> @@ -30,6 +30,7 @@ meson = { accepted = ">=1.12.0", installed = "1.12.0", 
> canary = "meson" }
>  # Please keep the installed versions in sync with docs/requirements.txt
>  sphinx = { accepted = ">=7.2.6", installed = "7.2.6", canary = 
> "sphinx-build" }
>  sphinx_rtd_theme = { accepted = ">=1.2.2", installed = "2.0.0" }
> +sphinxcontrib-plantuml = { accepted = ">=0.5", installed = "0.30" }
>  
>  # This test group is for dependencies required to run various tooling
>  # and tests that should always be installed at configure time. It should
> diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
> index c99f007798e..eca6748ac09 100644
> --- a/tests/lcitool/mappings.yml
> +++ b/tests/lcitool/mappings.yml
> @@ -3,6 +3,9 @@ mappings:
>    bindgen:
>      Ubuntu2204:
>  
> +  plantuml:
> +    default: plantuml
> +
>    python3:
>      CentOSStream9: python3.12
>  
> diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml
> index abbd3e3f0b8..de4395cd3c7 100644
> --- a/tests/lcitool/projects/qemu.yml
> +++ b/tests/lcitool/projects/qemu.yml
> @@ -89,6 +89,7 @@ packages:
>   - pcre-static
>   - pixman
>   - pkg-config
> + - plantuml
>   - pulseaudio
>   - python3
>   - python3-numpy

It will silently disable doc by default for most of the people
unfortunately, not sure it's the best move we can do.

Maybe a simpler solution could be to generate diagrams out of sphinx,
add them as a dependency, and generate a blank image (or an image with
diagram source and a message - please install plantuml) if not
available. What does plantuml brings compares to graphviz builtin extension?

Also, text diagrams (https://asciidraw.github.io/) with raw formatting
have the advantage to not require any external tool.

What do you think?

Regards,
Pierrick

Reply via email to