diff --git a/fuzz/meson.build b/fuzz/meson.build new file mode 100644 index 0000000..c6880d6 --- /dev/null +++ b/fuzz/meson.build @@ -0,0 +1,13 @@ +fuzzer_cargs = [ + '-DSRCDIR="@0@"'.format(meson.source_root()), + '-DTEST_RUN', +] + +foreach test_name : ['fuzzer', 'load_fuzzer', 'load_dafsa_fuzzer'] + source_file = 'libpsl_@0@.c'.format(test_name) + exe = executable(test_name, source_file, 'main.c', + link_with : libpsl, + c_args : fuzzer_cargs, + include_directories : [configinc, includedir]) + test(test_name, exe) +endforeach diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 0000000..bf73783 --- /dev/null +++ b/include/meson.build @@ -0,0 +1,17 @@ +version_arr = meson.project_version().split('.') +cdata = configuration_data() +cdata.set('LIBPSL_VERSION', meson.project_version()) +cdata.set('LIBPSL_VERSION_MAJOR', version_arr[0]) +cdata.set('LIBPSL_VERSION_MINOR', version_arr[1]) +cdata.set('LIBPSL_VERSION_PATCH', version_arr[2]) + +# FIXME: We should not run a command-line for this, but I don't think Meson +# has API for that. +printf = find_program('printf') +r = run_command(printf, '0x%02x%02x%02x', version_arr, check : true) +cdata.set('LIBPSL_VERSION_NUMBER', r.stdout().strip()) + +configure_file( + input : 'libpsl.h.in', + output : 'libpsl.h', + configuration : cdata) diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..3a69710 --- /dev/null +++ b/meson.build @@ -0,0 +1,104 @@ +project('libpsl', 'c', + version : '0.20.2', + meson_version : '>=0.47.0') + +cc = meson.get_compiler('c') + +enable_runtime = get_option('runtime') +enable_builtin = get_option('builtin') + +notfound = dependency('', required : false) +libidn2_dep = notfound +libicu_dep = notfound +libidn_dep = notfound +libunistring = notfound + +# FIXME: Cleanup this when Meson gets 'feature-combo' +# https://github.com/mesonbuild/meson/issues/4566 +if ['libidn2', 'auto'].contains(enable_runtime) or ['libidn2', 'auto'].contains(enable_builtin) + libidn2_dep = dependency('libidn2', required : false) + if libidn2_dep.found() + if enable_runtime == 'auto' + enable_runtime = 'libidn2' + endif + if enable_builtin == 'auto' + enable_builtin = 'libidn2' + endif + endif +endif + +if ['libicu', 'auto'].contains(enable_runtime) or ['libicu', 'auto'].contains(enable_builtin) + libicu_dep = dependency('icu-uc', required : false) + if libidn2_dep.found() + if enable_runtime == 'auto' + enable_runtime = 'libicu' + endif + if enable_builtin == 'auto' + enable_builtin = 'libicu' + endif + endif +endif + +if ['libidn', 'auto'].contains(enable_runtime) or ['libidn', 'auto'].contains(enable_builtin) + libidn_dep = dependency('libidn', required : false) + if libidn2_dep.found() + if enable_runtime == 'auto' + enable_runtime = 'libidn' + endif + if enable_builtin == 'auto' + enable_builtin = 'libidn' + endif + endif +endif + +if libidn2_dep.found() or libidn_dep.found() + # Check for libunistring, we need it for psl_str_to_utf8lower() + libunistring = cc.find_library('unistring') +endif + +if enable_runtime == 'auto' + enable_runtime = 'no' +endif +if enable_builtin == 'auto' + enable_builtin = 'no' +endif + +config = configuration_data() +config.set_quoted('PACKAGE_VERSION', meson.project_version()) +config.set('WITH_LIBIDN2', enable_runtime == 'libidn2') +config.set('WITH_LIBICU', enable_runtime == 'libicu') +config.set('WITH_LIBIDN', enable_runtime == 'libidn') +config.set('BUILTIN_GENERATOR_LIBIDN2', enable_builtin == 'libidn2') +config.set('BUILTIN_GENERATOR_LIBICU', enable_builtin == 'libicu') +config.set('BUILTIN_GENERATOR_LIBIDN', enable_builtin == 'libidn') +config.set('HAVE_UNISTD_H', cc.check_header('unistd.h')) +config.set('HAVE_STDINT_H', cc.check_header('stdint.h')) +config.set('HAVE_ALLOCA_H', cc.check_header('alloca.h')) +config.set('HAVE_ALLOCA', cc.has_function('alloca')) +config.set('HAVE_STRNDUP', cc.has_function('strndup')) +config.set('HAVE_CLOCK_GETTIME', cc.has_function('clock_gettime')) +config.set('HAVE_FMEMOPEN', cc.has_function('fmemopen')) +config.set('HAVE_NL_LANGINFO', cc.has_function('nl_langinfo')) +configure_file(output : 'config.h', configuration : config) + +configinc = include_directories('.') +includedir = include_directories('include') + +psl_distfile = get_option('psl_distfile') +psl_file = get_option('psl_file') +if psl_file == '' + psl_file = join_paths(meson.current_source_dir(), 'list', 'public_suffix_list.dat') +endif +psl_test_file = get_option('psl_testfile') +if psl_test_file == '' + psl_test_file = join_paths(meson.current_source_dir(), 'list', 'tests', 'tests.txt') +endif + +python = import('python').find_installation() +pkgconfig = import('pkgconfig') + +subdir('include') +subdir('src') +subdir('tools') +subdir('tests') +subdir('fuzz') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..eb80489 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,16 @@ +option('runtime', type : 'combo', + choices : ['libidn2', 'libicu', 'libidn', 'no', 'auto'], value : 'auto', + description : 'Specify the IDNA library used for libpsl run-time conversions') + +option('builtin', type : 'combo', + choices : ['libidn2', 'libicu', 'libidn', 'no', 'auto'], value : 'auto', + description : 'Specify the IDNA library used for built-in data generation') + +option('psl_distfile', type : 'string', value : '', + description : 'path to distribution-wide PSL file') + +option('psl_file', type : 'string', value : '', + description : 'path to PSL file') + +option('psl_testfile', type : 'string', value : '', + description : 'path to PSL test file') diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..6bb25b5 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,30 @@ +psl_make_dafsa = find_program('psl-make-dafsa') + +suffixes_dafsa_h = custom_target('suffixes_dafsa.h', + input : psl_file, + output : 'suffixes_dafsa.h', + command : [python, psl_make_dafsa, '--output-format=cxx+', '@INPUT@', '@OUTPUT@']) + +sources = [ + 'lookup_string_in_fixed_set.c', + 'psl.c', +] + +cargs = [ + '-DHAVE_CONFIG_H', + '-DBUILDING_PSL', + '-DPSL_DISTFILE="@0@"'.format(psl_distfile), +] + +libpsl = library('psl', sources, suffixes_dafsa_h, + include_directories : [configinc, includedir], + c_args : cargs, + dependencies : [libidn2_dep, libidn_dep, libicu_dep, libunistring], +) + +pkgconfig.generate(libpsl, + name : 'libpsl', + description : 'Public Suffix List C library') + +libpsl_dep = declare_dependency(link_with : libpsl, + include_directories : includedir) diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..b91da44 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,36 @@ +psl_dafsa = custom_target('psl.dafsa', + input : psl_file, + output : 'psl.dafsa', + command : [python, psl_make_dafsa, '--output-format=binary', '@INPUT@', '@OUTPUT@']) + +psl_ascii_dafsa = custom_target('psl_ascii.dafsa', + input : psl_file, + output : 'psl_ascii.dafsa', + command : [python, psl_make_dafsa, '--output-format=binary', '--encoding=ascii', '@INPUT@', '@OUTPUT@']) + +tests_cargs = [ + '-DSRCDIR="@0@"'.format(meson.source_root()), + '-DPSL_FILE="@0@"'.format(psl_file), + '-DPSL_TESTFILE="@0@"'.format(psl_test_file), + '-DPSL_DAFSA="@0@"'.format(psl_dafsa.full_path()), + '-DPSL_ASCII_DAFSA="@0@"'.format(psl_ascii_dafsa.full_path()), +] + +tests = [ + 'test-is-public', + 'test-is-public-all', + 'test-is-cookie-domain-acceptable', +] + +if enable_builtin != 'no' + tests += ['test-is-public-builtin', 'test-registrable-domain'] +endif + +foreach test_name : tests + source = test_name + '.c' + exe = executable(test_name, source, + c_args : tests_cargs, + link_with : libpsl, + include_directories : [configinc, includedir]) + test(test_name, exe, depends : [psl_dafsa, psl_ascii_dafsa]) +endforeach diff --git a/tools/meson.build b/tools/meson.build new file mode 100644 index 0000000..2cbdae9 --- /dev/null +++ b/tools/meson.build @@ -0,0 +1,4 @@ +psl = executable('psl', 'psl.c', + link_with : libpsl, + include_directories : [configinc, includedir], + c_args : ['-DHAVE_CONFIG_H'])