]>
Commit | Line | Data |
---|---|---|
1 | # SPDX-License-Identifier: LGPL-2.1-or-later | |
2 | ||
3 | # Project. | |
4 | project( | |
5 | 'lxc', | |
6 | 'c', | |
7 | version: '4.0.0-devel', | |
8 | license: 'LGPLv2+', | |
9 | default_options: [ | |
10 | 'b_lto=true', | |
11 | 'b_lto_mode=thin', | |
12 | 'b_colorout=always', | |
13 | 'b_asneeded=true', | |
14 | 'b_pie=true', | |
15 | 'b_staticpic=true', | |
16 | 'c_std=gnu11', | |
17 | 'warning_level=2', | |
18 | ], | |
19 | meson_version: '>= 0.61') | |
20 | ||
21 | cc = meson.get_compiler('c') | |
22 | pkgconfig = import('pkgconfig') | |
23 | pkgconfig_libs = [] | |
24 | ||
25 | # Version. | |
26 | liblxc_version = '1.7.0' | |
27 | version_data = configuration_data() | |
28 | version_data.set('LXC_VERSION_MAJOR', '4') | |
29 | version_data.set('LXC_VERSION_MINOR', '0') | |
30 | version_data.set('LXC_VERSION_MICRO', '0') | |
31 | version_data.set('LXC_VERSION_BETA', '') | |
32 | version_data.set('LXC_ABI', liblxc_version) | |
33 | version_data.set('LXC_DEVEL', '1') | |
34 | version_data.set('LXC_VERSION', meson.project_version()) | |
35 | ||
36 | # Path handling. | |
37 | project_source_root = meson.current_source_dir() | |
38 | project_build_root = meson.current_build_dir() | |
39 | prefixdir = get_option('prefix') | |
40 | ||
41 | apparmorcachedir = get_option('apparmor-cache-path') | |
42 | globalconfig = get_option('global-config-path') | |
43 | localstatedir = join_paths('/', get_option('localstatedir')) | |
44 | logpath = get_option('log-path') | |
45 | lxcpathprefix = get_option('data-path') | |
46 | rootfsmount = get_option('rootfs-mount-path') | |
47 | user_network_db_opt = get_option('usernet-db-path') | |
48 | user_network_conf_opt = get_option('usernet-config-path') | |
49 | ||
50 | bashcompletiondir = join_paths('/', 'usr', 'share', 'bash-completion', 'completions') | |
51 | bindir = join_paths(prefixdir, get_option('bindir')) | |
52 | datadir = join_paths(prefixdir, get_option('datadir')) | |
53 | mandir = join_paths(prefixdir, get_option('mandir')) | |
54 | docdir = join_paths(datadir, get_option('doc-path')) | |
55 | includedir = join_paths(prefixdir, get_option('includedir')) | |
56 | libdir = join_paths(prefixdir, get_option('libdir')) | |
57 | libexecdir = join_paths(prefixdir, get_option('libexecdir')) | |
58 | runtimepath = join_paths(prefixdir, get_option('runtime-path')) | |
59 | sbindir = join_paths(prefixdir, get_option('sbindir')) | |
60 | sysconfdir = join_paths(prefixdir, get_option('sysconfdir')) | |
61 | ||
62 | lxcapparmorcachedir = join_paths(localstatedir, apparmorcachedir) | |
63 | lxcconfdir = join_paths(sysconfdir, globalconfig) | |
64 | lxcdefaultconfig = join_paths(lxcconfdir, 'default.conf') | |
65 | lxcglobalconfig = join_paths(lxcconfdir, 'lxc.conf') | |
66 | lxcexamplesdir = join_paths(docdir, 'examples') | |
67 | lxchookbindir = join_paths(libexecdir, 'lxc/hooks') | |
68 | lxcinclude = join_paths(includedir, 'lxc') | |
69 | lxclibexec = join_paths(libexecdir, 'lxc') | |
70 | lxclogpath = join_paths(localstatedir, logpath) | |
71 | lxcpath = join_paths(localstatedir, lxcpathprefix) | |
72 | lxcrootfsmount = join_paths(libdir, rootfsmount) | |
73 | lxcdatadir = join_paths(datadir, 'lxc') | |
74 | lxchookdir = join_paths(lxcdatadir, 'hooks') | |
75 | lxcselinuxdir = join_paths(lxcdatadir, 'selinux') | |
76 | lxctemplateconfdir = join_paths(lxcdatadir, 'config') | |
77 | lxctemplateconfcommondir = join_paths(lxctemplateconfdir, 'common.conf.d') | |
78 | lxctemplatedir = join_paths(lxcdatadir, 'templates') | |
79 | lxc_user_network_conf = join_paths(sysconfdir, user_network_conf_opt) | |
80 | lxc_user_network_db = join_paths(runtimepath, user_network_db_opt) | |
81 | pam_security = join_paths(libdir, 'security') | |
82 | ||
83 | # Configuration options. | |
84 | srcconf = configuration_data() | |
85 | srcconf.set('_GNU_SOURCE', true) | |
86 | srcconf.set('_FILE_OFFSET_BITS', 64) | |
87 | srcconf.set('__STDC_FORMAT_MACROS', true) | |
88 | srcconf.set_quoted('APPARMOR_CACHE_DIR', lxcapparmorcachedir) | |
89 | srcconf.set_quoted('LIBEXECDIR', libexecdir) | |
90 | srcconf.set_quoted('LOGPATH', lxclogpath) | |
91 | srcconf.set_quoted('LXC_DEFAULT_CONFIG', lxcdefaultconfig) | |
92 | srcconf.set_quoted('LXC_GLOBAL_CONF', lxcglobalconfig) | |
93 | srcconf.set_quoted('LXCINITDIR', libexecdir) | |
94 | srcconf.set_quoted('LXCPATH', lxcpath) | |
95 | srcconf.set_quoted('LXCROOTFSMOUNT', lxcrootfsmount) | |
96 | srcconf.set_quoted('LXCTEMPLATECONFIG', lxctemplateconfdir) | |
97 | srcconf.set_quoted('LXCTEMPLATECONFIG', lxctemplateconfdir) | |
98 | srcconf.set_quoted('LXCTEMPLATEDIR', lxctemplatedir) | |
99 | srcconf.set_quoted('LXC_USERNIC_CONF', lxc_user_network_conf) | |
100 | srcconf.set_quoted('LXC_USERNIC_DB', lxc_user_network_db) | |
101 | srcconf.set_quoted('RUNTIME_PATH', runtimepath) | |
102 | srcconf.set_quoted('SBINDIR', sbindir) | |
103 | ||
104 | conf = configuration_data() | |
105 | conf.set('BINDIR', bindir) | |
106 | conf.set('LIBEXECDIR', libexecdir) | |
107 | conf.set('LOCALSTATEDIR', localstatedir) | |
108 | conf.set('LXC_GLOBAL_CONF', lxcglobalconfig) | |
109 | conf.set('LXCHOOKDIR', lxchookdir) | |
110 | conf.set('LXCINITDIR', libexecdir) | |
111 | conf.set('LXCROOTFSMOUNT', lxcrootfsmount) | |
112 | conf.set('LXCTEMPLATECONFIG', lxctemplateconfdir) | |
113 | conf.set('LXCTEMPLATEDIR', lxctemplatedir) | |
114 | conf.set('PACKAGE_VERSION', meson.project_version()) | |
115 | conf.set('RUNTIME_PATH', runtimepath) | |
116 | conf.set('SYSCONFDIR', sysconfdir) | |
117 | ||
118 | # Set sysconfdir | |
119 | fs = import('fs') | |
120 | if fs.is_dir('/etc/sysconfig') | |
121 | distrosysconfdir = join_paths(sysconfdir, 'sysconfig') | |
122 | conf.set('LXC_DISTRO_SYSCONF', distrosysconfdir) | |
123 | elif fs.is_dir('/etc/default') | |
124 | distrosysconfdir = join_paths(sysconfdir, 'default') | |
125 | conf.set('LXC_DISTRO_SYSCONF', distrosysconfdir) | |
126 | else | |
127 | distrosysconfdir = '' | |
128 | endif | |
129 | ||
130 | # Cross-compile on Android. | |
131 | srcconf.set10('IS_BIONIC', host_machine.system() == 'android') | |
132 | ||
133 | # Custom configuration. | |
134 | cgrouppattern = get_option('cgroup-pattern') | |
135 | coverity = get_option('coverity-build') | |
136 | init_script = get_option('init-script') | |
137 | sanitize = get_option('b_sanitize') | |
138 | want_examples = get_option('examples') | |
139 | want_io_uring = get_option('io-uring-event-loop') | |
140 | want_pam_cgroup = get_option('pam-cgroup') | |
141 | want_mans = get_option('man') | |
142 | want_tests = get_option('tests') | |
143 | want_tools = get_option('tools') | |
144 | want_commands = get_option('commands') | |
145 | want_capabilities = get_option('capabilities') | |
146 | want_apparmor = get_option('apparmor') | |
147 | want_openssl = get_option('openssl') | |
148 | want_selinux = get_option('selinux') | |
149 | want_oss_fuzz = get_option('oss-fuzz') | |
150 | want_seccomp = get_option('seccomp') | |
151 | want_thread_safety = get_option('thread-safety') | |
152 | want_memfd_rexec = get_option('memfd-rexec') | |
153 | ||
154 | srcconf.set_quoted('DEFAULT_CGROUP_PATTERN', cgrouppattern) | |
155 | if coverity | |
156 | srcconf.set('ENABLE_COVERITY_BUILD', 1) | |
157 | endif | |
158 | ||
159 | dummy_config_data = configuration_data() | |
160 | dummy_config_data.set_quoted('DUMMY_VARIABLE', '1') | |
161 | ||
162 | # Those generate many false positives, and we do not want to change the code to | |
163 | # avoid them. | |
164 | basic_disabled_warnings = [ | |
165 | '-Wno-format-signedness', | |
166 | '-Wno-missing-field-initializers', | |
167 | '-Wno-unused-parameter', | |
168 | ] | |
169 | ||
170 | # Build flags. | |
171 | possible_cc_flags = [ | |
172 | '-Wvla', | |
173 | '-Wimplicit-fallthrough=5', | |
174 | '-Wcast-align', | |
175 | '-Wstrict-prototypes', | |
176 | '-fno-strict-aliasing', | |
177 | '-fstack-clash-protection', | |
178 | '-fstack-protector-strong', | |
179 | '--param=ssp-buffer-size=4', | |
180 | '--mcet -fcf-protection', | |
181 | '-Werror=implicit-function-declaration', | |
182 | '-Wlogical-op', | |
183 | '-Wmissing-include-dirs', | |
184 | '-Wold-style-definition', | |
185 | '-Winit-self', | |
186 | '-Wunused-but-set-variable', | |
187 | '-Wno-unused-parameter', | |
188 | '-Wfloat-equal', | |
189 | '-Wsuggest-attribute=noreturn', | |
190 | '-Werror=return-type', | |
191 | '-Werror=incompatible-pointer-types', | |
192 | '-Wformat=2', | |
193 | '-Wshadow', | |
194 | '-Wendif-labels', | |
195 | '-Werror=overflow', | |
196 | '-fdiagnostics-show-option', | |
197 | '-Werror=shift-count-overflow', | |
198 | '-Werror=shift-overflow=2', | |
199 | '-Wdate-time', | |
200 | '-Wnested-externs', | |
201 | '-fasynchronous-unwind-tables', | |
202 | '-fexceptions', | |
203 | '-Warray-bounds', | |
204 | '-Wrestrict', | |
205 | '-Wreturn-local-addr', | |
206 | '-fsanitize=cfi', | |
207 | '-Wstringop-overflow', | |
208 | ] | |
209 | ||
210 | possible_link_flags = [ | |
211 | '-Wl,--gc-sections', | |
212 | '-Wl,-z,relro', | |
213 | '-Wl,-z,now', | |
214 | '-Wl,-fuse-ld=gold', | |
215 | '-fstack-protector', | |
216 | ] | |
217 | ||
218 | if sanitize == 'none' | |
219 | possible_link_flags += '-Wl,--warn-common' | |
220 | endif | |
221 | ||
222 | if cc.get_id() == 'clang' | |
223 | possible_cc_flags += [ | |
224 | '-Wno-typedef-redefinition', | |
225 | '-Wno-gnu-variable-sized-type-not-at-end', | |
226 | ] | |
227 | endif | |
228 | ||
229 | if meson.version().version_compare('>=0.46') | |
230 | add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language: 'c') | |
231 | else | |
232 | add_project_link_arguments(possible_link_flags, language: 'c') | |
233 | endif | |
234 | ||
235 | add_project_arguments(cc.get_supported_arguments(basic_disabled_warnings), language : 'c') | |
236 | add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language: 'c') | |
237 | ||
238 | if add_languages('cpp', required : want_oss_fuzz) | |
239 | # Used only for tests | |
240 | cxx = meson.get_compiler('cpp') | |
241 | cxx_cmd = ' '.join(cxx.cmd_array()) | |
242 | add_project_arguments(cxx.get_supported_arguments(basic_disabled_warnings), language : 'cpp') | |
243 | endif | |
244 | ||
245 | # Feature detection | |
246 | ## I/O uring. | |
247 | if want_io_uring | |
248 | liburing = dependency('liburing') | |
249 | if cc.has_function('io_uring_prep_poll_add', prefix: '#include <liburing.h>', dependencies: liburing) == false | |
250 | error('liburing version does not support IORING_POLL_ADD_MULTI') | |
251 | endif | |
252 | ||
253 | srcconf.set10('HAVE_LIBURING', true) | |
254 | else | |
255 | srcconf.set10('HAVE_LIBURING', false) | |
256 | endif | |
257 | ||
258 | ## Time EPOCH. | |
259 | sh = find_program('sh') | |
260 | date = find_program('date') | |
261 | git = find_program('git', required: false) | |
262 | time_epoch = run_command(sh, '-c', 'echo "$SOURCE_DATE_EPOCH"', check: true).stdout().strip() | |
263 | if time_epoch == '' and git.found() and run_command('test', '-e', '.git', check: false).returncode() == 0 | |
264 | # If we're in a git repository, use the creation time of the latest git tag. | |
265 | latest_tag = run_command(git, 'describe', '--abbrev=0', '--tags', check: false).stdout().strip() | |
266 | if latest_tag != '' | |
267 | time_epoch = run_command(git, 'log', '--no-show-signature', '-1', '--format=%at', latest_tag, check: true).stdout() | |
268 | endif | |
269 | endif | |
270 | ||
271 | # Fallback to current epoch. | |
272 | if time_epoch == '' | |
273 | time_epoch = run_command(date, '+%s', check: true).stdout() | |
274 | endif | |
275 | generate_date = run_command(date, '--utc', '--date=@' + time_epoch, '+%Y-%m-%d', check: true).stdout().strip() | |
276 | ||
277 | ## Manpages. | |
278 | sgml2man = find_program('docbook2X2man', 'docbook2x-man', 'db2x_docbook2man', 'docbook2man', 'docbook-to-man', required: want_mans) | |
279 | docbook2man = find_program('docbook2man', required: false) | |
280 | ||
281 | docconf = configuration_data() | |
282 | docconf.set('builddir', '.') | |
283 | docconf.set('BINDIR', bindir) | |
284 | docconf.set('DATADIR', datadir) | |
285 | docconf.set('DOCDIR', docdir) | |
286 | docconf.set('LOGPATH', lxclogpath) | |
287 | docconf.set('LXC_DEFAULT_CONFIG', lxcdefaultconfig) | |
288 | docconf.set('LXC_GENERATE_DATE', generate_date) | |
289 | docconf.set('LXC_GLOBAL_CONF', lxcglobalconfig) | |
290 | docconf.set('LXCPATH', lxcpath) | |
291 | docconf.set('LXCTEMPLATEDIR', lxctemplatedir) | |
292 | docconf.set('LXC_USERNIC_CONF', lxc_user_network_conf) | |
293 | docconf.set('LXC_USERNIC_DB', lxc_user_network_db) | |
294 | docconf.set('PACKAGE_VERSION', version_data.get('LXC_VERSION')) | |
295 | if sgml2man.found() and docbook2man.found() and sgml2man.full_path() == docbook2man.full_path() | |
296 | docconf.set('docdtd', '"-//Davenport//DTD DocBook V3.0//EN"') | |
297 | else | |
298 | docconf.set('docdtd', '"-//OASIS//DTD DocBook XML" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"') | |
299 | endif | |
300 | ||
301 | ## Threads. | |
302 | threads = dependency('threads') | |
303 | ||
304 | ## Seccomp. | |
305 | if want_seccomp | |
306 | libseccomp = dependency('libseccomp', required: false) | |
307 | srcconf.set10('HAVE_SECCOMP', libseccomp.found()) | |
308 | pkgconfig_libs += libseccomp | |
309 | if libseccomp.found() | |
310 | if libseccomp.version().version_compare('>=2.5.0') | |
311 | # https://github.com/seccomp/libseccomp/commit/dead12bc788b259b148cc4d93b970ef0bd602b1a | |
312 | srcconf.set10('HAVE_DECL_SECCOMP_NOTIFY_FD', true) | |
313 | else | |
314 | srcconf.set10('HAVE_DECL_SECCOMP_NOTIFY_FD', false) | |
315 | endif | |
316 | ||
317 | if libseccomp.version().version_compare('>=2.0.0') | |
318 | # https://github.com/seccomp/libseccomp/commit/6220c8c0fc479d97b6d3e3166a4e46fbfe25a3c0 | |
319 | srcconf.set10('HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH', true) | |
320 | else | |
321 | srcconf.set10('HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH', false) | |
322 | endif | |
323 | ||
324 | seccomp_headers = ''' | |
325 | #include <seccomp.h> | |
326 | ''' | |
327 | ||
328 | foreach decl: [ | |
329 | 'scmp_filter_ctx', | |
330 | 'struct seccomp_notif_sizes', | |
331 | 'struct clone_args', | |
332 | ] | |
333 | ||
334 | # We get -1 if the size cannot be determined | |
335 | if cc.sizeof(decl, prefix: seccomp_headers, args: '-D_GNU_SOURCE') > 0 | |
336 | srcconf.set10('HAVE_' + decl.underscorify().to_upper(), true) | |
337 | else | |
338 | srcconf.set10('HAVE_' + decl.underscorify().to_upper(), false) | |
339 | endif | |
340 | endforeach | |
341 | endif | |
342 | else | |
343 | srcconf.set10('HAVE_SECCOMP', false) | |
344 | endif | |
345 | ||
346 | ## SELinux. | |
347 | if want_selinux | |
348 | libselinux = dependency('libselinux', required: false) | |
349 | srcconf.set10('HAVE_SELINUX', libselinux.found()) | |
350 | pkgconfig_libs += libselinux | |
351 | else | |
352 | srcconf.set10('HAVE_SELINUX', false) | |
353 | endif | |
354 | ||
355 | ## AppArmor. | |
356 | if want_apparmor | |
357 | libapparmor = dependency('libapparmor', required: false) | |
358 | srcconf.set10('HAVE_APPARMOR', libapparmor.found()) | |
359 | else | |
360 | srcconf.set10('HAVE_APPARMOR', false) | |
361 | endif | |
362 | ||
363 | ## OpenSSL. | |
364 | if want_openssl | |
365 | libopenssl = dependency('openssl', required: false) | |
366 | srcconf.set10('HAVE_OPENSSL', libopenssl.found()) | |
367 | pkgconfig_libs += libopenssl | |
368 | else | |
369 | srcconf.set10('HAVE_OPENSSL', false) | |
370 | endif | |
371 | ||
372 | ## Libcap.. | |
373 | if want_capabilities | |
374 | libcap = dependency('libcap', required: false) | |
375 | if not libcap.found() | |
376 | # Compat with Ubuntu 14.04 which ships libcap w/o .pc file | |
377 | libcap = cc.find_library('cap', required: false) | |
378 | endif | |
379 | srcconf.set10('HAVE_LIBCAP', libcap.found()) | |
380 | pkgconfig_libs += libcap | |
381 | ||
382 | libcap_static = dependency('libcap', required: false, static: true) | |
383 | if not libcap_static.found() | |
384 | # Compat with Ubuntu 14.04 which ships libcap w/o .pc file | |
385 | libcap_static = cc.find_library('cap', required: false, static: true) | |
386 | endif | |
387 | ||
388 | code = ''' | |
389 | int main(int argc, char *argv[]) { return 0; }; | |
390 | ''' | |
391 | if libcap_static.found() | |
392 | libcap_static_linkable = cc.links(code, args: '-static', dependencies: libcap_static) | |
393 | srcconf.set10('HAVE_STATIC_LIBCAP', libcap_static_linkable) | |
394 | else | |
395 | srcconf.set10('HAVE_STATIC_LIBCAP', false) | |
396 | endif | |
397 | else | |
398 | srcconf.set10('HAVE_LIBCAP', false) | |
399 | srcconf.set10('HAVE_STATIC_LIBCAP', false) | |
400 | endif | |
401 | ||
402 | if want_oss_fuzz | |
403 | srcconf.set10('FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION', true) | |
404 | srcconf.set10('RUN_ON_OSS_FUZZ', true) | |
405 | fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine') | |
406 | endif | |
407 | ||
408 | srcconf.set10('ENFORCE_THREAD_SAFETY', want_thread_safety) | |
409 | srcconf.set10('ENFORCE_MEMFD_REXEC', want_memfd_rexec) | |
410 | ||
411 | ## PAM. | |
412 | pam = cc.find_library('pam', has_headers: 'security/pam_modules.h', required: want_pam_cgroup) | |
413 | srcconf.set10('HAVE_PAM', pam.found()) | |
414 | pkgconfig_libs += pam | |
415 | ||
416 | ## Others. | |
417 | have = cc.has_function('strchrnul', prefix: '#include <string.h>', args: '-D_GNU_SOURCE') | |
418 | srcconf.set10('HAVE_STRCHRNUL', have) | |
419 | ||
420 | have = cc.has_function('openpty', prefix: '#include <pty.h>', args: '-D_GNU_SOURCE') | |
421 | srcconf.set10('HAVE_OPENPTY', have) | |
422 | ||
423 | have_func_strerror_r = cc.has_function('strerror_r', prefix: '#include <string.h>', args: '-D_GNU_SOURCE') | |
424 | srcconf.set10('HAVE_STRERROR_R', have_func_strerror_r) | |
425 | ||
426 | have_func_strerror_r_char_p = false | |
427 | ||
428 | if have_func_strerror_r | |
429 | code = ''' | |
430 | #define _GNU_SOURCE | |
431 | #include <string.h> | |
432 | int func (void) { | |
433 | char error_string[256]; | |
434 | char *ptr = strerror_r (-2, error_string, 256); | |
435 | char c = *strerror_r (-2, error_string, 256); | |
436 | return c != 0 && ptr != (void*) 0L; | |
437 | } | |
438 | ''' | |
439 | ||
440 | have_func_strerror_r_char_p = cc.compiles(code, name : 'strerror_r() returns char *') | |
441 | endif | |
442 | ||
443 | srcconf.set10('STRERROR_R_CHAR_P', have_func_strerror_r_char_p) | |
444 | ||
445 | ## Compiler attributes. | |
446 | foreach ccattr: [ | |
447 | 'fallthrough', | |
448 | 'nonnull', | |
449 | 'returns_nonnull', | |
450 | ] | |
451 | ||
452 | srcconf.set10('HAVE_COMPILER_ATTR_' + ccattr.underscorify().to_upper(), cc.has_function_attribute(ccattr)) | |
453 | endforeach | |
454 | ||
455 | ## Syscalls. | |
456 | found_syscalls = [] | |
457 | missing_syscalls = [] | |
458 | foreach tuple: [ | |
459 | ['bpf'], | |
460 | ['close_range'], | |
461 | ['endmntent'], | |
462 | ['execveat'], | |
463 | ['faccessat'], | |
464 | ['strchrnul'], | |
465 | ['strerror_r'], | |
466 | ['fgetln'], | |
467 | ['fsconfig'], | |
468 | ['fsmount'], | |
469 | ['fsopen'], | |
470 | ['fspick'], | |
471 | ['getgrgid_r'], | |
472 | ['getline'], | |
473 | ['getsubopt'], | |
474 | ['gettid'], | |
475 | ['hasmntopt'], | |
476 | ['kcmp'], | |
477 | ['keyctl'], | |
478 | ['memfd_create'], | |
479 | ['mount_setattr'], | |
480 | ['move_mount'], | |
481 | ['openat2'], | |
482 | ['open_tree'], | |
483 | ['personality'], | |
484 | ['pidfd_open'], | |
485 | ['pidfd_send_signal'], | |
486 | ['pivot_root'], | |
487 | ['prlimit'], | |
488 | ['prlimit64'], | |
489 | ['renameat2'], | |
490 | ['sethostname'], | |
491 | ['setmntent'], | |
492 | ['setns'], | |
493 | ['sigdescr_np'], | |
494 | ['signalfd'], | |
495 | ['statx'], | |
496 | ['strlcat'], | |
497 | ['strlcpy'], | |
498 | ['unshare'], | |
499 | ] | |
500 | ||
501 | if tuple.length() >= 2 | |
502 | cond = tuple[1] | |
503 | else | |
504 | ident1 = 'HAVE_' + tuple[0].underscorify().to_upper() | |
505 | ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper() | |
506 | cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1 | |
507 | endif | |
508 | ||
509 | if cond | |
510 | found_syscalls += tuple[0] | |
511 | else | |
512 | missing_syscalls += tuple[0] | |
513 | endif | |
514 | endforeach | |
515 | ||
516 | ## Types. | |
517 | decl_headers = ''' | |
518 | #include <uchar.h> | |
519 | #include <sys/mount.h> | |
520 | #include <sys/stat.h> | |
521 | #include <linux/fs.h> | |
522 | #include <linux/types.h> | |
523 | #include <linux/openat2.h> | |
524 | #include <linux/sched.h> | |
525 | ''' | |
526 | ||
527 | foreach decl: [ | |
528 | '__aligned_u64', | |
529 | 'struct mount_attr', | |
530 | 'struct open_how', | |
531 | 'struct clone_args', | |
532 | ] | |
533 | ||
534 | # We get -1 if the size cannot be determined | |
535 | if cc.sizeof(decl, prefix: decl_headers, args: '-D_GNU_SOURCE') > 0 | |
536 | srcconf.set10('HAVE_' + decl.underscorify().to_upper(), true) | |
537 | else | |
538 | srcconf.set10('HAVE_' + decl.underscorify().to_upper(), false) | |
539 | endif | |
540 | endforeach | |
541 | ||
542 | found_types = [] | |
543 | missing_types = [] | |
544 | foreach tuple: [ | |
545 | ['scmp_filter_ctx'], | |
546 | ['struct seccomp_notif_sizes'], | |
547 | ['struct clone_args'], | |
548 | ['__aligned_u64'], | |
549 | ['struct mount_attr'], | |
550 | ['struct open_how'], | |
551 | ] | |
552 | ||
553 | if tuple.length() >= 2 | |
554 | cond = tuple[1] | |
555 | else | |
556 | ident1 = 'HAVE_' + tuple[0].underscorify().to_upper() | |
557 | ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper() | |
558 | cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1 | |
559 | endif | |
560 | ||
561 | if cond | |
562 | found_types += tuple[0] | |
563 | else | |
564 | missing_types += tuple[0] | |
565 | endif | |
566 | endforeach | |
567 | ||
568 | ## Headers. | |
569 | foreach ident: [ | |
570 | ['bpf', '''#include <sys/syscall.h> | |
571 | #include <unistd.h>'''], | |
572 | ['close_range', '''#include <unistd.h>'''], | |
573 | ['execveat', '''#include <unistd.h>'''], | |
574 | ['endmntent', '''#include <stdio.h> | |
575 | #include <mntent.h>'''], | |
576 | ['faccessat', '''#include <fcntl.h> | |
577 | #include <unistd.h>'''], | |
578 | ['fexecve', '''#include <unistd.h>'''], | |
579 | ['fgetln', '''#include <stdio.h>'''], | |
580 | ['fsconfig', '''#include <sys/mount.h>'''], | |
581 | ['fsmount', '''#include <sys/mount.h>'''], | |
582 | ['fsopen', '''#include <sys/mount.h>'''], | |
583 | ['fspick', '''#include <sys/mount.h>'''], | |
584 | ['getgrgid_r', '''#include <sys/types.h> | |
585 | #include <grp.h>'''], | |
586 | ['getline', '''#include <stdio.h>'''], | |
587 | ['getsubopt', '''#include <stdlib.h>'''], | |
588 | ['gettid', '''#include <sys/types.h> | |
589 | #include <unistd.h>'''], | |
590 | ['hasmntopt', '''#include <stdio.h> | |
591 | #include <mntent.h>'''], | |
592 | ['kcmp', '''#include <linux/kcmp.h>'''], | |
593 | ['keyctl', '''#include <sys/types.h> | |
594 | #include <keyutils.h>'''], | |
595 | ['memfd_create', '''#include <sys/mman.h>'''], | |
596 | ['mount_setattr', '''#include <sys/mount.h>'''], | |
597 | ['move_mount', '''#include <sys/mount.h>'''], | |
598 | ['openat2', '''#include <sys/types.h> | |
599 | #include <sys/stat.h> | |
600 | #include <fctnl.h>'''], | |
601 | ['open_tree', '''#include <sys/mount.h>'''], | |
602 | ['personality', '''#include <sys/personality.h>'''], | |
603 | ['pidfd_open', '''#include <stdlib.h> | |
604 | #include <unistd.h> | |
605 | #include <signal.h> | |
606 | #include <sys/wait.h>'''], | |
607 | ['pidfd_send_signal', '''#include <stdlib.h> | |
608 | #include <unistd.h> | |
609 | #include <signal.h> | |
610 | #include <sys/wait.h>'''], | |
611 | ['pivot_root', '''#include <stdlib.h> | |
612 | #include <unistd.h>'''], # no known header declares pivot_root | |
613 | ['prlimit', '''#include <sys/time.h> | |
614 | #include <sys/resource.h>'''], | |
615 | ['prlimit64', '''#include <sys/time.h> | |
616 | #include <sys/resource.h>'''], | |
617 | ['renameat2', '''#include <stdio.h> | |
618 | #include <fcntl.h>'''], | |
619 | ['sethostname', '''#include <unistd.h>'''], | |
620 | ['setmntent', '''#include <stdio.h> | |
621 | #include <mntent.h>'''], | |
622 | ['setns', '''#include <sched.h>'''], | |
623 | ['sigdescr_np', '''#include <string.h>'''], | |
624 | ['signalfd', '''#include <sys/signalfd.h>'''], | |
625 | ['statx', '''#include <sys/types.h> | |
626 | #include <sys/stat.h> | |
627 | #include <unistd.h>'''], | |
628 | ['strchrnul', '''#include <string.h>'''], | |
629 | ['strlcat', '''#include <string.h>'''], | |
630 | ['strlcpy', '''#include <string.h>'''], | |
631 | ['unshare', '''#include <sched.h>'''], | |
632 | ] | |
633 | ||
634 | have = cc.has_function(ident[0], prefix: ident[1], args: '-D_GNU_SOURCE') | |
635 | srcconf.set10('HAVE_' + ident[0].to_upper(), have) | |
636 | endforeach | |
637 | ||
638 | found_headers = [] | |
639 | missing_headers = [] | |
640 | foreach tuple: [ | |
641 | ['sys/resource.h'], | |
642 | ['sys/memfd.h'], | |
643 | ['sys/personality.h'], | |
644 | ['sys/signalfd.h'], | |
645 | ['sys/timerfd.h'], | |
646 | ['pty.h'], | |
647 | ['utmpx.h'], | |
648 | ] | |
649 | srcconf.set10('HAVE_' + tuple[0].underscorify().to_upper(), cc.has_header(tuple[0])) | |
650 | ||
651 | if tuple.length() >= 2 | |
652 | cond = tuple[1] | |
653 | else | |
654 | ident1 = 'HAVE_' + tuple[0].underscorify().to_upper() | |
655 | ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper() | |
656 | cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1 | |
657 | endif | |
658 | ||
659 | if cond | |
660 | found_headers += tuple[0] | |
661 | else | |
662 | missing_headers += tuple[0] | |
663 | endif | |
664 | endforeach | |
665 | ||
666 | ## Deps. | |
667 | found_deps = [] | |
668 | missing_deps = [] | |
669 | foreach tuple: [ | |
670 | ['AppArmor'], | |
671 | ['SECCOMP'], | |
672 | ['SELinux'], | |
673 | ['libcap'], | |
674 | ['static libcap'], | |
675 | ['pam'], | |
676 | ['openssl'], | |
677 | ['liburing'], | |
678 | ] | |
679 | ||
680 | if tuple.length() >= 2 | |
681 | cond = tuple[1] | |
682 | else | |
683 | ident1 = 'HAVE_' + tuple[0].underscorify().to_upper() | |
684 | ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper() | |
685 | cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1 | |
686 | endif | |
687 | ||
688 | if cond | |
689 | found_deps += tuple[0] | |
690 | else | |
691 | missing_deps += tuple[0] | |
692 | endif | |
693 | endforeach | |
694 | ||
695 | # Generate config.h | |
696 | config_h = configure_file( | |
697 | output: 'config.h', | |
698 | configuration: srcconf) | |
699 | ||
700 | add_project_arguments('-include', 'config.h', language: 'c') | |
701 | ||
702 | # Binaries. | |
703 | cmd_programs = [] | |
704 | hook_programs = [] | |
705 | public_programs = [] | |
706 | template_scripts = [] | |
707 | test_programs = [] | |
708 | ||
709 | # Includes. | |
710 | liblxc_includes = include_directories( | |
711 | '.', | |
712 | 'src', | |
713 | 'src/include', | |
714 | 'src/lxc', | |
715 | 'src/lxc/cgroups', | |
716 | 'src/lxc/storage') | |
717 | ||
718 | # Early sub-directories. | |
719 | subdir('src/include') | |
720 | subdir('src/lxc') | |
721 | subdir('src/lxc/pam') | |
722 | ||
723 | # Library. | |
724 | liblxc_dependencies = [ | |
725 | threads, | |
726 | ] | |
727 | ||
728 | if want_seccomp | |
729 | liblxc_dependencies += libseccomp | |
730 | endif | |
731 | ||
732 | if want_capabilities | |
733 | liblxc_dependencies += [libcap] | |
734 | endif | |
735 | ||
736 | if want_openssl | |
737 | liblxc_dependencies += [libopenssl] | |
738 | endif | |
739 | ||
740 | if want_selinux | |
741 | liblxc_dependencies += [libselinux] | |
742 | endif | |
743 | ||
744 | if want_apparmor | |
745 | liblxc_dependencies += [libapparmor] | |
746 | endif | |
747 | ||
748 | if want_io_uring | |
749 | liblxc_dependencies += [liburing] | |
750 | endif | |
751 | ||
752 | liblxc_link_whole = [liblxc_static] | |
753 | ||
754 | liblxc = shared_library( | |
755 | 'lxc', | |
756 | version: liblxc_version, | |
757 | include_directories: liblxc_includes, | |
758 | link_args: ['-DPIC'], | |
759 | c_args: ['-DPIC'], | |
760 | link_whole: liblxc_link_whole, | |
761 | dependencies: liblxc_dependencies, | |
762 | install: true) | |
763 | ||
764 | liblxc_dep = declare_dependency( | |
765 | link_with: liblxc, | |
766 | dependencies: liblxc_dependencies) | |
767 | ||
768 | # Rest of sub-directories. | |
769 | if want_apparmor | |
770 | subdir('config/apparmor') | |
771 | subdir('config/apparmor/abstractions') | |
772 | subdir('config/apparmor/profiles') | |
773 | endif | |
774 | subdir('config/bash') | |
775 | subdir('config/etc') | |
776 | subdir('config/init/common') | |
777 | subdir('config/init/systemd') | |
778 | subdir('config/init/sysvinit') | |
779 | subdir('config/init/upstart') | |
780 | if want_selinux | |
781 | subdir('config/selinux') | |
782 | endif | |
783 | subdir('config/sysconfig') | |
784 | subdir('config/templates') | |
785 | subdir('config/templates/common.conf.d') | |
786 | subdir('config/yum') | |
787 | subdir('doc') | |
788 | subdir('doc/ja') | |
789 | subdir('doc/ko') | |
790 | subdir('doc/examples') | |
791 | subdir('doc/rootfs') | |
792 | subdir('hooks') | |
793 | if want_commands | |
794 | subdir('src/lxc/cmd') | |
795 | endif | |
796 | if want_tools | |
797 | subdir('src/lxc/tools') | |
798 | endif | |
799 | subdir('src/lxc/tools/include') | |
800 | subdir('src/tests') | |
801 | subdir('templates') | |
802 | ||
803 | # Pkg-config. | |
804 | pkg_config_file = pkgconfig.generate(liblxc, | |
805 | description: 'linux container tools', | |
806 | version: version_data.get('LXC_VERSION'), | |
807 | url: 'http://linuxcontainers.org', | |
808 | libraries: '-lutil -lpthread -ldl', | |
809 | libraries_private: pkgconfig_libs, | |
810 | ) | |
811 | ||
812 | # Empty dirs. | |
813 | install_emptydir(join_paths(localstatedir, 'cache', 'lxc')) | |
814 | install_emptydir(join_paths(localstatedir, 'lib', 'lxc')) | |
815 | ||
816 | # RPM spec file. | |
817 | specconf = configuration_data() | |
818 | specconf.set('LXC_VERSION_BASE', meson.project_version()) | |
819 | specconf.set('LXC_VERSION_BETA', version_data.get('LXC_VERSION_BETA')) | |
820 | specconf.set('PACKAGE', meson.project_name()) | |
821 | specconf.set('LXC_DISTRO_SYSCONF', conf.get('LXC_DISTRO_SYSCONF')) | |
822 | ||
823 | configure_file( | |
824 | configuration: specconf, | |
825 | input: 'lxc.spec.in', | |
826 | output: 'lxc.spec', | |
827 | install: false) | |
828 | ||
829 | # Build overview. | |
830 | status = [ | |
831 | '@0@ @1@'.format(meson.project_name(), meson.project_version()), | |
832 | ||
833 | 'Meson version: @0@'.format(meson.version()), | |
834 | ||
835 | 'prefix directory: @0@'.format(prefixdir), | |
836 | 'bin directory: @0@'.format(bindir), | |
837 | 'data directory: @0@'.format(datadir), | |
838 | 'doc directory: @0@'.format(docdir), | |
839 | 'include directory: @0@'.format(includedir), | |
840 | 'lib directory: @0@'.format(libdir), | |
841 | 'libexec directory: @0@'.format(libexecdir), | |
842 | 'local state directory: @0@'.format(localstatedir), | |
843 | 'sbin directory: @0@'.format(sbindir), | |
844 | 'sysconf directory: @0@'.format(sysconfdir), | |
845 | ||
846 | 'lxc cgroup pattern: @0@'.format(cgrouppattern), | |
847 | 'lxc init directory: @0@'.format(libexecdir), | |
848 | 'runtime path: @0@'.format(runtimepath), | |
849 | ||
850 | 'lxc default config: @0@'.format(lxcdefaultconfig), | |
851 | 'lxc global config: @0@'.format(lxcglobalconfig), | |
852 | 'lxc hook directory: @0@'.format(lxchookdir), | |
853 | 'lxc hook bin directory: @0@'.format(lxchookbindir), | |
854 | 'lxc rootfs mount directory: @0@'.format(lxcrootfsmount), | |
855 | 'log path: @0@'.format(lxclogpath), | |
856 | 'lxc path: @0@'.format(lxcpath), | |
857 | 'lxc template config: @0@'.format(lxctemplateconfdir), | |
858 | 'lxc template directory: @0@'.format(lxctemplatedir), | |
859 | 'lxc user network config: @0@'.format(lxc_user_network_conf), | |
860 | 'lxc user network database: @0@'.format(lxc_user_network_db)] | |
861 | ||
862 | alt_time_epoch = run_command('date', '-Is', '-u', '-d', | |
863 | '@@0@'.format(time_epoch), check: true).stdout().strip() | |
864 | status += [ | |
865 | 'time epoch: @0@ (@1@)'.format(time_epoch, alt_time_epoch)] | |
866 | ||
867 | status += [ | |
868 | '', | |
869 | 'supported dependencies: @0@'.format(', '.join(found_deps)), | |
870 | '', | |
871 | 'unsupported dependencies: @0@'.format(', '.join(missing_deps)), | |
872 | ''] | |
873 | ||
874 | status += [ | |
875 | '', | |
876 | 'supported headers: @0@'.format(', '.join(found_headers)), | |
877 | '', | |
878 | 'unsupported headers: @0@'.format(', '.join(missing_headers)), | |
879 | ''] | |
880 | ||
881 | status += [ | |
882 | '', | |
883 | 'supported calls: @0@'.format(', '.join(found_syscalls)), | |
884 | '', | |
885 | 'unsupported calls: @0@'.format(', '.join(missing_syscalls)), | |
886 | ''] | |
887 | ||
888 | status += [ | |
889 | '', | |
890 | 'supported types: @0@'.format(', '.join(found_types)), | |
891 | '', | |
892 | 'unsupported types: @0@'.format(', '.join(missing_types)), | |
893 | ''] | |
894 | ||
895 | message('\n '.join(status)) |