Commit b2f98087 authored by Nirbheek Chauhan's avatar Nirbheek Chauhan 🐜 Committed by Tim-Philipp Müller

Add support for Meson as alternative/parallel build system

https://github.com/mesonbuild/meson

With contributions from:

Tim-Philipp Müller <tim@centricular.com>
Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
Jussi Pakkanen <jpakkane@gmail.com> (original port)

Highlights of the features provided are:
* Faster builds on Linux (~40-50% faster)
* The ability to build with MSVC on Windows
* Generate Visual Studio project files
* Generate XCode project files
* Much faster builds on Windows (on-par with Linux)
* Seriously fast configure and building on embedded

... and many more. For more details see:

http://blog.nirbheek.in/2016/05/gstreamer-and-meson-new-hope.html
http://blog.nirbheek.in/2016/07/building-and-developing-gstreamer-using.html

Building with Meson should work on both Linux and Windows, but may
need a few more tweaks on other operating systems.
parent 714d8aa4
......@@ -58,3 +58,4 @@ Build
*.swp
/tests/misc/netclock-replay
/build
This diff is collapsed.
configure_file(input : 'gstreamer.types.in',
output : 'gstreamer.types',
configuration : configuration_data())
gnome.gtkdoc('gstreamer',
main_sgml : 'gstreamer-docs.sgml',
src_dir : '@0@/gst'.format(meson.source_root()),
scan_args : ['--deprecated-guards=GST_DISABLE_DEPRECATED',
'--ignore-decorators=GST_EXPORT',
'--ignore-headers=gettext.h glib-compat-private.h glib-compat.h gst-i18n-app.h gst-i18n-lib.h gst_private.h gstelementdetails.h gstmacros.h grammar.tab.h grammar.tab.pre.h math-compat.h types.h'
],
install : true)
configure_file(input : 'gstreamer-libs.types',
output : 'gstreamer-libs.types',
configuration : configuration_data())
gnome.gtkdoc('gstreamer-libs',
main_sgml : 'gstreamer-libs-docs.sgml',
src_dir : '@0@/libs/gst'.format(meson.source_root()),
scan_args : ['--deprecated-guards=GST_DISABLE_DEPRECATED',
'--ignore-decorators=GST_EXPORT',
'--ignore-headers=gettext.h glib-compat-private.h glib-compat.h gst-i18n-app.h gst-i18n-lib.h gst_private.h gstelementdetails.h gstmacros.h grammar.tab.h grammar.tab.pre.h math-compat.h types.h'
],
install : true)
docconf = configuration_data()
docconf.set('GST_API_VERSION', apiversion)
docconf.set('PACKAGE_VERSION', gst_version)
docconf.set('PLUGINDIR', '@0@/lib/gstreamer-1.0'.format(get_option('prefix')))
configure_file(input : 'version.entities.in',
output : 'version.entities',
configuration : docconf)
subdir('gst')
subdir('libs')
#!/usr/bin/env python3
# This is in its own file rather than inside meson.build
# because a) mixing the two is ugly and b) trying to
# make special characters such as \n go through all
# backends is a fool's errand.
import sys, os, shutil, subprocess
h_array = ['--fhead',
"#ifndef __GST_ENUM_TYPES_H__\n#define __GST_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n",
'--fprod',
"\n/* enumerations from \"@filename@\" */\n",
'--vhead',
"GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n",
'--ftail',
"G_END_DECLS\n\n#endif /* __GST_ENUM_TYPES_H__ */"]
c_array = [
'--fhead',
"#include \"gst_private.h\"\n#include <gst/gst.h>\n#define C_ENUM(v) ((gint) v)\n#define C_FLAGS(v) ((guint) v)\n ",
'--fprod',
"\n/* enumerations from \"@filename@\" */",
'--vhead',
"GType\n@enum_name@_get_type (void)\n{\n static gsize id = 0;\n static const G@Type@Value values[] = {",
'--vprod',
" { C_@TYPE@(@VALUENAME@), \"@VALUENAME@\", \"@valuenick@\" },",
'--vtail',
" { 0, NULL, NULL }\n };\n\n if (g_once_init_enter (&id)) {\n GType tmp = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&id, tmp);\n }\n\n return (GType) id;\n}"
]
cmd = []
argn = 1
# Find the full command needed to run glib-mkenums
# On UNIX-like, this is just the full path to glib-mkenums
# On Windows, this is the full path to interpreter + full path to glib-mkenums
for arg in sys.argv[1:]:
cmd.append(arg)
argn += 1
if arg.endswith('glib-mkenums'):
break
ofilename = sys.argv[argn]
headers = sys.argv[argn + 1:]
if ofilename.endswith('.h'):
arg_array = h_array
else:
arg_array = c_array
pc = subprocess.Popen(cmd + arg_array + headers, stdout=subprocess.PIPE)
(stdo, _) = pc.communicate()
if pc.returncode != 0:
sys.exit(pc.returncode)
open(ofilename, 'wb').write(stdo)
gst_sources = [
'gst.c',
'gstobject.c',
'gstallocator.c',
'gstbin.c',
'gstbuffer.c',
'gstbufferlist.c',
'gstbufferpool.c',
'gstbus.c',
'gstcaps.c',
'gstcapsfeatures.c',
'gstchildproxy.c',
'gstclock.c',
'gstclock-linreg.c',
'gstcontext.c',
'gstcontrolbinding.c',
'gstcontrolsource.c',
'gstdatetime.c',
'gstdebugutils.c',
'gstdevice.c',
'gstdeviceprovider.c',
'gstdeviceproviderfactory.c',
'gstelement.c',
'gstelementfactory.c',
'gsterror.c',
'gstevent.c',
'gstformat.c',
'gstghostpad.c',
'gstdevicemonitor.c',
'gstinfo.c',
'gstiterator.c',
'gstatomicqueue.c',
'gstmessage.c',
'gstmeta.c',
'gstmemory.c',
'gstminiobject.c',
'gstpad.c',
'gstpadtemplate.c',
'gstparamspecs.c',
'gstpipeline.c',
'gstplugin.c',
'gstpluginfeature.c',
'gstpluginloader.c',
'gstpoll.c',
'gstpreset.c',
'gstprotection.c',
'gstquark.c',
'gstquery.c',
'gstregistry.c',
'gstregistrychunks.c',
'gstsample.c',
'gstsegment.c',
'gststreamcollection.c',
'gststreams.c',
'gststructure.c',
'gstsystemclock.c',
'gsttaglist.c',
'gsttagsetter.c',
'gsttask.c',
'gsttaskpool.c',
'gsttoc.c',
'gsttocsetter.c',
'gsttracer.c',
'gsttracerfactory.c',
'gsttracerrecord.c',
'gsttracerutils.c',
'gsttypefind.c',
'gsttypefindfactory.c',
'gsturi.c',
'gstutils.c',
'gstvalue.c',
'gstparse.c',
]
gst_headers = [
'gst.h',
'glib-compat.h',
'gstobject.h',
'gstallocator.h',
'gstbin.h',
'gstbuffer.h',
'gstbufferlist.h',
'gstbufferpool.h',
'gstbus.h',
'gstcaps.h',
'gstcapsfeatures.h',
'gstchildproxy.h',
'gstclock.h',
'gstcompat.h',
'gstcontext.h',
'gstcontrolbinding.h',
'gstcontrolsource.h',
'gstdatetime.h',
'gstdebugutils.h',
'gstelement.h',
'gstelementmetadata.h',
'gstdevice.h',
'gstdeviceprovider.h',
'gstdeviceproviderfactory.h',
'gstelementfactory.h',
'gsterror.h',
'gstevent.h',
'gstformat.h',
'gstghostpad.h',
'gstdevicemonitor.h',
'gstinfo.h',
'gstiterator.h',
'gstatomicqueue.h',
'gstmacros.h',
'gstmessage.h',
'gstmeta.h',
'gstmemory.h',
'gstminiobject.h',
'gstpad.h',
'gstpadtemplate.h',
'gstparamspecs.h',
'gstpipeline.h',
'gstplugin.h',
'gstpluginfeature.h',
'gstpoll.h',
'gstpreset.h',
'gstprotection.h',
'gstquery.h',
'gstsample.h',
'gstsegment.h',
'gststreamcollection.h',
'gststreams.h',
'gststructure.h',
'gstsystemclock.h',
'gsttaglist.h',
'gsttagsetter.h',
'gsttask.h',
'gsttaskpool.h',
'gsttoc.h',
'gsttocsetter.h',
'gsttracer.h',
'gsttracerfactory.h',
'gsttracerrecord.h',
'gsttypefind.h',
'gsttypefindfactory.h',
'gsturi.h',
'gstutils.h',
'gstvalue.h',
'gstregistry.h',
'gstparse.h',
'math-compat.h',
]
install_headers(gst_headers, subdir : 'gstreamer-1.0/gst')
if not get_option('disable_registry')
gst_registry = ['gstregistrybinary.c']
else
gst_registry = []
endif
configure_file(input : 'gstconfig.h.in',
output : 'gstconfig.h',
install_dir : 'include/gstreamer-1.0/gst',
configuration : cdata)
configure_file(input : 'gstversion.h.in',
output : 'gstversion.h',
install_dir : 'include/gstreamer-1.0/gst',
configuration : cdata)
mkenums = find_program('build_mkenum.py')
glib_mkenums = find_program('glib-mkenums')
gstenum_h = custom_target('gstenum_h',
output : 'gstenumtypes.h',
input : gst_headers,
install : true,
install_dir : 'include/gstreamer-1.0/gst',
command : [mkenums, glib_mkenums, '@OUTPUT@', '@INPUT@'])
gstenum_c = custom_target('gstenum_c',
output : 'gstenumtypes.c',
input : gst_headers,
depends : [gstenum_h],
command : [mkenums, glib_mkenums, '@OUTPUT@', '@INPUT@'])
subdir('parse')
subdir('printf')
libgst_c_args = gst_c_args + [
'-D_GNU_SOURCE',
'-DGST_EXPORTS',
'-DG_LOG_DOMAIN=g_log_domain_gstreamer',
'-DGST_DISABLE_DEPRECATED',
]
# Make it possible to build both static and shared versions
# at the same time. By default use shared for unit tests etc.
# This choice is arbitrary.
if libtype != 'shared'
libgst_static = static_library('gstreamer-1.0', gst_sources,
gstenum_h, gstenum_c, grammar, parser, gst_registry,
c_args : [libgst_c_args],
include_directories : [configinc,
# HACK, change include paths in .y and .l in final version.
include_directories('parse')],
install : true,
link_with : printf_lib,
dependencies : [gobject_dep, gmodule_dep, glib_dep, mathlib] + platform_deps,
)
libgst = libgst_static
endif
if libtype != 'static'
libgst_shared = shared_library('gstreamer-1.0', gst_sources,
gstenum_h, gstenum_c, grammar, parser, gst_registry,
version : libversion,
soversion : soversion,
c_args : libgst_c_args,
include_directories : [configinc,
# HACK, change include paths in .y and .l in final version.
include_directories('parse')],
link_with : printf_lib,
install : true,
dependencies : [gobject_dep, gmodule_dep, glib_dep, mathlib] + platform_deps,
vs_module_defs: vs_module_defs_dir + 'libgstreamer.def',
)
libgst = libgst_shared
if build_gir
gst_gir_extra_args = gir_init_section + [ '--c-include=gst/gst.h' ]
if meson.is_subproject()
# FIXME: There must be a better way to do this
# Need to pass the include path to find gst/gst.h and gst/gstenumtypes.h (built)
gst_gir_extra_args += ['--cflags-begin',
'-I' + meson.current_source_dir() + '/..',
'-I' + meson.current_build_dir() + '/..',
'--cflags-end']
endif
gnome.generate_gir(libgst_shared,
sources : gst_sources + gst_headers,
namespace : 'Gst',
nsversion : apiversion,
identifier_prefix : 'Gst',
symbol_prefix : 'gst',
export_packages : 'gstreamer-1.0',
includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0' ],
install : true,
extra_args : gst_gir_extra_args,
)
endif
endif
gst_dep = declare_dependency(link_with : libgst,
include_directories : [configinc],
dependencies : [glib_dep, gobject_dep, gmodule_dep],
# Everything that uses libgst needs this built to compile
sources : [gstenum_h],
)
#!/usr/bin/env python3
import subprocess, sys, shlex
cfile = sys.argv[1]
hfile = sys.argv[2]
yfile = sys.argv[3]
args = ['-d', '-v', '-ppriv_gst_parse_yy', yfile, '-o', cfile]
bison = [r'@BISON@'] + shlex.split(r'@BISON_ARGS@')
subprocess.check_call(bison + args)
prefix = '''
#ifdef HAVE_CONFIG_H
#include<config.h>
#endif
'''
contents = open(cfile).read()
content = prefix + contents
open(cfile, 'w').write(contents)
#!/usr/bin/env python3
import subprocess, sys, shlex
cfile = sys.argv[1]
hfile = sys.argv[2]
lfile = sys.argv[3]
tabhfile = sys.argv[4]
args = ['--header-file=' + hfile, '-o', cfile, '-Ppriv_gst_parse_yy', lfile]
flex = [r'@FLEX@'] + shlex.split(r'@FLEX_ARGS@')
subprocess.check_call(flex + args)
prefix = '''#ifdef HAVE_CONFIG_H
#include<config.h>
#endif
'''
parse_snippet = '''void priv_gst_parse_yyset_column (int column_no , void * yyscanner);
void priv_gst_parse_yyset_column (int column_no , void * yyscanner)
'''
contents = open(cfile).read()
if not 'priv_gst_parse_yyget_column' in contents:
contents = parse_snippet + contents
contents = prefix + contents
open(cfile, 'w').write(contents)
cc = meson.get_compiler('c')
py3 = find_program('python3', required : false)
if not py3.found()
# Maybe 'python' is Python 3
py3 = find_program('python')
endif
# Find flex, configure lex generator
flex_cdata = configuration_data()
flex = find_program('flex', required : false)
if not flex.found()
flex = find_program('win_flex', required : false)
if not flex.found()
error('flex not found')
endif
endif
flex_cdata.set('FLEX', flex.path())
if cc.get_id() == 'msvc'
flex_cdata.set('FLEX_ARGS', '--nounistd')
else
flex_cdata.set('FLEX_ARGS', '')
endif
gen_lex = configure_file(input : 'gen_lex.py.in',
output : 'gen_lex.py',
configuration : flex_cdata)
# Find bison, configure grammar generator
bison_cdata = configuration_data()
bison = find_program('bison', required : false)
if not bison.found()
bison = find_program('win_bison', required : false)
if not bison.found()
error('GNU bison not found')
endif
endif
bison_cdata.set('BISON', bison.path())
bison_cdata.set('BISON_ARGS', '')
gen_grammar = configure_file(input : 'gen_grammar.py.in',
output : 'gen_grammar.py',
configuration : bison_cdata)
# Custom targets
parser = custom_target('parselex',
input : 'parse.l',
output : ['lex.priv_gst_parse_yy.c', 'parse_lex.h'],
command : [py3, gen_lex, '@OUTPUT0@', '@OUTPUT1@', '@INPUT@', 'DUMMY']
)
grammar = custom_target('parsegrammar',
input : 'grammar.y',
output : ['grammar.tab.c', 'grammar.tab.h'],
command : [py3, gen_grammar, '@OUTPUT0@', '@OUTPUT1@', '@INPUT@'],
depends : [parser],
)
printf_sources = [
'asnprintf.c',
'printf-args.c',
'printf-parse.c',
'vasnprintf.c',
'printf.c',
'printf-extension.c',
]
printf_args = gst_c_args + [
# '-UHAVE_LONG_DOUBLE',
# '-UHAVE_LONG_LONG_FORMAT',
# ' -UHAVE_WCHAR_T',
# '-UHAVE_WCSLEN',
# '-UHAVE_WINT_T',
'-DSTATIC=G_GNUC_INTERNAL',
]
printf_lib = static_library('gstprintf',
printf_sources,
include_directories : [configinc],
c_args : printf_args + pic_args,
install : false,
dependencies : [glib_dep])
gst_base_sources = [
'gstadapter.c',
'gstbaseparse.c',
'gstbasesink.c',
'gstbasesrc.c',
'gstbasetransform.c',
'gstbitreader.c',
'gstbytereader.c',
'gstbytewriter.c',
'gstcollectpads.c',
'gstdataqueue.c',
'gstflowcombiner.c',
'gstpushsrc.c',
'gstqueuearray.c',
'gsttypefindhelper.c',
]
gst_base_headers = [
'base.h',
'gstadapter.h',
'gstbaseparse.h',
'gstbasesink.h',
'gstbasesrc.h',
'gstbasetransform.h',
'gstbitreader.h',
'gstbytereader.h',
'gstbytewriter.h',
'gstcollectpads.h',
'gstdataqueue.h',
'gstflowcombiner.h',
'gstpushsrc.h',
'gstqueuearray.h',
'gsttypefindhelper.h',
]
if libtype != 'shared'
gst_base_static = static_library('gstbase-@0@'.format(apiversion),
gst_base_sources,
c_args : gst_c_args,
install : true,
include_directories : [configinc, libsinc],
dependencies : [gobject_dep, glib_dep, gst_dep],
)
gst_base = gst_base_static
endif
if libtype != 'static'
gst_base_shared = shared_library('gstbase-@0@'.format(apiversion),
gst_base_sources,
c_args : gst_c_args,
version : libversion,
soversion : soversion,
install : true,
include_directories : [configinc, libsinc],
dependencies : [gobject_dep, glib_dep, gst_dep],
vs_module_defs: vs_module_defs_dir + 'libgstbase.def',
)
gst_base = gst_base_shared
if build_gir
gnome.generate_gir(gst_base_shared,
sources : gst_base_sources + gst_base_headers,
namespace : 'GstBase',
nsversion : apiversion,
identifier_prefix : 'Gst',
symbol_prefix : 'gst',
export_packages : 'gstreamer-base-1.0',
link_with : libgst_shared,
include_directories : [configinc, libsinc, privinc],
includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
install : true,
extra_args : gir_init_section,
)
endif
endif
gst_base_dep = declare_dependency(link_with : gst_base,
include_directories : [libsinc],
dependencies : [gst_dep])
install_headers('base.h',
'gstadapter.h',
'gstbaseparse.h',
'gstbasesink.h',
'gstbasesrc.h',
'gstbasetransform.h',
'gstbitreader.h',
'gstbytereader.h',
'gstbytewriter.h',
'gstcollectpads.h',
'gstdataqueue.h',
'gstflowcombiner.h',
'gstpushsrc.h',
'gstqueuearray.h',
'gsttypefindhelper.h',
subdir : 'gstreamer-1.0/gst/base',
)
libcheck_files = [
'check.c',
'check_error.c',
'check_list.c',
'check_log.c',
'check_msg.c',
'check_pack.c',
'check_print.c',
'check_run.c',
'check_str.c',
'libcompat.c'
]
if not cdata.has('HAVE_ALARM')
libcheck_files += [ 'alarm.c' ]
endif
if not cdata.has('HAVE_CLOCK_GETTIME')
libcheck_files += [ 'clock_gettime.c' ]
endif
if not cdata.has('HAVE_DECL_STRSIGNAL')
libcheck_files += [ 'strsignal.c' ]
endif
# FIXME: check for symbols timer_create, timer_settime, timer_delete as well
if not rt_lib.found()
libcheck_files += [ 'timer_create.c', 'timer_settime.c', 'timer_delete.c' ]
endif
configure_file(input : 'check.h.in',
output : 'check.h',
configuration : check_cdata)
internal_check_h_inc = include_directories('..')
libcheck = static_library('check',
libcheck_files,
include_directories : [ configinc, internal_check_h_inc ],
dependencies : [rt_lib, mathlib],
c_args: gst_c_args + pic_args)
gst_check_sources = [
'gstbufferstraw.c',
'gstcheck.c',
'gstconsistencychecker.c',
'gstharness.c',
'gsttestclock.c',
]
gst_check_headers = [
'check.h',
'gstbufferstraw.h',
'gstcheck.h',
'gstconsistencychecker.h',
'gstharness.h',
'gsttestclock.h',
]
install_headers(gst_check_headers, subdir : 'gstreamer-1.0/gst/check/')
check_cdata = configuration_data()
check_cdata.set('ENABLE_SUBUNIT', 0)
check_cdata.set('CHECK_MAJOR_VERSION', 0)
check_cdata.set('CHECK_MINOR_VERSION', 9)
check_cdata.set('CHECK_MICRO_VERSION', 14)
if host_machine.system() != 'windows'
check_cdata.set('HAVE_FORK', 1)
endif
subdir('libcheck')
configure_file(input : 'libcheck/check.h.in',
output : 'internal-check.h',
install : true,
install_dir : 'include/gstreamer-1.0/gst/check/',
configuration : check_cdata)
gst_check = shared_library('gstcheck',
gst_check_sources,
c_args : gst_c_args,
include_directories : [configinc, libsinc],
link_with : [libcheck],
dependencies : [gobject_dep, glib_dep, gst_dep],
)
gst_check_dep = declare_dependency(link_with : gst_check,
include_directories : [libsinc],
dependencies : [gst_dep])
gst_controller_sources = [
'gstargbcontrolbinding.c',
'gstdirectcontrolbinding.c',
'gsttimedvaluecontrolsource.c',
'gstinterpolationcontrolsource.c',
'gsttriggercontrolsource.c',
'gstlfocontrolsource.c',
]
gst_controller_headers = [
'gstargbcontrolbinding.h',
'gstdirectcontrolbinding.h',
'gsttimedvaluecontrolsource.h',
'gstinterpolationcontrolsource.h',
'gsttriggercontrolsource.h',
'gstlfocontrolsource.h',
'controller.h',
]
install_headers(gst_controller_headers, subdir : 'gstreamer-1.0/gst/controller/')
if libtype != 'shared'
gst_controller_static = static_library('gstcontroller-@0@'.format(apiversion),
gst_controller_sources,
c_args : gst_c_args,
install : true,
include_directories : [configinc, libsinc],
dependencies : [gobject_dep, glib_dep, mathlib, gst_dep],
)
gst_controller = gst_controller_static
endif
if libtype != 'static'
gst_controller_shared = shared_library('gstcontroller-@0@'.format(apiversion),
gst_controller_sources,
c_args : gst_c_args,
install : true,
version : libversion,
soversion : soversion,
include_directories : [configinc, libsinc],
dependencies : [gobject_dep, glib_dep, mathlib, gst_dep],
vs_module_defs: vs_module_defs_dir + 'libgstcontroller.def',
)
gst_controller = gst_controller_shared
if build_gir
gnome.generate_gir(gst_controller_shared,
sources : gst_controller_sources + gst_controller_headers,
namespace : 'GstController',
nsversion : apiversion,
identifier_prefix : 'Gst',
symbol_prefix : 'gst',
export_packages : 'gstreamer-controller-1.0',
link_with : libgst_shared,
include_directories : [configinc, libsinc, privinc],
includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
install : true,
extra_args : gir_init_section,
)
endif
endif
gst_controller_dep = declare_dependency(link_with : gst_controller,
include_directories : [libsinc],
dependencies : [gst_dep])
gst_plugin_scanner = executable('gst-plugin-scanner',
'gst-plugin-scanner.c',
c_args : gst_c_args,