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