[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