
22 changed files with 803 additions and 731 deletions
@ -1,4 +1,2 @@
@@ -1,4 +1,2 @@
|
||||
build/** |
||||
.waf-* |
||||
.lock-waf* |
||||
__pycache__ |
||||
|
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
[submodule "waflib"] |
||||
path = waflib |
||||
url = ../autowaf.git |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
configure_file(copy: true, input: '../../resources/serd.svg', output: 'serd.svg') |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
c_serd_rst = custom_target( |
||||
'C API ReST Documentation', |
||||
command: [dox_to_sphinx, '-f', '@INPUT0@', 'doc/c/api'], |
||||
input: [c_index_xml] + c_rst_files, |
||||
output: 'serd.rst') |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
config = configuration_data() |
||||
config.set('SERD_VERSION', meson.project_version()) |
||||
|
||||
conf_py = configure_file(configuration: config, |
||||
input: '../conf.py.in', |
||||
output: 'conf.py') |
||||
|
||||
configure_file(copy: true, input: '../summary.rst', output: 'summary.rst') |
||||
|
||||
c_rst_files = files( |
||||
'index.rst', |
||||
'overview.rst', |
||||
) |
||||
|
||||
foreach f : c_rst_files |
||||
configure_file(copy: true, input: f, output: '@PLAINNAME@') |
||||
endforeach |
||||
|
||||
subdir('xml') |
||||
subdir('api') |
||||
|
||||
docs = custom_target( |
||||
'C API Documentation (singlehtml)', |
||||
command: [sphinx_build, '-M', 'singlehtml', 'doc/c/', 'doc/c/', '-E', '-q', '-t', 'singlehtml'], |
||||
input: [c_rst_files, c_serd_rst, c_index_xml], |
||||
output: 'singlehtml', |
||||
build_by_default: true, |
||||
install: true, |
||||
install_dir: docdir / 'serd-0') |
||||
|
||||
docs = custom_target( |
||||
'C API Documentation (html)', |
||||
command: [sphinx_build, '-M', 'html', 'doc/c/', 'doc/c/', '-E', '-q', '-t', 'html'], |
||||
input: [c_rst_files, c_serd_rst, c_index_xml], |
||||
output: 'html', |
||||
build_by_default: true, |
||||
install: true, |
||||
install_dir: docdir / 'serd-0') |
@ -1,41 +0,0 @@
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
|
||||
def build(bld): |
||||
dox_to_sphinx = bld.path.find_node("../../scripts/dox_to_sphinx.py") |
||||
index_xml = bld.path.get_bld().make_node("xml/index.xml") |
||||
|
||||
files = [ |
||||
("../../resources/serd.svg", "sphinx/_static/serd.svg"), |
||||
("../summary.rst", "sphinx/summary.rst"), |
||||
("index.rst", "sphinx/index.rst"), |
||||
("overview.rst", "sphinx/overview.rst"), |
||||
] |
||||
|
||||
# Run Doxygen to generate XML documentation |
||||
bld(features="doxygen", doxyfile="Doxyfile") |
||||
|
||||
# Substitute variables to make Sphinx configuration file |
||||
bld(features="subst", |
||||
source="../conf.py.in", |
||||
target="sphinx/conf.py", |
||||
SERD_VERSION=bld.env.SERD_VERSION) |
||||
|
||||
# Copy static documentation files to Sphinx build directory |
||||
for f in files: |
||||
bld(features="subst", is_copy=True, source=f[0], target=f[1]) |
||||
|
||||
# Generate Sphinx markup from Doxygen XML |
||||
bld.add_group() |
||||
bld(rule="${PYTHON} " + dox_to_sphinx.abspath() + " -f ${SRC} ${TGT}", |
||||
source=index_xml, |
||||
target="sphinx/api/") |
||||
|
||||
doc_dir = bld.env.DOCDIR + "/serd-%s/" % bld.env.SERD_MAJOR_VERSION |
||||
|
||||
# Run Sphinx to generate HTML documentation |
||||
for builder in ["html", "singlehtml"]: |
||||
bld(features="sphinx", |
||||
sphinx_source=bld.path.get_bld().make_node("sphinx"), |
||||
sphinx_output_format=builder, |
||||
sphinx_options=["-E", "-q", "-t", builder], |
||||
install_path=doc_dir + "c/%s/" % builder) |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
doxygen = find_program('doxygen') |
||||
|
||||
c_doxygen_input = [] |
||||
foreach h : c_headers |
||||
c_doxygen_input += ['..' / h] |
||||
endforeach |
||||
|
||||
config = configuration_data() |
||||
config.set('SERD_HEADERS', ' '.join(c_doxygen_input)) |
||||
config.set('SERD_SRCDIR', serd_src_root) |
||||
|
||||
c_doxyfile = configure_file(configuration: config, |
||||
input: '../Doxyfile.in', |
||||
output: 'Doxyfile') |
||||
|
||||
c_index_xml = custom_target('c-index.xml', |
||||
command: [doxygen, '@INPUT0@'], |
||||
input: [c_doxyfile] + c_header_files, |
||||
output: 'index.xml') |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
docdir = get_option('datadir') / 'doc' |
||||
|
||||
doxygen = find_program('doxygen', required: get_option('docs')) |
||||
dox_to_sphinx = find_program('../scripts/dox_to_sphinx.py') |
||||
sphinx_build = find_program('sphinx-build', required: get_option('docs')) |
||||
|
||||
build_docs = doxygen.found() and sphinx_build.found() |
||||
|
||||
if build_docs |
||||
subdir('_static') |
||||
subdir('c') |
||||
endif |
||||
|
||||
if meson.version().version_compare('>=0.53.0') |
||||
summary('Documentation', build_docs, bool_yn: true) |
||||
endif |
||||
|
@ -0,0 +1,188 @@
@@ -0,0 +1,188 @@
|
||||
project('serd', ['c'], |
||||
version: '0.30.9', |
||||
license: 'ISC', |
||||
meson_version: '>= 0.49.2', |
||||
default_options: [ |
||||
'b_ndebug=if-release', |
||||
'buildtype=release', |
||||
'c_std=c99', |
||||
'default_library=shared', |
||||
'warning_level=2', |
||||
]) |
||||
|
||||
serd_src_root = meson.current_source_dir() |
||||
major_version = meson.project_version().split('.')[0] |
||||
version_suffix = '-@0@'.format(major_version) |
||||
versioned_name = 'serd' + version_suffix |
||||
|
||||
# Load build tools |
||||
pkg = import('pkgconfig') |
||||
cc = meson.get_compiler('c') |
||||
|
||||
# Set ultra strict warnings for developers, if requested |
||||
if get_option('strict') |
||||
subdir('meson') |
||||
|
||||
c_warnings = all_c_warnings |
||||
if cc.get_id() == 'clang' |
||||
c_warnings += [ |
||||
'-Wno-bad-function-cast', |
||||
'-Wno-cast-align', |
||||
'-Wno-cast-qual', |
||||
'-Wno-conversion', |
||||
'-Wno-covered-switch-default', |
||||
'-Wno-disabled-macro-expansion', |
||||
'-Wno-double-promotion', |
||||
'-Wno-format-nonliteral', |
||||
'-Wno-implicit-fallthrough', |
||||
'-Wno-nullability-extension', |
||||
'-Wno-nullable-to-nonnull-conversion', |
||||
'-Wno-padded', |
||||
'-Wno-reserved-id-macro', |
||||
'-Wno-sign-conversion', |
||||
] |
||||
elif cc.get_id() == 'gcc' |
||||
c_warnings += [ |
||||
'-Wno-bad-function-cast', |
||||
'-Wno-cast-align', |
||||
'-Wno-cast-qual', |
||||
'-Wno-float-conversion', |
||||
'-Wno-format-nonliteral', |
||||
'-Wno-inline', |
||||
'-Wno-padded', |
||||
'-Wno-sign-conversion', |
||||
'-Wno-switch-default', |
||||
'-Wno-unsuffixed-float-constants', |
||||
'-Wno-unused-const-variable', |
||||
] |
||||
elif cc.get_id() == 'msvc' |
||||
c_warnings += [ |
||||
'/wd4061', # enumerator in switch is not explicitly handled |
||||
'/wd4365', # signed/unsigned mismatch |
||||
'/wd4514', # unreferenced inline function has been removed |
||||
'/wd4706', # assignment within conditional expression |
||||
'/wd4710', # function not inlined |
||||
'/wd4711', # function selected for automatic inline expansion |
||||
'/wd4820', # padding added after construct |
||||
'/wd4996', # POSIX name for this item is deprecated |
||||
'/wd5045', # will insert Spectre mitigation for memory load |
||||
] |
||||
endif |
||||
|
||||
add_project_arguments(cc.get_supported_arguments(c_warnings), |
||||
language: ['c']) |
||||
endif |
||||
|
||||
# Add special arguments for MSVC |
||||
if cc.get_id() == 'msvc' |
||||
msvc_args = [ |
||||
'/D_CRT_SECURE_NO_WARNINGS', |
||||
'/TP', |
||||
'/experimental:external', |
||||
'/external:W0', |
||||
'/external:anglebrackets', |
||||
] |
||||
|
||||
add_project_arguments(msvc_args, language: ['c']) |
||||
endif |
||||
|
||||
c_headers = ['include/serd/serd.h'] |
||||
c_header_files = files(c_headers) |
||||
|
||||
sources = [ |
||||
'src/base64.c', |
||||
'src/byte_source.c', |
||||
'src/env.c', |
||||
'src/n3.c', |
||||
'src/node.c', |
||||
'src/reader.c', |
||||
'src/string.c', |
||||
'src/system.c', |
||||
'src/uri.c', |
||||
'src/writer.c', |
||||
] |
||||
|
||||
# System libraries |
||||
m_dep = cc.find_library('m', required: false) |
||||
|
||||
# Determine library type and the flags needed to build it |
||||
if get_option('default_library') == 'both' |
||||
if host_machine.system() == 'windows' |
||||
error('default_library=both is not supported on Windows') |
||||
endif |
||||
|
||||
library_type = 'both_libraries' |
||||
library_args = ['-DSERD_INTERNAL'] |
||||
prog_args = [] |
||||
elif get_option('default_library') == 'shared' |
||||
library_type = 'shared_library' |
||||
library_args = ['-DSERD_INTERNAL'] |
||||
prog_args = [] |
||||
else |
||||
library_type = 'static_library' |
||||
library_args = ['-DSERD_INTERNAL', '-DSERD_STATIC'] |
||||
prog_args = ['-DSERD_STATIC'] |
||||
endif |
||||
|
||||
# Build shared and/or static library/libraries |
||||
libserd = build_target( |
||||
versioned_name, |
||||
sources, |
||||
version: meson.project_version(), |
||||
include_directories: include_directories(['include']), |
||||
c_args: library_args, |
||||
dependencies: m_dep, |
||||
gnu_symbol_visibility: 'hidden', |
||||
install: true, |
||||
target_type: library_type) |
||||
|
||||
serd_dep = declare_dependency( |
||||
include_directories: include_directories(['include']), |
||||
link_with: libserd) |
||||
|
||||
pkg.generate( |
||||
libserd, |
||||
name: 'Serd', |
||||
filebase: versioned_name, |
||||
subdirs: [versioned_name], |
||||
version: meson.project_version(), |
||||
description: 'A lightweight library for working with RDF') |
||||
|
||||
# Build serdi command line utility |
||||
if get_option('utils') |
||||
|
||||
serdi = executable('serdi', 'src/serdi.c', |
||||
c_args: prog_args, |
||||
install: true, |
||||
dependencies: serd_dep) |
||||
|
||||
if not get_option('docs').disabled() |
||||
install_man('doc/serdi.1') |
||||
endif |
||||
endif |
||||
|
||||
# Install header to a versioned include directory |
||||
install_headers(c_headers, subdir: versioned_name / 'serd') |
||||
|
||||
if not get_option('docs').disabled() |
||||
subdir('doc') |
||||
endif |
||||
|
||||
if get_option('tests') |
||||
subdir('test') |
||||
endif |
||||
|
||||
if meson.version().version_compare('>=0.53.0') |
||||
summary('Tests', get_option('tests'), bool_yn: true) |
||||
summary('Utilities', get_option('utils'), bool_yn: true) |
||||
|
||||
summary('Install prefix', get_option('prefix')) |
||||
|
||||
summary('Headers', get_option('prefix') / get_option('includedir')) |
||||
summary('Libraries', get_option('prefix') / get_option('libdir')) |
||||
|
||||
if get_option('utils') |
||||
summary('Executables', get_option('prefix') / get_option('bindir')) |
||||
summary('Man pages', get_option('prefix') / get_option('mandir')) |
||||
endif |
||||
endif |
@ -0,0 +1,196 @@
@@ -0,0 +1,196 @@
|
||||
# General code to enable approximately all warnings. |
||||
# |
||||
# This is trivial for clang and MSVC, but GCC does not have such an option, and |
||||
# has several esoteric warnings, so we need to enable everything we want |
||||
# explicitly. We enable everything that does not require a value argument, |
||||
# except for warnings that are only relevant for very old languages (earlier |
||||
# than C99 or C++11) or non-standard extensions. |
||||
# |
||||
# Omitted common warnings: |
||||
# |
||||
# Wabi= |
||||
# Waggregate-return |
||||
# Walloc-size-larger-than=BYTES |
||||
# Walloca-larger-than=BYTES |
||||
# Wframe-larger-than=BYTES |
||||
# Wlarger-than=BYTES |
||||
# Wstack-usage=BYTES |
||||
# Wsystem-headers |
||||
# Wtraditional |
||||
# Wtraditional-conversion |
||||
# Wtrampolines |
||||
# Wvla-larger-than=BYTES |
||||
# |
||||
# Omitted C warnings: |
||||
# |
||||
# Wc90-c99-compat |
||||
# Wdeclaration-after-statement |
||||
# Wtraditional |
||||
# Wtraditional-conversion |
||||
# |
||||
# Omitted C++ warnings: |
||||
# |
||||
# Wnamespaces |
||||
# Wtemplates |
||||
|
||||
gcc_common_warnings = [ |
||||
'-Walloc-zero', |
||||
'-Walloca', |
||||
'-Wanalyzer-too-complex', |
||||
'-Warith-conversion', |
||||
'-Warray-bounds=2', |
||||
'-Wattribute-alias=2', |
||||
'-Wcast-align=strict', |
||||
'-Wcast-qual', |
||||
'-Wconversion', |
||||
'-Wdate-time', |
||||
'-Wdisabled-optimization', |
||||
'-Wdouble-promotion', |
||||
'-Wduplicated-branches', |
||||
'-Wduplicated-cond', |
||||
'-Wfloat-equal', |
||||
'-Wformat-overflow=2', |
||||
'-Wformat-signedness', |
||||
'-Wformat-truncation=2', |
||||
'-Wformat=2', |
||||
'-Wimplicit-fallthrough=2', |
||||
'-Winit-self', |
||||
'-Winline', |
||||
'-Winvalid-pch', |
||||
'-Wlogical-op', |
||||
'-Wmissing-declarations', |
||||
'-Wmissing-include-dirs', |
||||
'-Wmultichar', |
||||
'-Wnormalized=nfc', |
||||
'-Wnull-dereference', |
||||
'-Wpacked', |
||||
'-Wpadded', |
||||
'-Wredundant-decls', |
||||
'-Wscalar-storage-order', |
||||
'-Wshadow', |
||||
'-Wshift-overflow=2', |
||||
'-Wsizeof-array-argument', |
||||
'-Wstack-protector', |
||||
'-Wstrict-aliasing=3', |
||||
'-Wstrict-overflow=5', |
||||
'-Wstringop-overflow=3', |
||||
'-Wsuggest-attribute=cold', |
||||
'-Wsuggest-attribute=const', |
||||
'-Wsuggest-attribute=format', |
||||
'-Wsuggest-attribute=malloc', |
||||
'-Wsuggest-attribute=noreturn', |
||||
'-Wsuggest-attribute=pure', |
||||
'-Wswitch-default', |
||||
'-Wswitch-enum', |
||||
'-Wsync-nand', |
||||
'-Wundef', |
||||
'-Wunused-const-variable=2', |
||||
'-Wunused-macros', |
||||
'-Wvarargs', |
||||
'-Wvector-operation-performance', |
||||
'-Wvla', |
||||
'-Wwrite-strings', |
||||
] |
||||
|
||||
gcc_c_warnings = [ |
||||
'-Wbad-function-cast', |
||||
'-Wc++-compat', |
||||
'-Wc99-c11-compat', |
||||
'-Wdesignated-init', |
||||
'-Wdiscarded-array-qualifiers', |
||||
'-Wdiscarded-qualifiers', |
||||
'-Wincompatible-pointer-types', |
||||
'-Wjump-misses-init', |
||||
'-Wmissing-prototypes', |
||||
'-Wnested-externs', |
||||
'-Wold-style-definition', |
||||
'-Wstrict-prototypes', |
||||
'-Wunsuffixed-float-constants', |
||||
] |
||||
|
||||
# Set all_c_warnings for the current C compiler |
||||
if is_variable('cc') |
||||
if cc.get_id() == 'clang' |
||||
all_c_warnings = ['-Weverything'] |
||||
elif cc.get_id() == 'gcc' |
||||
all_c_warnings = gcc_common_warnings + [ |
||||
'-Wbad-function-cast', |
||||
'-Wc++-compat', |
||||
'-Wc99-c11-compat', |
||||
'-Wdesignated-init', |
||||
'-Wdiscarded-array-qualifiers', |
||||
'-Wdiscarded-qualifiers', |
||||
'-Wincompatible-pointer-types', |
||||
'-Wjump-misses-init', |
||||
'-Wmissing-prototypes', |
||||
'-Wnested-externs', |
||||
'-Wold-style-definition', |
||||
'-Wstrict-prototypes', |
||||
'-Wunsuffixed-float-constants', |
||||
] |
||||
elif cc.get_id() == 'msvc' |
||||
all_c_warnings = ['/Wall'] |
||||
else |
||||
all_c_warnings = [] |
||||
endif |
||||
endif |
||||
|
||||
# Set all_cpp_warnings for the current C++ compiler |
||||
if is_variable('cpp') |
||||
if cpp.get_id() == 'clang' |
||||
all_cpp_warnings = [ |
||||
'-Weverything', |
||||
'-Wno-c++98-compat', |
||||
'-Wno-c++98-compat-pedantic' |
||||
] |
||||
elif cpp.get_id() == 'gcc' |
||||
all_cpp_warnings = gcc_common_warnings + [ |
||||
'-Wabi-tag', |
||||
'-Waligned-new=all', |
||||
'-Wcatch-value=3', |
||||
'-Wcomma-subscript', |
||||
'-Wconditionally-supported', |
||||
'-Wctor-dtor-privacy', |
||||
'-Wdeprecated-copy-dtor', |
||||
'-Weffc++', |
||||
'-Wextra-semi', |
||||
'-Wmismatched-tags', |
||||
'-Wmultiple-inheritance', |
||||
'-Wnoexcept', |
||||
'-Wnoexcept-type', |
||||
'-Wnon-virtual-dtor', |
||||
'-Wold-style-cast', |
||||
'-Woverloaded-virtual', |
||||
'-Wplacement-new=2', |
||||
'-Wredundant-tags', |
||||
'-Wregister', |
||||
'-Wsign-promo', |
||||
'-Wstrict-null-sentinel', |
||||
'-Wsuggest-final-methods', |
||||
'-Wsuggest-final-types', |
||||
'-Wsuggest-override', |
||||
'-Wuseless-cast', |
||||
'-Wvirtual-inheritance', |
||||
'-Wvolatile', |
||||
'-Wzero-as-null-pointer-constant', |
||||
] |
||||
elif cpp.get_id() == 'msvc' |
||||
all_cpp_warnings = ['/Wall'] |
||||
else |
||||
all_cpp_warnings = [] |
||||
endif |
||||
endif |
||||
|
||||
# Set all_objc_warnings for the current Objective C compiler |
||||
if is_variable('objcc') |
||||
all_objc_warnings = [] |
||||
if objcc.get_id() == 'clang' |
||||
all_objc_warnings = ['-Weverything'] |
||||
elif objc.get_id() == 'gcc' |
||||
all_objc_warnings = gcc_common_warnings + [ |
||||
'-Wno-direct-ivar-access', |
||||
] |
||||
else |
||||
all_objc_warnings = [] |
||||
endif |
||||
endif |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
option('docs', type: 'feature', value: 'auto', yield: true, |
||||
description: 'Build documentation') |
||||
|
||||
option('strict', type: 'boolean', value: false, yield: true, |
||||
description: 'Enable ultra-strict warnings') |
||||
|
||||
option('tests', type: 'boolean', value: true, yield: true, |
||||
description: 'Build tests') |
||||
|
||||
option('utils', type: 'boolean', value: true, yield: true, |
||||
description: 'Build command line utilities') |
@ -1,11 +0,0 @@
@@ -1,11 +0,0 @@
|
||||
prefix=@PREFIX@ |
||||
exec_prefix=@EXEC_PREFIX@ |
||||
libdir=@LIBDIR@ |
||||
includedir=@INCLUDEDIR@ |
||||
|
||||
Name: Serd |
||||
Version: @SERD_VERSION@ |
||||
Description: Lightweight RDF syntax library |
||||
Libs: -L${libdir} -l@LIB_SERD@ |
||||
Libs.private: -lm |
||||
Cflags: -I${includedir}/serd-@SERD_MAJOR_VERSION@ |
@ -0,0 +1,167 @@
@@ -0,0 +1,167 @@
|
||||
autoship = find_program('autoship', required: false) |
||||
run_test_suite = find_program('run_test_suite.py') |
||||
wrapper = meson.get_cross_property('wrapper', '') |
||||
|
||||
unit_tests = [ |
||||
'env', |
||||
'free_null', |
||||
'node', |
||||
'read_chunk', |
||||
'reader_writer', |
||||
'string', |
||||
'uri', |
||||
] |
||||
|
||||
foreach unit : unit_tests |
||||
test(unit, |
||||
executable('test_@0@'.format(unit), |
||||
'test_@0@.c'.format(unit), |
||||
c_args: prog_args, |
||||
dependencies: serd_dep), |
||||
suite: 'unit') |
||||
endforeach |
||||
|
||||
if autoship.found() |
||||
test('autoship', autoship, args: ['test', serd_src_root], suite: 'data') |
||||
endif |
||||
|
||||
if get_option('utils') |
||||
|
||||
if wrapper != '' |
||||
script_args = ['--wrapper', wrapper, '--serdi', serdi.full_path()] |
||||
else |
||||
script_args = ['--serdi', serdi.full_path()] |
||||
endif |
||||
|
||||
serd_ttl = files('../serd.ttl')[0] |
||||
|
||||
test('serd.ttl', serdi, args: [serd_ttl], suite: 'data') |
||||
|
||||
# Command line options |
||||
|
||||
good_args = [ |
||||
['-v'], |
||||
['-h'], |
||||
['-s', '<urn:eg:s> a <urn:eg:T> .'], |
||||
] |
||||
|
||||
foreach args : good_args |
||||
test(args[0], serdi, args: args, suite: ['serdi', 'options']) |
||||
endforeach |
||||
|
||||
bad_args = [ |
||||
['-c'], |
||||
['-i', 'unknown'], |
||||
['-i'], |
||||
['-o', 'unknown'], |
||||
['-o'], |
||||
['-p'], |
||||
['-r'], |
||||
['-z'], |
||||
] |
||||
|
||||
foreach args : bad_args |
||||
name = ' '.join(args) |
||||
test(name, serdi, |
||||
args: args, |
||||
should_fail: true, |
||||
suite: ['serdi', 'options']) |
||||
endforeach |
||||
|
||||
test('none', serdi, should_fail: true, suite: ['serdi', 'options']) |
||||
|
||||
test('quiet', files('test_quiet.py'), |
||||
args: script_args + files('bad/bad-base.ttl'), |
||||
suite: ['serdi', 'options']) |
||||
|
||||
# Inputs |
||||
|
||||
test('stdin', files('test_stdin.py'), |
||||
args: script_args, |
||||
suite: ['serdi', 'input']) |
||||
|
||||
test('string', serdi, |
||||
args: ['-s', '<foo> a <Bar> .'], |
||||
should_fail: true, |
||||
suite: ['serdi', 'input']) |
||||
|
||||
test('missing', serdi, |
||||
args: ['-i', 'turtle'], |
||||
should_fail: true, |
||||
suite: ['serdi', 'input']) |
||||
|
||||
test('no_such_file', serdi, |
||||
args: ['no_such_file'], |
||||
should_fail: true, |
||||
suite: ['serdi', 'input']) |
||||
|
||||
test('remote', serdi, |
||||
args: ['ftp://example.org/unsupported.ttl'], |
||||
should_fail: true, |
||||
suite: ['serdi', 'input']) |
||||
|
||||
# IO errors |
||||
|
||||
test('read_dir', serdi, |
||||
args: ['-e', 'file://@0@/'.format(meson.source_root())], |
||||
should_fail: true, |
||||
suite: 'io_errors') |
||||
|
||||
test('bulk_read_dir', serdi, |
||||
args: ['file://@0@/'.format(meson.source_root())], |
||||
should_fail: true, |
||||
suite: 'io_errors') |
||||
|
||||
test('write_error', files('test_write_error.py'), |
||||
args: script_args + [serd_ttl], |
||||
suite: 'io_errors') |
||||
|
||||
# RDF test suites |
||||
|
||||
## Serd-specific test suites |
||||
|
||||
serd_suites = ['good', 'bad', 'lax'] |
||||
serd_base = 'http://drobilla.net/sw/serd/test/' |
||||
|
||||
### Run all suites with no special arguments |
||||
foreach name : serd_suites |
||||
manifest = files(name / 'manifest.ttl') |
||||
base_uri = serd_base + name + '/' |
||||
test(name, run_test_suite, |
||||
args: script_args + [manifest, base_uri], |
||||
suite: ['rdf', 'serd'], |
||||
timeout: 240) |
||||
endforeach |
||||
|
||||
|
||||
### Run the lax suite with lax parsing enabled as well |
||||
manifest = files('lax/manifest.ttl') |
||||
base_uri = serd_base + 'lax/' |
||||
test('lax', run_test_suite, |
||||
args: script_args + [manifest, base_uri, '--', '-l'], |
||||
suite: ['rdf', 'serd'], |
||||
timeout: 240) |
||||
|
||||
## Standard W3C test suites |
||||
|
||||
w3c_suites = ['Turtle', 'NTriples', 'NQuads', 'TriG'] |
||||
w3c_base = 'http://www.w3.org/2013/' |
||||
|
||||
foreach syntax : w3c_suites |
||||
|
||||
manifest = files(syntax + 'Tests' / 'manifest.ttl') |
||||
base_uri = w3c_base + syntax + 'Tests/' |
||||
|
||||
args = ['--syntax', syntax, manifest, base_uri] |
||||
if syntax == 'TriG' |
||||
args += ['--', '-a'] |
||||
endif |
||||
|
||||
test(syntax, run_test_suite, |
||||
args: script_args + args, |
||||
suite: ['rdf', 'w3c'], |
||||
timeout: 240) |
||||
|
||||
endforeach |
||||
|
||||
endif |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
"""Test serdi quiet option.""" |
||||
|
||||
import argparse |
||||
import sys |
||||
import shlex |
||||
import subprocess |
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__) |
||||
|
||||
parser.add_argument("--serdi", default="./serdi", help="path to serdi") |
||||
parser.add_argument("--wrapper", default="", help="executable wrapper") |
||||
parser.add_argument("input", help="invalid input file") |
||||
|
||||
args = parser.parse_args(sys.argv[1:]) |
||||
command = shlex.split(args.wrapper) + [args.serdi, "-q", args.input] |
||||
proc = subprocess.run(command, check=False, capture_output=True) |
||||
|
||||
assert proc.returncode != 0 |
||||
assert len(proc.stderr) == 0 |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
"""Test reading from stdin with serdi.""" |
||||
|
||||
import argparse |
||||
import sys |
||||
import shlex |
||||
import subprocess |
||||
import tempfile |
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__) |
||||
|
||||
parser.add_argument("--serdi", default="./serdi", help="path to serdi") |
||||
parser.add_argument("--wrapper", default="", help="executable wrapper") |
||||
|
||||
args = parser.parse_args(sys.argv[1:]) |
||||
command = shlex.split(args.wrapper) + [args.serdi, "-"] |
||||
|
||||
DOCUMENT = "<{0}s> <{0}p> <{0}o> .".format("http://example.org/") |
||||
|
||||
with tempfile.TemporaryFile() as out: |
||||
proc = subprocess.run( |
||||
command, |
||||
check=False, |
||||
encoding="utf-8", |
||||
input=DOCUMENT, |
||||
stdout=out, |
||||
stderr=subprocess.PIPE, |
||||
) |
||||
|
||||
assert proc.returncode == 0 |
||||
assert len(proc.stderr) == 0 |
||||
|
||||
out.seek(0) |
||||
lines = out.readlines() |
||||
|
||||
assert len(lines) == 1 |
||||
assert lines[0].decode("utf-8").strip() == DOCUMENT |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
"""Test errors writing to a file.""" |
||||
|
||||
import argparse |
||||
import sys |
||||
import shlex |
||||
import subprocess |
||||
import os |
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__) |
||||
|
||||
parser.add_argument("--serdi", default="./serdi", help="path to serdi") |
||||
parser.add_argument("--wrapper", default="", help="executable wrapper") |
||||
parser.add_argument("input", help="valid input file") |
||||
|
||||
args = parser.parse_args(sys.argv[1:]) |
||||
command = shlex.split(args.wrapper) + [args.serdi, args.input] |
||||
|
||||
if os.path.exists("/dev/full"): |
||||
|
||||
with open("/dev/full", "w") as out: |
||||
proc = subprocess.run( |
||||
command, check=False, stdout=out, stderr=subprocess.PIPE |
||||
) |
||||
|
||||
assert proc.returncode != 0 |
||||
assert "error" in proc.stderr.decode("utf-8") |
||||
|
||||
else: |
||||
sys.stderr.write("warning: /dev/full not present, skipping test") |
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
|
||||
# Minimal waf script for projects that include waflib directly |
||||
|
||||
import sys |
||||
import inspect |
||||
import os |
||||
|
||||
try: |
||||
from waflib import Context, Scripting |
||||
except Exception as e: |
||||
sys.stderr.write('error: Failed to import waf (%s)\n' % e) |
||||
if os.path.exists('.git'): |
||||
sys.stderr.write("Are submodules up to date? " |
||||
"Try 'git submodule update --init --recursive'\n") |
||||
|
||||
sys.exit(1) |
||||
|
||||
|
||||
def main(): |
||||
script_path = os.path.abspath(inspect.getfile(inspect.getmodule(main))) |
||||
project_path = os.path.dirname(script_path) |
||||
Scripting.waf_entry_point(os.getcwd(), Context.WAFVERSION, project_path) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
main() |
@ -1,506 +0,0 @@
@@ -1,506 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
|
||||
import glob |
||||
import os |
||||
import sys |
||||
|
||||
from waflib import Build, Logs, Options |
||||
from waflib.extras import autowaf |
||||
|
||||
# Library and package version (UNIX style major, minor, micro) |
||||
# major increment <=> incompatible changes |
||||
# minor increment <=> compatible changes (additions) |
||||
# micro increment <=> no interface changes |
||||
SERD_VERSION = '0.30.9' |
||||
SERD_MAJOR_VERSION = '0' |
||||
|
||||
# Mandatory waf variables |
||||
APPNAME = 'serd' # Package name for waf dist |
||||
VERSION = SERD_VERSION # Package version for waf dist |
||||
top = '.' # Source directory |
||||
out = 'build' # Build directory |
||||
|
||||
# Release variables |
||||
uri = 'http://drobilla.net/sw/serd' |
||||
dist_pattern = 'http://download.drobilla.net/serd-%d.%d.%d.tar.bz2' |
||||
post_tags = ['Hacking', 'RDF', 'Serd'] |
||||
|
||||
|
||||
def options(ctx): |
||||
ctx.load('compiler_c') |
||||
ctx.add_flags( |
||||
ctx.configuration_options(), |
||||
{'no-utils': 'do not build command line utilities', |
||||
'stack-check': 'include runtime stack sanity checks', |
||||
'static': 'build static library', |
||||
'no-shared': 'do not build shared library', |
||||
'static-progs': 'build programs as static binaries', |
||||
'largefile': 'build with large file support on 32-bit systems', |
||||
'no-posix': 'do not use POSIX functions, even if present'}) |
||||
|
||||
|
||||
def configure(conf): |
||||
conf.load('compiler_c', cache=True) |
||||
conf.load('autowaf', cache=True) |
||||
|
||||
if conf.env.DOCS: |
||||
conf.load('sphinx') |
||||
|
||||
if not autowaf.set_c_lang(conf, 'c11', mandatory=False): |
||||
autowaf.set_c_lang(conf, 'c99') |
||||
|
||||
if Options.options.strict: |
||||
# Check for programs used by lint target |
||||
conf.find_program("flake8", var="FLAKE8", mandatory=False) |
||||
conf.find_program("clang-tidy", var="CLANG_TIDY", mandatory=False) |
||||
conf.find_program("iwyu_tool", var="IWYU_TOOL", mandatory=False) |
||||
|
||||
if Options.options.ultra_strict: |
||||
autowaf.add_compiler_flags(conf.env, '*', { |
||||
'clang': [ |
||||
'-Wno-cast-align', |
||||
'-Wno-cast-qual', |
||||
'-Wno-conversion', |
||||
'-Wno-covered-switch-default', |
||||
'-Wno-disabled-macro-expansion', |
||||
'-Wno-double-promotion', |
||||
'-Wno-format-nonliteral', |
||||
'-Wno-implicit-fallthrough', |
||||
'-Wno-nullability-extension', |
||||
'-Wno-nullable-to-nonnull-conversion', |
||||
'-Wno-padded', |
||||
'-Wno-reserved-id-macro', |
||||
'-Wno-sign-conversion', |
||||
], |
||||
'gcc': [ |
||||
'-Wno-cast-align', |
||||
'-Wno-cast-qual', |
||||
'-Wno-float-conversion', |
||||
'-Wno-inline', |
||||
'-Wno-padded', |
||||
'-Wno-sign-conversion', |
||||
], |
||||
'msvc': [ |
||||
'/wd4061', # enumerator in switch is not explicitly handled |
||||
'/wd4365', # signed/unsigned mismatch |
||||
'/wd4514', # unreferenced inline function has been removed |
||||
'/wd4710', # function not inlined |
||||
'/wd4711', # function selected for automatic inline expansion |
||||
'/wd4820', # padding added after construct |
||||
'/wd4996', # POSIX name for this item is deprecated |
||||
], |
||||
}) |
||||
|
||||
autowaf.add_compiler_flags(conf.env, 'c', { |
||||
'clang': [ |
||||
'-Wno-bad-function-cast', |
||||
], |
||||
'gcc': [ |
||||
'-Wno-bad-function-cast', |
||||
], |
||||
'msvc': [ |
||||
'/wd4706', # assignment within conditional expression |
||||
'/wd5045', # will insert Spectre mitigation for memory load |
||||
], |
||||
}) |
||||
|
||||
if 'mingw' in conf.env.CC[0]: |
||||
conf.env.append_value('CFLAGS', '-Wno-unused-macros') |
||||
|
||||
conf.env.update({ |
||||
'BUILD_UTILS': not Options.options.no_utils, |
||||
'BUILD_SHARED': not Options.options.no_shared, |
||||
'STATIC_PROGS': Options.options.static_progs, |
||||
'BUILD_STATIC': (Options.options.static or |
||||
Options.options.static_progs)}) |
||||
|
||||
if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC: |
||||
conf.fatal('Neither a shared nor a static build requested') |
||||
|
||||
if Options.options.stack_check: |
||||
conf.define('SERD_STACK_CHECK', SERD_VERSION) |
||||
|
||||
if Options.options.largefile: |
||||
conf.env.append_unique('DEFINES', ['_FILE_OFFSET_BITS=64']) |
||||
|
||||
conf.check_function('c', 'aligned_alloc', |
||||
header_name = 'stdlib.h', |
||||
return_type = 'void*', |
||||
arg_types = 'size_t,size_t', |
||||
define_name = 'HAVE_ALIGNED_ALLOC', |
||||
mandatory = False) |
||||
|
||||
if not Options.options.no_posix: |
||||
funcs = {'posix_memalign': ('stdlib.h', 'int', 'void**,size_t,size_t'), |
||||
'posix_fadvise': ('fcntl.h', 'int', 'int,off_t,off_t,int'), |
||||
'fileno': ('stdio.h', 'int', 'FILE*')} |
||||
|
||||
for name, (header, ret, args) in funcs.items(): |
||||
conf.check_function('c', name, |
||||
header_name = header, |
||||
return_type = ret, |
||||
arg_types = args, |
||||
define_name = 'HAVE_' + name.upper(), |
||||
defines = ['_POSIX_C_SOURCE=200809L'], |
||||
mandatory = False) |
||||
|
||||
# Set up environment for building/using as a subproject |
||||
autowaf.set_lib_env(conf, 'serd', SERD_VERSION, |
||||
include_path=str(conf.path.find_node('include'))) |
||||
|
||||
if conf.env.BUILD_TESTS: |
||||
serdi_node = conf.path.get_bld().make_node('serdi_static') |
||||
else: |
||||
serdi_node = conf.path.get_bld().make_node('serdi') |
||||
|
||||
conf.env.SERDI = [serdi_node.abspath()] |
||||
|
||||
conf.define('SERD_NO_DEFAULT_CONFIG', 1) |
||||
|
||||
autowaf.display_summary( |
||||
conf, |
||||
{'Build static library': bool(conf.env['BUILD_STATIC']), |
||||
'Build shared library': bool(conf.env['BUILD_SHARED']), |
||||
'Build utilities': bool(conf.env['BUILD_UTILS']), |
||||
'Build unit tests': bool(conf.env['BUILD_TESTS'])}) |
||||
|
||||
|
||||
lib_headers = ['src/reader.h'] |
||||
|
||||
lib_source = ['src/base64.c', |
||||
'src/byte_source.c', |
||||
'src/env.c', |
||||
'src/n3.c', |
||||
'src/node.c', |
||||
'src/reader.c', |
||||
'src/string.c', |
||||
'src/system.c', |
||||
'src/uri.c', |
||||
'src/writer.c'] |
||||
|
||||
|
||||
def build(bld): |
||||
# C Headers |
||||
includedir = '${INCLUDEDIR}/serd-%s/serd' % SERD_MAJOR_VERSION |
||||
bld.install_files(includedir, bld.path.ant_glob('include/serd/*.h')) |
||||
|
||||
# Pkgconfig file |
||||
autowaf.build_pc(bld, 'SERD', SERD_VERSION, SERD_MAJOR_VERSION, [], |
||||
{'SERD_MAJOR_VERSION': SERD_MAJOR_VERSION}) |
||||
|
||||
defines = [] |
||||
lib_args = {'export_includes': ['include'], |
||||
'includes': ['include'], |
||||
'cflags': ['-fvisibility=hidden'], |
||||
'lib': ['m'], |
||||
'vnum': SERD_VERSION, |
||||
'install_path': '${LIBDIR}'} |
||||
if bld.env.MSVC_COMPILER: |
||||
lib_args['cflags'] = [] |
||||
lib_args['lib'] = [] |
||||
defines = [] |
||||
|
||||
# Shared Library |
||||
if bld.env.BUILD_SHARED: |
||||
bld(features = 'c cshlib', |
||||
source = lib_source, |
||||
name = 'libserd', |
||||
target = 'serd-%s' % SERD_MAJOR_VERSION, |
||||
defines = defines + ['SERD_INTERNAL'], |
||||
**lib_args) |
||||
|
||||
# Static library |
||||
if bld.env.BUILD_STATIC: |
||||
bld(features = 'c cstlib', |
||||
source = lib_source, |
||||
name = 'libserd_static', |
||||
target = 'serd-%s' % SERD_MAJOR_VERSION, |
||||
defines = defines + ['SERD_STATIC', 'SERD_INTERNAL'], |
||||
**lib_args) |
||||
|
||||
if bld.env.BUILD_TESTS: |
||||
coverage_flags = [''] if bld.env.NO_COVERAGE else ['--coverage'] |
||||
test_args = {'includes': ['include'], |
||||
'cflags': coverage_flags, |
||||
'linkflags': coverage_flags, |
||||
'lib': lib_args['lib'], |
||||
'install_path': ''} |
||||
|
||||
# Profiled static library for test coverage |
||||
bld(features = 'c cstlib', |
||||
source = lib_source, |
||||
name = 'libserd_profiled', |
||||
target = 'serd_profiled', |
||||
defines = defines + ['SERD_STATIC', 'SERD_INTERNAL'], |
||||
**test_args) |
||||
|
||||
# Test programs |
||||
for prog in [('serdi_static', 'src/serdi.c'), |
||||
('test_env', 'test/test_env.c'), |
||||
('test_free_null', 'test/test_free_null.c'), |
||||
('test_node', 'test/test_node.c'), |
||||
('test_read_chunk', 'test/test_read_chunk.c'), |
||||
('test_reader_writer', 'test/test_reader_writer.c'), |
||||
('test_string', 'test/test_string.c'), |
||||
('test_uri', 'test/test_uri.c')]: |
||||
bld(features = 'c cprogram', |
||||
source = prog[1], |
||||
use = 'libserd_profiled', |
||||
target = prog[0], |
||||
defines = defines + ['SERD_STATIC'], |
||||
**test_args) |
||||
|
||||
# Utilities |
||||
if bld.env.BUILD_UTILS: |
||||
obj = bld(features = 'c cprogram', |
||||
source = 'src/serdi.c', |
||||
target = 'serdi', |
||||
includes = ['include'], |
||||
use = 'libserd', |
||||
lib = lib_args['lib'], |
||||
install_path = '${BINDIR}') |
||||
if not bld.env.BUILD_SHARED or bld.env.STATIC_PROGS: |
||||
obj.use = 'libserd_static' |
||||
if bld.env.STATIC_PROGS: |
||||
obj.env.SHLIB_MARKER = obj.env.STLIB_MARKER |
||||
obj.linkflags = ['-static'] |
||||
|
||||
# Documentation |
||||
if bld.env.DOCS: |
||||
bld.recurse('doc/c') |
||||
|
||||
# Man page |
||||
bld.install_files('${MANDIR}/man1', 'doc/serdi.1') |
||||
|
||||
bld.add_post_fun(autowaf.run_ldconfig) |
||||
|
||||
|
||||
class LintContext(Build.BuildContext): |
||||
fun = cmd = 'lint' |
||||
|
||||
|
||||
def lint(ctx): |
||||
"checks code for style issues" |
||||
import subprocess |
||||
|
||||
st = 0 |
||||
|
||||
if "FLAKE8" in ctx.env: |
||||
Logs.info("Running flake8") |
||||
st = subprocess.call([ctx.env.FLAKE8[0], |
||||
"wscript", |
||||
"--ignore", |
||||
"E101,E129,W191,E221,W504,E251,E241,E741"]) |
||||
st += subprocess.call([ctx.env.FLAKE8[0], |
||||
"scripts/serd_bench.py", |
||||
"--ignore", |
||||
"E203"]) |
||||
else: |
||||
Logs.warn("Not running flake8") |
||||
|
||||
if "IWYU_TOOL" in ctx.env: |
||||
Logs.info("Running include-what-you-use") |
||||
cmd = [ctx.env.IWYU_TOOL[0], "-o", "clang", "-p", "build"] |
||||
output = subprocess.check_output(cmd).decode('utf-8') |
||||
if 'error: ' in output: |
||||
sys.stdout.write(output) |
||||
st += 1 |
||||
else: |
||||
Logs.warn("Not running include-what-you-use") |
||||
|
||||
if "CLANG_TIDY" in ctx.env and "clang" in ctx.env.CC[0]: |
||||
Logs.info("Running clang-tidy") |
||||
sources = glob.glob('include/serd/*.h*') |
||||
sources += glob.glob('src/*.c') |
||||
sources += glob.glob('test/*.c') |
||||
sources = list(map(os.path.abspath, sources)) |
||||
procs = [] |
||||
for source in sources: |
||||
cmd = [ctx.env.CLANG_TIDY[0], "--quiet", "-p=.", source] |
||||
procs += [subprocess.Popen(cmd, cwd="build")] |
||||
|
||||
for proc in procs: |
||||
stdout, stderr = proc.communicate() |
||||
st += proc.returncode |
||||
else: |
||||
Logs.warn("Not running clang-tidy") |
||||
|
||||
if st != 0: |
||||
sys.exit(st) |
||||
|
||||
|
||||
def amalgamate(ctx): |
||||
"builds single-file amalgamated source" |
||||
import shutil |
||||
import re |
||||
shutil.copy('serd/serd.h', 'build/serd.h') |
||||
|
||||
def include_line(line): |
||||
return (not re.match(r'#include "[^/]*\.h"', line) and |
||||
not re.match('#include "serd/serd.h"', line)) |
||||
|
||||
with open('build/serd.c', 'w') as amalgamation: |
||||
amalgamation.write('/* This is amalgamated code, do not edit! */\n') |
||||
amalgamation.write('#include "serd.h"\n\n') |
||||
|
||||
for header_path in ['src/serd_internal.h', |
||||
'src/system.h', |
||||
'src/byte_sink.h', |
||||
'src/byte_source.h', |
||||
'src/stack.h', |
||||
'src/string_utils.h', |
||||
'src/uri_utils.h', |
||||
'src/reader.h']: |
||||
with open(header_path) as header: |
||||
for l in header: |
||||
if include_line(l): |
||||
amalgamation.write(l) |
||||
|
||||
for f in lib_headers + lib_source: |
||||
with open(f) as fd: |
||||
amalgamation.write('\n/**\n @file %s\n*/' % f) |
||||
for l in fd: |
||||
if include_line(l): |
||||
amalgamation.write(l) |
||||
|
||||
for i in ['c', 'h']: |
||||
Logs.info('Wrote build/serd.%s' % i) |
||||
|
||||
|
||||
def test(tst): |
||||
import tempfile |
||||
|
||||
# Create test output directories |
||||
for i in ['bad', 'good', 'lax', |
||||
'TurtleTests', 'NTriplesTests', 'NQuadsTests', 'TriGTests']: |
||||
try: |
||||