Add check for __Static_assert() and asserts on struct sizes
[tinc] / src / meson.build
1 inc_conf = include_directories('include')
2
3 cdata = configuration_data()
4
5 cdata.set_quoted('PACKAGE', meson.project_name())
6 cdata.set_quoted('VERSION', meson.project_version())
7 cdata.set_quoted('CONFDIR', dir_sysconf)
8 cdata.set_quoted('RUNSTATEDIR', dir_run_state)
9 cdata.set_quoted('LOCALSTATEDIR', dir_local_state)
10 cdata.set_quoted('SBINDIR', dir_sbin)
11
12 cdata.set('HAVE_' + os_name.to_upper(), 1)
13
14 foreach attr : ['malloc', 'nonnull', 'warn_unused_result']
15   cc.has_function_attribute(attr)
16 endforeach
17
18 if cc.compiles('''
19     _Static_assert(1, "ok");
20     int main(void) { return 0; }
21 ''')
22   cdata.set('HAVE_STATIC_ASSERT', 1,
23             description: 'C11 _Static_assert()')
24 endif
25
26 check_headers = [
27   'alloca.h',
28   'arpa/inet.h',
29   'arpa/nameser.h',
30   'dirent.h',
31   'getopt.h',
32   'inttypes.h',
33   'net/ethernet.h',
34   'net/if.h',
35   'net/if_arp.h',
36   'net/if_types.h',
37   'netdb.h',
38   'netinet/icmp6.h',
39   'netinet/if_ether.h',
40   'netinet/in.h',
41   'netinet/in6.h',
42   'netinet/in_systm.h',
43   'netinet/ip.h',
44   'netinet/ip6.h',
45   'netinet/ip_icmp.h',
46   'netinet/tcp.h',
47   'resolv.h',
48   'stddef.h',
49   'sys/file.h',
50   'sys/ioctl.h',
51   'sys/mman.h',
52   'sys/param.h',
53   'sys/resource.h',
54   'sys/socket.h',
55   'sys/stat.h',
56   'sys/time.h',
57   'sys/types.h',
58   'sys/wait.h',
59   'syslog.h',
60   'string.h',
61   'termios.h',
62   'unistd.h',
63 ]
64
65 # 'struct msghdr' misses some required fields
66 if os_name != 'sunos'
67   check_headers += 'sys/un.h'
68 endif
69
70 check_functions = [
71   'asprintf',
72   'daemon',
73   'fchmod',
74   'gettimeofday',
75   'mlockall',
76   'putenv',
77   'strsignal',
78   'unsetenv',
79 ]
80
81 # Broken definition, fails to link
82 if os_name != 'windows'
83   check_functions += 'fork'
84 endif
85
86 check_types = [
87   'struct arphdr',
88   'struct ether_arp',
89   'struct ether_header',
90   'struct icmp',
91   'struct icmp6_hdr',
92   'struct ip',
93   'struct ip6_hdr',
94   'struct nd_neighbor_solicit',
95   'struct nd_opt_hdr',
96 ]
97
98 subdir('ed25519')
99 subdir('chacha-poly1305')
100
101 src_lib_common = [
102   'conf.c',
103   'dropin.c',
104   'keys.c',
105   'list.c',
106   'names.c',
107   'netutl.c',
108   'script.c',
109   'splay_tree.c',
110   'sptps.c',
111   'subnet_parse.c',
112   'utils.c',
113   'version.c',
114   'xoshiro.c',
115   'logger.c',
116 ]
117
118 src_tinc = [
119   'fsck.c',
120   'ifconfig.c',
121   'info.c',
122   'invitation.c',
123   'top.c',
124 ]
125
126 src_tincd = [
127   'address_cache.c',
128   'autoconnect.c',
129   'buffer.c',
130   'compression.h',
131   'conf_net.c',
132   'connection.c',
133   'control.c',
134   'dummy_device.c',
135   'edge.c',
136   'event.c',
137   'graph.c',
138   'meta.c',
139   'multicast_device.c',
140   'net.c',
141   'net_packet.c',
142   'net_setup.c',
143   'net_socket.c',
144   'node.c',
145   'process.c',
146   'protocol.c',
147   'protocol_auth.c',
148   'protocol_edge.c',
149   'protocol_key.c',
150   'protocol_misc.c',
151   'protocol_subnet.c',
152   'raw_socket_device.c',
153   'route.c',
154   'subnet.c',
155 ]
156
157 cc_flags_tincd = cc_flags
158
159 deps_common = []
160 deps_tinc = []
161 deps_tincd = [cc.find_library('m', required: false)]
162
163 if os_name in ['linux', 'android']
164   subdir('linux')
165 elif os_name.endswith('bsd') or os_name in ['dragonfly', 'darwin']
166   subdir('bsd')
167 elif os_name == 'sunos'
168   subdir('solaris')
169 elif os_name == 'windows'
170   subdir('windows')
171 endif
172
173 foreach h : check_headers
174   if cc.has_header(h)
175     cdata.set('HAVE_' + h.to_upper().underscorify(),
176               1,
177               description: '#include <' + h + '>')
178   endif
179 endforeach
180
181 if cdata.has('HAVE_SYS_UN_H')
182   src_tincd += 'fd_device.c'
183 endif
184
185 confdata = configuration_data()
186 confdata.merge_from(cdata)
187 configure_file(output: 'meson_config.h', configuration: confdata)
188
189 have_prefix = '''
190   #include "@0@/src/meson_config.h"
191   #include "@1@/have.h"
192 '''.format(build_root, meson.current_source_dir())
193
194 foreach f : check_functions
195   if cc.has_function(f, prefix: have_prefix, args: cc_defs)
196     cdata.set('HAVE_' + f.to_upper(),
197               1,
198               description: 'function ' + f)
199   endif
200 endforeach
201
202 if cc.has_function('res_init', prefix: '''
203   #include <netinet/in.h>
204   #include <resolv.h>
205 ''', args: cc_defs)
206   cdata.set('HAVE_DECL_RES_INIT', 1)
207 endif
208
209 foreach type : check_types
210   if cc.has_type(type, prefix: have_prefix, args: cc_defs)
211     name = 'HAVE_' + type.to_upper().underscorify()
212     cdata.set(name, 1, description: type)
213   endif
214 endforeach
215
216 if not cdata.has('HAVE_GETOPT_H') or not cc.has_function('getopt_long', prefix: have_prefix, args: cc_defs)
217   src_lib_common += ['getopt.c', 'getopt1.c']
218 endif
219
220 if not opt_miniupnpc.disabled()
221   dep_miniupnpc = dependency('miniupnpc', required: false, static: static)
222   if not dep_miniupnpc.found()
223     # No pkg-config files on MinGW
224     dep_miniupnpc = cc.find_library('miniupnpc', required: opt_miniupnpc, static: static)
225   endif
226   if dep_miniupnpc.found()
227     src_tincd += 'upnp.c'
228     deps_tincd += [
229       dependency('threads', static: static),
230       dep_miniupnpc,
231     ]
232     if static
233       cc_flags_tincd += '-DMINIUPNP_STATICLIB'
234     endif
235     cdata.set('HAVE_MINIUPNPC', 1)
236   endif
237 endif
238
239 if not opt_curses.disabled()
240   # The meta-dependency covers more alternatives, but is only available in 0.54+
241   curses_name = meson_version.version_compare('>=0.54') ? 'curses' : 'ncurses'
242   dep_curses = dependency(curses_name, required: opt_curses, static: static)
243   if dep_curses.found()
244     cdata.set('HAVE_CURSES', 1)
245     deps_tinc += dep_curses
246   endif
247 endif
248
249 # Some distributions do not supply pkg-config files for readline
250 if opt_readline.auto() and os_name == 'windows'
251   message('readline not available on Windows')
252 else
253   dep_readline = dependency('readline', required: opt_readline, static: static)
254   if not dep_readline.found()
255     dep_readline = cc.find_library('readline', required: opt_readline, static: static)
256   endif
257   if dep_readline.found() and \
258      cc.has_header('readline/readline.h', dependencies: dep_readline) and \
259      cc.has_header('readline/history.h', dependencies: dep_readline)
260     cdata.set('HAVE_READLINE', 1)
261     deps_tinc += dep_readline
262   endif
263 endif
264
265 dep_zlib = dependency('zlib',
266                       required: opt_zlib,
267                       static: static,
268                       fallback: ['zlib', 'zlib_dep'])
269 if dep_zlib.found()
270   cdata.set('HAVE_ZLIB', 1)
271   deps_tincd += dep_zlib
272 endif
273
274 if not opt_lzo.disabled()
275   dep_lzo = dependency('lzo2', required: false, static: static)
276   if not dep_lzo.found()
277     dep_lzo = cc.find_library('lzo2', required: opt_lzo, static: static)
278   endif
279   if not dep_lzo.found()
280     dep_lzo = dependency('lzo2',
281                          required: false,
282                          static: static,
283                          fallback: ['lzo2', 'lzo2_dep'])
284   endif
285   if dep_lzo.found()
286     if dep_lzo.type_name() == 'internal' or cc.has_header('lzo/lzo1x.h', dependencies: dep_lzo)
287       cdata.set('LZO1X_H', '<lzo/lzo1x.h>')
288     elif cc.has_header('lzo1x.h', dependencies: dep_lzo)
289       cdata.set('LZO1X_H', '<lzo1x.h>')
290     else
291       msg = 'lzo1x.h not found'
292       if opt_lzo.auto()
293         warning(msg)
294       else
295         error(msg)
296       endif
297     endif
298     if cdata.has('LZO1X_H')
299       cdata.set('HAVE_LZO', 1)
300       deps_tincd += dep_lzo
301     endif
302   endif
303 endif
304
305 dep_lz4 = dependency('liblz4',
306                      required: opt_lz4,
307                      static: static,
308                      fallback: ['lz4', 'liblz4_dep'])
309 if dep_lz4.found()
310   deps_tincd += dep_lz4
311   cdata.set('HAVE_LZ4', 1)
312 endif
313
314 dep_vde = dependency('vdeplug', required: opt_vde, static: static)
315 dep_dl = cc.find_library('dl', required: opt_vde)
316 if dep_vde.found() and dep_dl.found()
317   cdata.set('ENABLE_VDE', 1)
318   src_tincd += 'vde_device.c'
319   deps_tincd += [dep_dl, dep_vde]
320 endif
321
322 if opt_jumbograms
323   cdata.set('ENABLE_JUMBOGRAMS', 1)
324 endif
325
326 subdir(opt_crypto)
327
328 if opt_crypto != 'nolegacy'
329   src_lib_crypto += ['cipher.c', 'digest.c']
330 endif
331
332 subdir('include')
333
334 lib_crypto = static_library(
335   'tinc_crypto',
336   sources: src_lib_crypto,
337   dependencies: dep_crypto,
338   implicit_include_directories: false,
339   include_directories: inc_conf,
340   build_by_default: false,
341 )
342
343 deps_lib_common = [deps_common, dep_crypto]
344 deps_tinc += deps_lib_common
345 deps_tincd += deps_lib_common
346
347 lib_common = static_library(
348   'common',
349   sources: src_lib_common,
350   dependencies: deps_lib_common,
351   link_with: [lib_ed25519, lib_chacha_poly, lib_crypto],
352   implicit_include_directories: false,
353   include_directories: inc_conf,
354   build_by_default: false,
355 )
356
357 lib_tinc = static_library(
358   'tinc',
359   sources: src_tinc,
360   dependencies: deps_tinc,
361   link_with: lib_common,
362   implicit_include_directories: false,
363   include_directories: inc_conf,
364   build_by_default: false,
365 )
366
367 lib_tincd = static_library(
368   'tincd',
369   sources: src_tincd,
370   dependencies: deps_tincd,
371   link_with: lib_common,
372   c_args: cc_flags_tincd,
373   implicit_include_directories: false,
374   include_directories: inc_conf,
375   build_by_default: false,
376 )
377
378 exe_tinc = executable(
379   'tinc',
380   sources: 'tincctl.c',
381   dependencies: deps_tinc,
382   link_with: lib_tinc,
383   implicit_include_directories: false,
384   include_directories: inc_conf,
385   install: true,
386   install_dir: dir_sbin,
387 )
388
389 exe_tincd = executable(
390   'tincd',
391   sources: 'tincd.c',
392   dependencies: deps_tincd,
393   link_with: lib_tincd,
394   c_args: cc_flags_tincd,
395   implicit_include_directories: false,
396   include_directories: inc_conf,
397   install: true,
398   install_dir: dir_sbin,
399 )
400
401 exe_sptps_test = executable(
402   'sptps_test',
403   sources: 'sptps_test.c',
404   dependencies: deps_lib_common,
405   link_with: lib_common,
406   implicit_include_directories: false,
407   include_directories: inc_conf,
408   build_by_default: false,
409 )
410
411 exe_sptps_keypair = executable(
412   'sptps_keypair',
413   sources: 'sptps_keypair.c',
414   dependencies: deps_lib_common,
415   link_with: lib_common,
416   implicit_include_directories: false,
417   include_directories: inc_conf,
418   build_by_default: false,
419 )
420
421 if os_name == 'linux'
422   dep_rt = cc.find_library('rt')
423
424   exe_sptps_speed = executable(
425     'sptps_speed',
426     sources: 'sptps_speed.c',
427     dependencies: [deps_lib_common, dep_rt],
428     link_with: lib_common,
429     implicit_include_directories: false,
430     include_directories: inc_conf,
431     build_by_default: false,
432   )
433
434   benchmark('sptps_speed', exe_sptps_speed, timeout: 90)
435 endif
436