1project('p11-kit', 'c',
2        version: '0.24.0',
3        meson_version: '>= 0.49')
4
5version_arr = meson.project_version().split('.')
6major_version = version_arr[0].to_int()
7minor_version = version_arr[1].to_int()
8micro_version = version_arr[2].to_int()
9
10cc = meson.get_compiler('c')
11
12current = 3
13revision = 0
14age = 3
15
16soversion = current - age
17library_version = '@0@.@1@.@2@'.format(soversion, age, revision)
18
19configinc = include_directories('.')
20commoninc = include_directories('common')
21p11kitinc = include_directories('p11-kit')
22trustinc = include_directories('trust')
23
24add_project_arguments(['-D_GNU_SOURCE', '-DP11_KIT_FUTURE_UNSTABLE_API'],
25                      language: 'c')
26
27conf = configuration_data()
28
29conf.set_quoted('PACKAGE_NAME', meson.project_name())
30conf.set('PACKAGE_MAJOR', major_version)
31conf.set('PACKAGE_MINOR', minor_version)
32
33host_system = host_machine.system()
34if host_system == 'windows'
35  conf.set('OS_WIN32', 1)
36else
37  conf.set('OS_UNIX', 1)
38endif
39
40if host_system == 'windows'
41  shlext = '.dll'
42  exeext = '.exe'
43else
44  shlext = '.so'
45  exeext = ''
46endif
47
48conf.set_quoted('SHLEXT', shlext)
49conf.set_quoted('EXEEXT', exeext)
50
51if host_machine.endian() == 'big'
52  conf.set('WORDS_BIGENDIAN', 1)
53endif
54
55if get_option('debug')
56  conf.set('WITH_DEBUG', 1)
57  conf.set('_DEBUG', 1)
58endif
59
60conf.set10('WITH_STRICT', get_option('strict'))
61
62if get_option('nls') and cc.has_header('libintl.h')
63  conf.set('ENABLE_NLS', 1)
64endif
65
66prefix = get_option('prefix')
67datadir = get_option('datadir')
68bindir = get_option('bindir')
69libdir = get_option('libdir')
70libexecdir = get_option('libexecdir')
71sysconfdir = get_option('sysconfdir')
72mandir = get_option('mandir')
73pkgdatadir = datadir / meson.project_name()
74privatedir = libexecdir / meson.project_name()
75
76common_c_args = [
77  '-DBINDIR="@0@"'.format(prefix / bindir),
78  '-DPRIVATEDIR="@0@"'.format(prefix / privatedir),
79  '-DSYSCONFDIR="@0@"'.format(prefix / sysconfdir)
80]
81
82top_source_dir = meson.current_source_dir()
83top_build_dir = meson.current_build_dir()
84
85tests_c_args = [
86  '-DSRCDIR="@0@"'.format(top_source_dir),
87  '-DBUILDDIR="@0@"'.format(top_build_dir)
88]
89
90conf.set('SIZEOF_UNSIGNED_LONG', cc.sizeof('unsigned long'))
91
92nanosleep_deps = []
93dlopen_deps = []
94socket_deps = []
95thread_deps = []
96
97if host_system != 'windows'
98  thread_deps += dependency('threads')
99  if not cc.has_function('pthread_create', dependencies: thread_deps)
100    error('could not find pthread_create')
101  endif
102
103  if not cc.has_function('nanosleep')
104    librt = cc.find_library('rt', required: false)
105    if cc.has_function('nanosleep', dependencies: librt)
106      nanosleep_deps += librt
107    else
108      error('could not find nanosleep')
109    endif
110  endif
111
112  if not cc.has_function('dlopen')
113    libdl = cc.find_library('dl', required: false)
114    if cc.has_function('dlopen', dependencies: libdl)
115      dlopen_deps += libdl
116    else
117      error('could not find dlopen')
118    endif
119  endif
120
121  # for Solaris we need -lsocket -lnsl for socket stuff, gethostbyname
122  # is just a dummy to find -lnsl
123  libnsl = cc.find_library('nsl', required: false)
124  if libnsl.found()
125    if cc.has_function('gethostbyname', dependencies: libnsl)
126      socket_deps += libnsl
127    endif
128
129    libsocket = cc.find_library('socket', required: false)
130    if libsocket.found()
131      if cc.has_function('connect', dependencies: [libsocket, libnsl])
132        socket_deps += libsocket
133      else
134        error('could not find socket')
135      endif
136    endif
137  endif
138
139  if cc.has_header('locale.h')
140    conf.set('HAVE_LOCALE_H', 1)
141    if cc.has_type('locale_t', prefix: '#include <locale.h>')
142      conf.set('HAVE_LOCALE_T', 1)
143      if cc.has_function('newlocale', prefix: '#include <locale.h>')
144        conf.set('HAVE_NEWLOCALE', 1)
145      endif
146      if cc.has_function('strerror_l', prefix: '#include <string.h>')
147        conf.set('HAVE_STRERROR_L', 1)
148      endif
149    endif
150  endif
151
152  # These are things we can work around
153  headers = [
154    'sys/resource.h',
155    'sys/un.h',
156    'ucred.h'
157  ]
158
159  foreach h : headers
160    if cc.has_header(h)
161      conf.set('HAVE_' + h.underscorify().to_upper(), 1)
162    endif
163  endforeach
164
165  functions = [
166    'fdwalk',
167    'getauxval',
168    'getexecname',
169    'getpeereid',
170    'getpeerucred',
171    'getprogname',
172    'getresuid',
173    'issetugid',
174    'mkdtemp',
175    'mkstemp',
176    'secure_getenv',
177    'strndup'
178  ]
179
180  foreach f : functions
181    if cc.has_function(f)
182      conf.set('HAVE_' + f.underscorify().to_upper(), 1)
183    endif
184  endforeach
185
186  if cc.has_member('struct dirent', 'd_type', prefix: '#include <dirent.h>')
187    conf.set('HAVE_STRUCT_DIRENT_D_TYPE', 1)
188  endif
189
190  tls_test_code_template = '''
191#include <stdlib.h>
192int main (void) {
193static @0@ foo;
194return 0;
195}
196'''
197  foreach keyword : ['_Thread_local', '__thread']
198    if cc.compiles(tls_test_code_template.format(keyword),
199                   name: 'thread-local storage class')
200      conf.set('P11_TLS_KEYWORD', keyword)
201      break
202    endif
203  endforeach
204
205  if cc.has_function('gmtime_r')
206    conf.set('HAVE_GMTIME_R', 1)
207  else
208    error('could not find required gmtime_r() function')
209  endif
210
211  # Check if these are declared and/or available to link against
212  program_invocation_short_name_test_code = '''
213#define _GNU_SOURCE
214#include <errno.h>
215int main (void) { program_invocation_short_name = "test"; }
216'''
217  if cc.links(program_invocation_short_name_test_code,
218              name: 'program_invocation_short_name_test_code')
219    conf.set('HAVE_PROGRAM_INVOCATION_SHORT_NAME', 1)
220  else
221    __progname_test_code = '''
222extern char *__progname;
223int main (void) { __progname = (char*)0; return 0; }
224'''
225    if cc.links(__progname_test_code, name: '__progname')
226      conf.set('HAVE___PROGNAME', 1)
227    endif
228  endif
229
230  __libc_enable_secure_test_code = '''
231extern int __libc_enable_secure;
232int main (void) { __libc_enable_secure = 0; return 0; }
233'''
234  if cc.links(__libc_enable_secure_test_code, name: '__libc_enable_secure')
235    conf.set('HAVE___LIBC_ENABLE_SECURE', 1)
236  endif
237
238  vsock_availability_test_code = '''
239#include <sys/socket.h>
240#include <linux/vm_sockets.h>
241struct sockaddr_vm sa = { .svm_family = AF_VSOCK, .svm_cid = VMADDR_CID_ANY };
242'''
243  if cc.compiles(vsock_availability_test_code, name: 'vsock_test')
244    conf.set('HAVE_VSOCK', 1)
245  endif
246
247  foreach h : ['sys/types.h', 'signal.h']
248    foreach t : ['sighandler_t', 'sig_t', '__sighandler_t']
249      if cc.has_type(t, prefix: '#include <@0@>'.format(h))
250        define = 'HAVE_' + t.underscorify().to_upper()
251        conf.set(define, 1)
252      endif
253    endforeach
254  endforeach
255endif
256
257headers = [
258  'stdbool.h',
259]
260
261foreach h : headers
262  if cc.has_header(h)
263    conf.set('HAVE_' + h.underscorify().to_upper(), 1)
264  endif
265endforeach
266
267functions = [
268  'asprintf',
269  'basename',
270  'memdup',
271  'reallocarray',
272  'secure_getenv',
273  'setenv',
274  'strerror_r',
275  'strnstr',
276  'vasprintf'
277]
278
279foreach f : functions
280  if cc.has_function(f)
281    conf.set('HAVE_' + f.underscorify().to_upper(), 1)
282  endif
283endforeach
284
285conf.set10('HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME',
286           cc.has_header_symbol('errno.h',
287                                'program_invocation_short_name',
288                                prefix: '#define _GNU_SOURCE'))
289
290conf.set10('HAVE_DECL_ASPRINTF',
291           cc.has_header_symbol('stdio.h', 'asprintf',
292                                prefix: '#define _GNU_SOURCE'))
293
294conf.set10('HAVE_DECL_VASPRINTF',
295           cc.has_header_symbol('stdio.h', 'vasprintf',
296                                prefix: '#define _GNU_SOURCE'))
297
298conf.set10('HAVE_DECL_REALLOCARRAY',
299           cc.has_header_symbol('stdlib.h', 'reallocarray'))
300
301# --------------------------------------------------------------------
302# libffi
303
304libffi_deps = []
305libffi = dependency('libffi', version: '>= 3.0.0', required: get_option('libffi'))
306if libffi.found()
307  conf.set('WITH_FFI', 1)
308  libffi_deps += libffi
309endif
310
311closures = get_option('closures')
312if closures < 1
313  error('at least one closure must be compiled in')
314endif
315
316conf.set('P11_VIRTUAL_MAX_FIXED', closures)
317
318# ------------------------------------------------------------------------------
319# PKCS#11 Directories
320
321p11_package_config_modules = get_option('module_config')
322if p11_package_config_modules == ''
323  p11_package_config_modules = pkgdatadir / 'modules'
324endif
325
326p11_system_config = get_option('system_config')
327if p11_system_config == ''
328  p11_system_config = sysconfdir / 'pkcs11'
329endif
330
331p11_user_config = get_option('user_config')
332p11_module_path = get_option('module_path')
333if p11_module_path == ''
334  p11_module_path = libdir / 'pkcs11'
335endif
336
337p11_system_config_file = p11_system_config / 'pkcs11.conf'
338p11_system_config_modules = p11_system_config / 'modules'
339p11_user_config_file = p11_user_config / 'pkcs11.conf'
340p11_user_config_modules = p11_user_config / 'modules'
341
342# --------------------------------------------------------------------
343# Hash implementation
344
345hash_impl = get_option('hash_impl')
346if hash_impl == 'freebl'
347  libfreebl3 = cc.find_library('freebl3', required: false)
348  if libfreebl3.found() and cc.has_function('NSSLOW_Init',
349                                            dependencies: libfreebl3)
350    conf.set('WITH_FREEBL', 1)
351  else
352    error('could not find the freebl3 library')
353  endif
354endif
355
356# --------------------------------------------------------------------
357# Trust Module
358
359with_trust_module = false
360libtasn1_deps = []
361libtasn1 = dependency('libtasn1', version: '>= 2.3',
362                      required: get_option('trust_module'))
363if libtasn1.found()
364  asn1Parser = find_program('asn1Parser', required: get_option('trust_module'))
365  if asn1Parser.found()
366    conf.set('WITH_ASN1', 1)
367    libtasn1_deps += libtasn1
368    with_trust_module = true
369  endif
370endif
371
372trust_paths = get_option('trust_paths')
373conf.set_quoted('TRUST_PATHS', trust_paths)
374
375# --------------------------------------------------------------------
376# systemd
377
378with_systemd = false
379libsystemd_deps = []
380libsystemd = dependency('libsystemd', required: get_option('systemd'))
381systemd = dependency('systemd', required: get_option('systemd'))
382if libsystemd.found() and systemd.found()
383  systemduserunitdir = systemd.get_pkgconfig_variable('systemduserunitdir')
384  conf.set('WITH_SYSTEMD', 1)
385  libsystemd_deps += libsystemd
386  with_systemd = true
387endif
388
389configure_file(output: 'config.h', configuration: conf)
390
391gnome = import('gnome')
392i18n = import('i18n')
393pkg = import('pkgconfig')
394
395subdir('common')
396subdir('p11-kit')
397subdir('fuzz')
398if with_trust_module
399  subdir('trust')
400endif
401subdir('doc/manual')
402if get_option('nls')
403  subdir('po')
404endif
405subdir('bash-completion')
406