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@xxxxxxxxxx> --- Changes in v2: - Rebased upstream, adding test-overflow to the tests - Added files under python_modules/ as dependency of generated sources, so that if any of those are changed, ninja will trigger regeneration of the marshallers/demarshallers. Makefile.am | 2 + common/Makefile.am | 1 + common/meson.build | 132 ++++++++++++++++++++++++++++++++ docs/.gitignore | 1 + docs/Makefile.am | 1 + docs/meson.build | 10 +++ meson.build | 182 +++++++++++++++++++++++++++++++++++++++++++++ meson_options.txt | 37 +++++++++ python_modules/Makefile.am | 2 +- python_modules/meson.build | 6 ++ tests/Makefile.am | 1 + tests/meson.build | 41 ++++++++++ 12 files changed, 415 insertions(+), 1 deletion(-) create mode 100644 common/meson.build create mode 100644 docs/.gitignore create mode 100644 docs/meson.build create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100644 python_modules/meson.build create mode 100644 tests/meson.build diff --git a/Makefile.am b/Makefile.am index ee0a1e2..e5630a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/common/Makefile.am b/common/Makefile.am index ea15039..defcb35 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -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 \ diff --git a/common/meson.build b/common/meson.build new file mode 100644 index 0000000..ef130de --- /dev/null +++ b/common/meson.build @@ -0,0 +1,132 @@ +# +# libspice-common +# +spice_common_sources = [ + 'backtrace.c', + 'backtrace.h', + 'bitops.h', + 'canvas_utils.c', + 'canvas_utils.h', + 'client_demarshallers.h', + 'client_marshallers.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', + 'ssl_verify.c', + 'ssl_verify.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, + compile_args : spice_common_glib_cflags, + 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 = [] + + 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, + compile_args : spice_common_glib_cflags, + 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, + compile_args : spice_common_glib_cflags, + link_with : spice_common_server_lib, + dependencies : spice_common_dep) +endif diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..508590c --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +spice_protocol.html diff --git a/docs/Makefile.am b/docs/Makefile.am index 20f46ef..421e5f9 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -2,6 +2,7 @@ NULL = ASCIIDOC_FLAGS = -a icons -a toc EXTRA_DIST = \ + meson.build \ spice_protocol.txt \ $(NULL) diff --git a/docs/meson.build b/docs/meson.build new file mode 100644 index 0000000..5e10d76 --- /dev/null +++ b/docs/meson.build @@ -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 diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..9d44604 --- /dev/null +++ b/meson.build @@ -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'] + +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_info = '>= 2.46' +glib_encoded_version = 'GLIB_VERSION_2_46' +spice_protocol_version = '>= @0@'.format(get_option('protocol-version')) + +deps = [['spice-protocol', spice_protocol_version], + ['glib-2.0', glib_version_info], + ['gobject-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 + +spice_common_glib_cflags = ['-DGLIB_VERSION_MIN_REQUIRED=@0@'.format(glib_encoded_version), + '-DGLIB_VERSION_MAX_ALLOWED=@0@'.format(glib_encoded_version)] + +spice_common_global_cflags += spice_common_glib_cflags + +# +# Non-mandatory/optional dependencies +# +deps = [['opus', '>= 0.9.14', 'HAVE_OPUS'],] +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 + +spice_common_has_smartcard = smartcard_dep.found() or smartcard012_dep.found() + +# +# global C defines +# +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) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..8e27cbf --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,37 @@ +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('protocol-version', + type : 'string', + value : '0.12.12', + description : 'SPICE protocol version required (default=0.12.12)') + +option('generate-code', + type : 'combo', + choices : ['all', 'server', 'client'], + description : 'Which code should be built (default=all)') diff --git a/python_modules/Makefile.am b/python_modules/Makefile.am index 50e1a71..07e1917 100644 --- a/python_modules/Makefile.am +++ b/python_modules/Makefile.am @@ -9,7 +9,7 @@ PYTHON_MODULES = \ spice_parser.py \ $(NULL) -EXTRA_DIST = $(PYTHON_MODULES) +EXTRA_DIST = meson.build $(PYTHON_MODULES) DISTCLEANFILES = *.pyc diff --git a/python_modules/meson.build b/python_modules/meson.build new file mode 100644 index 0000000..5ae0fd7 --- /dev/null +++ b/python_modules/meson.build @@ -0,0 +1,6 @@ +spice_codegen_files += files('codegen.py', + 'demarshal.py', + '__init__.py', + 'marshal.py', + 'ptypes.py', + 'spice_parser.py') diff --git a/tests/Makefile.am b/tests/Makefile.am index d5ec1d7..85879d7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,6 +64,7 @@ generated_test_demarshallers.c: $(srcdir)/test-marshallers.proto $(MARSHALLERS_D EXTRA_DIST = \ $(TEST_MARSHALLERS) \ + meson.build \ test-marshallers.proto \ $(NULL) diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..9f7ae57 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,41 @@ +# +# 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)) -- 2.14.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel