1# Project definition
2project('usrsctplib', 'c',
3    version: '1.0.0',
4    default_options: ['c_std=c99'],
5    meson_version: '>=0.49.0')
6
7# Set compiler warning flags
8compiler = meson.get_compiler('c')
9if compiler.get_argument_syntax() == 'msvc'
10    compiler_args = compiler.get_supported_arguments([
11        '/wd4100', # 'identifier' : unreferenced formal parameter
12        '/wd4127', # conditional expression is constant
13        '/wd4200', # nonstandard extension used : zero-sized array in struct/union
14        '/wd4214', # bit field types other than int
15        '/wd4706', # assignment within conditional expression
16        '/wd4245', # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
17        '/wd4389', # 'operator' : signed/unsigned mismatch
18        '/wd4702', # unreachable code
19        '/wd4701', # Potentially uninitialized local variable 'name' used
20        '/wd4244', # 'conversion' conversion from 'type1' to 'type2', possible loss of data
21    ])
22else
23    compiler_args = compiler.get_supported_arguments([
24        '-pedantic',
25        '-Wall',
26        '-Wextra',
27        '-Wfloat-equal',
28        '-Wshadow',
29        '-Wpointer-arith',
30        '-Winit-self',
31        '-Wno-unused-function',
32        '-Wno-unused-parameter',
33        '-Wno-unreachable-code',
34        '-Wstrict-prototypes',
35    ])
36endif
37add_project_arguments(compiler_args, language: 'c')
38
39# Configuration
40compile_args = []
41
42# Dependency: Threads
43thread_dep = dependency('threads', required: true)
44
45# Dependencies list
46dependencies = [
47    thread_dep,
48]
49
50# Global settings
51add_project_arguments([
52    '-D__Userspace__',
53    '-DSCTP_SIMPLE_ALLOCATOR',
54    '-DSCTP_PROCESS_LEVEL_LOCKS',
55], language: 'c')
56
57# OS-specific settings
58system = host_machine.system()
59if system in ['linux', 'android']
60    add_project_arguments([
61        '-D_GNU_SOURCE',
62    ], language: 'c')
63elif system == 'freebsd'
64    add_project_arguments(compiler.get_supported_arguments([
65            '-Wno-address-of-packed-member',
66        ]), language: 'c')
67elif system in ['darwin', 'ios']
68    add_project_arguments([
69            '-D__APPLE_USE_RFC_2292',
70        ] + compiler.get_supported_arguments([
71            '-Wno-address-of-packed-member',
72            '-Wno-deprecated-declarations',
73        ]), language: 'c')
74elif system == 'windows'
75    dependencies += compiler.find_library('ws2_32', required: true)
76    dependencies += compiler.find_library('iphlpapi', required: true)
77    if compiler.get_id() == 'gcc'
78        add_project_arguments(compiler.get_supported_arguments([
79            '-Wno-format',
80            '-D_WIN32_WINNT=0x601',  # Enables inet_ntop and friends
81        ]), language: 'c')
82    endif
83else
84    error('Unknown system: @0@'.format(system))
85endif
86
87# Feature: sys/queue
88if compiler.has_header('sys/queue.h')
89    add_project_arguments('-DHAVE_SYS_QUEUE_H', language: 'c')
90endif
91
92# Feature: sys/socket, linux/ifaddr, linux/rtnetlink
93if compiler.has_header('sys/socket.h')
94    if compiler.has_header('linux/if_addr.h')
95        add_project_arguments('-DHAVE_LINUX_IF_ADDR_H', language: 'c')
96    endif
97
98    if compiler.has_header('linux/rtnetlink.h')
99        add_project_arguments('-DHAVE_LINUX_RTNETLINK_H', language: 'c')
100    endif
101endif
102
103# Feature: ICMP
104have_sys_types = compiler.has_header('sys/types.h')
105have_netinet_in = compiler.has_header('netinet/in.h')
106have_netinet_ip = compiler.has_header('netinet/ip.h')
107have_netinet_ip_icmp = compiler.has_header('netinet/ip_icmp.h')
108if have_sys_types and have_netinet_in and have_netinet_ip and have_netinet_ip_icmp
109    add_project_arguments('-DHAVE_NETINET_IP_ICMP_H', language: 'c')
110endif
111
112# Feature: stdatomic
113if compiler.has_header('stdatomic.h')
114    add_project_arguments('-DHAVE_STDATOMIC_H', language: 'c')
115endif
116
117# Feature: sockaddr.sa_len
118prefix = '''
119#include <sys/types.h>
120#include <sys/socket.h>
121'''
122have_sa_len = compiler.has_member('struct sockaddr', 'sa_len', prefix: prefix)
123if have_sa_len
124    add_project_arguments('-DHAVE_SA_LEN', language: 'c')
125endif
126
127# Feature: sockaddr_in.sin_len / sockaddr_in6.sin6_len / sockaddr_conn.sconn_len
128prefix = '''
129#include <sys/types.h>
130#include <netinet/in.h>
131'''
132have_sin_len = compiler.has_member('struct sockaddr_in', 'sin_len', prefix: prefix)
133if have_sin_len
134    add_project_arguments('-DHAVE_SIN_LEN', language: 'c')
135endif
136have_sin6_len = compiler.has_member('struct sockaddr_in6', 'sin6_len', prefix: prefix)
137if have_sin6_len
138    add_project_arguments('-DHAVE_SIN6_LEN', language: 'c')
139endif
140have_sconn_len = compiler.has_member('struct sockaddr_conn', 'sconn_len', prefix: '#include "usrsctp.h"', include_directories: include_directories('usrsctplib'))
141if have_sconn_len
142    add_project_arguments('-DHAVE_SCONN_LEN', language: 'c')
143endif
144
145# Options
146if get_option('sctp_invariants')
147    add_project_arguments('-DINVARIANTS', language: 'c')
148endif
149if get_option('sctp_debug')
150    add_project_arguments('-DSCTP_DEBUG', language: 'c')
151    compile_args += '-DSCTP_DEBUG'
152endif
153if get_option('sctp_inet')
154    add_project_arguments('-DINET', language: 'c')
155endif
156if get_option('sctp_inet6')
157    add_project_arguments('-DINET6', language: 'c')
158endif
159
160# Library
161subdir('usrsctplib')
162
163# Build library
164if compiler.get_id() == 'msvc' and get_option('default_library') == 'shared'
165    # Needed by usrsctp_def
166    find_program('dumpbin')
167
168    usrsctp_static = static_library('usrsctp-static', sources,
169        dependencies: dependencies,
170        include_directories: include_dirs)
171
172   usrsctp_def = custom_target('usrsctp.def',
173        command: [find_program('gen-def.py'), '@INPUT@'],
174        input: usrsctp_static,
175        output: 'usrsctp.def',
176        capture: true)
177
178    usrsctp = shared_library('usrsctp',
179        link_whole: usrsctp_static,
180        dependencies: dependencies,
181        vs_module_defs: usrsctp_def,
182        install: true,
183        version: meson.project_version())
184else
185    usrsctp = library('usrsctp', sources,
186        dependencies: dependencies,
187        include_directories: include_dirs,
188        install: true,
189        version: meson.project_version())
190endif
191
192# Declare dependency
193usrsctp_dep = declare_dependency(
194    compile_args: compile_args,
195    include_directories: include_dirs,
196    link_with: usrsctp)
197
198# Generate pkg-config file
199pkg = import('pkgconfig')
200pkg.generate(usrsctp,
201    name: 'usrsctp',
202    description: 'A portable SCTP userland stack',
203    url: 'https://github.com/sctplab/usrsctp',
204    extra_cflags: compile_args)
205
206# Programs (optional)
207if get_option('sctp_build_programs')
208    subdir('programs')
209
210    # Build executables
211    foreach name, sources : programs
212        executable(
213            name,
214            programs_helper_sources + sources,
215            dependencies: dependencies,
216            link_with: usrsctp,
217            include_directories: include_dirs)
218    endforeach
219endif
220