mirror of
https://github.com/zap-proto/c.git
synced 2026-10-30 15:05:52 +00:00
C had no front end for the schema language at all. The compiler directory holds a code generator plugin, which is handed a request by another tool and never sees schema text, so a .zap file could not be read here in either form -- indentation or braces. zapgen reads it. Whitespace-significant source is rewritten into the brace form BEFORE the parser, exactly as the Go reference does it: a near identity that only adds the two tokens the brace grammar requires where the indented form leaves them out. A file already in braces comes back byte for byte, so one grammar reads both styles and neither is a dialect of the other. The identifier grammar is not restated. Its Unicode ranges are taken from Go's own tables by gen/table, so a name this parser accepts is a name the Go parser accepts, and a Go release that moves Unicode moves both. The generated header gives each struct a view over the message bytes and one reader per field at a fixed offset. Reading is in place and total: a field past the end reads zero, a pointer into the head or out of the message reads null. zap_view.h is the one place that says so. Checked against the Go front end on every .zap in the estate plus 55 adversarial cases and 15000 random ones: the brace form each writes is byte-identical, the layout each reads is field-for-field the same, and they accept and refuse the same files for the same stated reason. A message built by the Go runtime reads back through these bindings with every field equal.
108 lines
3.0 KiB
Meson
108 lines
3.0 KiB
Meson
project('zap-c', ['c','cpp'], meson_version: '>=1.0.0', default_options : ['c_std=c99', 'cpp_std=c++17'])
|
|
|
|
common_c_args = []
|
|
common_cpp_args = ['-std=c++17']
|
|
libzap_c_args = []
|
|
libzap_src = [
|
|
'lib' / 'zap-malloc.c',
|
|
'lib' / 'zap-stream.c',
|
|
'lib' / 'zap.c',
|
|
]
|
|
|
|
libzap = library('zap', libzap_src,
|
|
c_args : common_c_args + libzap_c_args,
|
|
dependencies: [],
|
|
implicit_include_directories: false,
|
|
include_directories: include_directories(['compiler', 'lib'])
|
|
)
|
|
|
|
libzap_dep = declare_dependency(
|
|
link_with: libzap,
|
|
dependencies: [],
|
|
include_directories: include_directories(['compiler', 'lib'])
|
|
)
|
|
|
|
zapc_src = [
|
|
'compiler' / 'zapc-c.c',
|
|
'compiler' / 'schema.zap.c',
|
|
'compiler' / 'str.c'
|
|
]
|
|
|
|
zapc_c = executable('zapc-c', zapc_src,
|
|
include_directories: include_directories(['lib']),
|
|
dependencies: [libzap_dep],
|
|
c_args : common_c_args,
|
|
)
|
|
|
|
# zapgen reads a .zap schema - written either way, indentation or braces -
|
|
# and writes the C it describes.
|
|
zapgen_lib_src = [
|
|
'gen' / 'arena.c',
|
|
'gen' / 'desugar.c',
|
|
'gen' / 'emit.c',
|
|
'gen' / 'parse.c',
|
|
'gen' / 'rune.c',
|
|
'compiler' / 'str.c',
|
|
]
|
|
|
|
zapgen_inc = include_directories(['gen', 'compiler', 'lib'])
|
|
|
|
zapgen = executable('zapgen', zapgen_lib_src + ['gen' / 'main.c'],
|
|
include_directories: zapgen_inc,
|
|
c_args : common_c_args,
|
|
)
|
|
|
|
zap_test_src = [
|
|
'tests' / 'zap-test.cpp',
|
|
'tests' / 'zap-stream-test.cpp',
|
|
'tests' / 'example-test.cpp',
|
|
'tests' / 'addressbook.zap.c',
|
|
'compiler' / 'test.zap.c',
|
|
'compiler' / 'schema-test.cpp',
|
|
'compiler' / 'schema.zap.c'
|
|
]
|
|
|
|
if get_option('enable_tests') and not meson.is_subproject()
|
|
|
|
thread_dep = dependency('threads')
|
|
|
|
gtest_proj = subproject('gtest')
|
|
gtest_dep = gtest_proj.get_variable('gtest_dep')
|
|
gmock_dep = gtest_proj.get_variable('gmock_dep')
|
|
|
|
# Sanitizer runtimes are pulled in by the compiler driver via the
|
|
# -fsanitize flags that meson's b_sanitize option adds to both compile
|
|
# and link steps. No explicit find_library() is needed (and Apple clang
|
|
# ships no findable libasan/libubsan), so b_sanitize alone is portable.
|
|
test_dependencies = [libzap_dep, gtest_dep, gmock_dep, thread_dep]
|
|
|
|
exe = executable('zap-test', zap_test_src,
|
|
include_directories: include_directories(['lib', 'tests', 'compiler']),
|
|
dependencies: test_dependencies,
|
|
c_args : common_c_args,
|
|
cpp_args : common_cpp_args,
|
|
install: false,
|
|
install_rpath: '',
|
|
implicit_include_directories: false
|
|
)
|
|
test('zap-test', exe)
|
|
|
|
# The schema test generates its own bindings and compiles them, so a
|
|
# generator that cannot generate, or generates C that does not build,
|
|
# fails the suite rather than the next release.
|
|
echo_h = custom_target('echo.zap.h',
|
|
input: 'gen' / 'echo.zap',
|
|
output: 'echo.zap.h',
|
|
command: [zapgen, '-o', '@OUTDIR@', '@INPUT@'],
|
|
)
|
|
|
|
zapgen_test = executable('zapgen-test',
|
|
zapgen_lib_src + ['gen' / 'test.c', echo_h],
|
|
include_directories: zapgen_inc,
|
|
c_args : common_c_args,
|
|
install: false,
|
|
)
|
|
test('zapgen-test', zapgen_test)
|
|
|
|
endif
|