diff mbox series

[v4,3/4] meson: Move the detection logic for sphinx to meson

Message ID 20201015220626.418-4-luoyonggang@gmail.com
State Superseded
Headers show
Series Fixes docs building on msys2/mingw | expand

Commit Message

罗勇刚(Yonggang Luo) Oct. 15, 2020, 10:06 p.m. UTC
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 configure                     | 59 +++-------------------------------
 docs/meson.build              |  4 +--
 meson.build                   | 60 +++++++++++++++++++++++++++++++----
 meson_options.txt             |  5 ++-
 tests/qapi-schema/meson.build |  2 +-
 5 files changed, 64 insertions(+), 66 deletions(-)

Comments

Paolo Bonzini Oct. 16, 2020, 7:46 a.m. UTC | #1
Here is a better way to write the meson test:

if get_option('sphinx_build') == ''
  sphinx_build = find_program(['sphinx-build-3', 'sphinx-build'],
                              required: get_option('docs'))
else
  sphinx_build = find_program(get_option('sphinx_build'),
                              required: get_option('docs'))
endif

SPHINX_ARGS = [sphinx_build]
# If we're making warnings fatal, apply this to Sphinx runs as well
if get_option('werror')
  SPHINX_TEST_ARGS += [ '-W' ]
endif

# Check if tools are available to build documentation.
build_docs = false
if sphinx_build.found()
  # This is a bit awkward but works: create a trivial document and
  # try to run it with our configuration file (which enforces a
  # version requirement). This will fail if sphinx-build is too old.
  run_command('mkdir', ['-p', tmpdir / 'sphinx'])
  run_command('touch', [tmpdir / 'sphinx/index.rst'])
  sphinx_build_test_out = run_command(SPHINX_ARGS + [
    '-c', meson.current_source_dir() / 'docs',
    '-b', 'html', tmpdir / 'sphinx',
    tmpdir / 'sphinx/out'])
  build_docs = (sphinx_build_test_out.returncode() == 0)
endif

if not build_docs
  if sphinx_build_option != ''
    warning('@0@ exists but it is either too old or uses too old a Python version'.format(sphinx_build_option))
  endif
  if get_option('docs').enabled()
    error('Install a Python 3 version of python-sphinx')
  endif
endif



On 16/10/20 00:06, Yonggang Luo wrote:
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  configure                     | 59 +++-------------------------------
>  docs/meson.build              |  4 +--
>  meson.build                   | 60 +++++++++++++++++++++++++++++++----
>  meson_options.txt             |  5 ++-
>  tests/qapi-schema/meson.build |  2 +-
>  5 files changed, 64 insertions(+), 66 deletions(-)
> 
> diff --git a/configure b/configure
> index 1ce31f97b4..ff593a8542 100755
> --- a/configure
> +++ b/configure
> @@ -297,7 +297,7 @@ brlapi=""
>  curl=""
>  iconv="auto"
>  curses="auto"
> -docs=""
> +docs="auto"
>  fdt="auto"
>  netmap="no"
>  sdl="auto"
> @@ -822,15 +822,6 @@ do
>      fi
>  done
>  
> -sphinx_build=
> -for binary in sphinx-build-3 sphinx-build
> -do
> -    if has "$binary"
> -    then
> -        sphinx_build=$(command -v "$binary")
> -        break
> -    fi
> -done
>  
>  # Check for ancillary tools used in testing
>  genisoimage=
> @@ -1226,9 +1217,9 @@ for opt do
>    ;;
>    --disable-crypto-afalg) crypto_afalg="no"
>    ;;
> -  --disable-docs) docs="no"
> +  --disable-docs) docs="disabled"
>    ;;
> -  --enable-docs) docs="yes"
> +  --enable-docs) docs="enabled"
>    ;;
>    --disable-vhost-net) vhost_net="no"
>    ;;
> @@ -4413,45 +4404,6 @@ if check_include linux/btrfs.h ; then
>      btrfs=yes
>  fi
>  
> -# If we're making warnings fatal, apply this to Sphinx runs as well
> -sphinx_werror=""
> -if test "$werror" = "yes"; then
> -    sphinx_werror="-W"
> -fi
> -
> -# Check we have a new enough version of sphinx-build
> -has_sphinx_build() {
> -    # This is a bit awkward but works: create a trivial document and
> -    # try to run it with our configuration file (which enforces a
> -    # version requirement). This will fail if either
> -    # sphinx-build doesn't exist at all or if it is too old.
> -    mkdir -p "$TMPDIR1/sphinx"
> -    touch "$TMPDIR1/sphinx/index.rst"
> -    "$sphinx_build" $sphinx_werror -c "$source_path/docs" \
> -                    -b html "$TMPDIR1/sphinx" \
> -                    "$TMPDIR1/sphinx/out"  >> config.log 2>&1
> -}
> -
> -# Check if tools are available to build documentation.
> -if test "$docs" != "no" ; then
> -  if has_sphinx_build; then
> -    sphinx_ok=yes
> -  else
> -    sphinx_ok=no
> -  fi
> -  if test "$sphinx_ok" = "yes"; then
> -    docs=yes
> -  else
> -    if test "$docs" = "yes" ; then
> -      if has $sphinx_build && test "$sphinx_ok" != "yes"; then
> -        echo "Warning: $sphinx_build exists but it is either too old or uses too old a Python version" >&2
> -      fi
> -      feature_not_found "docs" "Install a Python 3 version of python-sphinx"
> -    fi
> -    docs=no
> -  fi
> -fi
> -
>  # Search for bswap_32 function
>  byteswap_h=no
>  cat > $TMPC << EOF
> @@ -6087,9 +6039,6 @@ qemu_version=$(head $source_path/VERSION)
>  echo "PKGVERSION=$pkgversion" >>$config_host_mak
>  echo "SRC_PATH=$source_path" >> $config_host_mak
>  echo "TARGET_DIRS=$target_list" >> $config_host_mak
> -if [ "$docs" = "yes" ] ; then
> -  echo "BUILD_DOCS=yes" >> $config_host_mak
> -fi
>  if test "$modules" = "yes"; then
>    # $shacmd can generate a hash started with digit, which the compiler doesn't
>    # like as an symbol. So prefix it with an underscore
> @@ -6794,7 +6743,6 @@ fi
>  echo "ROMS=$roms" >> $config_host_mak
>  echo "MAKE=$make" >> $config_host_mak
>  echo "PYTHON=$python" >> $config_host_mak
> -echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak
>  echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
>  echo "MESON=$meson" >> $config_host_mak
>  echo "CC=$cc" >> $config_host_mak
> @@ -7076,6 +7024,7 @@ NINJA=${ninja:-$PWD/ninjatool} $meson setup \
>          -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f \
>          -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \
>          -Diconv=$iconv -Dcurses=$curses \
> +        -Ddocs=$docs -Dsphinx_build=$sphinx_build \
>          $cross_arg \
>          "$PWD" "$source_path"
>  
> diff --git a/docs/meson.build b/docs/meson.build
> index 0340d489ac..f566809a6a 100644
> --- a/docs/meson.build
> +++ b/docs/meson.build
> @@ -37,7 +37,7 @@ if build_docs
>                  input: [files('conf.py'), files(manual / 'conf.py')],
>                  depfile: manual + '.d',
>                  depend_files: sphinx_extn_depends,
> -                command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
> +                command: SPHINX_ARGS + ['-Ddepfile=@DEPFILE@',
>                            '-Ddepfile_stamp=@OUTPUT0@',
>                            '-b', 'html', '-d', private_dir,
>                            input_dir, output_dir])
> @@ -59,7 +59,7 @@ if build_docs
>                           input: this_manual,
>                           install: build_docs,
>                           install_dir: install_dirs,
> -                         command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
> +                         command: SPHINX_ARGS + ['-b', 'man', '-d', private_dir,
>                                     input_dir, meson.current_build_dir()])
>      endif
>    endforeach
> diff --git a/meson.build b/meson.build
> index 8156df8b71..8940468208 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -17,7 +17,13 @@ cc = meson.get_compiler('c')
>  config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
>  enable_modules = 'CONFIG_MODULES' in config_host
>  enable_static = 'CONFIG_STATIC' in config_host
> -build_docs = 'BUILD_DOCS' in config_host
> +
> +# Temporary directory used for files created while
> +# configure runs. Since it is in the build directory
> +# we can safely blow away any previous version of it
> +# (and we need not jump through hoops to try to delete
> +# it when configure exits.)
> +tmpdir = meson.current_build_dir() / 'config-temp'
>  
>  if get_option('qemu_suffix').startswith('/')
>    error('qemu_suffix cannot start with a /')
> @@ -1235,12 +1241,52 @@ foreach d : hx_headers
>  endforeach
>  genh += hxdep
>  
> -SPHINX_ARGS = [config_host['SPHINX_BUILD'],
> -               '-Dversion=' + meson.project_version(),
> -               '-Drelease=' + config_host['PKGVERSION']]
> +sphinx_build = not_found
> +sphinx_build_option = get_option('sphinx_build')
> +if sphinx_build_option == ''
> +  sphinx_build = find_program('sphinx-build', required: false)
> +else
> +  sphinx_build = find_program(sphinx_build_option, required: false)
> +endif
>  
> +SPHINX_TEST_ARGS = []
> +# If we're making warnings fatal, apply this to Sphinx runs as well
>  if get_option('werror')
> -  SPHINX_ARGS += [ '-W' ]
> +  SPHINX_TEST_ARGS += [ '-W' ]
> +endif
> +
> +build_docs = false
> +docs_option = get_option('docs')
> +# Check if tools are available to build documentation.
> +if sphinx_build.found() and not docs_option.disabled()
> +    # This is a bit awkward but works: create a trivial document and
> +    # try to run it with our configuration file (which enforces a
> +    # version requirement). This will fail if either
> +    # sphinx-build doesn't exist at all or if it is too old.
> +    run_command('mkdir', ['-p', tmpdir / 'sphinx'])
> +    run_command('touch', [tmpdir / 'sphinx/index.rst'])
> +    sphinx_build_test_out = run_command(sphinx_build, SPHINX_TEST_ARGS + [
> +      '-c', meson.current_source_dir() / 'docs',
> +      '-b', 'html', tmpdir / 'sphinx',
> +      tmpdir / 'sphinx/out'])
> +    if sphinx_build_test_out.returncode() == 0
> +      build_docs = true
> +    else
> +      if docs_option.enabled()
> +        if sphinx_build_option != ''
> +          warning('Warning: @0@ exists but it is either too old or uses too old a Python version'.format(sphinx_build_option))
> +        endif
> +        error('Warning: Install a Python 3 version of python-sphinx')
> +      endif
> +      # do not building docs
> +    endif
> +endif
> +
> +SPHINX_ARGS = []
> +if build_docs
> +  SPHINX_ARGS = [sphinx_build]
> +  SPHINX_ARGS += SPHINX_TEST_ARGS
> +  SPHINX_ARGS += ['-Dversion=' + meson.project_version(), '-Drelease=' + config_host['PKGVERSION']]
>  endif
>  
>  sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
> @@ -1918,7 +1964,7 @@ summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
>  summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
>  summary_info += {'make':              config_host['MAKE']}
>  summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
> -summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
> +summary_info += {'sphinx-build':      sphinx_build.found()}
>  summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
>  # TODO: add back version
>  summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
> @@ -1986,7 +2032,7 @@ if config_host.has_key('CONFIG_XEN_BACKEND')
>    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
>  endif
>  summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
> -summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
> +summary_info += {'Documentation':     build_docs}
>  summary_info += {'PIE':               get_option('b_pie')}
>  summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
>  summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
> diff --git a/meson_options.txt b/meson_options.txt
> index e6cb1e589b..0e3fa7136b 100644
> --- a/meson_options.txt
> +++ b/meson_options.txt
> @@ -1,8 +1,11 @@
>  option('qemu_suffix', type : 'string', value: 'qemu',
>         description: 'Suffix for QEMU data/modules/config directories (can be empty)')
> +option('docs', type : 'feature', value : 'auto',
> +       description: 'Documentations build support')
>  option('docdir', type : 'string', value : 'doc',
>         description: 'Base directory for documentation installation (can be empty)')
> -
> +option('sphinx_build', type : 'string', value : '',
> +       description: 'Use specified sphinx-build [$sphinx_build] for building document (default to be empty)')
>  option('gettext', type : 'boolean', value : true,
>         description: 'Localization of the GTK+ user interface')
>  option('sparse', type : 'feature', value : 'auto',
> diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
> index 1f222a7a13..961b8367a9 100644
> --- a/tests/qapi-schema/meson.build
> +++ b/tests/qapi-schema/meson.build
> @@ -237,7 +237,7 @@ qapi_doc_out = custom_target('QAPI rST doc',
>                               # we want it to always really run the QAPI doc
>                               # generation code. It also means we don't
>                               # clutter up the build dir with the cache.
> -                             command: [SPHINX_ARGS,
> +                             command:  SPHINX_ARGS + [
>                                         '-b', 'text', '-E',
>                                         '-c', meson.source_root() / 'docs',
>                                         '-D', 'master_doc=doc-good',
>
罗勇刚(Yonggang Luo) Oct. 16, 2020, 7:52 a.m. UTC | #2
On Fri, Oct 16, 2020 at 3:46 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>

> Here is a better way to write the meson test:

>

> if get_option('sphinx_build') == ''

>   sphinx_build = find_program(['sphinx-build-3', 'sphinx-build'],

>                               required: get_option('docs'))

> else

>   sphinx_build = find_program(get_option('sphinx_build'),

>                               required: get_option('docs'))

> endif

>

> SPHINX_ARGS = [sphinx_build]

> # If we're making warnings fatal, apply this to Sphinx runs as well

> if get_option('werror')

>   SPHINX_TEST_ARGS += [ '-W' ]

> endif

>

> # Check if tools are available to build documentation.

> build_docs = false

> if sphinx_build.found()

>   # This is a bit awkward but works: create a trivial document and

>   # try to run it with our configuration file (which enforces a

>   # version requirement). This will fail if sphinx-build is too old.

>   run_command('mkdir', ['-p', tmpdir / 'sphinx'])

>   run_command('touch', [tmpdir / 'sphinx/index.rst'])

>   sphinx_build_test_out = run_command(SPHINX_ARGS + [

>     '-c', meson.current_source_dir() / 'docs',

>     '-b', 'html', tmpdir / 'sphinx',

>     tmpdir / 'sphinx/out'])

>   build_docs = (sphinx_build_test_out.returncode() == 0)

> endif

There is subtle error here, when  sphinx_build not found, there is
SPHINX_ARGS  should be [],
otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build
will cause error by meson
..
I'll add

else
  SPHINX_ARGS  = []
endif

>

> if not build_docs

>   if sphinx_build_option != ''

>     warning('@0@ exists but it is either too old or uses too old a Python

version'.format(sphinx_build_option))
>   endif

>   if get_option('docs').enabled()

>     error('Install a Python 3 version of python-sphinx')

>   endif

> endif

>

>

>

> On 16/10/20 00:06, Yonggang Luo wrote:

> > Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>

> > ---

> >  configure                     | 59 +++-------------------------------

> >  docs/meson.build              |  4 +--

> >  meson.build                   | 60 +++++++++++++++++++++++++++++++----

> >  meson_options.txt             |  5 ++-

> >  tests/qapi-schema/meson.build |  2 +-

> >  5 files changed, 64 insertions(+), 66 deletions(-)

> >

> > diff --git a/configure b/configure

> > index 1ce31f97b4..ff593a8542 100755

> > --- a/configure

> > +++ b/configure

> > @@ -297,7 +297,7 @@ brlapi=""

> >  curl=""

> >  iconv="auto"

> >  curses="auto"

> > -docs=""

> > +docs="auto"

> >  fdt="auto"

> >  netmap="no"

> >  sdl="auto"

> > @@ -822,15 +822,6 @@ do

> >      fi

> >  done

> >

> > -sphinx_build=

> > -for binary in sphinx-build-3 sphinx-build

> > -do

> > -    if has "$binary"

> > -    then

> > -        sphinx_build=$(command -v "$binary")

> > -        break

> > -    fi

> > -done

> >

> >  # Check for ancillary tools used in testing

> >  genisoimage=

> > @@ -1226,9 +1217,9 @@ for opt do

> >    ;;

> >    --disable-crypto-afalg) crypto_afalg="no"

> >    ;;

> > -  --disable-docs) docs="no"

> > +  --disable-docs) docs="disabled"

> >    ;;

> > -  --enable-docs) docs="yes"

> > +  --enable-docs) docs="enabled"

> >    ;;

> >    --disable-vhost-net) vhost_net="no"

> >    ;;

> > @@ -4413,45 +4404,6 @@ if check_include linux/btrfs.h ; then

> >      btrfs=yes

> >  fi

> >

> > -# If we're making warnings fatal, apply this to Sphinx runs as well

> > -sphinx_werror=""

> > -if test "$werror" = "yes"; then

> > -    sphinx_werror="-W"

> > -fi

> > -

> > -# Check we have a new enough version of sphinx-build

> > -has_sphinx_build() {

> > -    # This is a bit awkward but works: create a trivial document and

> > -    # try to run it with our configuration file (which enforces a

> > -    # version requirement). This will fail if either

> > -    # sphinx-build doesn't exist at all or if it is too old.

> > -    mkdir -p "$TMPDIR1/sphinx"

> > -    touch "$TMPDIR1/sphinx/index.rst"

> > -    "$sphinx_build" $sphinx_werror -c "$source_path/docs" \

> > -                    -b html "$TMPDIR1/sphinx" \

> > -                    "$TMPDIR1/sphinx/out"  >> config.log 2>&1

> > -}

> > -

> > -# Check if tools are available to build documentation.

> > -if test "$docs" != "no" ; then

> > -  if has_sphinx_build; then

> > -    sphinx_ok=yes

> > -  else

> > -    sphinx_ok=no

> > -  fi

> > -  if test "$sphinx_ok" = "yes"; then

> > -    docs=yes

> > -  else

> > -    if test "$docs" = "yes" ; then

> > -      if has $sphinx_build && test "$sphinx_ok" != "yes"; then

> > -        echo "Warning: $sphinx_build exists but it is either too old

or uses too old a Python version" >&2
> > -      fi

> > -      feature_not_found "docs" "Install a Python 3 version of

python-sphinx"
> > -    fi

> > -    docs=no

> > -  fi

> > -fi

> > -

> >  # Search for bswap_32 function

> >  byteswap_h=no

> >  cat > $TMPC << EOF

> > @@ -6087,9 +6039,6 @@ qemu_version=$(head $source_path/VERSION)

> >  echo "PKGVERSION=$pkgversion" >>$config_host_mak

> >  echo "SRC_PATH=$source_path" >> $config_host_mak

> >  echo "TARGET_DIRS=$target_list" >> $config_host_mak

> > -if [ "$docs" = "yes" ] ; then

> > -  echo "BUILD_DOCS=yes" >> $config_host_mak

> > -fi

> >  if test "$modules" = "yes"; then

> >    # $shacmd can generate a hash started with digit, which the compiler

doesn't
> >    # like as an symbol. So prefix it with an underscore

> > @@ -6794,7 +6743,6 @@ fi

> >  echo "ROMS=$roms" >> $config_host_mak

> >  echo "MAKE=$make" >> $config_host_mak

> >  echo "PYTHON=$python" >> $config_host_mak

> > -echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak

> >  echo "GENISOIMAGE=$genisoimage" >> $config_host_mak

> >  echo "MESON=$meson" >> $config_host_mak

> >  echo "CC=$cc" >> $config_host_mak

> > @@ -7076,6 +7024,7 @@ NINJA=${ninja:-$PWD/ninjatool} $meson setup \

> >          -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f \

> >          -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \

> >          -Diconv=$iconv -Dcurses=$curses \

> > +        -Ddocs=$docs -Dsphinx_build=$sphinx_build \

> >          $cross_arg \

> >          "$PWD" "$source_path"

> >

> > diff --git a/docs/meson.build b/docs/meson.build

> > index 0340d489ac..f566809a6a 100644

> > --- a/docs/meson.build

> > +++ b/docs/meson.build

> > @@ -37,7 +37,7 @@ if build_docs

> >                  input: [files('conf.py'), files(manual / 'conf.py')],

> >                  depfile: manual + '.d',

> >                  depend_files: sphinx_extn_depends,

> > -                command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',

> > +                command: SPHINX_ARGS + ['-Ddepfile=@DEPFILE@',

> >                            '-Ddepfile_stamp=@OUTPUT0@',

> >                            '-b', 'html', '-d', private_dir,

> >                            input_dir, output_dir])

> > @@ -59,7 +59,7 @@ if build_docs

> >                           input: this_manual,

> >                           install: build_docs,

> >                           install_dir: install_dirs,

> > -                         command: [SPHINX_ARGS, '-b', 'man', '-d',

private_dir,
> > +                         command: SPHINX_ARGS + ['-b', 'man', '-d',

private_dir,
> >                                     input_dir,

meson.current_build_dir()])
> >      endif

> >    endforeach

> > diff --git a/meson.build b/meson.build

> > index 8156df8b71..8940468208 100644

> > --- a/meson.build

> > +++ b/meson.build

> > @@ -17,7 +17,13 @@ cc = meson.get_compiler('c')

> >  config_host = keyval.load(meson.current_build_dir() /

'config-host.mak')
> >  enable_modules = 'CONFIG_MODULES' in config_host

> >  enable_static = 'CONFIG_STATIC' in config_host

> > -build_docs = 'BUILD_DOCS' in config_host

> > +

> > +# Temporary directory used for files created while

> > +# configure runs. Since it is in the build directory

> > +# we can safely blow away any previous version of it

> > +# (and we need not jump through hoops to try to delete

> > +# it when configure exits.)

> > +tmpdir = meson.current_build_dir() / 'config-temp'

> >

> >  if get_option('qemu_suffix').startswith('/')

> >    error('qemu_suffix cannot start with a /')

> > @@ -1235,12 +1241,52 @@ foreach d : hx_headers

> >  endforeach

> >  genh += hxdep

> >

> > -SPHINX_ARGS = [config_host['SPHINX_BUILD'],

> > -               '-Dversion=' + meson.project_version(),

> > -               '-Drelease=' + config_host['PKGVERSION']]

> > +sphinx_build = not_found

> > +sphinx_build_option = get_option('sphinx_build')

> > +if sphinx_build_option == ''

> > +  sphinx_build = find_program('sphinx-build', required: false)

> > +else

> > +  sphinx_build = find_program(sphinx_build_option, required: false)

> > +endif

> >

> > +SPHINX_TEST_ARGS = []

> > +# If we're making warnings fatal, apply this to Sphinx runs as well

> >  if get_option('werror')

> > -  SPHINX_ARGS += [ '-W' ]

> > +  SPHINX_TEST_ARGS += [ '-W' ]

> > +endif

> > +

> > +build_docs = false

> > +docs_option = get_option('docs')

> > +# Check if tools are available to build documentation.

> > +if sphinx_build.found() and not docs_option.disabled()

> > +    # This is a bit awkward but works: create a trivial document and

> > +    # try to run it with our configuration file (which enforces a

> > +    # version requirement). This will fail if either

> > +    # sphinx-build doesn't exist at all or if it is too old.

> > +    run_command('mkdir', ['-p', tmpdir / 'sphinx'])

> > +    run_command('touch', [tmpdir / 'sphinx/index.rst'])

> > +    sphinx_build_test_out = run_command(sphinx_build, SPHINX_TEST_ARGS

+ [
> > +      '-c', meson.current_source_dir() / 'docs',

> > +      '-b', 'html', tmpdir / 'sphinx',

> > +      tmpdir / 'sphinx/out'])

> > +    if sphinx_build_test_out.returncode() == 0

> > +      build_docs = true

> > +    else

> > +      if docs_option.enabled()

> > +        if sphinx_build_option != ''

> > +          warning('Warning: @0@ exists but it is either too old or

uses too old a Python version'.format(sphinx_build_option))
> > +        endif

> > +        error('Warning: Install a Python 3 version of python-sphinx')

> > +      endif

> > +      # do not building docs

> > +    endif

> > +endif

> > +

> > +SPHINX_ARGS = []

> > +if build_docs

> > +  SPHINX_ARGS = [sphinx_build]

> > +  SPHINX_ARGS += SPHINX_TEST_ARGS

> > +  SPHINX_ARGS += ['-Dversion=' + meson.project_version(), '-Drelease='

+ config_host['PKGVERSION']]
> >  endif

> >

> >  sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',

> > @@ -1918,7 +1964,7 @@ summary_info += {'QEMU_CFLAGS':

config_host['QEMU_CFLAGS']}
> >  summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}

> >  summary_info += {'make':              config_host['MAKE']}

> >  summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(),

python.language_version())}
> > -summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}

> > +summary_info += {'sphinx-build':      sphinx_build.found()}

> >  summary_info += {'genisoimage':       config_host['GENISOIMAGE']}

> >  # TODO: add back version

> >  summary_info += {'slirp support':     slirp_opt == 'disabled' ? false

: slirp_opt}
> > @@ -1986,7 +2032,7 @@ if config_host.has_key('CONFIG_XEN_BACKEND')

> >    summary_info += {'xen ctrl version':

 config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
> >  endif

> >  summary_info += {'brlapi support':

 config_host.has_key('CONFIG_BRLAPI')}
> > -summary_info += {'Documentation':

config_host.has_key('BUILD_DOCS')}
> > +summary_info += {'Documentation':     build_docs}

> >  summary_info += {'PIE':               get_option('b_pie')}

> >  summary_info += {'vde support':

config_host.has_key('CONFIG_VDE')}
> >  summary_info += {'netmap support':

 config_host.has_key('CONFIG_NETMAP')}
> > diff --git a/meson_options.txt b/meson_options.txt

> > index e6cb1e589b..0e3fa7136b 100644

> > --- a/meson_options.txt

> > +++ b/meson_options.txt

> > @@ -1,8 +1,11 @@

> >  option('qemu_suffix', type : 'string', value: 'qemu',

> >         description: 'Suffix for QEMU data/modules/config directories

(can be empty)')
> > +option('docs', type : 'feature', value : 'auto',

> > +       description: 'Documentations build support')

> >  option('docdir', type : 'string', value : 'doc',

> >         description: 'Base directory for documentation installation

(can be empty)')
> > -

> > +option('sphinx_build', type : 'string', value : '',

> > +       description: 'Use specified sphinx-build [$sphinx_build] for

building document (default to be empty)')
> >  option('gettext', type : 'boolean', value : true,

> >         description: 'Localization of the GTK+ user interface')

> >  option('sparse', type : 'feature', value : 'auto',

> > diff --git a/tests/qapi-schema/meson.build

b/tests/qapi-schema/meson.build
> > index 1f222a7a13..961b8367a9 100644

> > --- a/tests/qapi-schema/meson.build

> > +++ b/tests/qapi-schema/meson.build

> > @@ -237,7 +237,7 @@ qapi_doc_out = custom_target('QAPI rST doc',

> >                               # we want it to always really run the

QAPI doc
> >                               # generation code. It also means we don't

> >                               # clutter up the build dir with the cache.

> > -                             command: [SPHINX_ARGS,

> > +                             command:  SPHINX_ARGS + [

> >                                         '-b', 'text', '-E',

> >                                         '-c', meson.source_root() /

'docs',
> >                                         '-D', 'master_doc=doc-good',

> >

>



--
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo
<div dir="ltr"><br><br>On Fri, Oct 16, 2020 at 3:46 PM Paolo Bonzini &lt;<a href="mailto:pbonzini@redhat.com">pbonzini@redhat.com</a>&gt; wrote:<br>&gt;<br>&gt; Here is a better way to write the meson test:<br>&gt;<br>&gt; if get_option(&#39;sphinx_build&#39;) == &#39;&#39;<br>&gt;   sphinx_build = find_program([&#39;sphinx-build-3&#39;, &#39;sphinx-build&#39;],<br>&gt;                               required: get_option(&#39;docs&#39;))<br>&gt; else<br>&gt;   sphinx_build = find_program(get_option(&#39;sphinx_build&#39;),<br>&gt;                               required: get_option(&#39;docs&#39;))<br>&gt; endif<br>&gt;<br>&gt; SPHINX_ARGS = [sphinx_build]<br>&gt; # If we&#39;re making warnings fatal, apply this to Sphinx runs as well<br>&gt; if get_option(&#39;werror&#39;)<br>&gt;   SPHINX_TEST_ARGS += [ &#39;-W&#39; ]<br>&gt; endif<br>&gt;<br>&gt; # Check if tools are available to build documentation.<br>&gt; build_docs = false<br>&gt; if sphinx_build.found()<br>&gt;   # This is a bit awkward but works: create a trivial document and<br>&gt;   # try to run it with our configuration file (which enforces a<br>&gt;   # version requirement). This will fail if sphinx-build is too old.<br>&gt;   run_command(&#39;mkdir&#39;, [&#39;-p&#39;, tmpdir / &#39;sphinx&#39;])<br>&gt;   run_command(&#39;touch&#39;, [tmpdir / &#39;sphinx/index.rst&#39;])<br>&gt;   sphinx_build_test_out = run_command(SPHINX_ARGS + [<br>&gt;     &#39;-c&#39;, meson.current_source_dir() / &#39;docs&#39;,<br>&gt;     &#39;-b&#39;, &#39;html&#39;, tmpdir / &#39;sphinx&#39;,<br>&gt;     tmpdir / &#39;sphinx/out&#39;])<br>&gt;   build_docs = (sphinx_build_test_out.returncode() == 0)<br>&gt; endif<br>There is subtle error here, when  sphinx_build not found, there is 

SPHINX_ARGS  should be [],<div>otherwise, latter place using 

SPHINX_ARGS  have not found sphinx_build will cause error by meson</div><div>..</div><div>I&#39;ll add</div><div><br></div><div>else</div><div>  SPHINX_ARGS  = []  <br></div><div>endif</div><div><br>&gt;<br>&gt; if not build_docs<br>&gt;   if sphinx_build_option != &#39;&#39;<br>&gt;     warning(&#39;@0@ exists but it is either too old or uses too old a Python version&#39;.format(sphinx_build_option))<br>&gt;   endif<br>&gt;   if get_option(&#39;docs&#39;).enabled()<br>&gt;     error(&#39;Install a Python 3 version of python-sphinx&#39;)<br>&gt;   endif<br>&gt; endif<br>&gt;<br>&gt;<br>&gt;<br>&gt; On 16/10/20 00:06, Yonggang Luo wrote:<br>&gt; &gt; Signed-off-by: Yonggang Luo &lt;<a href="mailto:luoyonggang@gmail.com">luoyonggang@gmail.com</a>&gt;<br>&gt; &gt; ---<br>&gt; &gt;  configure                     | 59 +++-------------------------------<br>&gt; &gt;  docs/meson.build              |  4 +--<br>&gt; &gt;  meson.build                   | 60 +++++++++++++++++++++++++++++++----<br>&gt; &gt;  meson_options.txt             |  5 ++-<br>&gt; &gt;  tests/qapi-schema/meson.build |  2 +-<br>&gt; &gt;  5 files changed, 64 insertions(+), 66 deletions(-)<br>&gt; &gt;<br>&gt; &gt; diff --git a/configure b/configure<br>&gt; &gt; index 1ce31f97b4..ff593a8542 100755<br>&gt; &gt; --- a/configure<br>&gt; &gt; +++ b/configure<br>&gt; &gt; @@ -297,7 +297,7 @@ brlapi=&quot;&quot;<br>&gt; &gt;  curl=&quot;&quot;<br>&gt; &gt;  iconv=&quot;auto&quot;<br>&gt; &gt;  curses=&quot;auto&quot;<br>&gt; &gt; -docs=&quot;&quot;<br>&gt; &gt; +docs=&quot;auto&quot;<br>&gt; &gt;  fdt=&quot;auto&quot;<br>&gt; &gt;  netmap=&quot;no&quot;<br>&gt; &gt;  sdl=&quot;auto&quot;<br>&gt; &gt; @@ -822,15 +822,6 @@ do<br>&gt; &gt;      fi<br>&gt; &gt;  done<br>&gt; &gt;<br>&gt; &gt; -sphinx_build=<br>&gt; &gt; -for binary in sphinx-build-3 sphinx-build<br>&gt; &gt; -do<br>&gt; &gt; -    if has &quot;$binary&quot;<br>&gt; &gt; -    then<br>&gt; &gt; -        sphinx_build=$(command -v &quot;$binary&quot;)<br>&gt; &gt; -        break<br>&gt; &gt; -    fi<br>&gt; &gt; -done<br>&gt; &gt;<br>&gt; &gt;  # Check for ancillary tools used in testing<br>&gt; &gt;  genisoimage=<br>&gt; &gt; @@ -1226,9 +1217,9 @@ for opt do<br>&gt; &gt;    ;;<br>&gt; &gt;    --disable-crypto-afalg) crypto_afalg=&quot;no&quot;<br>&gt; &gt;    ;;<br>&gt; &gt; -  --disable-docs) docs=&quot;no&quot;<br>&gt; &gt; +  --disable-docs) docs=&quot;disabled&quot;<br>&gt; &gt;    ;;<br>&gt; &gt; -  --enable-docs) docs=&quot;yes&quot;<br>&gt; &gt; +  --enable-docs) docs=&quot;enabled&quot;<br>&gt; &gt;    ;;<br>&gt; &gt;    --disable-vhost-net) vhost_net=&quot;no&quot;<br>&gt; &gt;    ;;<br>&gt; &gt; @@ -4413,45 +4404,6 @@ if check_include linux/btrfs.h ; then<br>&gt; &gt;      btrfs=yes<br>&gt; &gt;  fi<br>&gt; &gt;<br>&gt; &gt; -# If we&#39;re making warnings fatal, apply this to Sphinx runs as well<br>&gt; &gt; -sphinx_werror=&quot;&quot;<br>&gt; &gt; -if test &quot;$werror&quot; = &quot;yes&quot;; then<br>&gt; &gt; -    sphinx_werror=&quot;-W&quot;<br>&gt; &gt; -fi<br>&gt; &gt; -<br>&gt; &gt; -# Check we have a new enough version of sphinx-build<br>&gt; &gt; -has_sphinx_build() {<br>&gt; &gt; -    # This is a bit awkward but works: create a trivial document and<br>&gt; &gt; -    # try to run it with our configuration file (which enforces a<br>&gt; &gt; -    # version requirement). This will fail if either<br>&gt; &gt; -    # sphinx-build doesn&#39;t exist at all or if it is too old.<br>&gt; &gt; -    mkdir -p &quot;$TMPDIR1/sphinx&quot;<br>&gt; &gt; -    touch &quot;$TMPDIR1/sphinx/index.rst&quot;<br>&gt; &gt; -    &quot;$sphinx_build&quot; $sphinx_werror -c &quot;$source_path/docs&quot; \<br>&gt; &gt; -                    -b html &quot;$TMPDIR1/sphinx&quot; \<br>&gt; &gt; -                    &quot;$TMPDIR1/sphinx/out&quot;  &gt;&gt; config.log 2&gt;&amp;1<br>&gt; &gt; -}<br>&gt; &gt; -<br>&gt; &gt; -# Check if tools are available to build documentation.<br>&gt; &gt; -if test &quot;$docs&quot; != &quot;no&quot; ; then<br>&gt; &gt; -  if has_sphinx_build; then<br>&gt; &gt; -    sphinx_ok=yes<br>&gt; &gt; -  else<br>&gt; &gt; -    sphinx_ok=no<br>&gt; &gt; -  fi<br>&gt; &gt; -  if test &quot;$sphinx_ok&quot; = &quot;yes&quot;; then<br>&gt; &gt; -    docs=yes<br>&gt; &gt; -  else<br>&gt; &gt; -    if test &quot;$docs&quot; = &quot;yes&quot; ; then<br>&gt; &gt; -      if has $sphinx_build &amp;&amp; test &quot;$sphinx_ok&quot; != &quot;yes&quot;; then<br>&gt; &gt; -        echo &quot;Warning: $sphinx_build exists but it is either too old or uses too old a Python version&quot; &gt;&amp;2<br>&gt; &gt; -      fi<br>&gt; &gt; -      feature_not_found &quot;docs&quot; &quot;Install a Python 3 version of python-sphinx&quot;<br>&gt; &gt; -    fi<br>&gt; &gt; -    docs=no<br>&gt; &gt; -  fi<br>&gt; &gt; -fi<br>&gt; &gt; -<br>&gt; &gt;  # Search for bswap_32 function<br>&gt; &gt;  byteswap_h=no<br>&gt; &gt;  cat &gt; $TMPC &lt;&lt; EOF<br>&gt; &gt; @@ -6087,9 +6039,6 @@ qemu_version=$(head $source_path/VERSION)<br>&gt; &gt;  echo &quot;PKGVERSION=$pkgversion&quot; &gt;&gt;$config_host_mak<br>&gt; &gt;  echo &quot;SRC_PATH=$source_path&quot; &gt;&gt; $config_host_mak<br>&gt; &gt;  echo &quot;TARGET_DIRS=$target_list&quot; &gt;&gt; $config_host_mak<br>&gt; &gt; -if [ &quot;$docs&quot; = &quot;yes&quot; ] ; then<br>&gt; &gt; -  echo &quot;BUILD_DOCS=yes&quot; &gt;&gt; $config_host_mak<br>&gt; &gt; -fi<br>&gt; &gt;  if test &quot;$modules&quot; = &quot;yes&quot;; then<br>&gt; &gt;    # $shacmd can generate a hash started with digit, which the compiler doesn&#39;t<br>&gt; &gt;    # like as an symbol. So prefix it with an underscore<br>&gt; &gt; @@ -6794,7 +6743,6 @@ fi<br>&gt; &gt;  echo &quot;ROMS=$roms&quot; &gt;&gt; $config_host_mak<br>&gt; &gt;  echo &quot;MAKE=$make&quot; &gt;&gt; $config_host_mak<br>&gt; &gt;  echo &quot;PYTHON=$python&quot; &gt;&gt; $config_host_mak<br>&gt; &gt; -echo &quot;SPHINX_BUILD=$sphinx_build&quot; &gt;&gt; $config_host_mak<br>&gt; &gt;  echo &quot;GENISOIMAGE=$genisoimage&quot; &gt;&gt; $config_host_mak<br>&gt; &gt;  echo &quot;MESON=$meson&quot; &gt;&gt; $config_host_mak<br>&gt; &gt;  echo &quot;CC=$cc&quot; &gt;&gt; $config_host_mak<br>&gt; &gt; @@ -7076,6 +7024,7 @@ NINJA=${ninja:-$PWD/ninjatool} $meson setup \<br>&gt; &gt;          -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f \<br>&gt; &gt;          -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \<br>&gt; &gt;          -Diconv=$iconv -Dcurses=$curses \<br>&gt; &gt; +        -Ddocs=$docs -Dsphinx_build=$sphinx_build \<br>&gt; &gt;          $cross_arg \<br>&gt; &gt;          &quot;$PWD&quot; &quot;$source_path&quot;<br>&gt; &gt;<br>&gt; &gt; diff --git a/docs/meson.build b/docs/meson.build<br>&gt; &gt; index 0340d489ac..f566809a6a 100644<br>&gt; &gt; --- a/docs/meson.build<br>&gt; &gt; +++ b/docs/meson.build<br>&gt; &gt; @@ -37,7 +37,7 @@ if build_docs<br>&gt; &gt;                  input: [files(&#39;conf.py&#39;), files(manual / &#39;conf.py&#39;)],<br>&gt; &gt;                  depfile: manual + &#39;.d&#39;,<br>&gt; &gt;                  depend_files: sphinx_extn_depends,<br>&gt; &gt; -                command: [SPHINX_ARGS, &#39;-Ddepfile=@DEPFILE@&#39;,<br>&gt; &gt; +                command: SPHINX_ARGS + [&#39;-Ddepfile=@DEPFILE@&#39;,<br>&gt; &gt;                            &#39;-Ddepfile_stamp=@OUTPUT0@&#39;,<br>&gt; &gt;                            &#39;-b&#39;, &#39;html&#39;, &#39;-d&#39;, private_dir,<br>&gt; &gt;                            input_dir, output_dir])<br>&gt; &gt; @@ -59,7 +59,7 @@ if build_docs<br>&gt; &gt;                           input: this_manual,<br>&gt; &gt;                           install: build_docs,<br>&gt; &gt;                           install_dir: install_dirs,<br>&gt; &gt; -                         command: [SPHINX_ARGS, &#39;-b&#39;, &#39;man&#39;, &#39;-d&#39;, private_dir,<br>&gt; &gt; +                         command: SPHINX_ARGS + [&#39;-b&#39;, &#39;man&#39;, &#39;-d&#39;, private_dir,<br>&gt; &gt;                                     input_dir, meson.current_build_dir()])<br>&gt; &gt;      endif<br>&gt; &gt;    endforeach<br>&gt; &gt; diff --git a/meson.build b/meson.build<br>&gt; &gt; index 8156df8b71..8940468208 100644<br>&gt; &gt; --- a/meson.build<br>&gt; &gt; +++ b/meson.build<br>&gt; &gt; @@ -17,7 +17,13 @@ cc = meson.get_compiler(&#39;c&#39;)<br>&gt; &gt;  config_host = keyval.load(meson.current_build_dir() / &#39;config-host.mak&#39;)<br>&gt; &gt;  enable_modules = &#39;CONFIG_MODULES&#39; in config_host<br>&gt; &gt;  enable_static = &#39;CONFIG_STATIC&#39; in config_host<br>&gt; &gt; -build_docs = &#39;BUILD_DOCS&#39; in config_host<br>&gt; &gt; +<br>&gt; &gt; +# Temporary directory used for files created while<br>&gt; &gt; +# configure runs. Since it is in the build directory<br>&gt; &gt; +# we can safely blow away any previous version of it<br>&gt; &gt; +# (and we need not jump through hoops to try to delete<br>&gt; &gt; +# it when configure exits.)<br>&gt; &gt; +tmpdir = meson.current_build_dir() / &#39;config-temp&#39;<br>&gt; &gt;<br>&gt; &gt;  if get_option(&#39;qemu_suffix&#39;).startswith(&#39;/&#39;)<br>&gt; &gt;    error(&#39;qemu_suffix cannot start with a /&#39;)<br>&gt; &gt; @@ -1235,12 +1241,52 @@ foreach d : hx_headers<br>&gt; &gt;  endforeach<br>&gt; &gt;  genh += hxdep<br>&gt; &gt;<br>&gt; &gt; -SPHINX_ARGS = [config_host[&#39;SPHINX_BUILD&#39;],<br>&gt; &gt; -               &#39;-Dversion=&#39; + meson.project_version(),<br>&gt; &gt; -               &#39;-Drelease=&#39; + config_host[&#39;PKGVERSION&#39;]]<br>&gt; &gt; +sphinx_build = not_found<br>&gt; &gt; +sphinx_build_option = get_option(&#39;sphinx_build&#39;)<br>&gt; &gt; +if sphinx_build_option == &#39;&#39;<br>&gt; &gt; +  sphinx_build = find_program(&#39;sphinx-build&#39;, required: false)<br>&gt; &gt; +else<br>&gt; &gt; +  sphinx_build = find_program(sphinx_build_option, required: false)<br>&gt; &gt; +endif<br>&gt; &gt;<br>&gt; &gt; +SPHINX_TEST_ARGS = []<br>&gt; &gt; +# If we&#39;re making warnings fatal, apply this to Sphinx runs as well<br>&gt; &gt;  if get_option(&#39;werror&#39;)<br>&gt; &gt; -  SPHINX_ARGS += [ &#39;-W&#39; ]<br>&gt; &gt; +  SPHINX_TEST_ARGS += [ &#39;-W&#39; ]<br>&gt; &gt; +endif<br>&gt; &gt; +<br>&gt; &gt; +build_docs = false<br>&gt; &gt; +docs_option = get_option(&#39;docs&#39;)<br>&gt; &gt; +# Check if tools are available to build documentation.<br>&gt; &gt; +if sphinx_build.found() and not docs_option.disabled()<br>&gt; &gt; +    # This is a bit awkward but works: create a trivial document and<br>&gt; &gt; +    # try to run it with our configuration file (which enforces a<br>&gt; &gt; +    # version requirement). This will fail if either<br>&gt; &gt; +    # sphinx-build doesn&#39;t exist at all or if it is too old.<br>&gt; &gt; +    run_command(&#39;mkdir&#39;, [&#39;-p&#39;, tmpdir / &#39;sphinx&#39;])<br>&gt; &gt; +    run_command(&#39;touch&#39;, [tmpdir / &#39;sphinx/index.rst&#39;])<br>&gt; &gt; +    sphinx_build_test_out = run_command(sphinx_build, SPHINX_TEST_ARGS + [<br>&gt; &gt; +      &#39;-c&#39;, meson.current_source_dir() / &#39;docs&#39;,<br>&gt; &gt; +      &#39;-b&#39;, &#39;html&#39;, tmpdir / &#39;sphinx&#39;,<br>&gt; &gt; +      tmpdir / &#39;sphinx/out&#39;])<br>&gt; &gt; +    if sphinx_build_test_out.returncode() == 0<br>&gt; &gt; +      build_docs = true<br>&gt; &gt; +    else<br>&gt; &gt; +      if docs_option.enabled()<br>&gt; &gt; +        if sphinx_build_option != &#39;&#39;<br>&gt; &gt; +          warning(&#39;Warning: @0@ exists but it is either too old or uses too old a Python version&#39;.format(sphinx_build_option))<br>&gt; &gt; +        endif<br>&gt; &gt; +        error(&#39;Warning: Install a Python 3 version of python-sphinx&#39;)<br>&gt; &gt; +      endif<br>&gt; &gt; +      # do not building docs<br>&gt; &gt; +    endif<br>&gt; &gt; +endif<br>&gt; &gt; +<br>&gt; &gt; +SPHINX_ARGS = []<br>&gt; &gt; +if build_docs<br>&gt; &gt; +  SPHINX_ARGS = [sphinx_build]<br>&gt; &gt; +  SPHINX_ARGS += SPHINX_TEST_ARGS<br>&gt; &gt; +  SPHINX_ARGS += [&#39;-Dversion=&#39; + meson.project_version(), &#39;-Drelease=&#39; + config_host[&#39;PKGVERSION&#39;]]<br>&gt; &gt;  endif<br>&gt; &gt;<br>&gt; &gt;  sphinx_extn_depends = [ meson.source_root() / &#39;docs/sphinx/depfile.py&#39;,<br>&gt; &gt; @@ -1918,7 +1964,7 @@ summary_info += {&#39;QEMU_CFLAGS&#39;:       config_host[&#39;QEMU_CFLAGS&#39;]}<br>&gt; &gt;  summary_info += {&#39;QEMU_LDFLAGS&#39;:      config_host[&#39;QEMU_LDFLAGS&#39;]}<br>&gt; &gt;  summary_info += {&#39;make&#39;:              config_host[&#39;MAKE&#39;]}<br>&gt; &gt;  summary_info += {&#39;python&#39;:            &#39;@0@ (version: @1@)&#39;.format(python.full_path(), python.language_version())}<br>&gt; &gt; -summary_info += {&#39;sphinx-build&#39;:      config_host[&#39;SPHINX_BUILD&#39;]}<br>&gt; &gt; +summary_info += {&#39;sphinx-build&#39;:      sphinx_build.found()}<br>&gt; &gt;  summary_info += {&#39;genisoimage&#39;:       config_host[&#39;GENISOIMAGE&#39;]}<br>&gt; &gt;  # TODO: add back version<br>&gt; &gt;  summary_info += {&#39;slirp support&#39;:     slirp_opt == &#39;disabled&#39; ? false : slirp_opt}<br>&gt; &gt; @@ -1986,7 +2032,7 @@ if config_host.has_key(&#39;CONFIG_XEN_BACKEND&#39;)<br>&gt; &gt;    summary_info += {&#39;xen ctrl version&#39;:  config_host[&#39;CONFIG_XEN_CTRL_INTERFACE_VERSION&#39;]}<br>&gt; &gt;  endif<br>&gt; &gt;  summary_info += {&#39;brlapi support&#39;:    config_host.has_key(&#39;CONFIG_BRLAPI&#39;)}<br>&gt; &gt; -summary_info += {&#39;Documentation&#39;:     config_host.has_key(&#39;BUILD_DOCS&#39;)}<br>&gt; &gt; +summary_info += {&#39;Documentation&#39;:     build_docs}<br>&gt; &gt;  summary_info += {&#39;PIE&#39;:               get_option(&#39;b_pie&#39;)}<br>&gt; &gt;  summary_info += {&#39;vde support&#39;:       config_host.has_key(&#39;CONFIG_VDE&#39;)}<br>&gt; &gt;  summary_info += {&#39;netmap support&#39;:    config_host.has_key(&#39;CONFIG_NETMAP&#39;)}<br>&gt; &gt; diff --git a/meson_options.txt b/meson_options.txt<br>&gt; &gt; index e6cb1e589b..0e3fa7136b 100644<br>&gt; &gt; --- a/meson_options.txt<br>&gt; &gt; +++ b/meson_options.txt<br>&gt; &gt; @@ -1,8 +1,11 @@<br>&gt; &gt;  option(&#39;qemu_suffix&#39;, type : &#39;string&#39;, value: &#39;qemu&#39;,<br>&gt; &gt;         description: &#39;Suffix for QEMU data/modules/config directories (can be empty)&#39;)<br>&gt; &gt; +option(&#39;docs&#39;, type : &#39;feature&#39;, value : &#39;auto&#39;,<br>&gt; &gt; +       description: &#39;Documentations build support&#39;)<br>&gt; &gt;  option(&#39;docdir&#39;, type : &#39;string&#39;, value : &#39;doc&#39;,<br>&gt; &gt;         description: &#39;Base directory for documentation installation (can be empty)&#39;)<br>&gt; &gt; -<br>&gt; &gt; +option(&#39;sphinx_build&#39;, type : &#39;string&#39;, value : &#39;&#39;,<br>&gt; &gt; +       description: &#39;Use specified sphinx-build [$sphinx_build] for building document (default to be empty)&#39;)<br>&gt; &gt;  option(&#39;gettext&#39;, type : &#39;boolean&#39;, value : true,<br>&gt; &gt;         description: &#39;Localization of the GTK+ user interface&#39;)<br>&gt; &gt;  option(&#39;sparse&#39;, type : &#39;feature&#39;, value : &#39;auto&#39;,<br>&gt; &gt; diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build<br>&gt; &gt; index 1f222a7a13..961b8367a9 100644<br>&gt; &gt; --- a/tests/qapi-schema/meson.build<br>&gt; &gt; +++ b/tests/qapi-schema/meson.build<br>&gt; &gt; @@ -237,7 +237,7 @@ qapi_doc_out = custom_target(&#39;QAPI rST doc&#39;,<br>&gt; &gt;                               # we want it to always really run the QAPI doc<br>&gt; &gt;                               # generation code. It also means we don&#39;t<br>&gt; &gt;                               # clutter up the build dir with the cache.<br>&gt; &gt; -                             command: [SPHINX_ARGS,<br>&gt; &gt; +                             command:  SPHINX_ARGS + [<br>&gt; &gt;                                         &#39;-b&#39;, &#39;text&#39;, &#39;-E&#39;,<br>&gt; &gt;                                         &#39;-c&#39;, meson.source_root() / &#39;docs&#39;,<br>&gt; &gt;                                         &#39;-D&#39;, &#39;master_doc=doc-good&#39;,<br>&gt; &gt;<br>&gt;<br><br><br>--<br>         此致<br>礼<br>罗勇刚<br>Yours<br>    sincerely,<br>Yonggang Luo<br></div></div>
Paolo Bonzini Oct. 16, 2020, 7:57 a.m. UTC | #3
On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:
> 
>> build_docs = false
>> if sphinx_build.found()
>>   # This is a bit awkward but works: create a trivial document and
>>   # try to run it with our configuration file (which enforces a
>>   # version requirement). This will fail if sphinx-build is too old.
>>   run_command('mkdir', ['-p', tmpdir / 'sphinx'])
>>   run_command('touch', [tmpdir / 'sphinx/index.rst'])
>>   sphinx_build_test_out = run_command(SPHINX_ARGS + [
>>     '-c', meson.current_source_dir() / 'docs',
>>     '-b', 'html', tmpdir / 'sphinx',
>>     tmpdir / 'sphinx/out'])
>>   build_docs = (sphinx_build_test_out.returncode() == 0)
>> endif
> There is subtle error here, when  sphinx_build not found, there is
> SPHINX_ARGS  should be [],
> otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build
> will cause error by meson
> ..
> I'll add
> 
> else
>   SPHINX_ARGS  = []  
> endif

All uses of SPHINX_ARGS are protected by build_docs, and in turn
build_docs is false if "not sphinx_build.found()".  Am I missing something?

Paolo
罗勇刚(Yonggang Luo) Oct. 16, 2020, 7:58 a.m. UTC | #4
On Fri, Oct 16, 2020 at 3:57 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>

> On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:

> >

> >> build_docs = false

> >> if sphinx_build.found()

> >>   # This is a bit awkward but works: create a trivial document and

> >>   # try to run it with our configuration file (which enforces a

> >>   # version requirement). This will fail if sphinx-build is too old.

> >>   run_command('mkdir', ['-p', tmpdir / 'sphinx'])

> >>   run_command('touch', [tmpdir / 'sphinx/index.rst'])

> >>   sphinx_build_test_out = run_command(SPHINX_ARGS + [

> >>     '-c', meson.current_source_dir() / 'docs',

> >>     '-b', 'html', tmpdir / 'sphinx',

> >>     tmpdir / 'sphinx/out'])

> >>   build_docs = (sphinx_build_test_out.returncode() == 0)

> >> endif

> > There is subtle error here, when  sphinx_build not found, there is

> > SPHINX_ARGS  should be [],

> > otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build

> > will cause error by meson

> > ..

> > I'll add

> >

> > else

> >   SPHINX_ARGS  = []

> > endif

>

> All uses of SPHINX_ARGS are protected by build_docs, and in turn

> build_docs is false if "not sphinx_build.found()".  Am I missing

something?
Not all protected, missed in qapi/schema tests
>

> Paolo

>



--
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo
<div dir="ltr"><br><br>On Fri, Oct 16, 2020 at 3:57 PM Paolo Bonzini &lt;<a href="mailto:pbonzini@redhat.com">pbonzini@redhat.com</a>&gt; wrote:<br>&gt;<br>&gt; On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:<br>&gt; &gt;<br>&gt; &gt;&gt; build_docs = false<br>&gt; &gt;&gt; if sphinx_build.found()<br>&gt; &gt;&gt;   # This is a bit awkward but works: create a trivial document and<br>&gt; &gt;&gt;   # try to run it with our configuration file (which enforces a<br>&gt; &gt;&gt;   # version requirement). This will fail if sphinx-build is too old.<br>&gt; &gt;&gt;   run_command(&#39;mkdir&#39;, [&#39;-p&#39;, tmpdir / &#39;sphinx&#39;])<br>&gt; &gt;&gt;   run_command(&#39;touch&#39;, [tmpdir / &#39;sphinx/index.rst&#39;])<br>&gt; &gt;&gt;   sphinx_build_test_out = run_command(SPHINX_ARGS + [<br>&gt; &gt;&gt;     &#39;-c&#39;, meson.current_source_dir() / &#39;docs&#39;,<br>&gt; &gt;&gt;     &#39;-b&#39;, &#39;html&#39;, tmpdir / &#39;sphinx&#39;,<br>&gt; &gt;&gt;     tmpdir / &#39;sphinx/out&#39;])<br>&gt; &gt;&gt;   build_docs = (sphinx_build_test_out.returncode() == 0)<br>&gt; &gt;&gt; endif<br>&gt; &gt; There is subtle error here, when  sphinx_build not found, there is<br>&gt; &gt; SPHINX_ARGS  should be [],<br>&gt; &gt; otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build<br>&gt; &gt; will cause error by meson<br>&gt; &gt; ..<br>&gt; &gt; I&#39;ll add<br>&gt; &gt;<br>&gt; &gt; else<br>&gt; &gt;   SPHINX_ARGS  = []  <br>&gt; &gt; endif<br>&gt;<br>&gt; All uses of SPHINX_ARGS are protected by build_docs, and in turn<br>&gt; build_docs is false if &quot;not sphinx_build.found()&quot;.  Am I missing something?<div>Not all protected, missed in qapi/schema tests<br>&gt;<br>&gt; Paolo<br>&gt;<br><br><br>--<br>         此致<br>礼<br>罗勇刚<br>Yours<br>    sincerely,<br>Yonggang Luo</div></div>
罗勇刚(Yonggang Luo) Oct. 16, 2020, 7:58 a.m. UTC | #5
On Fri, Oct 16, 2020 at 3:57 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:
> >
> >> build_docs = false
> >> if sphinx_build.found()
> >>   # This is a bit awkward but works: create a trivial document and
> >>   # try to run it with our configuration file (which enforces a
> >>   # version requirement). This will fail if sphinx-build is too old.
> >>   run_command('mkdir', ['-p', tmpdir / 'sphinx'])
> >>   run_command('touch', [tmpdir / 'sphinx/index.rst'])
> >>   sphinx_build_test_out = run_command(SPHINX_ARGS + [
> >>     '-c', meson.current_source_dir() / 'docs',
> >>     '-b', 'html', tmpdir / 'sphinx',
> >>     tmpdir / 'sphinx/out'])
> >>   build_docs = (sphinx_build_test_out.returncode() == 0)
> >> endif
> > There is subtle error here, when  sphinx_build not found, there is
> > SPHINX_ARGS  should be [],
> > otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build
> > will cause error by meson
> > ..
> > I'll add
> >
> > else
> >   SPHINX_ARGS  = []
> > endif
>
> All uses of SPHINX_ARGS are protected by build_docs, and in turn
> build_docs is false if "not sphinx_build.found()".  Am I missing
something?
>
> Paolo
>
Rfer to
https://github.com/lygstate/qemu/runs/1261141240?check_suite_focus=true

--
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo
<div dir="ltr"><br><br>On Fri, Oct 16, 2020 at 3:57 PM Paolo Bonzini &lt;<a href="mailto:pbonzini@redhat.com">pbonzini@redhat.com</a>&gt; wrote:<br>&gt;<br>&gt; On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:<br>&gt; &gt;<br>&gt; &gt;&gt; build_docs = false<br>&gt; &gt;&gt; if sphinx_build.found()<br>&gt; &gt;&gt;   # This is a bit awkward but works: create a trivial document and<br>&gt; &gt;&gt;   # try to run it with our configuration file (which enforces a<br>&gt; &gt;&gt;   # version requirement). This will fail if sphinx-build is too old.<br>&gt; &gt;&gt;   run_command(&#39;mkdir&#39;, [&#39;-p&#39;, tmpdir / &#39;sphinx&#39;])<br>&gt; &gt;&gt;   run_command(&#39;touch&#39;, [tmpdir / &#39;sphinx/index.rst&#39;])<br>&gt; &gt;&gt;   sphinx_build_test_out = run_command(SPHINX_ARGS + [<br>&gt; &gt;&gt;     &#39;-c&#39;, meson.current_source_dir() / &#39;docs&#39;,<br>&gt; &gt;&gt;     &#39;-b&#39;, &#39;html&#39;, tmpdir / &#39;sphinx&#39;,<br>&gt; &gt;&gt;     tmpdir / &#39;sphinx/out&#39;])<br>&gt; &gt;&gt;   build_docs = (sphinx_build_test_out.returncode() == 0)<br>&gt; &gt;&gt; endif<br>&gt; &gt; There is subtle error here, when  sphinx_build not found, there is<br>&gt; &gt; SPHINX_ARGS  should be [],<br>&gt; &gt; otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build<br>&gt; &gt; will cause error by meson<br>&gt; &gt; ..<br>&gt; &gt; I&#39;ll add<br>&gt; &gt;<br>&gt; &gt; else<br>&gt; &gt;   SPHINX_ARGS  = []  <br>&gt; &gt; endif<br>&gt;<br>&gt; All uses of SPHINX_ARGS are protected by build_docs, and in turn<br>&gt; build_docs is false if &quot;not sphinx_build.found()&quot;.  Am I missing something?<br>&gt;<br>&gt; Paolo<br>&gt;<br>Rfer to <a href="https://github.com/lygstate/qemu/runs/1261141240?check_suite_focus=true">https://github.com/lygstate/qemu/runs/1261141240?check_suite_focus=true</a><br><br>--<br>         此致<br>礼<br>罗勇刚<br>Yours<br>    sincerely,<br>Yonggang Luo</div>
Paolo Bonzini Oct. 16, 2020, 8:05 a.m. UTC | #6
On 16/10/20 09:57, Paolo Bonzini wrote:
> On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:
>>
>>> build_docs = false
>>> if sphinx_build.found()
>>>   # This is a bit awkward but works: create a trivial document and
>>>   # try to run it with our configuration file (which enforces a
>>>   # version requirement). This will fail if sphinx-build is too old.
>>>   run_command('mkdir', ['-p', tmpdir / 'sphinx'])
>>>   run_command('touch', [tmpdir / 'sphinx/index.rst'])
>>>   sphinx_build_test_out = run_command(SPHINX_ARGS + [
>>>     '-c', meson.current_source_dir() / 'docs',
>>>     '-b', 'html', tmpdir / 'sphinx',
>>>     tmpdir / 'sphinx/out'])
>>>   build_docs = (sphinx_build_test_out.returncode() == 0)
>>> endif
>> There is subtle error here, when  sphinx_build not found, there is
>> SPHINX_ARGS  should be [],
>> otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build
>> will cause error by meson
>> ..
>> I'll add
>>
>> else
>>   SPHINX_ARGS  = []  
>> endif
> 
> All uses of SPHINX_ARGS are protected by build_docs, and in turn
> build_docs is false if "not sphinx_build.found()".  Am I missing something?

Ah there are uses in tests/ too, those should all be under "if
build_docs" too.

Paolo
罗勇刚(Yonggang Luo) Oct. 16, 2020, 8:12 a.m. UTC | #7
On Fri, Oct 16, 2020 at 4:05 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>

> On 16/10/20 09:57, Paolo Bonzini wrote:

> > On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:

> >>

> >>> build_docs = false

> >>> if sphinx_build.found()

> >>>   # This is a bit awkward but works: create a trivial document and

> >>>   # try to run it with our configuration file (which enforces a

> >>>   # version requirement). This will fail if sphinx-build is too old.

> >>>   run_command('mkdir', ['-p', tmpdir / 'sphinx'])

> >>>   run_command('touch', [tmpdir / 'sphinx/index.rst'])

> >>>   sphinx_build_test_out = run_command(SPHINX_ARGS + [

> >>>     '-c', meson.current_source_dir() / 'docs',

> >>>     '-b', 'html', tmpdir / 'sphinx',

> >>>     tmpdir / 'sphinx/out'])

> >>>   build_docs = (sphinx_build_test_out.returncode() == 0)

> >>> endif

> >> There is subtle error here, when  sphinx_build not found, there is

> >> SPHINX_ARGS  should be [],

> >> otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build

> >> will cause error by meson

> >> ..

> >> I'll add

> >>

> >> else

> >>   SPHINX_ARGS  = []

> >> endif

> >

> > All uses of SPHINX_ARGS are protected by build_docs, and in turn

> > build_docs is false if "not sphinx_build.found()".  Am I missing

something?
>

> Ah there are uses in tests/ too, those should all be under "if

> build_docs" too.

Yeap, I did it before, but that changes a lot and not easy to review, you
can do it in separate patch.
Anyway setting  SPHINX_ARGS  to [] are more robust.
>

> Paolo

>



--
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo
<div dir="ltr"><br><br>On Fri, Oct 16, 2020 at 4:05 PM Paolo Bonzini &lt;<a href="mailto:pbonzini@redhat.com">pbonzini@redhat.com</a>&gt; wrote:<br>&gt;<br>&gt; On 16/10/20 09:57, Paolo Bonzini wrote:<br>&gt; &gt; On 16/10/20 09:52, 罗勇刚(Yonggang Luo) wrote:<br>&gt; &gt;&gt;<br>&gt; &gt;&gt;&gt; build_docs = false<br>&gt; &gt;&gt;&gt; if sphinx_build.found()<br>&gt; &gt;&gt;&gt;   # This is a bit awkward but works: create a trivial document and<br>&gt; &gt;&gt;&gt;   # try to run it with our configuration file (which enforces a<br>&gt; &gt;&gt;&gt;   # version requirement). This will fail if sphinx-build is too old.<br>&gt; &gt;&gt;&gt;   run_command(&#39;mkdir&#39;, [&#39;-p&#39;, tmpdir / &#39;sphinx&#39;])<br>&gt; &gt;&gt;&gt;   run_command(&#39;touch&#39;, [tmpdir / &#39;sphinx/index.rst&#39;])<br>&gt; &gt;&gt;&gt;   sphinx_build_test_out = run_command(SPHINX_ARGS + [<br>&gt; &gt;&gt;&gt;     &#39;-c&#39;, meson.current_source_dir() / &#39;docs&#39;,<br>&gt; &gt;&gt;&gt;     &#39;-b&#39;, &#39;html&#39;, tmpdir / &#39;sphinx&#39;,<br>&gt; &gt;&gt;&gt;     tmpdir / &#39;sphinx/out&#39;])<br>&gt; &gt;&gt;&gt;   build_docs = (sphinx_build_test_out.returncode() == 0)<br>&gt; &gt;&gt;&gt; endif<br>&gt; &gt;&gt; There is subtle error here, when  sphinx_build not found, there is<br>&gt; &gt;&gt; SPHINX_ARGS  should be [],<br>&gt; &gt;&gt; otherwise, latter place using  SPHINX_ARGS  have not found sphinx_build<br>&gt; &gt;&gt; will cause error by meson<br>&gt; &gt;&gt; ..<br>&gt; &gt;&gt; I&#39;ll add<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; else<br>&gt; &gt;&gt;   SPHINX_ARGS  = []  <br>&gt; &gt;&gt; endif<br>&gt; &gt;<br>&gt; &gt; All uses of SPHINX_ARGS are protected by build_docs, and in turn<br>&gt; &gt; build_docs is false if &quot;not sphinx_build.found()&quot;.  Am I missing something?<br>&gt;<br>&gt; Ah there are uses in tests/ too, those should all be under &quot;if<br>&gt; build_docs&quot; too.<div>Yeap, I did it before, but that changes a lot and not easy to review, you can do it in separate patch.</div><div>Anyway setting 

SPHINX_ARGS  to [] are more robust.<br>&gt;<br>&gt; Paolo<br>&gt;<br><br><br>--<br>         此致<br>礼<br>罗勇刚<br>Yours<br>    sincerely,<br>Yonggang Luo</div></div>
diff mbox series

Patch

diff --git a/configure b/configure
index 1ce31f97b4..ff593a8542 100755
--- a/configure
+++ b/configure
@@ -297,7 +297,7 @@  brlapi=""
 curl=""
 iconv="auto"
 curses="auto"
-docs=""
+docs="auto"
 fdt="auto"
 netmap="no"
 sdl="auto"
@@ -822,15 +822,6 @@  do
     fi
 done
 
-sphinx_build=
-for binary in sphinx-build-3 sphinx-build
-do
-    if has "$binary"
-    then
-        sphinx_build=$(command -v "$binary")
-        break
-    fi
-done
 
 # Check for ancillary tools used in testing
 genisoimage=
@@ -1226,9 +1217,9 @@  for opt do
   ;;
   --disable-crypto-afalg) crypto_afalg="no"
   ;;
-  --disable-docs) docs="no"
+  --disable-docs) docs="disabled"
   ;;
-  --enable-docs) docs="yes"
+  --enable-docs) docs="enabled"
   ;;
   --disable-vhost-net) vhost_net="no"
   ;;
@@ -4413,45 +4404,6 @@  if check_include linux/btrfs.h ; then
     btrfs=yes
 fi
 
-# If we're making warnings fatal, apply this to Sphinx runs as well
-sphinx_werror=""
-if test "$werror" = "yes"; then
-    sphinx_werror="-W"
-fi
-
-# Check we have a new enough version of sphinx-build
-has_sphinx_build() {
-    # This is a bit awkward but works: create a trivial document and
-    # try to run it with our configuration file (which enforces a
-    # version requirement). This will fail if either
-    # sphinx-build doesn't exist at all or if it is too old.
-    mkdir -p "$TMPDIR1/sphinx"
-    touch "$TMPDIR1/sphinx/index.rst"
-    "$sphinx_build" $sphinx_werror -c "$source_path/docs" \
-                    -b html "$TMPDIR1/sphinx" \
-                    "$TMPDIR1/sphinx/out"  >> config.log 2>&1
-}
-
-# Check if tools are available to build documentation.
-if test "$docs" != "no" ; then
-  if has_sphinx_build; then
-    sphinx_ok=yes
-  else
-    sphinx_ok=no
-  fi
-  if test "$sphinx_ok" = "yes"; then
-    docs=yes
-  else
-    if test "$docs" = "yes" ; then
-      if has $sphinx_build && test "$sphinx_ok" != "yes"; then
-        echo "Warning: $sphinx_build exists but it is either too old or uses too old a Python version" >&2
-      fi
-      feature_not_found "docs" "Install a Python 3 version of python-sphinx"
-    fi
-    docs=no
-  fi
-fi
-
 # Search for bswap_32 function
 byteswap_h=no
 cat > $TMPC << EOF
@@ -6087,9 +6039,6 @@  qemu_version=$(head $source_path/VERSION)
 echo "PKGVERSION=$pkgversion" >>$config_host_mak
 echo "SRC_PATH=$source_path" >> $config_host_mak
 echo "TARGET_DIRS=$target_list" >> $config_host_mak
-if [ "$docs" = "yes" ] ; then
-  echo "BUILD_DOCS=yes" >> $config_host_mak
-fi
 if test "$modules" = "yes"; then
   # $shacmd can generate a hash started with digit, which the compiler doesn't
   # like as an symbol. So prefix it with an underscore
@@ -6794,7 +6743,6 @@  fi
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "PYTHON=$python" >> $config_host_mak
-echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak
 echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
 echo "MESON=$meson" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
@@ -7076,6 +7024,7 @@  NINJA=${ninja:-$PWD/ninjatool} $meson setup \
         -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f \
         -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \
         -Diconv=$iconv -Dcurses=$curses \
+        -Ddocs=$docs -Dsphinx_build=$sphinx_build \
         $cross_arg \
         "$PWD" "$source_path"
 
diff --git a/docs/meson.build b/docs/meson.build
index 0340d489ac..f566809a6a 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -37,7 +37,7 @@  if build_docs
                 input: [files('conf.py'), files(manual / 'conf.py')],
                 depfile: manual + '.d',
                 depend_files: sphinx_extn_depends,
-                command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
+                command: SPHINX_ARGS + ['-Ddepfile=@DEPFILE@',
                           '-Ddepfile_stamp=@OUTPUT0@',
                           '-b', 'html', '-d', private_dir,
                           input_dir, output_dir])
@@ -59,7 +59,7 @@  if build_docs
                          input: this_manual,
                          install: build_docs,
                          install_dir: install_dirs,
-                         command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
+                         command: SPHINX_ARGS + ['-b', 'man', '-d', private_dir,
                                    input_dir, meson.current_build_dir()])
     endif
   endforeach
diff --git a/meson.build b/meson.build
index 8156df8b71..8940468208 100644
--- a/meson.build
+++ b/meson.build
@@ -17,7 +17,13 @@  cc = meson.get_compiler('c')
 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
 enable_modules = 'CONFIG_MODULES' in config_host
 enable_static = 'CONFIG_STATIC' in config_host
-build_docs = 'BUILD_DOCS' in config_host
+
+# Temporary directory used for files created while
+# configure runs. Since it is in the build directory
+# we can safely blow away any previous version of it
+# (and we need not jump through hoops to try to delete
+# it when configure exits.)
+tmpdir = meson.current_build_dir() / 'config-temp'
 
 if get_option('qemu_suffix').startswith('/')
   error('qemu_suffix cannot start with a /')
@@ -1235,12 +1241,52 @@  foreach d : hx_headers
 endforeach
 genh += hxdep
 
-SPHINX_ARGS = [config_host['SPHINX_BUILD'],
-               '-Dversion=' + meson.project_version(),
-               '-Drelease=' + config_host['PKGVERSION']]
+sphinx_build = not_found
+sphinx_build_option = get_option('sphinx_build')
+if sphinx_build_option == ''
+  sphinx_build = find_program('sphinx-build', required: false)
+else
+  sphinx_build = find_program(sphinx_build_option, required: false)
+endif
 
+SPHINX_TEST_ARGS = []
+# If we're making warnings fatal, apply this to Sphinx runs as well
 if get_option('werror')
-  SPHINX_ARGS += [ '-W' ]
+  SPHINX_TEST_ARGS += [ '-W' ]
+endif
+
+build_docs = false
+docs_option = get_option('docs')
+# Check if tools are available to build documentation.
+if sphinx_build.found() and not docs_option.disabled()
+    # This is a bit awkward but works: create a trivial document and
+    # try to run it with our configuration file (which enforces a
+    # version requirement). This will fail if either
+    # sphinx-build doesn't exist at all or if it is too old.
+    run_command('mkdir', ['-p', tmpdir / 'sphinx'])
+    run_command('touch', [tmpdir / 'sphinx/index.rst'])
+    sphinx_build_test_out = run_command(sphinx_build, SPHINX_TEST_ARGS + [
+      '-c', meson.current_source_dir() / 'docs',
+      '-b', 'html', tmpdir / 'sphinx',
+      tmpdir / 'sphinx/out'])
+    if sphinx_build_test_out.returncode() == 0
+      build_docs = true
+    else
+      if docs_option.enabled()
+        if sphinx_build_option != ''
+          warning('Warning: @0@ exists but it is either too old or uses too old a Python version'.format(sphinx_build_option))
+        endif
+        error('Warning: Install a Python 3 version of python-sphinx')
+      endif
+      # do not building docs
+    endif
+endif
+
+SPHINX_ARGS = []
+if build_docs
+  SPHINX_ARGS = [sphinx_build]
+  SPHINX_ARGS += SPHINX_TEST_ARGS
+  SPHINX_ARGS += ['-Dversion=' + meson.project_version(), '-Drelease=' + config_host['PKGVERSION']]
 endif
 
 sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
@@ -1918,7 +1964,7 @@  summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
 summary_info += {'make':              config_host['MAKE']}
 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
-summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
+summary_info += {'sphinx-build':      sphinx_build.found()}
 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
 # TODO: add back version
 summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
@@ -1986,7 +2032,7 @@  if config_host.has_key('CONFIG_XEN_BACKEND')
   summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
 endif
 summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
-summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
+summary_info += {'Documentation':     build_docs}
 summary_info += {'PIE':               get_option('b_pie')}
 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
diff --git a/meson_options.txt b/meson_options.txt
index e6cb1e589b..0e3fa7136b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,8 +1,11 @@ 
 option('qemu_suffix', type : 'string', value: 'qemu',
        description: 'Suffix for QEMU data/modules/config directories (can be empty)')
+option('docs', type : 'feature', value : 'auto',
+       description: 'Documentations build support')
 option('docdir', type : 'string', value : 'doc',
        description: 'Base directory for documentation installation (can be empty)')
-
+option('sphinx_build', type : 'string', value : '',
+       description: 'Use specified sphinx-build [$sphinx_build] for building document (default to be empty)')
 option('gettext', type : 'boolean', value : true,
        description: 'Localization of the GTK+ user interface')
 option('sparse', type : 'feature', value : 'auto',
diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index 1f222a7a13..961b8367a9 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -237,7 +237,7 @@  qapi_doc_out = custom_target('QAPI rST doc',
                              # we want it to always really run the QAPI doc
                              # generation code. It also means we don't
                              # clutter up the build dir with the cache.
-                             command: [SPHINX_ARGS,
+                             command:  SPHINX_ARGS + [
                                        '-b', 'text', '-E',
                                        '-c', meson.source_root() / 'docs',
                                        '-D', 'master_doc=doc-good',