1 # Copyright (c) 2022-2023, PostgreSQL Global Development Group
3 # Entry point for building PostgreSQL with meson
5 # Good starting points for writing meson.build files are:
6 # - https://mesonbuild.com/Syntax.html
7 # - https://mesonbuild.com/Reference-manual.html
12 license: 'PostgreSQL',
14 # We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for
15 # RHEL 7 has 0.55. < 0.54 would require replacing some uses of the fs
16 # module, < 0.53 all uses of fs. So far there's no need to go to >=0.56.
17 meson_version: '>=0.54',
19 'warning_level=1', #-Wall equivalent
21 'buildtype=debugoptimized', # -O2 + debug
22 # For compatibility with the autoconf build, set a default prefix. This
23 # works even on windows, where it's a drive-relative path (i.e. when on
24 # d:/somepath it'll install to d:/usr/local/pgsql)
25 'prefix=/usr/local/pgsql',
31 ###############################################################
33 ###############################################################
36 pkgconfig = import('pkgconfig')
38 host_system = host_machine.system()
39 build_system = build_machine.system()
40 host_cpu = host_machine.cpu_family()
42 cc = meson.get_compiler('c')
44 not_found_dep = dependency('', required: false)
45 thread_dep = dependency('threads')
46 auto_features = get_option('auto_features')
50 ###############################################################
52 ###############################################################
54 # It's very easy to get into confusing states when the source directory
55 # contains an in-place build. E.g. the wrong pg_config.h will be used. So just
56 # refuse to build in that case.
58 # There's a more elaborate check later, that checks for conflicts around all
59 # generated files. But we can only do that much further down the line, so this
60 # quick check seems worth it. Adhering to this advice should clean up the
61 # conflict, but won't protect against somebody doing make distclean or just
62 # removing pg_config.h
63 errmsg_nonclean_base = '''
65 Non-clean source code directory detected.
67 To build with meson the source tree may not have an in-place, ./configure
68 style, build configured. You can have both meson and ./configure style builds
69 for the same source tree by building out-of-source / VPATH with
70 configure. Alternatively use a separate check out for meson based builds.
74 if fs.exists(meson.current_source_dir() / 'src' / 'include' / 'pg_config.h')
75 errmsg_cleanup = 'To clean up, run make maintainer-clean in the source tree.'
76 error(errmsg_nonclean_base.format(errmsg_cleanup))
81 ###############################################################
82 # Variables to be determined
83 ###############################################################
85 postgres_inc_d = ['src/include']
86 postgres_inc_d += get_option('extra_include_dirs')
88 postgres_lib_d = get_option('extra_lib_dirs')
107 backend_both_deps = []
113 # source of data for pg_config.h etc
114 cdata = configuration_data()
118 ###############################################################
119 # Version and other metadata
120 ###############################################################
122 pg_version = meson.project_version()
124 if pg_version.endswith('devel')
125 pg_version_arr = [pg_version.split('devel')[0], '0']
126 elif pg_version.contains('beta')
127 pg_version_arr = [pg_version.split('beta')[0], '0']
128 elif pg_version.contains('rc')
129 pg_version_arr = [pg_version.split('rc')[0], '0']
131 pg_version_arr = pg_version.split('.')
134 pg_version_major = pg_version_arr[0].to_int()
135 pg_version_minor = pg_version_arr[1].to_int()
136 pg_version_num = (pg_version_major * 10000) + pg_version_minor
138 pg_url = 'https://www.postgresql.org/'
140 cdata.set_quoted('PACKAGE_NAME', 'PostgreSQL')
141 cdata.set_quoted('PACKAGE_BUGREPORT', 'pgsql-bugs@lists.postgresql.org')
142 cdata.set_quoted('PACKAGE_URL', pg_url)
143 cdata.set_quoted('PACKAGE_VERSION', pg_version)
144 cdata.set_quoted('PACKAGE_STRING', 'PostgreSQL @0@'.format(pg_version))
145 cdata.set_quoted('PACKAGE_TARNAME', 'postgresql')
147 pg_version += get_option('extra_version')
148 cdata.set_quoted('PG_VERSION', pg_version)
149 cdata.set_quoted('PG_MAJORVERSION', pg_version_major.to_string())
150 cdata.set('PG_MAJORVERSION_NUM', pg_version_major)
151 cdata.set('PG_MINORVERSION_NUM', pg_version_minor)
152 cdata.set('PG_VERSION_NUM', pg_version_num)
153 # PG_VERSION_STR is built later, it depends on compiler test results
154 cdata.set_quoted('CONFIGURE_ARGS', '')
158 ###############################################################
159 # Basic platform specific configuration
160 ###############################################################
162 exesuffix = '' # overridden below where necessary
163 dlsuffix = '.so' # overridden below where necessary
164 library_path_var = 'LD_LIBRARY_PATH'
166 # Format of file to control exports from libraries, and how to pass them to
167 # the compiler. For export_fmt @0@ is the path to the file export file.
168 export_file_format = 'gnu'
169 export_file_suffix = 'list'
170 export_fmt = '-Wl,--version-script=@0@'
172 # Flags to add when linking a postgres extension, @0@ is path to
173 # the relevant object on the platform.
174 mod_link_args_fmt = []
176 memset_loop_limit = 1024
178 # Choice of shared memory and semaphore implementation
182 # We implement support for some operating systems by pretending they're
183 # another. Map here, before determining system properties below
184 if host_system == 'dragonfly'
185 # apparently the most similar
186 host_system = 'netbsd'
189 # meson's system names don't quite map to our "traditional" names. In some
190 # places we need the "traditional" name, e.g., for mapping
191 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
193 portname = host_system
195 if host_system == 'aix'
196 library_path_var = 'LIBPATH'
198 export_file_format = 'aix'
199 export_fmt = '-Wl,-bE:@0@'
200 mod_link_args_fmt = ['-Wl,-bI:@0@']
201 mod_link_with_dir = 'libdir'
202 mod_link_with_name = '@0@.imp'
204 # M:SRE sets a flag indicating that an object is a shared library. Seems to
205 # work in some circumstances without, but required in others.
206 ldflags_sl += '-Wl,-bM:SRE'
207 ldflags_be += '-Wl,-brtllib'
209 # Native memset() is faster, tested on:
210 # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
211 # - AIX 5.3 ML3, gcc 4.0.1
212 memset_loop_limit = 0
214 elif host_system == 'cygwin'
215 sema_kind = 'unnamed_posix'
216 cppflags += '-D_GNU_SOURCE'
218 mod_link_args_fmt = ['@0@']
219 mod_link_with_name = 'lib@0@.exe.a'
220 mod_link_with_dir = 'libdir'
222 elif host_system == 'darwin'
224 library_path_var = 'DYLD_LIBRARY_PATH'
226 export_file_format = 'darwin'
227 export_fmt = '-Wl,-exported_symbols_list,@0@'
229 mod_link_args_fmt = ['-bundle_loader', '@0@']
230 mod_link_with_dir = 'bindir'
231 mod_link_with_name = '@0@'
233 sysroot_args = [files('src/tools/darwin_sysroot'), get_option('darwin_sysroot')]
234 pg_sysroot = run_command(sysroot_args, check:true).stdout().strip()
235 message('darwin sysroot: @0@'.format(pg_sysroot))
237 cflags += ['-isysroot', pg_sysroot]
238 ldflags += ['-isysroot', pg_sysroot]
241 # meson defaults to -Wl,-undefined,dynamic_lookup for modules, which we
242 # don't want because a) it's different from what we do for autoconf, b) it
243 # causes warnings in macOS Ventura. But using -Wl,-undefined,error causes a
244 # warning starting in Sonoma. So only add -Wl,-undefined,error if it does
245 # not cause a warning.
246 if cc.has_multi_link_arguments('-Wl,-undefined,error', '-Werror')
247 ldflags_mod += '-Wl,-undefined,error'
250 # Starting in Sonoma, the linker warns about the same library being
251 # linked twice. Which can easily happen when multiple dependencies
252 # depend on the same library. Quiesce the ill considered warning.
253 ldflags += cc.get_supported_link_arguments('-Wl,-no_warn_duplicate_libraries')
255 elif host_system == 'freebsd'
256 sema_kind = 'unnamed_posix'
258 elif host_system == 'linux'
259 sema_kind = 'unnamed_posix'
260 cppflags += '-D_GNU_SOURCE'
262 elif host_system == 'netbsd'
263 # We must resolve all dynamic linking in the core server at program start.
264 # Otherwise the postmaster can self-deadlock due to signals interrupting
265 # resolution of calls, since NetBSD's linker takes a lock while doing that
266 # and some postmaster signal handlers do things that will also acquire that
267 # lock. As long as we need "-z now", might as well specify "-z relro" too.
268 # While there's not a hard reason to adopt these settings for our other
269 # executables, there's also little reason not to, so just add them to
271 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
273 elif host_system == 'openbsd'
276 elif host_system == 'sunos'
278 export_fmt = '-Wl,-M@0@'
279 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
281 elif host_system == 'windows'
285 library_path_var = ''
287 export_file_format = 'win'
288 export_file_suffix = 'def'
289 if cc.get_id() == 'msvc'
290 export_fmt = '/DEF:@0@'
291 mod_link_with_name = '@0@.exe.lib'
294 mod_link_with_name = 'lib@0@.exe.a'
296 mod_link_args_fmt = ['@0@']
297 mod_link_with_dir = 'libdir'
302 cdata.set('WIN32_STACK_RLIMIT', 4194304)
303 if cc.get_id() == 'msvc'
304 ldflags += '/INCREMENTAL:NO'
305 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
306 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
308 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
309 # Need to allow multiple definitions, we e.g. want to override getopt.
310 ldflags += '-Wl,--allow-multiple-definition'
311 # Ensure we get MSVC-like linking behavior.
312 ldflags += '-Wl,--disable-auto-import'
315 os_deps += cc.find_library('ws2_32', required: true)
316 secur32_dep = cc.find_library('secur32', required: true)
317 backend_deps += secur32_dep
318 libpq_deps += secur32_dep
320 postgres_inc_d += 'src/include/port/win32'
321 if cc.get_id() == 'msvc'
322 postgres_inc_d += 'src/include/port/win32_msvc'
325 windows = import('windows')
328 # XXX: Should we add an option to override the host_system as an escape
330 error('unknown host system: @0@'.format(host_system))
335 ###############################################################
337 ###############################################################
340 perl = find_program(get_option('PERL'), required: true, native: true)
341 python = find_program(get_option('PYTHON'), required: true, native: true)
342 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35')
343 bison = find_program(get_option('BISON'), native: true, version: '>= 2.3')
344 sed = find_program(get_option('SED'), 'sed', native: true)
345 prove = find_program(get_option('PROVE'), native: true, required: false)
346 tar = find_program(get_option('TAR'), native: true)
347 gzip = find_program(get_option('GZIP'), native: true)
348 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
349 openssl = find_program(get_option('OPENSSL'), native: true, required: false)
350 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
351 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
352 missing = find_program('config/missing', native: true)
353 cp = find_program('cp', required: false, native: true)
354 xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
355 xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
359 bison_version_c = run_command(bison, '--version', check: true)
360 # bison version string helpfully is something like
361 # >>bison (GNU bison) 3.8.1<<
362 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
363 if bison_version.version_compare('>=3.0')
364 bison_flags += ['-Wno-deprecated']
367 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
369 'output': ['@BASENAME@.c', '@BASENAME@.h'],
370 'command': bison_cmd,
374 flex_wrapper = files('src/tools/pgflex')
375 flex_cmd = [python, flex_wrapper,
376 '--builddir', '@BUILD_ROOT@',
377 '--srcdir', '@SOURCE_ROOT@',
378 '--privatedir', '@PRIVATE_DIR@',
379 '--flex', flex, '--perl', perl,
380 '-i', '@INPUT@', '-o', '@OUTPUT0@',
383 wget = find_program('wget', required: false, native: true)
384 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
386 install_files = files('src/tools/install_files')
390 ###############################################################
391 # Path to meson (for tests etc)
392 ###############################################################
394 # NB: this should really be part of meson, see
395 # https://github.com/mesonbuild/meson/issues/8511
396 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
398 if meson_binpath_r.stdout() == ''
399 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
400 meson_binpath_r.returncode(),
401 meson_binpath_r.stdout(),
402 meson_binpath_r.stderr()))
405 meson_binpath_s = meson_binpath_r.stdout().split('\n')
406 meson_binpath_len = meson_binpath_s.length()
408 if meson_binpath_len < 1
409 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
416 foreach e : meson_binpath_s
427 if meson_impl not in ['muon', 'meson']
428 error('unknown meson implementation "@0@"'.format(meson_impl))
431 meson_bin = find_program(meson_binpath, native: true)
435 ###############################################################
437 ###############################################################
439 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
441 blocksize = get_option('blocksize').to_int() * 1024
443 if get_option('segsize_blocks') != 0
444 if get_option('segsize') != 1
445 warning('both segsize and segsize_blocks specified, segsize_blocks wins')
448 segsize = get_option('segsize_blocks')
450 segsize = (get_option('segsize') * 1024 * 1024 * 1024) / blocksize
453 cdata.set('BLCKSZ', blocksize, description:
454 '''Size of a disk block --- this also limits the size of a tuple. You can set
455 it bigger if you need bigger tuples (although TOAST should reduce the need
456 to have large tuples, since fields can be spread across multiple tuples).
457 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
458 currently 2^15 (32768). This is determined by the 15-bit widths of the
459 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
460 Changing BLCKSZ requires an initdb.''')
462 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
463 cdata.set('RELSEG_SIZE', segsize)
464 cdata.set('DEF_PGPORT', get_option('pgport'))
465 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
466 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
467 if get_option('system_tzdata') != ''
468 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
473 ###############################################################
475 ###############################################################
477 # These are set by the equivalent --xxxdir configure options. We
478 # append "postgresql" to some of them, if the string does not already
479 # contain "pgsql" or "postgres", in order to avoid directory clutter.
483 dir_prefix = get_option('prefix')
485 dir_prefix_contains_pg = (dir_prefix.contains('pgsql') or dir_prefix.contains('postgres'))
487 dir_bin = get_option('bindir')
489 dir_data = get_option('datadir')
490 if not (dir_prefix_contains_pg or dir_data.contains('pgsql') or dir_data.contains('postgres'))
491 dir_data = dir_data / pkg
494 dir_sysconf = get_option('sysconfdir')
495 if not (dir_prefix_contains_pg or dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
496 dir_sysconf = dir_sysconf / pkg
499 dir_lib = get_option('libdir')
501 dir_lib_pkg = dir_lib
502 if not (dir_prefix_contains_pg or dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
503 dir_lib_pkg = dir_lib_pkg / pkg
506 dir_pgxs = dir_lib_pkg / 'pgxs'
508 dir_include = get_option('includedir')
510 dir_include_pkg = dir_include
511 dir_include_pkg_rel = ''
512 if not (dir_prefix_contains_pg or dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
513 dir_include_pkg = dir_include_pkg / pkg
514 dir_include_pkg_rel = pkg
517 dir_man = get_option('mandir')
519 # FIXME: These used to be separately configurable - worth adding?
520 dir_doc = get_option('datadir') / 'doc' / 'postgresql'
521 dir_doc_html = dir_doc / 'html'
523 dir_locale = get_option('localedir')
527 dir_bitcode = dir_lib_pkg / 'bitcode'
528 dir_include_internal = dir_include_pkg / 'internal'
529 dir_include_server = dir_include_pkg / 'server'
530 dir_include_extension = dir_include_server / 'extension'
531 dir_data_extension = dir_data / 'extension'
535 ###############################################################
536 # Search paths, preparation for compiler tests
538 # NB: Arguments added later are not automatically used for subsequent
539 # configuration-time checks (so they are more isolated). If they should be
540 # used, they need to be added to test_c_args as well.
541 ###############################################################
543 postgres_inc = [include_directories(postgres_inc_d)]
544 test_lib_d = postgres_lib_d
545 test_c_args = cppflags + cflags
549 ###############################################################
551 ###############################################################
553 bsd_authopt = get_option('bsd_auth')
554 bsd_auth = not_found_dep
555 if cc.check_header('bsd_auth.h', required: bsd_authopt,
556 args: test_c_args, include_directories: postgres_inc)
557 cdata.set('USE_BSD_AUTH', 1)
558 bsd_auth = declare_dependency()
563 ###############################################################
566 # For now don't search for DNSServiceRegister in a library - only Apple's
567 # Bonjour implementation, which is always linked, works.
568 ###############################################################
570 bonjouropt = get_option('bonjour')
571 bonjour = not_found_dep
572 if cc.check_header('dns_sd.h', required: bonjouropt,
573 args: test_c_args, include_directories: postgres_inc) and \
574 cc.has_function('DNSServiceRegister',
575 args: test_c_args, include_directories: postgres_inc)
576 cdata.set('USE_BONJOUR', 1)
577 bonjour = declare_dependency()
582 ###############################################################
583 # Option: docs in HTML and man page format
584 ###############################################################
586 docs_opt = get_option('docs')
587 docs_dep = not_found_dep
588 if not docs_opt.disabled()
589 if xmllint_bin.found() and xsltproc_bin.found()
590 docs_dep = declare_dependency()
591 elif docs_opt.enabled()
592 error('missing required tools for docs in HTML / man page format')
598 ###############################################################
599 # Option: docs in PDF format
600 ###############################################################
602 docs_pdf_opt = get_option('docs_pdf')
603 docs_pdf_dep = not_found_dep
604 if not docs_pdf_opt.disabled()
605 fop = find_program(get_option('FOP'), native: true, required: docs_pdf_opt)
606 if xmllint_bin.found() and xsltproc_bin.found() and fop.found()
607 docs_pdf_dep = declare_dependency()
608 elif docs_pdf_opt.enabled()
609 error('missing required tools for docs in PDF format')
615 ###############################################################
617 ###############################################################
619 gssapiopt = get_option('gssapi')
622 if not gssapiopt.disabled()
623 gssapi = dependency('krb5-gssapi', required: gssapiopt)
624 have_gssapi = gssapi.found()
627 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
628 args: test_c_args, include_directories: postgres_inc)
629 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
630 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
631 cdata.set('HAVE_GSSAPI_H', 1)
637 elif cc.check_header('gssapi/gssapi_ext.h', dependencies: gssapi, required: false,
638 args: test_c_args, include_directories: postgres_inc)
639 cdata.set('HAVE_GSSAPI_GSSAPI_EXT_H', 1)
640 elif cc.check_header('gssapi_ext.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
641 cdata.set('HAVE_GSSAPI_EXT_H', 1)
647 elif cc.has_function('gss_store_cred_into', dependencies: gssapi,
648 args: test_c_args, include_directories: postgres_inc)
649 cdata.set('ENABLE_GSS', 1)
651 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
652 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
653 elif gssapiopt.enabled()
654 error('''could not find function 'gss_store_cred_into' required for GSSAPI''')
660 gssapi = not_found_dep
665 ###############################################################
667 ###############################################################
669 ldapopt = get_option('ldap')
670 if ldapopt.disabled()
672 ldap_r = not_found_dep
673 elif host_system == 'windows'
674 ldap = cc.find_library('wldap32', required: ldapopt)
677 # macos framework dependency is buggy for ldap (one can argue whether it's
678 # Apple's or meson's fault), leading to an endless recursion with ldap.h
679 # including itself. See https://github.com/mesonbuild/meson/issues/10002
680 # Luckily we only need pkg-config support, so the workaround isn't
682 ldap = dependency('ldap', method: 'pkg-config', required: false)
685 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
688 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
689 has_headers: 'ldap.h', header_include_directories: postgres_inc)
691 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
692 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
693 # library from a separate OpenLDAP installation). The most reliable
694 # way to check that is to check for a function introduced in 2.5.
696 # don't have ldap, we shouldn't check for ldap_r
697 elif cc.has_function('ldap_verify_credentials',
698 dependencies: ldap, args: test_c_args)
699 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
702 # Use ldap_r for FE if available, else assume ldap is thread-safe.
703 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
704 has_headers: 'ldap.h', header_include_directories: postgres_inc)
705 if not ldap_r.found()
708 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
709 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
712 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
713 # process. Check for OpenLDAP versions known not to tolerate doing so;
714 # assume non-OpenLDAP implementations are safe. The dblink test suite
715 # exercises the hazardous interaction directly.
716 compat_test_code = '''
718 #if !defined(LDAP_VENDOR_VERSION) || \
719 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
720 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
724 if not cc.compiles(compat_test_code,
725 name: 'LDAP implementation compatible',
726 dependencies: ldap, args: test_c_args)
728 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
729 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
730 *** also uses LDAP will crash on exit.''')
735 if ldap.found() and cc.has_function('ldap_initialize',
736 dependencies: ldap, args: test_c_args)
737 cdata.set('HAVE_LDAP_INITIALIZE', 1)
742 assert(ldap_r.found())
743 cdata.set('USE_LDAP', 1)
745 assert(not ldap_r.found())
750 ###############################################################
752 ###############################################################
754 llvmopt = get_option('llvm')
756 if add_languages('cpp', required: llvmopt, native: false)
757 llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
761 cdata.set('USE_LLVM', 1)
763 cpp = meson.get_compiler('cpp')
765 llvm_binpath = llvm.get_variable(configtool: 'bindir')
767 ccache = find_program('ccache', native: true, required: false)
768 clang = find_program(llvm_binpath / 'clang', required: true)
771 message('llvm requires a C++ compiler')
776 ###############################################################
778 ###############################################################
780 icuopt = get_option('icu')
781 if not icuopt.disabled()
782 icu = dependency('icu-uc', required: icuopt)
783 icu_i18n = dependency('icu-i18n', required: icuopt)
786 cdata.set('USE_ICU', 1)
791 icu_i18n = not_found_dep
796 ###############################################################
798 ###############################################################
800 libxmlopt = get_option('libxml')
801 if not libxmlopt.disabled()
802 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
805 cdata.set('USE_LIBXML', 1)
808 libxml = not_found_dep
813 ###############################################################
815 ###############################################################
817 libxsltopt = get_option('libxslt')
818 if not libxsltopt.disabled()
819 libxslt = dependency('libxslt', required: libxsltopt)
822 cdata.set('USE_LIBXSLT', 1)
825 libxslt = not_found_dep
830 ###############################################################
832 ###############################################################
834 lz4opt = get_option('lz4')
835 if not lz4opt.disabled()
836 lz4 = dependency('liblz4', required: lz4opt)
839 cdata.set('USE_LZ4', 1)
840 cdata.set('HAVE_LIBLZ4', 1)
849 ###############################################################
850 # Library: Tcl (for pltcl)
852 # NB: tclConfig.sh is used in autoconf build for getting
853 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
854 # variables. For now we have not seen a need to copy
855 # that behaviour to the meson build.
856 ###############################################################
858 tclopt = get_option('pltcl')
859 tcl_version = get_option('tcl_version')
860 tcl_dep = not_found_dep
861 if not tclopt.disabled()
864 tcl_dep = dependency(tcl_version, required: false)
866 if not tcl_dep.found()
867 tcl_dep = cc.find_library(tcl_version,
872 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
873 tcl_dep = not_found_dep
879 ###############################################################
881 ###############################################################
883 pamopt = get_option('pam')
884 if not pamopt.disabled()
885 pam = dependency('pam', required: false)
888 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
892 pam_header_found = false
894 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
895 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
896 args: test_c_args, include_directories: postgres_inc)
897 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
898 pam_header_found = true
899 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
900 args: test_c_args, include_directories: postgres_inc)
901 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
902 pam_header_found = true
906 cdata.set('USE_PAM', 1)
917 ###############################################################
918 # Library: Perl (for plperl)
919 ###############################################################
921 perlopt = get_option('plperl')
922 perl_dep = not_found_dep
923 if not perlopt.disabled()
926 # First verify that perl has the necessary dependencies installed
927 perl_mods = run_command(
929 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
932 if perl_mods.returncode() != 0
933 perl_may_work = false
934 perl_msg = 'perl installation does not have the required modules'
937 # Then inquire perl about its configuration
939 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
940 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
941 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
942 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
943 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
945 perl_inc_dir = '@0@/CORE'.format(archlibexp)
947 if perlversion.version_compare('< 5.14')
948 perl_may_work = false
949 perl_msg = 'Perl version 5.14 or later is required, but this is @0@'.format(perlversion)
950 elif useshrplib != 'true'
951 perl_may_work = false
952 perl_msg = 'need a shared perl'
957 # On most platforms, archlibexp is also where the Perl include files live ...
958 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
959 # ... but on newer macOS versions, we must use -iwithsysroot to look
961 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
962 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
963 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
966 # check compiler finds header
967 if not cc.has_header('perl.h', required: false,
968 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
969 perl_may_work = false
970 perl_msg = 'missing perl.h'
975 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
977 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
978 foreach flag : perl_ccflags_r.split(' ')
979 if flag.startswith('-D') and \
980 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
985 if host_system == 'windows'
986 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
988 if cc.get_id() == 'msvc'
989 # prevent binary mismatch between MSVC built plperl and Strawberry or
990 # msys ucrt perl libraries
991 perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE']
995 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
996 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
998 # We are after Embed's ldopts, but without the subset mentioned in
999 # Config's ccdlflags and ldflags. (Those are the choices of those who
1000 # built the Perl installation, which are not necessarily appropriate
1001 # for building PostgreSQL.)
1002 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
1003 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
1004 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
1007 foreach ldopt : ldopts.split(' ')
1008 if ldopt == '' or ldopt in undesired
1012 perl_ldopts += ldopt.strip('"')
1015 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
1016 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
1018 perl_dep_int = declare_dependency(
1019 compile_args: perl_ccflags,
1020 link_args: perl_ldopts,
1021 version: perlversion,
1024 # While we're at it, check that we can link to libperl.
1025 # On most platforms, if perl.h is there then libperl.so will be too, but
1026 # at this writing Debian packages them separately.
1027 perl_link_test = '''
1030 #define __inline__ inline
1038 if not cc.links(perl_link_test, name: 'libperl',
1039 args: test_c_args + perl_ccflags + perl_ldopts,
1040 include_directories: postgres_inc)
1041 perl_may_work = false
1042 perl_msg = 'missing libperl'
1045 endif # perl_may_work
1048 perl_dep = perl_dep_int
1050 if perlopt.enabled()
1051 error('dependency plperl failed: @0@'.format(perl_msg))
1053 message('disabling optional dependency plperl: @0@'.format(perl_msg))
1060 ###############################################################
1061 # Library: Python (for plpython)
1062 ###############################################################
1064 pyopt = get_option('plpython')
1065 python3_dep = not_found_dep
1066 if not pyopt.disabled()
1067 pm = import('python')
1068 python3_inst = pm.find_installation(python.path(), required: pyopt)
1069 if python3_inst.found()
1070 python3_dep = python3_inst.dependency(embed: true, required: pyopt)
1071 # Remove this check after we depend on Meson >= 1.1.0
1072 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt)
1073 python3_dep = not_found_dep
1080 ###############################################################
1082 ###############################################################
1084 if not get_option('readline').disabled()
1085 libedit_preferred = get_option('libedit_preferred')
1086 # Set the order of readline dependencies
1087 check_readline_deps = libedit_preferred ? \
1088 ['libedit', 'readline'] : ['readline', 'libedit']
1090 foreach readline_dep : check_readline_deps
1091 readline = dependency(readline_dep, required: false)
1092 if not readline.found()
1093 readline = cc.find_library(readline_dep,
1094 required: get_option('readline'),
1103 cdata.set('HAVE_LIBREADLINE', 1)
1106 'header_prefix': 'editline/',
1107 'flag_prefix': 'EDITLINE_',
1110 'header_prefix': 'readline/',
1111 'flag_prefix': 'READLINE_',
1114 'header_prefix': '',
1118 # Set the order of prefixes
1119 prefixes = libedit_preferred ? \
1120 [editline_prefix, default_prefix, readline_prefix] : \
1121 [readline_prefix, default_prefix, editline_prefix]
1123 at_least_one_header_found = false
1124 foreach header : ['history', 'readline']
1126 foreach prefix : prefixes
1127 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1128 # Check history.h and readline.h
1129 if not is_found and cc.has_header(header_file,
1130 args: test_c_args, include_directories: postgres_inc,
1131 dependencies: [readline], required: false)
1132 if header == 'readline'
1133 readline_h = header_file
1135 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1137 at_least_one_header_found = true
1142 if not at_least_one_header_found
1143 error('''readline header not found
1144 If you have @0@ already installed, see meson-logs/meson-log.txt for details on the
1145 failure. It is possible the compiler isn't looking in the proper directory.
1146 Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
1151 'history_truncate_file',
1152 'rl_completion_matches',
1153 'rl_filename_completion_function',
1154 'rl_reset_screen_size',
1158 foreach func : check_funcs
1159 found = cc.has_function(func, dependencies: [readline],
1160 args: test_c_args, include_directories: postgres_inc)
1161 cdata.set('HAVE_' + func.to_upper(), found ? 1 : false)
1165 'rl_completion_suppress_quote',
1166 'rl_filename_quote_characters',
1167 'rl_filename_quoting_function',
1170 foreach var : check_vars
1171 cdata.set('HAVE_' + var.to_upper(),
1172 cc.has_header_symbol(readline_h, var,
1173 args: test_c_args, include_directories: postgres_inc,
1174 prefix: '#include <stdio.h>',
1175 dependencies: [readline]) ? 1 : false)
1178 # If found via cc.find_library() ensure headers are found when using the
1179 # dependency. On meson < 0.57 one cannot do compiler checks using the
1180 # dependency returned by declare_dependency(), so we can't do this above.
1181 if readline.type_name() == 'library'
1182 readline = declare_dependency(dependencies: readline,
1183 include_directories: postgres_inc)
1186 # On windows with mingw readline requires auto-import to successfully
1187 # link, as the headers don't use declspec(dllimport)
1188 if host_system == 'windows' and cc.get_id() != 'msvc'
1189 readline = declare_dependency(dependencies: readline,
1190 link_args: '-Wl,--enable-auto-import')
1194 # XXX: Figure out whether to implement mingw warning equivalent
1196 readline = not_found_dep
1201 ###############################################################
1203 ###############################################################
1205 selinux = not_found_dep
1206 selinuxopt = get_option('selinux')
1207 if meson.version().version_compare('>=0.59')
1208 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1210 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1211 cdata.set('HAVE_LIBSELINUX',
1212 selinux.found() ? 1 : false)
1216 ###############################################################
1218 ###############################################################
1220 systemd = not_found_dep
1221 systemdopt = get_option('systemd')
1222 if meson.version().version_compare('>=0.59')
1223 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1225 systemd = dependency('libsystemd', required: systemdopt)
1226 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1230 ###############################################################
1232 ###############################################################
1235 ssl_library = 'none'
1236 sslopt = get_option('ssl')
1238 if sslopt == 'auto' and auto_features.disabled()
1242 if sslopt in ['auto', 'openssl']
1243 openssl_required = (sslopt == 'openssl')
1245 # Try to find openssl via pkg-config et al, if that doesn't work
1246 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1247 # the library names that we know about.
1249 # via pkg-config et al
1250 ssl = dependency('openssl', required: false)
1251 # only meson >= 0.57 supports declare_dependency() in cc.has_function(), so
1252 # we pass cc.find_library() results if necessary
1255 # via library + headers
1257 ssl_lib = cc.find_library('ssl',
1259 header_include_directories: postgres_inc,
1260 has_headers: ['openssl/ssl.h', 'openssl/err.h'],
1261 required: openssl_required)
1262 crypto_lib = cc.find_library('crypto',
1264 required: openssl_required)
1265 if ssl_lib.found() and crypto_lib.found()
1266 ssl_int = [ssl_lib, crypto_lib]
1267 ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc)
1269 elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \
1270 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required)
1278 ['CRYPTO_new_ex_data', {'required': true}],
1279 ['SSL_new', {'required': true}],
1281 # Functions introduced in OpenSSL 1.0.2.
1282 ['X509_get_signature_nid'],
1283 ['SSL_CTX_set_cert_cb'], # not in LibreSSL
1285 # Functions introduced in OpenSSL 1.1.0. We used to check for
1286 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1287 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1288 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1290 ['OPENSSL_init_ssl'],
1292 ['ASN1_STRING_get0_data'],
1296 # OpenSSL versions before 1.1.0 required setting callback functions, for
1297 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1298 # function was removed.
1301 # Function introduced in OpenSSL 1.1.1
1302 ['X509_get_signature_info'],
1305 are_openssl_funcs_complete = true
1306 foreach c : check_funcs
1308 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1309 required = c.get(1, {}).get('required', false)
1310 if required and not val
1311 are_openssl_funcs_complete = false
1313 error('openssl function @0@ is required'.format(func))
1317 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1321 if are_openssl_funcs_complete
1322 cdata.set('USE_OPENSSL', 1,
1323 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1324 cdata.set('OPENSSL_API_COMPAT', '0x10001000L',
1325 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
1326 ssl_library = 'openssl'
1333 if sslopt == 'auto' and auto_features.enabled() and not ssl.found()
1334 error('no SSL library found')
1339 ###############################################################
1341 ###############################################################
1343 uuidopt = get_option('uuid')
1344 if uuidopt != 'none'
1345 uuidname = uuidopt.to_upper()
1346 if uuidopt == 'e2fs'
1347 uuid = dependency('uuid', required: true)
1348 uuidfunc = 'uuid_generate'
1349 uuidheader = 'uuid/uuid.h'
1350 elif uuidopt == 'bsd'
1351 # libc should have uuid function
1352 uuid = declare_dependency()
1353 uuidfunc = 'uuid_to_string'
1354 uuidheader = 'uuid.h'
1355 elif uuidopt == 'ossp'
1356 uuid = dependency('ossp-uuid', required: true)
1357 uuidfunc = 'uuid_export'
1358 uuidheader = 'uuid.h'
1360 error('unknown uuid build option value: @0@'.format(uuidopt))
1363 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1364 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1366 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1368 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1369 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1371 uuid = not_found_dep
1376 ###############################################################
1378 ###############################################################
1380 zlibopt = get_option('zlib')
1381 zlib = not_found_dep
1382 if not zlibopt.disabled()
1383 zlib_t = dependency('zlib', required: zlibopt)
1385 if zlib_t.type_name() == 'internal'
1386 # if fallback was used, we don't need to test if headers are present (they
1387 # aren't built yet, so we can't test)
1389 elif not zlib_t.found()
1390 warning('did not find zlib')
1391 elif not cc.has_header('zlib.h',
1392 args: test_c_args, include_directories: postgres_inc,
1393 dependencies: [zlib_t], required: zlibopt)
1394 warning('zlib header not found')
1395 elif not cc.has_type('z_streamp',
1396 dependencies: [zlib_t], prefix: '#include <zlib.h>',
1397 args: test_c_args, include_directories: postgres_inc)
1398 if zlibopt.enabled()
1399 error('zlib version is too old')
1401 warning('zlib version is too old')
1408 cdata.set('HAVE_LIBZ', 1)
1414 ###############################################################
1415 # Library: tap test dependencies
1416 ###############################################################
1418 # Check whether tap tests are enabled or not
1419 tap_tests_enabled = false
1420 tapopt = get_option('tap_tests')
1421 if not tapopt.disabled()
1422 # Checking for perl modules for tap tests
1423 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1424 if perl_ipc_run_check.returncode() != 0
1425 message(perl_ipc_run_check.stderr().strip())
1427 error('Additional Perl modules are required to run TAP tests.')
1429 warning('Additional Perl modules are required to run TAP tests.')
1432 tap_tests_enabled = true
1438 ###############################################################
1440 ###############################################################
1442 zstdopt = get_option('zstd')
1443 if not zstdopt.disabled()
1444 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1447 cdata.set('USE_ZSTD', 1)
1448 cdata.set('HAVE_LIBZSTD', 1)
1452 zstd = not_found_dep
1457 ###############################################################
1459 ###############################################################
1461 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1462 # unnecessarily, because we optionally rely on newer features.
1464 #include <stdbool.h>
1465 #include <complex.h>
1467 #include <inttypes.h>
1469 struct named_init_test {
1474 extern void structfunc(struct named_init_test);
1476 int main(int argc, char **argv)
1478 struct named_init_test nit = {
1483 for (int loop_var = 0; loop_var < 3; loop_var++)
1488 structfunc((struct named_init_test){1, 0});
1494 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1495 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1496 args: test_c_args + ['-std=c99'])
1497 test_c_args += '-std=c99'
1498 cflags += '-std=c99'
1500 error('C compiler does not support C99')
1504 sizeof_long = cc.sizeof('long', args: test_c_args)
1505 cdata.set('SIZEOF_LONG', sizeof_long)
1507 cdata.set('HAVE_LONG_INT_64', 1)
1508 cdata.set('PG_INT64_TYPE', 'long int')
1509 cdata.set_quoted('INT64_MODIFIER', 'l')
1510 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1511 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1512 cdata.set('PG_INT64_TYPE', 'long long int')
1513 cdata.set_quoted('INT64_MODIFIER', 'll')
1515 error('do not know how to get a 64bit int')
1518 if host_machine.endian() == 'big'
1519 cdata.set('WORDS_BIGENDIAN', 1)
1522 alignof_types = ['short', 'int', 'long', 'double']
1524 foreach t : alignof_types
1525 align = cc.alignment(t, args: test_c_args)
1529 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1531 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1533 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1534 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1537 # Check if __int128 is a working 128 bit integer type, and if so
1538 # define PG_INT128_TYPE to that typename.
1540 # This currently only detects a GCC/clang extension, but support for other
1541 # environments may be added in the future.
1543 # For the moment we only test for support for 128bit math; support for
1544 # 128bit literals and snprintf is not required.
1547 * We don't actually run this test, just link it to verify that any support
1548 * functions needed for __int128 are present.
1550 * These are globals to discourage the compiler from folding all the
1551 * arithmetic tests down to compile-time constants. We do not have
1552 * convenient support for 128bit literals at this point...
1554 __int128 a = 48828125;
1555 __int128 b = 97656250;
1560 a = (a << 12) + 1; /* 200000000001 */
1561 b = (b << 12) + 5; /* 400000000005 */
1562 /* try the most relevant arithmetic ops */
1565 /* must use the results, else compiler may optimize arithmetic away */
1571 buggy_int128 = false
1573 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1574 # If not cross-compiling, we can test for bugs and disable use of __int128
1575 # with buggy compilers. If cross-compiling, hope for the best.
1576 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1577 if not meson.is_cross_build()
1579 /* This must match the corresponding code in c.h: */
1580 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1581 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1582 #elif defined(_MSC_VER)
1583 #define pg_attribute_aligned(a) __declspec(align(a))
1585 typedef __int128 int128a
1586 #if defined(pg_attribute_aligned)
1587 pg_attribute_aligned(8)
1592 void pass_by_val(void *buffer, int128a par) { holder = par; }
1596 long int i64 = 97656225L << 12;
1598 pass_by_val(main, (int128a) i64);
1602 name: '__int128 alignment bug',
1604 assert(r.compiled())
1605 if r.returncode() != 0
1607 message('__int128 support present but buggy and thus disabled')
1612 cdata.set('PG_INT128_TYPE', '__int128')
1613 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.alignment('__int128', args: test_c_args))
1618 # Check if the C compiler knows computed gotos (gcc extension, also
1619 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1621 # Checking whether computed gotos are supported syntax-wise ought to
1622 # be enough, as the syntax is otherwise illegal.
1624 static inline int foo(void)
1626 void *labeladdrs[] = {&&my_label};
1627 goto *labeladdrs[0];
1632 cdata.set('HAVE_COMPUTED_GOTO', 1)
1636 # Check if the C compiler understands _Static_assert(),
1637 # and define HAVE__STATIC_ASSERT if so.
1639 # We actually check the syntax ({ _Static_assert(...) }), because we need
1640 # gcc-style compound expressions to be able to wrap the thing into macros.
1642 int main(int arg, char **argv)
1644 ({ _Static_assert(1, "foo"); });
1648 cdata.set('HAVE__STATIC_ASSERT', 1)
1652 # We use <stdbool.h> if we have it and it declares type bool as having
1653 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1654 if cc.has_type('_Bool', args: test_c_args) \
1655 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1656 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1657 cdata.set('HAVE__BOOL', 1)
1658 cdata.set('PG_USE_STDBOOL', 1)
1662 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1663 # warning for each use of %m.
1664 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1666 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1667 static void call_log(void)
1669 emit_log(0, "error: %s: %m", "foo");
1672 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1673 foreach a : printf_attributes
1674 if cc.compiles(testsrc.format(a),
1675 args: test_c_args + attrib_error_args, name: 'format ' + a)
1676 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1682 if cc.has_function_attribute('visibility:default') and \
1683 cc.has_function_attribute('visibility:hidden')
1684 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1686 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1687 # inlineshidden to C code as well... And either way, we want to put these
1688 # flags into exported files (pgxs, .pc files).
1689 cflags_mod += '-fvisibility=hidden'
1690 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1691 ldflags_mod += '-fvisibility=hidden'
1695 # Check if various builtins exist. Some builtins are tested separately,
1696 # because we want to test something more complicated than the generic case.
1709 foreach builtin : builtins
1710 fname = '__builtin_@0@'.format(builtin)
1711 if cc.has_function(fname, args: test_c_args)
1712 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1717 # Check if the C compiler understands __builtin_types_compatible_p,
1718 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1720 # We check usage with __typeof__, though it's unlikely any compiler would
1721 # have the former and not the latter.
1724 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1726 name: '__builtin_types_compatible_p',
1728 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1732 # Check if the C compiler understands __builtin_$op_overflow(),
1733 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1735 # Check for the most complicated case, 64 bit multiplication, as a
1736 # proxy for all of the operations. To detect the case where the compiler
1737 # knows the function but library support is missing, we must link not just
1738 # compile, and store the results in global variables so the compiler doesn't
1739 # optimize away the call.
1747 return __builtin_mul_overflow(a, b, &result);
1749 name: '__builtin_mul_overflow',
1750 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1752 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1756 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1757 # here. To prevent problems due to two detection methods working, stop
1758 # checking after one.
1761 int main(int arg, char **argv)
1763 unsigned int exx[4] = {0, 0, 0, 0};
1764 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1766 ''', name: '__get_cpuid',
1768 cdata.set('HAVE__GET_CPUID', 1)
1771 int main(int arg, char **argv)
1773 unsigned int exx[4] = {0, 0, 0, 0};
1776 ''', name: '__cpuid',
1778 cdata.set('HAVE__CPUID', 1)
1782 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1783 # versions of clang do not understand -fexcess-precision=standard, the use of
1784 # x87 floating point operations leads to problems like isinf possibly returning
1785 # false for a value that is infinite when converted from the 80bit register to
1786 # the 8byte memory representation.
1788 # Only perform the test if the compiler doesn't understand
1789 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1791 if '-fexcess-precision=standard' not in cflags
1792 if not cc.compiles('''
1793 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1796 name: '', args: test_c_args)
1797 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1803 ###############################################################
1805 ###############################################################
1807 common_functional_flags = [
1808 # Disable strict-aliasing rules; needed for gcc 3.3+
1809 '-fno-strict-aliasing',
1810 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1812 '-fexcess-precision=standard',
1815 cflags += cc.get_supported_arguments(common_functional_flags)
1817 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1820 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1821 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1823 common_warning_flags = [
1824 '-Wmissing-prototypes',
1826 # Really don't want VLAs to be used in our dialect of C
1828 # On macOS, complain about usage of symbols newer than the deployment target
1829 '-Werror=unguarded-availability-new',
1831 '-Wmissing-format-attribute',
1832 '-Wimplicit-fallthrough=3',
1833 '-Wcast-function-type',
1834 '-Wshadow=compatible-local',
1835 # This was included in -Wall/-Wformat in older GCC versions
1836 '-Wformat-security',
1839 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1841 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1844 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1845 # the result for them
1846 cflags_no_decl_after_statement = []
1847 if cc.has_argument('-Wdeclaration-after-statement')
1848 cflags_warn += '-Wdeclaration-after-statement'
1849 cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
1853 # The following tests want to suppress various unhelpful warnings by adding
1854 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1855 # switches, so we have to test for the positive form and if that works,
1856 # add the negative form.
1858 negative_warning_flags = [
1859 # Suppress clang's unhelpful unused-command-line-argument warnings.
1860 'unused-command-line-argument',
1862 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1863 # of warnings when building plperl because of usages in the Perl headers.
1864 'compound-token-split-by-macro',
1866 # Similarly disable useless truncation warnings from gcc 8+
1867 'format-truncation',
1868 'stringop-truncation',
1870 # Suppress clang 16's strict warnings about function casts
1871 'cast-function-type-strict',
1873 # To make warning_level=2 / -Wextra work, we'd need at least the following
1875 # 'missing-field-initializers',
1877 # 'unused-parameter',
1880 foreach w : negative_warning_flags
1881 if cc.has_argument('-W' + w)
1882 cflags_warn += '-Wno-' + w
1884 if llvm.found() and cpp.has_argument('-W' + w)
1885 cxxflags_warn += '-Wno-' + w
1891 if cc.get_id() == 'msvc'
1893 '/wd4018', # signed/unsigned mismatch
1894 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1895 '/wd4273', # inconsistent DLL linkage
1896 '/wd4101', # unreferenced local variable
1897 '/wd4102', # unreferenced label
1898 '/wd4090', # different 'modifier' qualifiers
1899 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1907 '/D_CRT_SECURE_NO_DEPRECATE',
1908 '/D_CRT_NONSTDC_NO_DEPRECATE',
1911 # We never need export libraries. As link.exe reports their creation, they
1912 # are unnecessarily noisy. Similarly, we don't need import library for
1913 # modules, we only import them dynamically, and they're also noisy.
1915 ldflags_mod += '/NOIMPLIB'
1920 ###############################################################
1922 ###############################################################
1924 if not get_option('spinlocks')
1925 warning('Not using spinlocks will cause poor performance')
1927 cdata.set('HAVE_SPINLOCKS', 1)
1930 if not get_option('atomics')
1931 warning('Not using atomics will cause poor performance')
1933 # XXX: perhaps we should require some atomics support in this case these
1935 cdata.set('HAVE_ATOMICS', 1)
1938 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
1939 'desc': '__sync_lock_test_and_set(char)',
1942 __sync_lock_test_and_set(&lock, 1);
1943 __sync_lock_release(&lock);'''},
1945 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
1946 'desc': '__sync_lock_test_and_set(int32)',
1949 __sync_lock_test_and_set(&lock, 1);
1950 __sync_lock_release(&lock);'''},
1952 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
1953 'desc': '__sync_val_compare_and_swap(int32)',
1956 __sync_val_compare_and_swap(&val, 0, 37);'''},
1958 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
1959 'desc': '__sync_val_compare_and_swap(int64)',
1962 __sync_val_compare_and_swap(&val, 0, 37);'''},
1964 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
1965 'desc': ' __atomic_compare_exchange_n(int32)',
1969 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1971 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
1972 'desc': ' __atomic_compare_exchange_n(int64)',
1976 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1979 foreach check : atomic_checks
1984 }'''.format(check['test'])
1986 cdata.set(check['name'],
1988 name: check['desc'],
1989 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
1997 ###############################################################
1998 # Select CRC-32C implementation.
2000 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
2001 # use the special CRC instructions for calculating CRC-32C. If we're not
2002 # targeting such a processor, but we can nevertheless produce code that uses
2003 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
2004 # implementations and select which one to use at runtime, depending on whether
2005 # SSE 4.2 is supported by the processor we're running on.
2007 # Similarly, if we are targeting an ARM processor that has the CRC
2008 # instructions that are part of the ARMv8 CRC Extension, use them. And if
2009 # we're not targeting such a processor, but can nevertheless produce code that
2010 # uses the CRC instructions, compile both, and select at runtime.
2011 ###############################################################
2013 have_optimized_crc = false
2015 if host_cpu == 'x86' or host_cpu == 'x86_64'
2017 if cc.get_id() == 'msvc'
2018 cdata.set('USE_SSE42_CRC32C', false)
2019 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2020 have_optimized_crc = true
2024 #include <nmmintrin.h>
2028 unsigned int crc = 0;
2029 crc = _mm_crc32_u8(crc, 0);
2030 crc = _mm_crc32_u32(crc, 0);
2031 /* return computed value, to prevent the above being optimized away */
2036 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
2038 # Use Intel SSE 4.2 unconditionally.
2039 cdata.set('USE_SSE42_CRC32C', 1)
2040 have_optimized_crc = true
2041 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
2042 args: test_c_args + ['-msse4.2'])
2043 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
2044 # the runtime check.
2045 cflags_crc += '-msse4.2'
2046 cdata.set('USE_SSE42_CRC32C', false)
2047 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2048 have_optimized_crc = true
2053 elif host_cpu == 'arm' or host_cpu == 'aarch64'
2056 #include <arm_acle.h>
2060 unsigned int crc = 0;
2061 crc = __crc32cb(crc, 0);
2062 crc = __crc32ch(crc, 0);
2063 crc = __crc32cw(crc, 0);
2064 crc = __crc32cd(crc, 0);
2066 /* return computed value, to prevent the above being optimized away */
2071 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
2073 # Use ARM CRC Extension unconditionally
2074 cdata.set('USE_ARMV8_CRC32C', 1)
2075 have_optimized_crc = true
2076 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
2077 args: test_c_args + ['-march=armv8-a+crc'])
2078 # Use ARM CRC Extension, with runtime check
2079 cflags_crc += '-march=armv8-a+crc'
2080 cdata.set('USE_ARMV8_CRC32C', false)
2081 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
2082 have_optimized_crc = true
2086 if not have_optimized_crc
2087 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
2089 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
2094 ###############################################################
2095 # Other CPU specific stuff
2096 ###############################################################
2098 if host_cpu == 'x86_64'
2103 long long x = 1; long long r;
2104 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
2106 name: '@0@: popcntq instruction'.format(host_cpu),
2108 cdata.set('HAVE_X86_64_POPCNTQ', 1)
2111 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
2112 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
2113 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
2116 addi(int ra, int si)
2119 if (__builtin_constant_p(si))
2120 __asm__ __volatile__(
2121 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
2124 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2127 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2134 ###############################################################
2135 # Library / OS tests
2136 ###############################################################
2138 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2139 # unnecessary checks over and over, particularly on windows.
2153 'sys/personality.h',
2162 foreach header : header_checks
2163 varname = 'HAVE_' + header.underscorify().to_upper()
2165 # Emulate autoconf behaviour of not-found->undef, found->1
2166 found = cc.has_header(header,
2167 include_directories: postgres_inc, args: test_c_args)
2168 cdata.set(varname, found ? 1 : false,
2169 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2174 ['F_FULLFSYNC', 'fcntl.h'],
2175 ['fdatasync', 'unistd.h'],
2176 ['posix_fadvise', 'fcntl.h'],
2177 ['strlcat', 'string.h'],
2178 ['strlcpy', 'string.h'],
2179 ['strnlen', 'string.h'],
2182 # Need to check for function declarations for these functions, because
2183 # checking for library symbols wouldn't handle deployment target
2184 # restrictions on macOS
2186 ['preadv', 'sys/uio.h'],
2187 ['pwritev', 'sys/uio.h'],
2190 foreach c : decl_checks
2194 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2196 found = cc.has_header_symbol(header, func,
2197 args: test_c_args, include_directories: postgres_inc,
2199 cdata.set10(varname, found, description:
2200 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2201 don't.'''.format(func))
2205 if cc.has_type('struct option',
2206 args: test_c_args, include_directories: postgres_inc,
2207 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2208 cdata.set('HAVE_STRUCT_OPTION', 1)
2212 foreach c : ['opterr', 'optreset']
2213 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2222 '''.format(c), name: c, args: test_c_args)
2223 cdata.set(varname, 1)
2225 cdata.set(varname, false)
2229 if cc.has_type('socklen_t',
2230 args: test_c_args, include_directories: postgres_inc,
2232 #include <sys/socket.h>''')
2233 cdata.set('HAVE_SOCKLEN_T', 1)
2236 if cc.has_member('struct sockaddr', 'sa_len',
2237 args: test_c_args, include_directories: postgres_inc,
2239 #include <sys/types.h>
2240 #include <sys/socket.h>''')
2241 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2244 if cc.has_member('struct tm', 'tm_zone',
2245 args: test_c_args, include_directories: postgres_inc,
2247 #include <sys/types.h>
2250 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2255 extern int foo(void);
2258 return timezone / 60;
2261 name: 'global variable `timezone\' exists',
2262 args: test_c_args, include_directories: postgres_inc)
2263 cdata.set('HAVE_INT_TIMEZONE', 1)
2265 cdata.set('HAVE_INT_TIMEZONE', false)
2268 if cc.has_type('union semun',
2270 include_directories: postgres_inc,
2272 #include <sys/types.h>
2273 #include <sys/ipc.h>
2274 #include <sys/sem.h>
2276 cdata.set('HAVE_UNION_SEMUN', 1)
2284 switch (strerror_r(1, buf, sizeof(buf)))
2285 { case 0: break; default: break; }
2288 args: test_c_args, include_directories: postgres_inc)
2289 cdata.set('STRERROR_R_INT', 1)
2291 cdata.set('STRERROR_R_INT', false)
2294 # Check for the locale_t type and find the right header file. macOS
2295 # needs xlocale.h; standard is locale.h, but glibc also has an
2296 # xlocale.h file that we should not use. MSVC has a replacement
2297 # defined in src/include/port/win32_port.h.
2298 if cc.has_type('locale_t', prefix: '#include <locale.h>')
2299 cdata.set('HAVE_LOCALE_T', 1)
2300 elif cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2301 cdata.set('HAVE_LOCALE_T', 1)
2302 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2303 elif cc.get_id() == 'msvc'
2304 cdata.set('HAVE_LOCALE_T', 1)
2307 # Check if the C compiler understands typeof or a variant. Define
2308 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2309 foreach kw : ['typeof', '__typeof__', 'decltype']
2320 args: test_c_args, include_directories: postgres_inc)
2322 cdata.set('HAVE_TYPEOF', 1)
2324 cdata.set('typeof', kw)
2332 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2333 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2334 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2335 wcstombs_l_test = '''
2347 if (not cc.compiles(wcstombs_l_test.format(''),
2348 name: 'wcstombs_l') and
2349 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2350 name: 'wcstombs_l in xlocale.h'))
2351 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2355 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2356 # understands, because it conflicts with __declspec(restrict). Therefore we
2357 # define pg_restrict to the appropriate definition, which presumably won't
2360 # We assume C99 support, so we don't need to make this conditional.
2362 # XXX: Historically we allowed platforms to disable restrict in template
2363 # files, but that was only added for AIX when building with XLC, which we
2364 # don't support yet.
2365 cdata.set('pg_restrict', '__restrict')
2368 # Most libraries are included only if they demonstrably provide a function we
2369 # need, but libm is an exception: always include it, because there are too
2370 # many compilers that play cute optimization games that will break probes for
2371 # standard functions such as pow().
2372 os_deps += cc.find_library('m', required: false)
2374 rt_dep = cc.find_library('rt', required: false)
2376 dl_dep = cc.find_library('dl', required: false)
2378 util_dep = cc.find_library('util', required: false)
2379 posix4_dep = cc.find_library('posix4', required: false)
2381 getopt_dep = cc.find_library('getopt', required: false)
2382 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2383 # Check if we want to replace getopt/getopt_long even if provided by the system
2384 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2385 # so always use our version on Windows
2386 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2387 # (i.e., allow '-' as a flag character), so use our version on those platforms
2388 # - We want to use system's getopt_long() only if the system provides struct
2390 always_replace_getopt = host_system in ['windows', 'cygwin', 'openbsd', 'solaris']
2391 always_replace_getopt_long = host_system in ['windows', 'cygwin'] or not cdata.has('HAVE_STRUCT_OPTION')
2394 execinfo_dep = cc.find_library('execinfo', required: false)
2396 if host_system == 'cygwin'
2397 cygipc_dep = cc.find_library('cygipc', required: false)
2399 cygipc_dep = not_found_dep
2402 if host_system == 'sunos'
2403 socket_dep = cc.find_library('socket', required: false)
2405 socket_dep = not_found_dep
2408 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2409 # unnecessary checks over and over, particularly on windows.
2411 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2412 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2413 ['clock_gettime', {'dependencies': [rt_dep, posix4_dep], 'define': false}],
2415 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2416 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2417 # required. Just checking for dlsym() ought to suffice.
2418 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2420 ['fdatasync', {'dependencies': [rt_dep, posix4_dep], 'define': false}], # Solaris
2422 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2423 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2433 ['posix_fallocate'],
2436 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2437 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2438 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2439 ['setproctitle', {'dependencies': [util_dep]}],
2440 ['setproctitle_fast'],
2441 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2442 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2443 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2444 ['socket', {'dependencies': [socket_dep], 'define': false}],
2446 ['strerror_r', {'dependencies': [thread_dep]}],
2451 ['sync_file_range'],
2457 func_check_results = {}
2458 foreach c : func_checks
2460 kwargs = c.get(1, {})
2461 deps = kwargs.get('dependencies', [])
2463 if kwargs.get('skip', false)
2467 found = cc.has_function(func, args: test_c_args)
2474 found = cc.has_function(func, args: test_c_args,
2475 dependencies: [dep])
2483 func_check_results += {func: found}
2485 if kwargs.get('define', true)
2486 # Emulate autoconf behaviour of not-found->undef, found->1
2487 cdata.set('HAVE_' + func.underscorify().to_upper(),
2489 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2494 if cc.has_function('syslog', args: test_c_args) and \
2495 cc.check_header('syslog.h', args: test_c_args)
2496 cdata.set('HAVE_SYSLOG', 1)
2500 # MSVC has replacements defined in src/include/port/win32_port.h.
2501 if cc.get_id() == 'msvc'
2502 cdata.set('HAVE_WCSTOMBS_L', 1)
2503 cdata.set('HAVE_MBSTOWCS_L', 1)
2507 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2509 if sema_kind == 'unnamed_posix' and \
2510 not func_check_results.get('sem_init', false)
2514 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2515 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2517 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2518 cdata.set_quoted('DLSUFFIX', dlsuffix)
2521 # built later than the rest of the version metadata, we need SIZEOF_VOID_P
2522 cdata.set_quoted('PG_VERSION_STR',
2523 'PostgreSQL @0@ on @1@-@2@, compiled by @3@-@4@, @5@-bit'.format(
2524 pg_version, host_machine.cpu_family(), host_system,
2525 cc.get_id(), cc.version(), cdata.get('SIZEOF_VOID_P') * 8,
2531 ###############################################################
2533 ###############################################################
2535 # XXX: About to rely on thread safety in the autoconf build, so not worth
2536 # implementing a fallback.
2537 cdata.set('ENABLE_THREAD_SAFETY', 1)
2541 ###############################################################
2543 ###############################################################
2545 nlsopt = get_option('nls')
2546 libintl = not_found_dep
2548 if not nlsopt.disabled()
2549 # otherwise there'd be lots of
2550 # "Gettext not found, all translation (po) targets will be ignored."
2551 # warnings if not found.
2552 msgfmt = find_program('msgfmt', required: nlsopt, native: true)
2554 # meson 0.59 has this wrapped in dependency('intl')
2555 if (msgfmt.found() and
2556 cc.check_header('libintl.h', required: nlsopt,
2557 args: test_c_args, include_directories: postgres_inc))
2560 if cc.has_function('ngettext')
2561 libintl = declare_dependency()
2563 libintl = cc.find_library('intl',
2564 has_headers: ['libintl.h'], required: nlsopt,
2565 header_include_directories: postgres_inc,
2571 i18n = import('i18n')
2572 cdata.set('ENABLE_NLS', 1)
2578 ###############################################################
2580 ###############################################################
2582 # Set up compiler / linker arguments to be used everywhere, individual targets
2583 # can add further args directly, or indirectly via dependencies
2584 add_project_arguments(cflags, language: ['c'])
2585 add_project_arguments(cppflags, language: ['c'])
2586 add_project_arguments(cflags_warn, language: ['c'])
2587 add_project_arguments(cxxflags, language: ['cpp'])
2588 add_project_arguments(cppflags, language: ['cpp'])
2589 add_project_arguments(cxxflags_warn, language: ['cpp'])
2590 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2593 # Collect a number of lists of things while recursing through the source
2594 # tree. Later steps then can use those.
2596 # list of targets for various alias targets
2597 backend_targets = []
2600 contrib_targets = []
2601 testprep_targets = []
2605 # Define the tests to distribute them to the correct test styles later
2610 # Default options for targets
2612 # First identify rpaths
2613 bin_install_rpaths = []
2614 lib_install_rpaths = []
2615 mod_install_rpaths = []
2618 # Don't add rpaths on darwin for now - as long as only absolute references to
2619 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2620 # their final destination.
2621 if host_system != 'darwin'
2622 # Add absolute path to libdir to rpath. This ensures installed binaries /
2623 # libraries find our libraries (mainly libpq).
2624 bin_install_rpaths += dir_prefix / dir_lib
2625 lib_install_rpaths += dir_prefix / dir_lib
2626 mod_install_rpaths += dir_prefix / dir_lib
2628 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2630 # Not needed on darwin even if we use relative rpaths for our own libraries,
2631 # as the install_name of libraries in extra_lib_dirs will point to their
2633 bin_install_rpaths += postgres_lib_d
2634 lib_install_rpaths += postgres_lib_d
2635 mod_install_rpaths += postgres_lib_d
2639 # Define arguments for default targets
2641 default_target_args = {
2642 'implicit_include_directories': false,
2646 default_lib_args = default_target_args + {
2650 internal_lib_args = default_lib_args + {
2651 'build_by_default': false,
2655 default_mod_args = default_lib_args + {
2657 'install_dir': dir_lib_pkg,
2660 default_bin_args = default_target_args + {
2661 'install_dir': dir_bin,
2664 if get_option('rpath')
2665 default_lib_args += {
2666 'install_rpath': ':'.join(lib_install_rpaths),
2669 default_mod_args += {
2670 'install_rpath': ':'.join(mod_install_rpaths),
2673 default_bin_args += {
2674 'install_rpath': ':'.join(bin_install_rpaths),
2679 # Helper for exporting a limited number of symbols
2680 gen_export_kwargs = {
2681 'input': 'exports.txt',
2682 'output': '@BASENAME@.'+export_file_suffix,
2683 'command': [perl, files('src/tools/gen_export.pl'),
2684 '--format', export_file_format,
2685 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2686 'build_by_default': false,
2693 ### Helpers for custom targets used across the tree
2696 catalog_pm = files('src/backend/catalog/Catalog.pm')
2697 perfect_hash_pm = files('src/tools/PerfectHash.pm')
2698 gen_kwlist_deps = [perfect_hash_pm]
2700 perl, '-I', '@SOURCE_ROOT@/src/tools',
2701 files('src/tools/gen_keywordlist.pl'),
2702 '--output', '@OUTDIR@', '@INPUT@']
2707 ### windows resources related stuff
2710 if host_system == 'windows'
2711 pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico'
2712 win32ver_rc = files('src/port/win32ver.rc')
2713 rcgen = find_program('src/tools/rcgen', native: true)
2716 '--srcdir', '@SOURCE_DIR@',
2717 '--builddir', meson.build_root(),
2718 '--rcout', '@OUTPUT0@',
2719 '--out', '@OUTPUT1@',
2720 '--input', '@INPUT@',
2724 if cc.get_argument_syntax() == 'msvc'
2725 rc = find_program('rc', required: true)
2726 rcgen_base_args += ['--rc', rc.path()]
2727 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.res']
2729 windres = find_program('windres', required: true)
2730 rcgen_base_args += ['--windres', windres.path()]
2731 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.obj']
2734 # msbuild backend doesn't support this atm
2735 if meson.backend() == 'ninja'
2736 rcgen_base_args += ['--depfile', '@DEPFILE@']
2739 rcgen_bin_args = rcgen_base_args + [
2740 '--VFT_TYPE', 'VFT_APP',
2741 '--FILEENDING', 'exe',
2745 rcgen_lib_args = rcgen_base_args + [
2746 '--VFT_TYPE', 'VFT_DLL',
2747 '--FILEENDING', 'dll',
2750 rc_bin_gen = generator(rcgen,
2751 depfile: '@BASENAME@.d',
2752 arguments: rcgen_bin_args,
2753 output: rcgen_outputs,
2756 rc_lib_gen = generator(rcgen,
2757 depfile: '@BASENAME@.d',
2758 arguments: rcgen_lib_args,
2759 output: rcgen_outputs,
2765 # headers that the whole build tree depends on
2766 generated_headers = []
2767 # headers that the backend build depends on
2768 generated_backend_headers = []
2769 # configure_files() output, needs a way of converting to file names
2770 configure_files = []
2772 # generated files that might conflict with a partial in-tree autoconf build
2773 generated_sources = []
2774 # same, for paths that differ between autoconf / meson builds
2775 # elements are [dir, [files]]
2776 generated_sources_ac = {}
2779 # First visit src/include - all targets creating headers are defined
2780 # within. That makes it easy to add the necessary dependencies for the
2781 # subsequent build steps.
2783 subdir('src/include')
2787 # Then through src/port and src/common, as most other things depend on them
2789 frontend_port_code = declare_dependency(
2790 compile_args: ['-DFRONTEND'],
2791 include_directories: [postgres_inc],
2792 dependencies: os_deps,
2795 backend_port_code = declare_dependency(
2796 compile_args: ['-DBUILDING_DLL'],
2797 include_directories: [postgres_inc],
2798 sources: [errcodes], # errcodes.h is needed due to use of ereport
2799 dependencies: os_deps,
2804 frontend_common_code = declare_dependency(
2805 compile_args: ['-DFRONTEND'],
2806 include_directories: [postgres_inc],
2807 sources: generated_headers,
2808 dependencies: [os_deps, zlib, zstd],
2811 backend_common_code = declare_dependency(
2812 compile_args: ['-DBUILDING_DLL'],
2813 include_directories: [postgres_inc],
2814 sources: generated_headers,
2815 dependencies: [os_deps, zlib, zstd],
2818 subdir('src/common')
2820 # all shared libraries should depend on shlib_code
2821 shlib_code = declare_dependency(
2822 link_args: ldflags_sl,
2825 # all static libraries not part of the backend should depend on this
2826 frontend_stlib_code = declare_dependency(
2827 include_directories: [postgres_inc],
2828 link_with: [common_static, pgport_static],
2829 sources: generated_headers,
2830 dependencies: [os_deps, libintl],
2833 # all shared libraries not part of the backend should depend on this
2834 frontend_shlib_code = declare_dependency(
2835 include_directories: [postgres_inc],
2836 link_with: [common_shlib, pgport_shlib],
2837 sources: generated_headers,
2838 dependencies: [shlib_code, os_deps, libintl],
2841 # Dependencies both for static and shared libpq
2851 subdir('src/interfaces/libpq')
2852 # fe_utils depends on libpq
2853 subdir('src/fe_utils')
2855 # for frontend binaries
2856 frontend_code = declare_dependency(
2857 include_directories: [postgres_inc],
2858 link_with: [fe_utils, common_static, pgport_static],
2859 sources: generated_headers,
2860 dependencies: [os_deps, libintl],
2863 backend_both_deps += [
2880 backend_mod_deps = backend_both_deps + os_deps
2882 backend_code = declare_dependency(
2883 compile_args: ['-DBUILDING_DLL'],
2884 include_directories: [postgres_inc],
2885 link_args: ldflags_be,
2887 sources: generated_headers + generated_backend_headers,
2888 dependencies: os_deps + backend_both_deps + backend_deps,
2891 # install these files only during test, not main install
2892 test_install_data = []
2893 test_install_libs = []
2895 # src/backend/meson.build defines backend_mod_code used for extension
2899 # Then through the main sources. That way contrib can have dependencies on
2900 # main sources. Note that this explicitly doesn't enter src/test, right now a
2901 # few regression tests depend on contrib files.
2908 subdir('src/interfaces/libpq/test')
2909 subdir('src/interfaces/ecpg/test')
2911 subdir('doc/src/sgml')
2913 generated_sources_ac += {'': ['GNUmakefile']}
2915 # After processing src/test, add test_install_libs to the testprep_targets
2917 testprep_targets += test_install_libs
2920 # If there are any files in the source directory that we also generate in the
2921 # build directory, they might get preferred over the newly generated files,
2922 # e.g. because of a #include "file", which always will search in the current
2924 message('checking for file conflicts between source and build directory')
2925 conflicting_files = []
2926 potentially_conflicting_files_t = []
2927 potentially_conflicting_files_t += generated_headers
2928 potentially_conflicting_files_t += generated_backend_headers
2929 potentially_conflicting_files_t += generated_backend_sources
2930 potentially_conflicting_files_t += generated_sources
2932 potentially_conflicting_files = []
2934 # convert all sources of potentially conflicting files into uniform shape
2935 foreach t : potentially_conflicting_files_t
2936 potentially_conflicting_files += t.full_path()
2938 foreach t1 : configure_files
2939 if meson.version().version_compare('>=0.59')
2940 t = fs.parent(t1) / fs.name(t1)
2942 t = '@0@'.format(t1)
2944 potentially_conflicting_files += meson.current_build_dir() / t
2946 foreach sub, fnames : generated_sources_ac
2947 sub = meson.build_root() / sub
2948 foreach fname : fnames
2949 potentially_conflicting_files += sub / fname
2953 # find and report conflicting files
2954 foreach build_path : potentially_conflicting_files
2955 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
2956 # str.replace is in 0.56
2957 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
2958 if fs.exists(src_path) or fs.is_symlink(src_path)
2959 conflicting_files += src_path
2962 # XXX: Perhaps we should generate a file that would clean these up? The list
2964 if conflicting_files.length() > 0
2965 errmsg_cleanup = '''
2966 Conflicting files in source directory:
2969 The conflicting files need to be removed, either by removing the files listed
2970 above, or by running configure and then make maintainer-clean.
2972 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
2973 error(errmsg_nonclean_base.format(errmsg_cleanup))
2978 ###############################################################
2980 ###############################################################
2983 # We want to define additional install targets beyond what meson provides. For
2984 # that we need to define targets depending on nearly everything. We collected
2985 # the results of i18n.gettext() invocations into nls_targets, that also
2986 # includes maintainer targets though. Collect the ones we want as a dependency.
2988 # i18n.gettext() doesn't return the dependencies before 0.60 - but the gettext
2989 # generation happens during install, so that's not a real issue.
2991 if libintl.found() and meson.version().version_compare('>=0.60')
2992 # use range() to avoid the flattening of the list that foreach() would do
2993 foreach off : range(0, nls_targets.length())
2994 # i18n.gettext() list containing 1) list of built .mo files 2) maintainer
2995 # -pot target 3) maintainer -pot target
2996 nls_mo_targets += nls_targets[off][0]
2998 alias_target('nls', nls_mo_targets)
3013 # Meson's default install target is quite verbose. Provide one that is quiet.
3014 install_quiet = custom_target('install-quiet',
3015 output: 'install-quiet',
3016 build_always_stale: true,
3017 build_by_default: false,
3018 command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'],
3022 # Target to install files used for tests, which aren't installed by default
3023 install_test_files_args = [
3025 '--prefix', dir_prefix,
3026 '--install', contrib_data_dir, test_install_data,
3027 '--install', dir_lib_pkg, test_install_libs,
3029 run_target('install-test-files',
3030 command: [python] + install_test_files_args,
3031 depends: testprep_targets,
3036 ###############################################################
3038 ###############################################################
3040 # DESTDIR for the installation we'll run tests in
3041 test_install_destdir = meson.build_root() / 'tmp_install/'
3043 # DESTDIR + prefix appropriately munged
3044 if build_system != 'windows'
3045 # On unixoid systems this is trivial, we just prepend the destdir
3046 assert(dir_prefix.startswith('/')) # enforced by meson
3047 test_install_location = '@0@@1@'.format(test_install_destdir, dir_prefix)
3049 # drives, drive-relative paths, etc make this complicated on windows, call
3050 # into a copy of meson's logic for it
3053 'import sys; from pathlib import PurePath; d1=sys.argv[1]; d2=sys.argv[2]; print(str(PurePath(d1, *PurePath(d2).parts[1:])))',
3054 test_install_destdir, dir_prefix]
3055 test_install_location = run_command(command, check: true).stdout().strip()
3058 meson_install_args = meson_args + ['install'] + {
3059 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
3063 # setup tests should be run first,
3064 # so define priority for these
3065 setup_tests_priority = 100
3067 meson_bin, args: meson_install_args ,
3068 env: {'DESTDIR':test_install_destdir},
3069 priority: setup_tests_priority,
3074 test('install_test_files',
3076 args: install_test_files_args + ['--destdir', test_install_destdir],
3077 priority: setup_tests_priority,
3081 test_result_dir = meson.build_root() / 'testrun'
3084 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
3085 # inevitable conflicts from running tests in parallel, hackishly assign
3086 # different ports for different tests.
3090 test_env = environment()
3092 temp_install_bindir = test_install_location / get_option('bindir')
3093 test_env.set('PG_REGRESS', pg_regress.full_path())
3094 test_env.set('REGRESS_SHLIB', regress_module.full_path())
3096 # Test suites that are not safe by default but can be run if selected
3097 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
3098 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
3099 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
3101 # Add the temporary installation to the library search path on platforms where
3102 # that works (everything but windows, basically). On windows everything
3103 # library-like gets installed into bindir, solving that issue.
3104 if library_path_var != ''
3105 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
3110 ###############################################################
3112 ###############################################################
3114 # When using a meson version understanding exclude_suites, define a
3115 # 'tmp_install' test setup (the default) that excludes tests running against a
3116 # pre-existing install and a 'running' setup that conflicts with creation of
3117 # the temporary installation and tap tests (which don't support running
3118 # against a running server).
3122 if meson.version().version_compare('>=0.57')
3125 runningcheck = false
3128 testwrap = files('src/tools/testwrap')
3130 foreach test_dir : tests
3133 '--basedir', meson.build_root(),
3134 '--srcdir', test_dir['sd'],
3137 foreach kind, v : test_dir
3138 if kind in ['sd', 'bd', 'name']
3144 if kind in ['regress', 'isolation', 'ecpg']
3145 if kind == 'regress'
3147 fallback_dbname = 'regression_@0@'
3148 elif kind == 'isolation'
3149 runner = pg_isolation_regress
3150 fallback_dbname = 'isolation_regression_@0@'
3152 runner = pg_regress_ecpg
3153 fallback_dbname = 'ecpg_regression_@0@'
3156 test_group = test_dir['name']
3157 test_group_running = test_dir['name'] + '-running'
3159 test_output = test_result_dir / test_group / kind
3160 test_output_running = test_result_dir / test_group_running/ kind
3162 # Unless specified by the test, choose a non-conflicting database name,
3163 # to avoid conflicts when running against existing server.
3164 dbname = t.get('dbname',
3165 fallback_dbname.format(test_dir['name']))
3167 test_command_base = [
3169 '--inputdir', t.get('inputdir', test_dir['sd']),
3170 '--expecteddir', t.get('expecteddir', test_dir['sd']),
3172 '--dlpath', test_dir['bd'],
3173 '--max-concurrent-tests=20',
3175 ] + t.get('regress_args', [])
3178 if t.has_key('schedule')
3179 test_selection += ['--schedule', t['schedule'],]
3182 if kind == 'isolation'
3183 test_selection += t.get('specs', [])
3185 test_selection += t.get('sql', [])
3189 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
3195 'depends': test_deps + t.get('deps', []),
3197 } + t.get('test_kwargs', {})
3199 test(test_group / kind,
3203 '--testgroup', test_group,
3207 '--outputdir', test_output,
3208 '--temp-instance', test_output / 'tmp_check',
3209 '--port', testport.to_string(),
3213 kwargs: test_kwargs,
3215 install_suites += test_group
3217 # some tests can't support running against running DB
3218 if runningcheck and t.get('runningcheck', true)
3219 test(test_group_running / kind,
3223 '--testgroup', test_group_running,
3227 '--outputdir', test_output_running,
3230 is_parallel: t.get('runningcheck-parallel', true),
3231 suite: test_group_running,
3232 kwargs: test_kwargs,
3234 running_suites += test_group_running
3239 if not tap_tests_enabled
3245 '-I', meson.source_root() / 'src/test/perl',
3246 '-I', test_dir['sd'],
3249 # Add temporary install, the build directory for non-installed binaries and
3250 # also test/ for non-installed test binaries built separately.
3252 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
3254 foreach name, value : t.get('env', {})
3255 env.set(name, value)
3258 test_group = test_dir['name']
3261 'suite': test_group,
3263 'depends': test_deps + t.get('deps', []),
3265 } + t.get('test_kwargs', {})
3267 foreach onetap : t['tests']
3268 # Make tap test names prettier, remove t/ and .pl
3270 if onetap_p.startswith('t/')
3271 onetap_p = onetap.split('t/')[1]
3273 if onetap_p.endswith('.pl')
3274 onetap_p = fs.stem(onetap_p)
3277 test(test_dir['name'] / onetap_p,
3279 kwargs: test_kwargs,
3280 args: testwrap_base + [
3281 '--testgroup', test_dir['name'],
3282 '--testname', onetap_p,
3284 test_dir['sd'] / onetap,
3288 install_suites += test_group
3290 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
3293 endforeach # kinds of tests
3295 endforeach # directories with tests
3297 # repeat condition so meson realizes version dependency
3298 if meson.version().version_compare('>=0.57')
3299 add_test_setup('tmp_install',
3301 exclude_suites: running_suites)
3302 add_test_setup('running',
3303 exclude_suites: ['setup'] + install_suites)
3308 ###############################################################
3310 ###############################################################
3312 alias_target('backend', backend_targets)
3313 alias_target('bin', bin_targets + [libpq_st])
3314 alias_target('pl', pl_targets)
3315 alias_target('contrib', contrib_targets)
3316 alias_target('testprep', testprep_targets)
3317 alias_target('install-world', install_quiet, installdocs)
3321 ###############################################################
3322 # The End, The End, My Friend
3323 ###############################################################
3325 if meson.version().version_compare('>=0.57')
3329 'data block size': '@0@ kB'.format(cdata.get('BLCKSZ') / 1024),
3330 'WAL block size': '@0@ kB'.format(cdata.get('XLOG_BLCKSZ') / 1024),
3331 'segment size': get_option('segsize_blocks') != 0 ?
3332 '@0@ blocks'.format(cdata.get('RELSEG_SIZE')) :
3333 '@0@ GB'.format(get_option('segsize')),
3335 section: 'Data layout',
3340 'host system': '@0@ @1@'.format(host_system, host_cpu),
3341 'build system': '@0@ @1@'.format(build_machine.system(),
3342 build_machine.cpu_family()),
3349 'linker': '@0@'.format(cc.get_linker_id()),
3350 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
3352 section: 'Compiler',
3357 'CPP FLAGS': ' '.join(cppflags),
3358 'C FLAGS, functional': ' '.join(cflags),
3359 'C FLAGS, warnings': ' '.join(cflags_warn),
3360 'C FLAGS, modules': ' '.join(cflags_mod),
3361 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3362 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3364 section: 'Compiler Flags',
3370 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3372 section: 'Compiler',
3377 'C++ FLAGS, functional': ' '.join(cxxflags),
3378 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3379 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3381 section: 'Compiler Flags',
3387 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3390 section: 'Programs',
3396 'bsd_auth': bsd_auth,
3398 'docs_pdf': docs_pdf_dep,
3410 'plpython': python3_dep,
3412 'readline': readline,
3419 section: 'External libraries',