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