summaryrefslogtreecommitdiff
path: root/meson.build
blob: 0dffee33db2b663fe6f78761e6d8770728fcb2ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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 <stdlib.h>')
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
# <assert.h> 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 <assert.h>')
  alabaster_args += ['-DAL_ASSERT_FUNCTION=__assert_fail', '-DAL_ASSERT_INCLUDE_FUNC']
elif compiler.has_function('_assert', prefix: '#include <assert.h>')
  # 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 <assert.h>')
  # 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 <stdlib.h>')
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