[Spice-devel] [PATCH spice-server v4 1/2] Add support for building with meson/ninja

Frediano Ziglio fziglio at redhat.com
Thu Jul 26 11:46:57 UTC 2018


> 
> In a comparison with current autotools build system, meson/ninja
> provides a huge improvement in build speed, while keeping the same
> functionalities currently available and being considered more user
> friendly.
> 
> The new system coexists within the same repository with the current one,
> so we can do more extensive testing of its functionality before deciding
> if the old system can be removed, or for some reason, has to stay for
> good.
> 
> - Meson: https://mesonbuild.com
> 
>   This is the equivalent of autogen/configure step in autotools. It
>   generates the files that will be used by ninja to actually build the
>   source code.
> 
>   The project has received lots of traction recently, with many GNOME
>   projects willing to move to this new build system. The following wiki
>   page has more details of the status of the many projects being ported:
> 
>     https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting
> 
>   Meson has a python-like syntax, easy to read, and the documentation
>   on the project is very complete, with a dedicated page on how to port
>   from autotools, explaining how most common use cases can be
>   implemented using meson.
> 
>     http://mesonbuild.com/Porting-from-autotools.html
> 
>   Other important sources of information:
> 
>     http://mesonbuild.com/howtox.html
>     http://mesonbuild.com/Syntax.html
>     http://mesonbuild.com/Reference-manual.html
> 
> - Ninja: https://ninja-build.org
> 
>   Ninja is the equivalent of make in an autotools setup, which actually
>   builds the source code. It has being used by large and complex
>   projects such as Google Chrome, Android and LLVM. There is not much to
>   say about ninja (other than it is much faster than make) because we
>   won't interact directly with it as much, as meson does the middle man
>   job here. The reasoning for creating ninja in the first place is
>   explained on the following post:
> 
>     http://neugierig.org/software/chromium/notes/2011/02/ninja.html
> 
>   Also its manual provides more in-depth information about the design
>   principles:
> 
>     https://ninja-build.org/manual.html
> 
> - Basic workflow:
> 
>   Meson package is available for most if not all distros, so, taking
>   Fedora as an example, we only need to run:
> 
>     # dnf -y install meson ninja-build.
> 
>   With Meson, building in-tree is not possible at all, so we need to
>   pass a directory as argument to meson where we want the build to be
>   done. This has the advantage of creating builds with different options
>   under the same parent directory, e.g.:
> 
>     $ meson ./build --prefix=/usr
>     $ meson ./build-extra -Dextra-checks=true -Dalignment-checks=true
> 
>   After configuration is done, we call ninja to actually do the build.
> 
>     $ ninja -C ./build
>     $ ninja -C ./build install
> 
>   Ninja defaults to parallel builds, and this can be changed with the -j
>   flag.
> 
>     $ ninja -j 10 -C ./build
> 
> - Hacking:
> 
>   * meson.build: Mandatory for the project root and usually found under
>                  each directory you want something to be built.
> 
>   * meson_options.txt: Options that can interfere with the result of the
>                        build.
> 
> Signed-off-by: Eduardo Lima (Etrunko) <etrunko at redhat.com>
> Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
>  Makefile.am                        |   3 +
>  build-aux/meson/check-spice-common |   5 +
>  docs/Makefile.am                   |   1 +
>  docs/manual/Makefile.am            |   1 +
>  docs/manual/meson.build            |  18 +++
>  docs/meson.build                   |  14 +++
>  meson.build                        | 219
>  +++++++++++++++++++++++++++++++++++++
>  meson_options.txt                  |  52 +++++++++
>  server/Makefile.am                 |   1 +
>  server/meson.build                 | 188 +++++++++++++++++++++++++++++++
>  server/tests/Makefile.am           |   1 +
>  server/tests/meson.build           |  85 ++++++++++++++
>  subprojects/spice-common           |   2 +-
>  tools/Makefile.am                  |   4 +
>  tools/meson.build                  |   4 +
>  15 files changed, 597 insertions(+), 1 deletion(-)
>  create mode 100755 build-aux/meson/check-spice-common
>  create mode 100644 docs/manual/meson.build
>  create mode 100644 docs/meson.build
>  create mode 100644 meson.build
>  create mode 100644 meson_options.txt
>  create mode 100644 server/meson.build
>  create mode 100644 server/tests/meson.build
>  create mode 100644 tools/meson.build
> 

....

> diff --git a/docs/meson.build b/docs/meson.build
> new file mode 100644
> index 00000000..82864bb8
> --- /dev/null
> +++ b/docs/meson.build
> @@ -0,0 +1,14 @@
> +if get_option('manual')
> +  asciidoc = find_program('asciidoc', required : false)
> +  if asciidoc.found()
> +    asciidoc_args = ['-a', 'data-uri', '-a', 'icons', '-a', 'toc']
> +    foreach doc : ['style', 'threading_model']
> +      custom_target('spice_ at 0@.html'.format(doc),
> +                    input : 'spice_ at 0@.txt'.format(doc),
> +                    output : 'spice_ at 0@.html'.format(doc),
> +                    build_by_default: true,
> +                    command : [asciidoc, '-n', asciidoc_args, '-o',
> '@OUTPUT@', '@INPUT@'])
> +    endforeach
> +  endif
> +  subdir('manual')
> +endif
> diff --git a/meson.build b/meson.build
> new file mode 100644
> index 00000000..b7b7fee7
> --- /dev/null
> +++ b/meson.build
> @@ -0,0 +1,219 @@
> +#
> +# project definition
> +#
> +project('spice', 'c',
> +        version : run_command('build-aux/git-version-gen',
> '${MESON_SOURCE_ROOT}/.tarball-version').stdout().strip(),
> +        license : 'LGPLv2.1',
> +        meson_version : '>= 0.47.0')
> +
> +# double check meson.project_version()
> +# we can not use 'check' keyword in run_command() for git-version-gen above
> +# https://github.com/mesonbuild/meson/issues/3944
> +version = run_command('build-aux/git-version-gen',
> '${MESON_SOURCE_ROOT}/.tarball-version', check : true).stdout().strip()
> +if meson.project_version() != version
> +  error('Wrong project version')
> +endif
> +
> +message('Updating submodules')
> +run_command('build-aux/meson/check-spice-common', check : true)
> +
> +# some global vars
> +spice_server_so_version = '1.12.4'
> +
> +spice_server_global_cflags = ['-fvisibility=hidden',
> +                              '-DSPICE_SERVER_INTERNAL',
> +                              '-DG_LOG_DOMAIN="Spice"',
> +                              '-DHAVE_CONFIG_H',
> +                              #'-Werror',
> +                              '-Wall',
> +                              '-Wextra',
> +                              '-Wno-sign-compare',
> +                              '-Wno-unused-parameter']
> +
> +compiler = meson.get_compiler('c')
> +spice_server_config_data = configuration_data()
> +spice_server_include = [include_directories('.')]
> +spice_server_deps = []
> +spice_server_link_args = []
> +spice_server_requires = ''
> +
> +#
> +# Spice common subproject
> +#
> +spice_common = subproject('spice-common', default_options :
> 'generate-code=server')
> +spice_server_config_data.merge_from(spice_common.get_variable('spice_common_config_data'))
> +spice_server_deps += spice_common.get_variable('spice_common_server_dep')
> +
> +#
> +# check for system headers
> +#
> +headers = ['sys/time.h',
> +           'execinfo.h',
> +           'linux/sockios.h',
> +           'pthread_np.h']
> +
> +foreach header : headers
> +  if compiler.has_header(header)
> +
> spice_server_config_data.set('HAVE_ at 0@'.format(header.underscorify().to_upper()),
> '1')
> +  endif
> +endforeach
> +
> +# TCP_KEEPIDLE definition in netinet/tcp.h
> +if compiler.has_header_symbol('netinet/tcp.h', 'TCP_KEEPIDLE')
> +  spice_server_config_data.set('HAVE_TCP_KEEPIDLE', '1')
> +endif
> +
> +#
> +# check for mandatory dependencies
> +#
> +spice_protocol_version='>= 0.12.15'
> +
> +glib_version = '2.38'
> +glib_version_info = '>= @0@'.format(glib_version)
> +
> +deps = [['spice-protocol', spice_protocol_version],
> +        ['glib-2.0', glib_version_info],
> +        ['gio-2.0', glib_version_info],
> +        ['gobject-2.0', glib_version_info],
> +        ['pixman-1', '>= 0.17.7'],
> +        ['openssl', '>= 1.0.0']]
> +
> +foreach dep : deps
> +  spice_server_deps += dependency(dep[0], version : dep[1])
> +endforeach
> +
> +# TODO: specify minimum version for jpeg and zlib?
> +foreach dep : ['libjpeg', 'zlib']
> +  spice_server_deps += dependency(dep)
> +endforeach
> +
> +foreach dep : ['librt', 'libm']
> +  spice_server_deps += compiler.find_library(dep)
> +endforeach
> +
> +#
> +# Non-mandatory/optional dependencies
> +#
> +optional_deps = [
> +                  ['celt051', '>= 0.5.1.1'],
> +                  ['opus', '>= 0.9.14'],
> +                ]
> +foreach dep : optional_deps
> +  option_value = get_option(dep[0])
> +  if option_value != 'false'
> +    d = dependency(dep[0], required: (option_value == 'true'), version :
> dep[1])
> +    if d.found()
> +      spice_server_deps += d
> +
> spice_server_config_data.set('HAVE_ at 0@'.format(dep[0].underscorify().to_upper()),
> '1')
> +    endif
> +  endif
> +endforeach
> +
> +# gstreamer
> +spice_server_has_gstreamer = false
> +spice_server_gst_version = get_option('gstreamer')
> +if spice_server_gst_version != 'no'
> +  gst_deps = ['gstreamer', 'gstreamer-base', 'gstreamer-app',
> 'gstreamer-video']
> +  foreach dep : gst_deps
> +    dep = '@0 at -@1@'.format(dep, spice_server_gst_version)
> +    spice_server_deps += dependency(dep)
> +  endforeach
> +  spice_server_deps += dependency('orc-0.4')
> +
> +  gst_def = 'HAVE_GSTREAMER'
> +  if spice_server_gst_version == '1.0'
> +    gst_def = 'HAVE_GSTREAMER_1_0'
> +  endif
> +
> +  spice_server_config_data.set(gst_def, '1')
> +  spice_server_has_gstreamer = true
> +endif
> +
> +# lz4
> +spice_server_has_lz4 = false
> +if get_option('lz4')
> +  lz4_dep = dependency('liblz4', required : false, version : '>= 129')
> +  if not lz4_dep.found()
> +    lz4_dep = dependency('liblz4', version : '>= 1.7.3')
> +  endif
> +
> +  if compiler.has_function('LZ4_compress_fast_continue', dependencies :
> lz4_dep)
> +    spice_server_config_data.set('HAVE_LZ4_COMPRESS_FAST_CONTINUE', '1')
> +  endif
> +
> +  spice_server_deps += lz4_dep
> +  spice_server_config_data.set('USE_LZ4', '1')
> +  spice_server_has_lz4 = true
> +endif
> +
> +# sasl
> +spice_server_has_sasl = false
> +if get_option('sasl')
> +  spice_server_deps += dependency('libsasl2')
> +  spice_server_config_data.set('HAVE_SASL', '1')
> +  spice_server_has_sasl = true
> +endif
> +
> +# smartcard check
> +spice_server_has_smartcard = false
> +if get_option('smartcard')
> +  smartcard_dep = dependency('libcacard', required : false, version : '>=
> 2.5.1')
> +  if smartcard_dep.found()
> +    spice_server_deps += smartcard_dep
> +    spice_server_config_data.set('USE_SMARTCARD', '1')
> +  else
> +    smartcard012_dep = dependency('libcacard', required : false, version :
> '>= 0.1.2')
> +    if smartcard012_dep.found()
> +      spice_server_deps += smartcard012_dep
> +      spice_server_config_data.set('USE_SMARTCARD_012', '1')
> +    endif
> +  endif
> +
> +  spice_server_has_smartcard = smartcard_dep.found() or
> smartcard012_dep.found()
> +  if not spice_server_has_smartcard
> +    error('Building with smartcard support but dependency not found')
> +  endif
> +endif
> +
> +#
> +# global C defines
> +#
> +glib_major_minor = glib_version.split('.')
> +glib_encoded_version = 'GLIB_VERSION_ at 0@_ at 1@'.format(glib_major_minor[0],
> glib_major_minor[1])
> +spice_server_global_cflags +=
> ['-DGLIB_VERSION_MIN_REQUIRED=@0@'.format(glib_encoded_version),
> +
> '-DGLIB_VERSION_MAX_ALLOWED=@0@'.format(glib_encoded_version)]
> +
> +foreach arg : spice_server_global_cflags
> +  add_project_arguments(arg, language : 'c')
> +endforeach
> +
> +#
> +# Subdirectories
> +#
> +subdir('server')
> +subdir('tools')
> +subdir('docs')
> +
> +#
> +# write config.h
> +#
> +spice_server_config_data.set_quoted('VERSION', meson.project_version())
> +spice_server_config_data.set('SPICE_USE_SAFER_CONTAINEROF', '1')
> +
> +if get_option('statistics')
> +  spice_server_config_data.set('RED_STATISTICS', '1')
> +endif
> +
> +configure_file(output : 'config.h',
> +               install : false,
> +               configuration : spice_server_config_data)
> +
> +#
> +# write spice-server.pc
> +#
> +pkgconfig = import('pkgconfig')
> +pkgconfig.generate(spice_server_shared_lib,
> +                   description : 'SPICE server library',
> +                   requires : 'spice-protocol
> @0@'.format(spice_protocol_version),
> +                   variables : 'exec_prefix=${prefix}',
> +                   subdirs : 'spice-server')

Was testing the difference in installed files. From autoconf:

-----
prefix=/home/freddy/qemu
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: spice
Description: SPICE server library
Version: 0.14.0.292-aad0-dirty

Requires: spice-protocol >= 0.12.15
Requires.private:  libcacard >= 0.1.2 glib-2.0 >= 2.32 gio-2.0 >= 2.32 gobject-2.0 >= 2.32 pixman-1 >= 0.17.7 openssl
Libs: -L${libdir} -lspice-server
Libs.private:  -pthread -lm -lrt
Cflags: -I${includedir}/spice-server
----

>From Meson:
-----
prefix=/usr/local
libdir=${prefix}/lib64
includedir=${prefix}/include

exec_prefix=${prefix}

Name: spice-server
Description: SPICE server library
Version: 0.14.0.292-aad0-dirty
Requires: spice-protocol >=  0.12.15, spice-protocol >=  0.12.12
Requires.private: glib-2.0 >=  2.38, gio-2.0 >=  2.38, gthread-2.0 >=  2.38, pixman-1 >=  0.17.7, openssl >=  1.0.0, celt051 >=  0.5.1.1, opus >=  0.9.14, libcacard >=  0.1.2, gobject-2.0 >=  2.38, libjpeg, zlib, gstreamer-1.0, gstreamer-base-1.0, gstreamer-app-1.0, gstreamer-video-1.0, orc-0.4, liblz4 >=  1.7.3, libsasl2
Libs: -L${libdir} -lspice-server
Libs.private: -lm -L${libdir} -lspice-common -lm -lm -lspice-common-server -lm /usr/lib64/librt.so /usr/lib64/libm.so
Cflags: -I${includedir}/spice-server
-----

Beside directories that is up to the setup:
- Name is spice for autotools, spice-server for Meson, seems more correct Meson
- Requires in Meson specify 2 times spice-protocol, should not be an issue
- Requires.private in Meson contains a lot of more libraries, this cause pkg-config --cflags to add a lot of include directories which are not required to link to spice library and IMHO should be avoided
- Libs.private contains duplications, direct shared library names (why?) and libraries (spice-common) which should not be there. Not clear where this directive is used, pkg-config --libs seems not to consider these libraries.
I don't know how to solve these, maybe the spice-common library should be more a static library (in libtool they are called convenience libraries).

....

Frediano


More information about the Spice-devel mailing list