Permalink
Browse files

Add support for building with the Meson build system

The Meson build system is being adopted by projects
such as GNOME, GTK, GStreamer, and there is support
for it in Pango as well.

Having support for building with Meson in fribidi
would facilitate builds of GTK, Pango, etc. via
Meson's subproject support.

Meson also supports builds on Windows with MSVC.

Cross-compilation is of course also supported, but
has not been tested yet for this build.

Try with:

 $ meson --prefix=/tmp/prefix builddir
 $ ninja -C builddir
 $ ninja -C builddir test
 $ ninja -C builddir install

Build time comparison:

 - autotools: 18 seconds
 - meson: 4 seconds

http://mesonbuild.com for more information.
  • Loading branch information...
tp-m committed Feb 16, 2018
1 parent 4c97999 commit a991b009b11fb791a9217af23659b092eb45377e
Showing with 390 additions and 0 deletions.
  1. +27 −0 bin/meson.build
  2. +39 −0 doc/meson.build
  3. +79 −0 gen.tab/meson.build
  4. +75 −0 lib/meson.build
  5. +100 −0 meson.build
  6. +6 −0 meson_options.txt
  7. +20 −0 test/meson.build
  8. +25 −0 test/test-runner.py
  9. +19 −0 test/unicode-conformance/meson.build
@@ -0,0 +1,27 @@
fribidi = executable('fribidi',
'fribidi-main.c', 'getopt.c', 'getopt1.c', fribidi_unicode_version_h,
c_args: ['-DHAVE_CONFIG_H'],
include_directories: incs,
link_with: libfribidi,
install: true)
executable('fribidi-benchmark',
'fribidi-benchmark.c', 'getopt.c', 'getopt1.c', fribidi_unicode_version_h,
c_args: ['-DHAVE_CONFIG_H'],
include_directories: incs,
link_with: libfribidi,
install: false)
executable('fribidi-bidi-types',
'fribidi-bidi-types.c', fribidi_unicode_version_h,
c_args: ['-DHAVE_CONFIG_H'],
include_directories: incs,
link_with: libfribidi,
install: false)
executable('fribidi-caprtl2utf8',
'fribidi-caprtl2utf8.c', fribidi_unicode_version_h,
c_args: ['-DHAVE_CONFIG_H'],
include_directories: incs,
link_with: libfribidi,
install: false)
@@ -0,0 +1,39 @@
c2man = find_program('c2man', required: false)
if not c2man.found()
error('c2man is required to build documentation. Or disable with -Ddocs=false')
endif
# Extract list of man pages (one man page per symbol) from lib/libfribidi.def
python3 = import('python3').find_python()
result = run_command(python3,
'-c', 'import sys; print(open(sys.argv[1], "r").read())',
files('../lib/fribidi.def'))
if result.returncode() != 0
error('Could not extract list of symbols from fribidi.def.')
endif
gen_man_pages = []
syms = result.stdout().strip().split('\n')
foreach sym : syms
gen_man_pages += ['@0@.3'.format(sym)]
endforeach
c2man_incs = []
c2man_incs += ['-I' + join_paths(meson.source_root(), 'lib')]
c2man_incs += ['-I' + join_paths(meson.build_root(), 'lib')]
c2man_incs += ['-I' + join_paths(meson.source_root(), 'gen.tab')]
c2man_incs += ['-I' + join_paths(meson.build_root(), 'gen.tab')]
custom_target('man pages',
command: [c2man, '-v', '-T', 'n', '-M', 'Programmer\'s Manual', c2man_incs,
'-D__FRIBIDI_DOC', '-DDONT_HAVE_FRIBIDI_CONFIG_H',
'-o@0@'.format(meson.current_build_dir()),
fribidi_headers],
depends: [fribidi_unicode_version_h],
output: gen_man_pages,
install_dir: join_paths(get_option('prefix'), get_option('mandir'), 'man3'),
install: true)
@@ -0,0 +1,79 @@
# gen.tab
native_cc = meson.get_compiler('c')
# Don't pick up top-level config.h, as that has defines for the cross-compiler
# (if we're cross-compiling), but here we need values for the host compiler/env
# in that case. We shall pass those on the command line since it's just a few.
native_args = ['-UHAVE_CONFIG_H']
# This is available pretty much everywhere
native_args += ['-DHAVE_STRINGIZE']
native_args += ['-DDONT_HAVE_FRIBIDI_CONFIG_H']
if native_cc.has_header('stdlib.h')
native_args += ['-DHAVE_STDLIB_H']
endif
if native_cc.has_header('string.h')
native_args += ['-DHAVE_STRING_H']
endif
if native_cc.has_header('strings.h')
native_args += ['-DHAVE_STRINGS_H']
# Not entirely correct, but sufficient for us. Should move away from this
# ancient define and just include individual headers based on individual defs.
# stdlib.h and string.h are standard nowadays, but strings.h not (msvc)
native_args += ['-DSTDC_HEADERS=1']
endif
gen_unicode_version = executable('gen-unicode-version',
'gen-unicode-version.c',
include_directories: incs,
c_args: native_args,
install: false)
fribidi_unicode_version_h = custom_target('fribidi-unicode-version.h',
input: files('unidata/ReadMe.txt', 'unidata/BidiMirroring.txt'),
output: 'fribidi-unicode-version.h',
command: [gen_unicode_version, '@INPUT0@', '@INPUT1@', 'gen-unicode-version'],
capture: true,
install_dir: join_paths(get_option('includedir'), 'fribidi'),
install: true)
COMPRESSION='2'
tabs = [
['bidi-type', files('unidata/UnicodeData.txt')],
['joining-type', files('unidata/UnicodeData.txt', 'unidata/ArabicShaping.txt')],
['arabic-shaping', files('unidata/UnicodeData.txt')],
['mirroring', files('unidata/BidiMirroring.txt')],
['brackets', files('unidata/BidiBrackets.txt', 'unidata/UnicodeData.txt')],
['brackets-type', files('unidata/BidiBrackets.txt')],
]
generated_tab_include_files = []
foreach tab : tabs
gen_prog_name = 'gen-@0@-tab'.format(tab[0])
gen_prog_src = 'gen-@0@-tab.c'.format(tab[0])
gen_prog_out = '@0@.tab.i'.format(tab[0])
gen_prog_inputs = tab[1]
gen_exe = executable(gen_prog_name,
fribidi_unicode_version_h,
gen_prog_src, 'packtab.c',
include_directories: incs,
c_args: native_args,
install: false)
tab_inc_file = custom_target(gen_prog_name,
input: gen_prog_inputs,
output: gen_prog_out,
command: [gen_exe, COMPRESSION, '@INPUT@', gen_prog_name],
capture: true)
generated_tab_include_files += [tab_inc_file]
endforeach
@@ -0,0 +1,75 @@
fribidi_config = configuration_data()
fribidi_config.set('configure_input', 'fribidi-config.h file generated by Meson')
fribidi_config.set('PACKAGE', meson.project_name())
fribidi_config.set('PACKAGE_NAME', 'GNU FriBidi')
fribidi_config.set('PACKAGE_BUGREPORT', 'https://github.com/fribidi/fribidi/issues/new')
fribidi_config.set('FRIBIDI_VERSION', meson.project_version())
version_arr = meson.project_version().split('.')
fribidi_config.set('FRIBIDI_MAJOR_VERSION', version_arr[0].to_int())
fribidi_config.set('FRIBIDI_MINOR_VERSION', version_arr[1].to_int())
fribidi_config.set('FRIBIDI_MICRO_VERSION', version_arr[2].to_int())
fribidi_config.set('FRIBIDI_INTERFACE_VERSION', interface_version)
fribidi_config.set('SIZEOF_INT', cc.sizeof('int'))
fribidi_config_h = configure_file(input: files('fribidi-config.h.in'),
output: 'fribidi-config.h',
configuration: fribidi_config,
install_dir: join_paths(get_option('includedir'), 'fribidi'))
fribidi_headers = files(
'fribidi-arabic.h',
'fribidi-begindecls.h',
'fribidi-bidi.h',
'fribidi-bidi-types.h',
'fribidi-bidi-types-list.h',
'fribidi-char-sets.h',
'fribidi-char-sets-list.h',
'fribidi-common.h',
'fribidi-deprecated.h',
'fribidi-enddecls.h',
'fribidi-flags.h',
'fribidi-joining.h',
'fribidi-joining-types.h',
'fribidi-joining-types-list.h',
'fribidi-mirroring.h',
'fribidi-brackets.h',
'fribidi-shape.h',
'fribidi-types.h',
'fribidi-unicode.h',
'fribidi.h',
)
install_headers(fribidi_headers, subdir: 'fribidi')
fribidi_sources = [
'fribidi.c',
'fribidi-arabic.c',
'fribidi-bidi.c',
'fribidi-bidi-types.c',
'fribidi-char-sets.c',
'fribidi-char-sets-cap-rtl.c',
'fribidi-char-sets-cp1255.c',
'fribidi-char-sets-cp1256.c',
'fribidi-char-sets-iso8859-6.c',
'fribidi-char-sets-iso8859-8.c',
'fribidi-char-sets-utf8.c',
'fribidi-deprecated.c',
'fribidi-joining.c',
'fribidi-joining-types.c',
'fribidi-mirroring.c',
'fribidi-brackets.c',
'fribidi-run.c',
'fribidi-shape.c',
]
libfribidi = library('fribidi',
fribidi_sources, fribidi_unicode_version_h, fribidi_config_h,
generated_tab_include_files, config_h,
include_directories: incs,
c_args: ['-DHAVE_CONFIG_H'] + visibility_args,
version: libversion,
soversion: soversion,
install: true)
@@ -0,0 +1,100 @@
project('fribidi', 'c', version: '1.0.1',
meson_version : '>= 0.44')
# New release:
# interface_age++
# micro version++
#
# If any functions have been added:
# interface_age = 0
# interface_version++
#
# If binary backwards compatibility has been broken:
# panic!
interface_age = 0
interface_version = 4
soversion = 0
libversion = '@0@.@1@.0'.format(soversion, interface_version, interface_age)
# C compiler. This is the cross compiler if we're cross-compiling
cc = meson.get_compiler('c')
if cc.get_id() == 'gcc' and cc.has_argument('-ansi')
add_project_arguments('-ansi', language: 'c')
endif
# Symbol visibility
have_visibility_hidden = cc.has_argument('-fvisibility=hidden')
if have_visibility_hidden
add_project_arguments('-fvisibility=hidden', language: 'c')
endif
# Must explicitly make symbols public if default visibility is hidden
if have_visibility_hidden
visibility_args = ['-DFRIBIDI_ENTRY=extern __attribute__ ((visibility ("default")))']
else
if host_machine.system() == 'windows'
visibility_args = ['-DFRIBIDI_ENTRY=__declspec(dllexport)']
else
visibility_args = ['-DFRIBIDI_ENTRY=extern']
endif
endif
cdata = configuration_data()
# Checks for library functions
foreach f : ['memmove', 'memset', 'strdup']
cdata.set('HAVE_' + f.to_upper(), cc.has_function(f))
endforeach
# Checks for header files
# Some HAVE_FOO defines need to be defined to either 1 or 0, others need to
# be defined or undefined. The code base is a bit inconsistent there.
foreach h : ['stdlib.h', 'string.h', 'memory.h']
cdata.set10('HAVE_' + h.underscorify().to_upper(), cc.has_header(h))
endforeach
foreach h : ['strings.h', 'sys/times.h']
cdata.set('HAVE_' + h.underscorify().to_upper(), cc.has_header(h))
endforeach
# Not entirely correct, but sufficient for us. Should move away from this
# ancient define and just include individual headers based on individual defs
if cc.has_header('strings.h')
# define to 1 or leave undefined otherwise, don't simplify
cdata.set('STDC_HEADERS', 1)
endif
# This is available pretty much everywhere
cdata.set('HAVE_STRINGIZE', 1)
buildtype = get_option('buildtype')
if buildtype == 'debug' or buildtype == 'debugoptimized'
cdata.set('DEBUG', 1)
endif
no_deprecated = not get_option('deprecated')
cdata.set('FRIBIDI_NO_DEPRECATED', no_deprecated)
# write config.h
config_h = configure_file(output: 'config.h', configuration: cdata)
incs = include_directories('.', 'lib')
subdir('gen.tab')
subdir('lib')
subdir('bin')
subdir('test')
if get_option('docs')
subdir('doc')
endif
# fribidi.pc
pkg = import('pkgconfig')
pkg.generate(name: 'GNU FriBidi',
filebase: 'fribidi',
description: 'Unicode Bidirectional Algorithm Library',
libraries: libfribidi,
subdirs: 'fribidi',
version: meson.project_version())
@@ -0,0 +1,6 @@
option('deprecated', type : 'boolean', value : true,
description: 'Build deprecated functionality')
option('docs', type : 'boolean', value : true,
description: 'Build documentation')
option('glib', type : 'boolean', value : true,
description: 'Use GLib (in unit tests)')
@@ -0,0 +1,20 @@
tests = [
['CapRTL', 'explicit'],
['CapRTL', 'implicit'],
['ISO8859-8', 'hebrew'],
['UTF-8', 'persian'],
['UTF-8', 'reordernsm'],
]
test_runner = find_program('test-runner.py')
foreach t : tests
charset = t[0]
suffix = t[1]
test_name = '@0@_@1@'.format(charset, suffix)
input_file = files('test_@0@.input'.format(test_name))
reference_file = files('test_@0@.reference'.format(test_name))
test(test_name, test_runner, args: [fribidi, charset, input_file, reference_file])
endforeach
subdir('unicode-conformance')
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
# Test runner that calls ../bin/fribidi --test --charset CHARSET *.input,
# captures the output and compares it to the data in the reference file given
import subprocess
import sys
if len(sys.argv) != 5:
raise Exception('Expected 4 command-line arguments: test_exe charset test.input test.reference')
script = sys.argv[0]
test_exe = sys.argv[1]
charset = sys.argv[2]
input_file = sys.argv[3]
reference_file = sys.argv[4]
try:
output = subprocess.check_output([test_exe, '--test', '--charset', charset, input_file])
ref_data = open(reference_file, "rb").read()
if output != ref_data:
print('Output:\n', output)
print('Reference file:\n', ref_data)
raise Exception('fribidi --test output for charset ' + charset + ' and input file ' + input_file + ' does not match data from reference file ' + reerence_file)
except:
raise Exception('fribidi --test failed for charset ' + charset + ' and input file ' + input_file)
@@ -0,0 +1,19 @@
with_glib = get_option('glib')
if with_glib
glib_dep = dependency('glib-2.0', version: '>= 2.4', required: false)
if glib_dep.found()
tests = [
['BidiTest', 'test.c'],
['BidiCharacterTest', 'test-character.c'],
]
foreach t : tests
exe = executable(t[0],
t[1], fribidi_unicode_version_h,
c_args: ['-DHAVE_CONFIG_H'],
include_directories: incs,
dependencies: glib_dep,
link_with: libfribidi)
test(t[0], exe, args: files('@0@.txt'.format(t[0])))
endforeach
endif
endif

0 comments on commit a991b00

Please sign in to comment.