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

Frediano Ziglio fziglio at redhat.com
Wed Apr 11 11:27:37 UTC 2018


> 
> Signed-off-by: Eduardo Lima (Etrunko) <etrunko at redhat.com>
> ---
>  docs/manual/meson.build       |  21 +++++
>  docs/meson.build              |  16 ++++
>  meson.build                   | 175 ++++++++++++++++++++++++++++++++++++
>  meson_options.txt             |  39 ++++++++
>  server/meson.build            | 205
>  ++++++++++++++++++++++++++++++++++++++++++
>  server/tests/meson.build      |  88 ++++++++++++++++++
>  subprojects/spice-common.wrap |   4 +
>  tools/meson.build             |   5 ++
>  8 files changed, 553 insertions(+)
>  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 subprojects/spice-common.wrap
>  create mode 100644 tools/meson.build
> 
> diff --git a/docs/manual/meson.build b/docs/manual/meson.build
> new file mode 100644
> index 00000000..178ac325
> --- /dev/null
> +++ b/docs/manual/meson.build
> @@ -0,0 +1,21 @@
> +txt = files('manual.txt')
> +dir = meson.current_build_dir()
> +
> +if asciidoc.found()
> +  custom_target('manual.html',
> +                input : txt,
> +                output : 'manual.html',
> +                command : [asciidoc, '-n', asciidoc_args, '-o', '@OUTPUT@',
> '@INPUT@'],
> +                install_dir : dir, # FIXME: used to force the build of the
> documentation,
> +                install : true)    #        if install is false, it will not
> be done.
> +endif
> +
> +a2x = find_program('a2x', required : false)
> +if a2x.found()
> +  custom_target('manual.chunked',
> +                input : txt,
> +                output : 'manual.chunked',
> +                command : [a2x, '-f', 'chunked', '-D', dir, asciidoc_args,
> '@INPUT@'],
> +                install_dir : dir, # FIXME: used to force the build of the
> documentation,
> +                install : true)    #        if install is false, it will not
> be done.
> +endif
> diff --git a/docs/meson.build b/docs/meson.build
> new file mode 100644
> index 00000000..0b37e931
> --- /dev/null
> +++ b/docs/meson.build
> @@ -0,0 +1,16 @@
> +if get_option('manual')
> +  asciidoc = find_program('asciidoc', required : false)
> +  asciidoc_args = ['-a', 'data-uri', '-a', 'icons', '-a', 'toc']
> +
> +  if asciidoc.found()
> +    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),
> +                    command : [asciidoc, '-n', asciidoc_args, '-o',
> '@OUTPUT@', '@INPUT@'],
> +                    install_dir : meson.current_build_dir(), # FIXME: used
> to force the build of the documentation,
> +                    install : true)                          #        if
> install is false, it will not be done.
> +    endforeach
> +  endif
> +  subdir('manual')
> +endif
> diff --git a/meson.build b/meson.build
> new file mode 100644
> index 00000000..f373e662
> --- /dev/null
> +++ b/meson.build
> @@ -0,0 +1,175 @@
> +#
> +# project definition
> +#
> +# TODO: double check meson.project_version()
> +# Ideally we would use the output of git-version-gen as input for meson,
> because
> +# we can not check the result of the command before declaring project().
> +#
> +project('spice', 'c',
> +         version : run_command('build-aux/git-version-gen',
> '.tarball-version').stdout().strip(),
> +         license : 'LGPLv2.1',
> +         meson_version : '>= 0.45.0')
> +
> +#
> +# global C defines
> +#
> +spice_server_global_cflags = [#'-std=c99', # fails compiling
> spice-common/bitops.h
> +                              '-fvisibility=hidden',
> +                              '-DSPICE_SERVER_INTERNAL',
> +                              '-DHAVE_CONFIG_H',
> +                              '-Wall',
> +                              '-Wextra',
> +                              #'-Werror',
> +                              '-Wno-sign-compare',
> +                              '-Wno-unused-parameter']
> +

about this, autoconf spend a lot of time looking at a lot of warning
options, how can be done in Meson?

On overall I think we should have a transition period where we
move from a system to the other trying to have the new one
feature equivalent. For instance rpm spec still uses autoconf stuff.

> +foreach arg : spice_server_global_cflags
> +  add_global_arguments(arg, language : 'c')
> +endforeach
> +
> +# other global vars
> +compiler = meson.get_compiler('c')
> +spice_server_config_data = configuration_data()
> +spice_server_config_data.set_quoted('VERSION', meson.project_version())
> +spice_protocol_min_version='0.12.14'
> +spice_server_include = [include_directories('.')]
> +spice_server_libs = []
> +spice_server_deps = []
> +spice_server_link_args = []
> +spice_server_requires = ''
> +
> +#
> +# Spice common subproject
> +#
> +spice_common_options =
> ['protocol-version=@0@'.format(spice_protocol_min_version),
> +                        'generate-code=server']
> +
> +spice_common = subproject('spice-common', default_options :
> spice_common_options)
> +spice_server_config_data.merge_from(spice_common.get_variable('spice_common_config_data'))
> +spice_server_include += spice_common.get_variable('spice_common_include')
> +
> +foreach dep : ['spice_common_deps', 'spice_common_server_dep']
> +  spice_server_deps += [spice_common.get_variable(dep)]
> +endforeach
> +
> +foreach lib : ['spice_common_lib', 'spice_common_server_lib']
> +  spice_server_libs += spice_common.get_variable(lib)
> +endforeach
> +
> +#
> +# check for system headers
> +#
> +headers = [['sys/time.h', 'HAVE_SYS_TIME_H'],
> +           ['execinfo.h', 'HAVE_EXECINFO_H'],
> +           ['linux/sockios.h', 'HAVE_LINUX_SOCKIOS_H'],
> +           ['pthread_np.h', 'HAVE_PTHREAD_NP_H']]
> +

seems quite manual having to specify both header name and
macro name, can that be automated like in configure.ac?
How much Python Meson is?

> +foreach h : headers
> +  if compiler.has_header(h[0])
> +    spice_server_config_data.set(h[1], '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
> +#
> +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
> +#
> +
> +# 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
> +
> +  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')

are these "dependency" using pkg-config? What about packages not
using pkg-config?

> +  spice_server_config_data.set('HAVE_SASL', '1')
> +  spice_server_has_sasl = true
> +endif
> +
> +# checks for smartcard are done in spice_common
> +spice_server_has_smartcard = false
> +if get_option('smartcard')
> +  if not spice_common.get_variable('spice_common_has_smartcard')
> +    error('Building with smartcard support but dependency not found')
> +  else
> +    spice_server_has_smartcard = true
> +  endif
> +endif
> +
> +#
> +# Subdirectories
> +#
> +subdir('server')
> +subdir('tools')
> +subdir('docs')
> +
> +#
> +# write config.h
> +#
> +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
> +# TODO: use built-in pkgconfig generator
> +#
> +pkgconfig = import('pkgconfig')
> +pkgconfig.generate(name : 'spice-server',
> +    version : meson.project_version(),
> +    description : 'SPICE server library',
> +    subdirs : ['spice-server'],
> +    libraries : spice_server_lib,
> +    requires : ['spice-protocol >= @0@'.format(spice_protocol_min_version)],
> +    variables : ['exec_prefix=${prefix}'])
> diff --git a/meson_options.txt b/meson_options.txt
> new file mode 100644
> index 00000000..d82e3b87
> --- /dev/null
> +++ b/meson_options.txt
> @@ -0,0 +1,39 @@
> +option('gstreamer',
> +    type : 'combo',
> +    choices : ['1.0', '0.10', 'no'],
> +    description : 'Enable gstreamer support (default=1.0)')
> +
> +option('lz4',
> +    type : 'boolean',
> +    value : true,
> +    description: 'Enable lz4 compression support (default=true)')
> +
> +option('sasl',
> +    type : 'boolean',
> +    value : true,
> +    description : 'Use cyrus SASL authentication (default=true)')
> +
> +option('smartcard',
> +    type : 'boolean',
> +    value : true,
> +    description : 'Enable smartcard support (default=true)')
> +
> +option('alignment-checks',
> +    type : 'boolean',
> +    value : false,
> +    description : 'Enable runtime checks for cast alignment
> (default=false)')
> +

why this is not in spice-common?

> +option('extra-checks',
> +    type : 'boolean',
> +    value: false,
> +    description : 'Enable extra checks on code (default=false)')
> +
> +option('statistics',
> +    type : 'boolean',
> +    value: false,
> +    description : 'Build SPICE with statistic code enabled (default=false)')
> +
> +option('manual',
> +    type : 'boolean',
> +    value : true,
> +    description : 'Build SPICE manual (default=true)')
> diff --git a/server/meson.build b/server/meson.build
> new file mode 100644
> index 00000000..0825497a
> --- /dev/null
> +++ b/server/meson.build
> @@ -0,0 +1,205 @@
> +#
> +# generate spice-version.h
> +#
> +version_info = meson.project_version().split('.')
> +major = '@0@'.format(version_info[0])
> +minor = '@0@'.format(version_info[1])
> +micro = version_info[2].to_int()
> +if not version_info[3].contains('git')
> +  micro += 1
> +endif
> +micro = '@0@'.format(micro)
> +cmd = run_command('printf', ['"0x%02x%02x%02x"', major, minor, micro])
> +version_data = configuration_data()
> +version_data.set('SPICE_SERVER_VERSION', cmd.stdout().strip())
> +spice_version_h = configure_file(input : 'spice-version.h.in',
> +                                 output : 'spice-version.h',
> +                                 configuration : version_data)
> +
> +#
> +# libspice-server.so
> +#
> +spice_server_headers = [
> +  spice_version_h,
> +  'spice-audio.h',
> +  'spice-char.h',
> +  'spice-core.h',
> +  'spice-experimental.h',
> +  'spice-input.h',
> +  'spice-migration.h',
> +  'spice-qxl.h',
> +  'spice-server.h',
> +  'spice-replay.h',
> +  'spice.h',
> +]
> +
> +install_headers(spice_server_headers, subdir : 'spice-server')
> +
> +# generate enums
> +gnome = import('gnome')
> +spice_server_enums = gnome.mkenums('spice-server-enums',
> +                                   sources : 'spice-server.h',
> +                                   c_template : 'spice-server-enums.c.tmpl',
> +                                   h_template : 'spice-server-enums.h.tmpl')
> +
> +spice_server_sources = [
> +  spice_server_headers,
> +  spice_server_enums,
> +  'agent-msg-filter.c',
> +  'agent-msg-filter.h',
> +  'cache-item.h',
> +  'char-device.c',
> +  'char-device.h',
> +  'common-graphics-channel.c',
> +  'common-graphics-channel.h',
> +  'cursor-channel.c',
> +  'cursor-channel-client.c',
> +  'cursor-channel-client.h',
> +  'cursor-channel.h',
> +  'dcc.c',
> +  'dcc.h',
> +  'dcc-private.h',
> +  'dcc-send.c',
> +  'demarshallers.h',
> +  'dispatcher.c',
> +  'dispatcher.h',
> +  'display-channel.c',
> +  'display-channel.h',
> +  'display-channel-private.h',
> +  'display-limits.h',
> +  'event-loop.c',
> +  'glib-compat.h',
> +  'glz-encoder.c',
> +  'glz-encoder-dict.c',
> +  'glz-encoder-dict.h',
> +  'glz-encoder.h',
> +  'glz-encoder-priv.h',
> +  'image-cache.c',
> +  'image-cache.h',
> +  'image-encoders.c',
> +  'image-encoders.h',
> +  'inputs-channel.c',
> +  'inputs-channel-client.c',
> +  'inputs-channel-client.h',
> +  'inputs-channel.h',
> +  'jpeg-encoder.c',
> +  'jpeg-encoder.h',
> +  'main-channel.c',
> +  'main-channel-client.c',
> +  'main-channel-client.h',
> +  'main-channel.h',
> +  'main-dispatcher.c',
> +  'main-dispatcher.h',
> +  'memslot.c',
> +  'memslot.h',
> +  'migration-protocol.h',
> +  'mjpeg-encoder.c',
> +  'net-utils.c',
> +  'net-utils.h',
> +  'pixmap-cache.c',
> +  'pixmap-cache.h',
> +  'red-channel.c',
> +  'red-channel-capabilities.c',
> +  'red-channel-capabilities.h',
> +  'red-channel-client.c',
> +  'red-channel-client.h',
> +  'red-channel.h',
> +  'red-client.c',
> +  'red-client.h',
> +  'red-common.h',
> +  'red-parse-qxl.c',
> +  'red-parse-qxl.h',
> +  'red-pipe-item.c',
> +  'red-pipe-item.h',
> +  'red-qxl.c',
> +  'red-qxl.h',
> +  'red-record-qxl.c',
> +  'red-record-qxl.h',
> +  'red-replay-qxl.c',
> +  'reds.c',
> +  'reds.h',
> +  'reds-private.h',
> +  'red-stream.c',
> +  'red-stream.h',
> +  'red-worker.c',
> +  'red-worker.h',
> +  'sound.c',
> +  'sound.h',
> +  'spice-bitmap-utils.c',
> +  'spice-bitmap-utils.h',
> +  'spicevmc.c',
> +  'stat-file.c',
> +  'stat-file.h',
> +  'stat.h',
> +  'stream-channel.c',
> +  'stream-channel.h',
> +  'red-stream-device.c',
> +  'red-stream-device.h',
> +  'sw-canvas.c',
> +  'tree.c',
> +  'tree.h',
> +  'utils.c',
> +  'utils.h',
> +  'video-encoder.h',
> +  'video-stream.c',
> +  'video-stream.h',
> +  'zlib-encoder.c',
> +  'zlib-encoder.h',
> +]
> +
> +if spice_server_has_lz4 == true
> +  spice_server_sources += ['lz4-encoder.c',
> +                           'lz4-encoder.h']
> +endif
> +
> +if spice_server_has_smartcard == true
> +  spice_server_sources += ['smartcard.c',
> +                           'smartcard.h',
> +                           'smartcard-channel-client.c',
> +                           'smartcard-channel-client.h']

for coherence I'd use a syntax like

  spice_server_sources += [
    'smartcard.c',
    'smartcard.h',
    'smartcard-channel-client.c',
    'smartcard-channel-client.h',
  ]

(just space changes)

is possible to do something like

  spice_server_sources += '''
    smartcard.c
    smartcard.h
    smartcard-channel-client.c
    smartcard-channel-client.h
  '''.split()

??

> +endif
> +
> +if spice_server_has_gstreamer == true
> +  spice_server_sources += ['gstreamer-encoder.c']
> +endif
> +
> +#
> +# custom link_args
> +#
> +ld_cmd = run_command('ld', '--help').stdout().strip()
> +
> +# version-script
> +# TODO: should be done automatically,
> https://github.com/mesonbuild/meson/issues/3047
> +spice_server_syms = files('spice-server.syms')
> +if ld_cmd.contains('--version-script')
> +  spice_server_syms_path = join_paths(meson.current_source_dir(),
> 'spice-server.syms')
> +  spice_server_link_args +=
> '-Wl,--version-script=@0@'.format(spice_server_syms_path)
> +endif
> +
> +# Check for how to avoid indirect lib deps (--no-copy-dt-needed-entries)
> +# from virt-linker-no-indirect
> +if ld_cmd.contains('--no-copy-dt-needed-entries')
> +  spice_server_link_args += '-Wl,--no-copy-dt-needed-entries'
> +endif
> +
> +# Check for how to force completely read-only GOT table (relro)
> +# from virt-link-relro.m4
> +if ld_cmd.contains('-z relro')
> +  spice_server_link_args += ['-Wl,-z', '-Wl,relro']
> +endif
> +
> +if ld_cmd.contains('-z now')
> +  spice_server_link_args += ['-Wl,-z', '-Wl,now']
> +endif
> +
> +spice_server_lib = library('spice-server', spice_server_sources,
> +                           version : '1.12.4',
> +                           install : true,
> +                           include_directories : spice_server_include,
> +                           c_args :
> spice_common.get_variable('spice_common_glib_cflags'),
> +                           link_args : spice_server_link_args,
> +                           link_depends : spice_server_syms,
> +                           link_with : spice_server_libs,
> +                           dependencies : spice_server_deps)
> +
> +subdir('tests')
> diff --git a/server/tests/meson.build b/server/tests/meson.build
> new file mode 100644
> index 00000000..94b16445
> --- /dev/null
> +++ b/server/tests/meson.build
> @@ -0,0 +1,88 @@
> +test_lib_include = [spice_server_include, include_directories('.', '..')]
> +test_lib_deps = [spice_server_deps, dependency('gio-unix-2.0')]
> +test_objs = spice_server_lib.extract_all_objects()
> +
> +test_lib_sources = [
> +  spice_server_enums, # FIXME: extract_all_objects won't list generated
> source files?
> +  'basic-event-loop.c',
> +  'basic-event-loop.h',
> +  'test-display-base.c',
> +  'test-display-base.h',
> +  'test-glib-compat.c',
> +  'test-glib-compat.h',
> +]
> +
> +test_libs = [spice_server_libs]
> +test_libs += static_library('testlib', test_lib_sources,
> +                            link_with: spice_server_lib,
> +                            include_directories : test_lib_include,
> +                            dependencies : test_lib_deps,
> +                            install : false)
> +
> +stat_test_libs = [['1', '0', '0'], ['2', '0', '1'], ['3', '1', '0'], ['4',
> '1', '1']]
> +foreach t : stat_test_libs
> +  test_libs += static_library('testlib_stat at 0@'.format(t[0]), 'stat-test.c',
> +                              c_args :
> ['-DTEST_NAME=stat_test at 0@'.format(t[0]),
> +
> '-DTEST_COMPRESS_STAT=@0@'.format(t[1]),
> +
> '-DTEST_RED_WORKER_STAT=@0@'.format(t[2])],
> +                              include_directories : test_lib_include,
> +                              dependencies : test_lib_deps,
> +                              install : false)
> +endforeach
> +
> +tests = [
> +  ['test-codecs-parsing', true],
> +  ['test-options', true],
> +  ['test-stat', true],
> +  ['test-stream', true],
> +  ['test-agent-msg-filter', true],
> +  ['test-loop', true],
> +  ['test-qxl-parsing', true],
> +  ['test-stat-file', true],
> +  ['test-leaks', true],
> +  ['test-vdagent', true],
> +  ['test-fail-on-null-core-interface', true],
> +  ['test-empty-success', true],
> +  ['test-channel', true],
> +  ['test-stream-device', true],
> +  ['test-listen', true],
> +  ['test-display-no-ssl', false],
> +  ['test-display-streaming', false],
> +  ['test-playback', false],
> +  ['test-display-resolution-changes', false],
> +  ['test-two-servers', false],
> +  ['test-display-width-stride', false],
> +]
> +
> +if spice_server_has_sasl
> +  tests += [['test-sasl', true],]
> +endif
> +
> +if spice_server_has_gstreamer
> +  tests += [['test-gst', false],]
> +  if get_option('extra-checks')
> +    test('video-encoders', files('video-encoders'))
> +  endif
> +endif
> +
> +foreach t : tests
> +  exe = executable(t[0],
> +                   sources : '@0 at .c'.format(t[0]),
> +                   link_with : test_libs,
> +                   include_directories : test_lib_include,
> +                   c_args :
> ['-DSPICE_TOP_SRCDIR="@0@"'.format(meson.source_root())],
> +                   dependencies : test_lib_deps,
> +                   objects : test_objs,
> +                   install : false)
> +
> +  if t[1]
> +    test(t[0], exe)
> +  endif
> +endforeach
> +
> +executable('spice-server-replay',
> +           sources : ['replay.c', join_paths('..', 'event-loop.c'),
> 'basic-event-loop.c', 'basic-event-loop.h'],
> +           link_with : [spice_server_libs, spice_server_lib],
> +           include_directories : test_lib_include,
> +           dependencies : test_lib_deps,
> +           install : false)
> diff --git a/subprojects/spice-common.wrap b/subprojects/spice-common.wrap
> new file mode 100644
> index 00000000..6117c631
> --- /dev/null
> +++ b/subprojects/spice-common.wrap
> @@ -0,0 +1,4 @@
> +[wrap-git]
> +directory=spice-common
> +url=https://gitlab.com/etrunko/spice-common.git
> +revision=meson

is possible to have relative URL? So for instance you could
clone spice-server and spice-common and avoid having to change this file?
Something like

url=../spice-common.git

> diff --git a/tools/meson.build b/tools/meson.build
> new file mode 100644
> index 00000000..a5b27c4d
> --- /dev/null
> +++ b/tools/meson.build
> @@ -0,0 +1,5 @@
> +executable('reds_stat', 'reds_stat.c',
> +           install : false,
> +           include_directories : spice_server_include,
> +           link_with : spice_server_libs,
> +           dependencies : spice_server_deps)

Frediano


More information about the Spice-devel mailing list