project('libalabaster', 'c', version: '0.01', meson_version: '>=0.63.0', default_options: ['warning_level=2', 'c_std=c99'], license: 'GPL-3.0-only') compiler = meson.get_compiler('c') is_debug = get_option('debug') is_msvc = compiler.get_id() == 'msvc' or compiler.get_id() == 'clang-cl' is_msvc_specifically = compiler.cmd_array()[0] == 'cl' is_windows = host_machine.system() == 'windows' supports_needed_gnu_extensions = not is_msvc_specifically have_builtin_expect = compiler.has_function('__builtin_expect') have_typeof = compiler.compiles('__typeof__(1) j;') if not have_typeof error('Compiler support for \'__typeof__()\' is required.') endif have_posix_memalign = compiler.has_function( 'posix_memalign', prefix: '#define _POSIX_C_SOURCE 200112L\n#include ') have_wide_string = compiler.has_function('wcsrtombs') have_wide_string_width = compiler.has_function('wcswidth') # For testing: '-Wshadow', '-Wconversion', '-Wc++-compat' alabaster_args = ['-fstrict-aliasing', '-Wstrict-aliasing'] if is_debug alabaster_args += ['-DAL_DEBUG'] elif get_option('release-asserts') # It's possible that some external code would rely on NDEBUG for conditionally # excluding something other than asserts. The trade-off here is to accept that rather # than possibly miss an assert. alabaster_args += ['-DAL_RELEASE_ASSERTS'] else alabaster_args += ['-DNDEBUG'] endif # The definition of the assert() macro is determined by the _last_ place where # was included, because it redefines itself each time. Making it # unnecessarily complicated to predict if assert() will be active or a no-op. # Maybe I just haven't seen why this could make sense but to me it's counterintuitive. # We define al_assert() to be unchanging and let any dependencies figure it out for themselves. # Another note, which I hadn't heard before but, this clearly makes relying on NDEBUG # for anything other than asserts a very bad practice. # https://sourceware.org/git/?p=glibc.git;a=blob;f=assert/assert.h;h=31892aebcb9115a3b48be4d179eb9e8ab2f8784f;hb=HEAD#l24 if compiler.has_function('__assert_fail', prefix: '#include ') alabaster_args += ['-DAL_ASSERT_FUNCTION=__assert_fail', '-DAL_ASSERT_INCLUDE_FUNC'] elif compiler.has_function('_assert', prefix: '#include ') # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/assert-macro-assert-wassert?view=msvc-170 alabaster_args += ['-DAL_ASSERT_FUNCTION=_assert'] elif compiler.has_function('__assert', prefix: '#include ') # https://github.com/aosp-mirror/platform_bionic/blob/731631f300090436d7f5df80d50b6275c8c60a93/libc/include/assert.h#L63 alabaster_args += ['-DAL_ASSERT_FUNCTION=__assert', '-DAL_ASSERT_EXPR_LAST'] endif if is_msvc_specifically alabaster_args += ['/arch:AVX'] endif if compiler.has_function('rand_r', prefix: '#define _POSIX_C_SOURCE 200112L\n#include ') elif is_windows # This is supposed to be a check for if libc = Microsoft CRT. # https://learn.microsoft.com/en-us/previous-versions/f0d4wb4t(v=vs.140)?redirectedfrom=MSDN # "The srand function sets ... in the current thread." alabaster_args += ['-DAL_SRAND_THREAD_LOCAL'] else error('No thread-local rand().') endif if supports_needed_gnu_extensions alabaster_args += ['-DAL_HAVE_GNU_EXTENSIONS'] endif if have_builtin_expect alabaster_args += ['-DAL_HAVE_BUILTIN_EXPECT'] endif if have_posix_memalign alabaster_args += ['-DAL_HAVE_POSIX_MEMALIGN'] endif if have_wide_string alabaster_args += ['-DAL_HAVE_WIDE_STRING'] endif if have_wide_string_width alabaster_args += ['-DAL_HAVE_WIDE_STRING_WIDTH'] endif c89atomic = subproject('c89atomic').get_variable('c89atomic') alabaster_src = [ 'src/lib.c', 'src/random.c', 'src/str.c', 'src/ring_buffer.c', 'src/log.c' ] alabaster_inc = include_directories('include') alabaster_deps = [c89atomic] alabaster = declare_dependency(include_directories: alabaster_inc, dependencies: alabaster_deps, sources: alabaster_src, compile_args: alabaster_args) if get_option('tests').allowed() tests_src = [ 'tests/main.c', 'tests/lib.c', 'tests/array.c', 'tests/str.c', 'tests/ring_buffer.c' ] if supports_needed_gnu_extensions tests_src += ['tests/array_typed.c'] endif executable('tests', tests_src, dependencies: alabaster, install: false) endif