Add support for building with meson/ninja

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@redhat.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
Eduardo Lima (Etrunko) 2018-05-31 18:14:34 -03:00 committed by Frediano Ziglio
parent 836bbd0e41
commit 55070333f6
12 changed files with 419 additions and 1 deletions

View File

@ -4,6 +4,8 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = python_modules common tests docs
EXTRA_DIST = \
meson.build \
meson_options.txt \
spice_codegen.py \
spice.proto \
spice1.proto \

View File

@ -129,6 +129,7 @@ generated_server_marshallers.h: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS)
EXTRA_DIST = \
$(CLIENT_MARSHALLERS) \
$(SERVER_MARSHALLERS) \
meson.build \
canvas_base.c \
canvas_base.h \
lz_compress_tmpl.c \

130
common/meson.build Normal file
View File

@ -0,0 +1,130 @@
#
# libspice-common
#
spice_common_sources = [
'backtrace.c',
'backtrace.h',
'bitops.h',
'canvas_utils.c',
'canvas_utils.h',
'draw.h',
'lines.c',
'lines.h',
'log.c',
'log.h',
'lz.c',
'lz.h',
'lz_common.h',
'lz_config.h',
'macros.h',
'marshaller.c',
'marshaller.h',
'mem.c',
'mem.h',
'messages.h',
'pixman_utils.c',
'pixman_utils.h',
'quic.c',
'quic.h',
'quic_config.h',
'rect.h',
'region.c',
'region.h',
'ring.h',
'rop3.c',
'rop3.h',
'snd_codec.c',
'snd_codec.h',
'spice_common.h',
'verify.h'
]
spice_common_lib = static_library('spice-common', spice_common_sources,
install : false,
include_directories : spice_common_include,
dependencies : spice_common_deps)
spice_common_dep = declare_dependency(link_with : spice_common_lib,
include_directories : spice_common_include,
dependencies : spice_common_deps)
#
# libspice-common-client
#
if spice_common_generate_client_code
targets = [
['client_demarshallers', spice_proto, 'generated_client_demarshallers.c', ['--generate-demarshallers', '--client', '--include', 'common/messages.h', '@INPUT@', '@OUTPUT@']],
['client_demarshallers1', spice1_proto, 'generated_client_demarshallers1.c', ['--generate-demarshallers', '--client', '--include', 'common/messages.h', '--prefix', '1', '--ptrsize', '8', '@INPUT@', '@OUTPUT@']],
['client_marshalers', spice_proto, 'generated_client_marshallers.c', ['--generate-marshallers', '-P', '--client', '--include', 'client_marshallers.h', '@INPUT@', '@OUTPUT@']],
['client_marshallers1', spice1_proto, 'generated_client_marshallers1.c', ['--generate-marshallers', '-P', '--client', '--include', 'common/messages.h', '--include', 'client_marshallers.h', '--prefix', '1', '--ptrsize', '8', '@INPUT@', '@OUTPUT@']],
['client_marshallers_h', spice_proto, 'generated_client_marshallers.h', ['--generate-marshallers', '-P', '--client', '--include', 'common/messages.h', '-H', '@INPUT@', '@OUTPUT@']],
]
spice_common_client_sources = [
'client_demarshallers.h',
'client_marshallers.h',
'ssl_verify.c',
'ssl_verify.h',
]
foreach t : targets
cmd = [python, spice_codegen] + t[3]
target = custom_target(t[0], input : t[1], output : t[2], install : false, command : cmd, depend_files : spice_codegen_files)
spice_common_client_sources += target
endforeach
spice_common_client_lib = static_library('spice-common-client', spice_common_client_sources,
install : false,
dependencies : spice_common_dep)
spice_common_client_dep = declare_dependency(sources : target,
link_with : spice_common_client_lib,
dependencies : spice_common_dep)
endif
#
# libspice-common-server
#
if spice_common_generate_server_code
structs_args = [
'-M', 'String',
'-M', 'Rect',
'-M', 'Point',
'-M', 'DisplayBase',
'-M', 'Fill',
'-M', 'Opaque',
'-M', 'Copy',
'-M', 'Blend',
'-M', 'Blackness',
'-M', 'Whiteness',
'-M', 'Invers',
'-M', 'Rop3',
'-M', 'Stroke',
'-M', 'Text',
'-M', 'Transparent',
'-M', 'AlphaBlend',
'-M', 'Composite',
]
targets = [
['server_demarshallers', spice_proto, 'generated_server_demarshallers.c', ['--generate-demarshallers', '--server', '--include', 'common/messages.h', '@INPUT@', '@OUTPUT@']],
['server_marshallers', spice_proto, 'generated_server_marshallers.c', ['--generate-marshallers', '--server'] + structs_args + ['--include', 'common/messages.h', '@INPUT@', '@OUTPUT@']],
['server_marshallers_h', spice_proto, 'generated_server_marshallers.h', ['--generate-marshallers', '--server'] + structs_args + ['--include', 'common/messages.h', '-H', '@INPUT@', '@OUTPUT@']],
]
spice_common_server_sources = []
foreach t : targets
cmd = [python, spice_codegen] + t[3]
target = custom_target(t[0], input : t[1], output : t[2], install : false, command : cmd, depend_files : spice_codegen_files)
spice_common_server_sources += target
endforeach
spice_common_server_lib = static_library('spice-common-server', spice_common_server_sources,
install : false,
dependencies : spice_common_dep)
spice_common_server_dep = declare_dependency(sources : target,
link_with : spice_common_server_lib,
dependencies : spice_common_dep)
endif

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
spice_protocol.html

View File

@ -2,6 +2,7 @@ NULL =
ASCIIDOC_FLAGS = -a icons -a toc
EXTRA_DIST = \
meson.build \
spice_protocol.txt \
$(NULL)

10
docs/meson.build Normal file
View File

@ -0,0 +1,10 @@
if get_option('manual')
asciidoc = find_program('asciidoc', required : false)
if asciidoc.found()
custom_target('spice_protocol.html',
input : files('spice_protocol.txt'),
output : 'spice_protocol.html',
build_by_default : true,
command : [asciidoc, '-n', '-a', 'icons', '-a', 'toc', '-o', '@OUTPUT@', '@INPUT@'])
endif
endif

182
meson.build Normal file
View File

@ -0,0 +1,182 @@
#
# project definition
#
project('spice-common', 'c',
meson_version : '>= 0.45.0',
license : 'LGPLv2.1')
if not meson.is_subproject()
warning('This project is only intended to be used as a subproject!')
endif
# some global vars
spice_common_global_cflags = [#'-std=c99', # fails compiling bitops.h
'-DHAVE_CONFIG_H',
'-DG_LOG_DOMAIN="Spice"',
'-Wall',
'-Wextra',
'-Werror',
'-Wno-unused-parameter']
if get_option('alignment-checks')
spice_common_global_cflags += ['-DSPICE_DEBUG_ALIGNMENT']
endif
spice_common_deps = []
spice_common_include = include_directories('.')
spice_proto = files('spice.proto')
spice1_proto = files('spice1.proto')
spice_codegen = files('spice_codegen.py')
spice_codegen_files = [spice_codegen]
compiler = meson.get_compiler('c')
spice_common_config_data = configuration_data()
if get_option('extra-checks')
spice_common_config_data.set('ENABLE_EXTRA_CHECKS', '1')
endif
spice_common_generate_code = get_option('generate-code')
spice_common_generate_client_code = spice_common_generate_code == 'all' or spice_common_generate_code == 'client'
spice_common_generate_server_code = spice_common_generate_code == 'all' or spice_common_generate_code == 'server'
#
# check for system headers
#
headers = ['alloca.h',
'arpa/inet.h',
'dlfcn.h',
'inttypes.h',
'malloc.h',
'memory.h',
'netinet/in.h',
'stddef.h',
'stdint.h',
'stdlib.h',
'strings.h',
'string.h',
'sys/socket.h',
'sys/stat.h',
'sys/types.h',
'unistd.h',
'vfork.h']
foreach header : headers
if compiler.has_header(header)
spice_common_config_data.set('HAVE_@0@'.format(header.underscorify().to_upper()), '1')
endif
endforeach
#
# check for system functions
#
functions = ['alloca',
'dup2',
'floor',
'fork',
'inet_ntoa',
'memmove',
'memset',
'pow',
'sqrt',
'vfork']
foreach func : functions
if compiler.has_function(func)
spice_common_config_data.set('HAVE_@0@'.format(func.to_upper()), '1')
endif
endforeach
#
# check for mandatory dependencies
#
glib_version = '2.38'
glib_version_info = '>= @0@'.format(glib_version)
deps = [['spice-protocol', '>= 0.12.12'],
['glib-2.0', glib_version_info],
['gio-2.0', glib_version_info],
['gthread-2.0', glib_version_info],
['pixman-1', '>= 0.17.7'],
['openssl', '>= 1.0.0']]
foreach dep : deps
spice_common_deps += dependency(dep[0], version : dep[1])
endforeach
#
# Non-mandatory/optional dependencies
#
deps = [['opus', '>= 0.9.14', 'HAVE_OPUS'],]
# Check deps which are optional but enabled by default. This foreach block only
# checks the option, and adds the package to the deps list, while the real check
# for the dependency is done in the foeach block below.
optional_deps = [['celt051', '>= 0.5.1.1', 'HAVE_CELT051'],]
foreach dep : optional_deps
if get_option(dep[0])
deps += [dep]
endif
endforeach
foreach dep : deps
d = dependency(dep[0], required : false, version : dep[1])
if d.found()
spice_common_deps += d
spice_common_config_data.set(dep[2], '1')
endif
endforeach
# Python
if get_option('python-checks')
dependency('python3')
py_module = import('python3')
python = py_module.find_python()
foreach module : ['six', 'pyparsing']
cmd = run_command(python, '-m', module)
if cmd.returncode() != 0
error('Python module @0@ not found'.format(module))
endif
endforeach
endif
# smartcard check
smartcard_dep = dependency('libcacard', required : false, version : '>= 2.5.1')
if smartcard_dep.found()
spice_common_deps += smartcard_dep
spice_common_config_data.set('USE_SMARTCARD', '1')
else
smartcard012_dep = dependency('libcacard', required : false, version : '>= 0.1.2')
if smartcard012_dep.found()
spice_common_deps += smartcard012_dep
spice_common_config_data.set('USE_SMARTCARD_012', '1')
endif
endif
#
# global C defines
#
glib_major_minor = glib_version.split('.')
glib_encoded_version = 'GLIB_VERSION_@0@_@1@'.format(glib_major_minor[0], glib_major_minor[1])
spice_common_global_cflags += ['-DGLIB_VERSION_MIN_REQUIRED=@0@'.format(glib_encoded_version),
'-DGLIB_VERSION_MAX_ALLOWED=@0@'.format(glib_encoded_version)]
foreach arg : spice_common_global_cflags
add_project_arguments(arg, language : 'c')
endforeach
#
# Subdirectories
#
subdir('python_modules')
subdir('common')
subdir('tests')
subdir('docs')
#
# write config.h
#
configure_file(output : 'config.h',
install : false,
configuration : spice_common_config_data)

32
meson_options.txt Normal file
View File

@ -0,0 +1,32 @@
option('alignment-checks',
type : 'boolean',
value : false,
yield : true,
description : 'Enable runtime checks for cast alignment (default=false)')
option('extra-checks',
type : 'boolean',
value : false,
yield : true,
description : 'Enable extra checks on code (default=false)')
option('celt051',
type : 'boolean',
value : true,
description: 'Enable celt051 audio codec (default=true)')
option('python-checks',
type : 'boolean',
value : true,
description : 'Enable checks for Python modules needed to build from git (default=true)')
option('manual',
type : 'boolean',
value : true,
yield : true,
description : 'Build SPICE manual (default=true)')
option('generate-code',
type : 'combo',
choices : ['all', 'server', 'client'],
description : 'Which code should be built (default=all)')

View File

@ -9,7 +9,7 @@ PYTHON_MODULES = \
spice_parser.py \
$(NULL)
EXTRA_DIST = $(PYTHON_MODULES)
EXTRA_DIST = meson.build $(PYTHON_MODULES)
DISTCLEANFILES = *.pyc

View File

@ -0,0 +1,6 @@
spice_codegen_files += files('codegen.py',
'demarshal.py',
'__init__.py',
'marshal.py',
'ptypes.py',
'spice_parser.py')

View File

@ -85,6 +85,7 @@ generated_test_demarshallers.c: $(srcdir)/test-marshallers.proto $(MARSHALLERS_D
EXTRA_DIST = \
$(TEST_MARSHALLERS) \
meson.build \
test-marshallers.proto \
$(NULL)

52
tests/meson.build Normal file
View File

@ -0,0 +1,52 @@
#
# Build tests
#
tests = ['test-logging']
tests_deps = [spice_common_dep]
if spice_common_generate_code == 'all'
tests += ['test-overflow']
tests_deps += [spice_common_client_dep, spice_common_server_dep]
endif
foreach t : tests
name = t.underscorify()
exe = executable(name, '@0@.c'.format(t),
dependencies : tests_deps,
install : false)
test(name, exe)
endforeach
#
# test_marshallers
#
test_proto = files('test-marshallers.proto')
test_marshallers_sources = ['test-marshallers.c', 'test-marshallers.h']
targets = [
['test_marshallers', test_proto, 'generated_test_marshallers.c', ['--generate-marshallers', '--server', '--include', 'test-marshallers.h', '@INPUT@', '@OUTPUT@']],
['test_marshallers_h', test_proto, 'generated_test_marshallers.h', ['--generate-marshallers', '--server', '--include', 'test-marshallers.h', '-H', '@INPUT@', '@OUTPUT@']],
['test_demarshallers', test_proto, 'generated_test_demarshallers.c', ['--generate-demarshallers', '--client', '--include', 'test-marshallers.h', '@INPUT@', '@OUTPUT@']],
]
foreach t : targets
cmd = [python, spice_codegen] + t[3]
test_marshallers_sources += custom_target(t[0], input: t[1], output : t[2], command: cmd, depend_files : spice_codegen_files)
endforeach
test('test_marshallers',
executable('test_marshallers', test_marshallers_sources,
dependencies : spice_common_dep,
install : false))
#
# test_quic
#
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version : '>= 2.26', required : false)
if gdk_pixbuf_dep.found()
test('test_quic',
executable('test_quic', 'test-quic.c',
dependencies : [spice_common_dep, gdk_pixbuf_dep],
install : false))
endif