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