On 11/6/2026 12:36 PM, Alex Bennée wrote: > Pierrick Bouvier <[email protected]> writes: > >> 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. > > plantuml seems to be pretty widely packaged so in this sense its just > another dependency. > >> 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? > > Ohh I didn't realize there was graphviz - I'll see if I can recreate > with that. >
If graphviz is not installed, a warning is emitted, which stops the build since we turn warnings into error. The warning emitted has no type, so it can't be filtered with suppress_warning setting from sphinx-build. However, since sphinx uses standard logging framework, you can silence it this way: https://github.com/sphinx-doc/sphinx/issues/10219 ``` --- a/docs/conf.py +++ b/docs/conf.py @@ -24,6 +24,7 @@ +import logging import os import sys import sphinx @@ -66,8 +67,20 @@ 'qapi_domain', 'qapidoc', 'qmp_lexer', + 'sphinx.ext.graphviz', ] +# Render graphviz diagrams as SVG so they scale cleanly in HTML output. +graphviz_output_format = 'svg' + +# Silence the warning emitted by sphinx.ext.graphviz when 'dot' is not +# installed. Diagrams are then rendered as their raw source instead. +class _NoDotWarning(logging.Filter): + def filter(self, record): + return 'cannot be run (needed for graphviz output)' not in record.getMessage() + +logging.getLogger('sphinx.sphinx.ext.graphviz').addFilter(_NoDotWarning()) ``` The advantage is that graphviz is not a required dependency, so doc is still built for anyone having sphinx installed. That's a nice end result I think. >> Also, text diagrams (https://asciidraw.github.io/) with raw formatting >> have the advantage to not require any external tool. > > I have the ascii original although ditaa seemed more of a stretch: > > --8<---------------cut here---------------start------------->8--- > #+name: QEMU Development Process > #+begin_src ditaa :cmdline -T -o :file images/qemu-dev-process.png > Developer QEMU Community > Subsystem Maintainer > +-=--------------------------+ > +-=---------------------------------------------------+ > +-=----------------------+ > | | | > | | | > | +-------------------+ | | > +-----------------------------------------------+ | | +----------------+ > | > | |{io} | | | |{io} > | | | |{io} | | > | | Develop and | | +--->| Code Review on List > | | +---->| Add Maintainer | | > | | Test feature | | | | | > | | | | | Sign-off | | > | | | | | | > +------+----------------+----------------+------+ | | | | | > | > | +--------+----------+ | | | | | > | | | | +-------+--------+ | > | | | | | V V > V | | | | | > | V | | : +-------------+ +-------------+ > +-------------+ | | | v | > | +-------------------+ | | | |{d} | |{d} | |{io} > | | | | +----------------+ | > | |{io} | | | | | Review | | Review | | > Maintainer | | | | |{s} | | > | +->| Post to List +-----+ | | Comments | | Tags | | > accepts | | | | | GIT Branch | | > | | | | | | | | | | | > some or all | | | | | foo/next | | > | | +-------------------+ | | | | | | | > patches | | | | | | | > | | : | +------+------+ +------+------+ > +------+------+ | | : | | | > | | +-------------------+ | | | | > | | | | | | | > | | |{io} |<----------------+ | > +-----------+ | | | | > | | | Incorporate | | > | | | | | > | | | Feedback |<---------------------------------+ > | | | | | > | | +--------+----------+ | | > : | +-------+--------+ | > | | | : > +-----------------------------------------------------+ | | > | > | | v | > | V | > | | +-------------------+ | QEMU Maintainer > | +----------------+ | > | | |{io} | | > +-=-----------------------------------------------------+ | |{io} > | | > | | | Prepare n+1 | | | +-------------+ +--------------+ > +----------------+ | | | Sign & Submit | | > | | | | | | |{io} | |{s} | |{io} > | | | | Pull | | > | | +--------+----------+ | | | Tag Release |<-+ qemu.git |<-+ Test > and Merge |<-------+ Request | | > | | | | | | | | master | | > Pull Reqs |<-+ | | | | > | +-----------+ | | | | | | | > | || | +----------------+ | > | | | +------+------+ +--------------+ > +----------------+ || | | > +----------------------------+ > +--------+----------------------------------------------+| > +------------------------+ > +----------------+ > | > | > | > V > | Pull Requests > +--------------+ > +---- from > |{d} | > Other Maintainers > | QEMU | > | Release | > | | > | | > +--------------+ > > #+end_src > --8<---------------cut here---------------end--------------->8--- > Nice diagram! Better in picture indeed. > >> >> What do you think? >> >> Regards, >> Pierrick >
