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 # meson's system names don't quite map to our "traditional" names. In some
163 # places we need the "traditional" name, e.g., for mapping
164 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
166 portname = host_system
168 exesuffix = '' # overridden below where necessary
169 dlsuffix = '.so' # overridden below where necessary
170 library_path_var = 'LD_LIBRARY_PATH'
172 # Format of file to control exports from libraries, and how to pass them to
173 # the compiler. For export_fmt @0@ is the path to the file export file.
174 export_file_format = 'gnu'
175 export_file_suffix = 'list'
176 export_fmt = '-Wl,--version-script=@0@'
178 # Flags to add when linking a postgres extension, @0@ is path to
179 # the relevant object on the platform.
180 mod_link_args_fmt = []
182 memset_loop_limit = 1024
184 # Choice of shared memory and semaphore implementation
188 # We implement support for some operating systems by pretending they're
189 # another. Map here, before determining system properties below
190 if host_system == 'dragonfly'
191 # apparently the most similar
192 host_system = 'netbsd'
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]
240 # meson defaults to -Wl,-undefined,dynamic_lookup for modules, which we
241 # don't want because a) it's different from what we do for autoconf, b) it
242 # causes warnings starting in macOS Ventura
243 ldflags_mod += ['-Wl,-undefined,error']
245 elif host_system == 'freebsd'
246 sema_kind = 'unnamed_posix'
248 elif host_system == 'linux'
249 sema_kind = 'unnamed_posix'
250 cppflags += '-D_GNU_SOURCE'
252 elif host_system == 'netbsd'
253 # We must resolve all dynamic linking in the core server at program start.
254 # Otherwise the postmaster can self-deadlock due to signals interrupting
255 # resolution of calls, since NetBSD's linker takes a lock while doing that
256 # and some postmaster signal handlers do things that will also acquire that
257 # lock. As long as we need "-z now", might as well specify "-z relro" too.
258 # While there's not a hard reason to adopt these settings for our other
259 # executables, there's also little reason not to, so just add them to
261 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
263 elif host_system == 'openbsd'
266 elif host_system == 'sunos'
268 export_fmt = '-Wl,-M@0@'
269 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
271 elif host_system == 'windows'
275 library_path_var = ''
277 export_file_format = 'win'
278 export_file_suffix = 'def'
279 if cc.get_id() == 'msvc'
280 export_fmt = '/DEF:@0@'
281 mod_link_with_name = '@0@.exe.lib'
284 mod_link_with_name = 'lib@0@.exe.a'
286 mod_link_args_fmt = ['@0@']
287 mod_link_with_dir = 'libdir'
292 cdata.set('WIN32_STACK_RLIMIT', 4194304)
293 if cc.get_id() == 'msvc'
294 ldflags += '/INCREMENTAL:NO'
295 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
296 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
298 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
299 # Need to allow multiple definitions, we e.g. want to override getopt.
300 ldflags += '-Wl,--allow-multiple-definition'
301 # Ensure we get MSVC-like linking behavior.
302 ldflags += '-Wl,--disable-auto-import'
305 os_deps += cc.find_library('ws2_32', required: true)
306 secur32_dep = cc.find_library('secur32', required: true)
307 backend_deps += secur32_dep
308 libpq_deps += secur32_dep
310 postgres_inc_d += 'src/include/port/win32'
311 if cc.get_id() == 'msvc'
312 postgres_inc_d += 'src/include/port/win32_msvc'
315 windows = import('windows')
318 # XXX: Should we add an option to override the host_system as an escape
320 error('unknown host system: @0@'.format(host_system))
325 ###############################################################
327 ###############################################################
330 perl = find_program(get_option('PERL'), required: true, native: true)
331 python = find_program(get_option('PYTHON'), required: true, native: true)
332 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35')
333 bison = find_program(get_option('BISON'), native: true, version: '>= 2.3')
334 sed = find_program(get_option('SED'), 'sed', native: true)
335 prove = find_program(get_option('PROVE'), native: true, required: false)
336 tar = find_program(get_option('TAR'), native: true)
337 gzip = find_program(get_option('GZIP'), native: true)
338 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
339 openssl = find_program(get_option('OPENSSL'), native: true, required: false)
340 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
341 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
342 missing = find_program('config/missing', native: true)
343 cp = find_program('cp', required: false, native: true)
344 xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
345 xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
349 bison_version_c = run_command(bison, '--version', check: true)
350 # bison version string helpfully is something like
351 # >>bison (GNU bison) 3.8.1<<
352 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
353 if bison_version.version_compare('>=3.0')
354 bison_flags += ['-Wno-deprecated']
357 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
359 'output': ['@BASENAME@.c', '@BASENAME@.h'],
360 'command': bison_cmd,
365 flex_version_c = run_command(flex, '--version', check: true)
366 flex_version = flex_version_c.stdout().split(' ')[1].split('\n')[0]
368 flex_wrapper = files('src/tools/pgflex')
369 flex_cmd = [python, flex_wrapper,
370 '--builddir', '@BUILD_ROOT@',
371 '--srcdir', '@SOURCE_ROOT@',
372 '--privatedir', '@PRIVATE_DIR@',
373 '--flex', flex, '--perl', perl,
374 '-i', '@INPUT@', '-o', '@OUTPUT0@',
377 wget = find_program('wget', required: false, native: true)
378 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
380 install_files = files('src/tools/install_files')
384 ###############################################################
385 # Path to meson (for tests etc)
386 ###############################################################
388 # NB: this should really be part of meson, see
389 # https://github.com/mesonbuild/meson/issues/8511
390 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
392 if meson_binpath_r.stdout() == ''
393 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
394 meson_binpath_r.returncode(),
395 meson_binpath_r.stdout(),
396 meson_binpath_r.stderr()))
399 meson_binpath_s = meson_binpath_r.stdout().split('\n')
400 meson_binpath_len = meson_binpath_s.length()
402 if meson_binpath_len < 1
403 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
410 foreach e : meson_binpath_s
421 if meson_impl not in ['muon', 'meson']
422 error('unknown meson implementation "@0@"'.format(meson_impl))
425 meson_bin = find_program(meson_binpath, native: true)
429 ###############################################################
431 ###############################################################
433 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
435 blocksize = get_option('blocksize').to_int() * 1024
437 if get_option('segsize_blocks') != 0
438 if get_option('segsize') != 1
439 warning('both segsize and segsize_blocks specified, segsize_blocks wins')
442 segsize = get_option('segsize_blocks')
444 segsize = (get_option('segsize') * 1024 * 1024 * 1024) / blocksize
447 cdata.set('BLCKSZ', blocksize, description:
448 '''Size of a disk block --- this also limits the size of a tuple. You can set
449 it bigger if you need bigger tuples (although TOAST should reduce the need
450 to have large tuples, since fields can be spread across multiple tuples).
451 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
452 currently 2^15 (32768). This is determined by the 15-bit widths of the
453 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
454 Changing BLCKSZ requires an initdb.''')
456 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
457 cdata.set('RELSEG_SIZE', segsize)
458 cdata.set('DEF_PGPORT', get_option('pgport'))
459 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
460 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
461 if get_option('system_tzdata') != ''
462 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
467 ###############################################################
469 ###############################################################
471 # These are set by the equivalent --xxxdir configure options. We
472 # append "postgresql" to some of them, if the string does not already
473 # contain "pgsql" or "postgres", in order to avoid directory clutter.
477 dir_prefix = get_option('prefix')
479 dir_prefix_contains_pg = (dir_prefix.contains('pgsql') or dir_prefix.contains('postgres'))
481 dir_bin = get_option('bindir')
483 dir_data = get_option('datadir')
484 if not (dir_prefix_contains_pg or dir_data.contains('pgsql') or dir_data.contains('postgres'))
485 dir_data = dir_data / pkg
488 dir_sysconf = get_option('sysconfdir')
489 if not (dir_prefix_contains_pg or dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
490 dir_sysconf = dir_sysconf / pkg
493 dir_lib = get_option('libdir')
495 dir_lib_pkg = dir_lib
496 if not (dir_prefix_contains_pg or dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
497 dir_lib_pkg = dir_lib_pkg / pkg
500 dir_pgxs = dir_lib_pkg / 'pgxs'
502 dir_include = get_option('includedir')
504 dir_include_pkg = dir_include
505 dir_include_pkg_rel = ''
506 if not (dir_prefix_contains_pg or dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
507 dir_include_pkg = dir_include_pkg / pkg
508 dir_include_pkg_rel = pkg
511 dir_man = get_option('mandir')
513 # FIXME: These used to be separately configurable - worth adding?
514 dir_doc = get_option('datadir') / 'doc' / 'postgresql'
515 dir_doc_html = dir_doc / 'html'
517 dir_locale = get_option('localedir')
521 dir_bitcode = dir_lib_pkg / 'bitcode'
522 dir_include_internal = dir_include_pkg / 'internal'
523 dir_include_server = dir_include_pkg / 'server'
524 dir_include_extension = dir_include_server / 'extension'
525 dir_data_extension = dir_data / 'extension'
529 ###############################################################
530 # Search paths, preparation for compiler tests
532 # NB: Arguments added later are not automatically used for subsequent
533 # configuration-time checks (so they are more isolated). If they should be
534 # used, they need to be added to test_c_args as well.
535 ###############################################################
537 postgres_inc = [include_directories(postgres_inc_d)]
538 test_lib_d = postgres_lib_d
539 test_c_args = cppflags + cflags
543 ###############################################################
545 ###############################################################
547 bsd_authopt = get_option('bsd_auth')
548 bsd_auth = not_found_dep
549 if cc.check_header('bsd_auth.h', required: bsd_authopt,
550 args: test_c_args, include_directories: postgres_inc)
551 cdata.set('USE_BSD_AUTH', 1)
552 bsd_auth = declare_dependency()
557 ###############################################################
560 # For now don't search for DNSServiceRegister in a library - only Apple's
561 # Bonjour implementation, which is always linked, works.
562 ###############################################################
564 bonjouropt = get_option('bonjour')
565 bonjour = not_found_dep
566 if cc.check_header('dns_sd.h', required: bonjouropt,
567 args: test_c_args, include_directories: postgres_inc) and \
568 cc.has_function('DNSServiceRegister',
569 args: test_c_args, include_directories: postgres_inc)
570 cdata.set('USE_BONJOUR', 1)
571 bonjour = declare_dependency()
576 ###############################################################
577 # Option: docs in HTML and man page format
578 ###############################################################
580 docs_opt = get_option('docs')
581 docs_dep = not_found_dep
582 if not docs_opt.disabled()
583 if xmllint_bin.found() and xsltproc_bin.found()
584 docs_dep = declare_dependency()
585 elif docs_opt.enabled()
586 error('missing required tools for docs in HTML / man page format')
592 ###############################################################
593 # Option: docs in PDF format
594 ###############################################################
596 docs_pdf_opt = get_option('docs_pdf')
597 docs_pdf_dep = not_found_dep
598 if not docs_pdf_opt.disabled()
599 fop = find_program(get_option('FOP'), native: true, required: docs_pdf_opt)
600 if xmllint_bin.found() and xsltproc_bin.found() and fop.found()
601 docs_pdf_dep = declare_dependency()
602 elif docs_pdf_opt.enabled()
603 error('missing required tools for docs in PDF format')
609 ###############################################################
611 ###############################################################
613 gssapiopt = get_option('gssapi')
616 if not gssapiopt.disabled()
617 gssapi = dependency('krb5-gssapi', required: gssapiopt)
618 have_gssapi = gssapi.found()
621 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
622 args: test_c_args, include_directories: postgres_inc)
623 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
624 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
625 cdata.set('HAVE_GSSAPI_H', 1)
631 elif cc.check_header('gssapi/gssapi_ext.h', dependencies: gssapi, required: false,
632 args: test_c_args, include_directories: postgres_inc)
633 cdata.set('HAVE_GSSAPI_GSSAPI_EXT_H', 1)
634 elif cc.check_header('gssapi_ext.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
635 cdata.set('HAVE_GSSAPI_EXT_H', 1)
641 elif cc.has_function('gss_store_cred_into', dependencies: gssapi,
642 args: test_c_args, include_directories: postgres_inc)
643 cdata.set('ENABLE_GSS', 1)
645 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
646 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
647 elif gssapiopt.enabled()
648 error('''could not find function 'gss_store_cred_into' required for GSSAPI''')
654 gssapi = not_found_dep
659 ###############################################################
661 ###############################################################
663 ldapopt = get_option('ldap')
664 if ldapopt.disabled()
666 ldap_r = not_found_dep
667 elif host_system == 'windows'
668 ldap = cc.find_library('wldap32', required: ldapopt)
671 # macos framework dependency is buggy for ldap (one can argue whether it's
672 # Apple's or meson's fault), leading to an endless recursion with ldap.h
673 # including itself. See https://github.com/mesonbuild/meson/issues/10002
674 # Luckily we only need pkg-config support, so the workaround isn't
676 ldap = dependency('ldap', method: 'pkg-config', required: false)
679 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
682 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
683 has_headers: 'ldap.h', header_include_directories: postgres_inc)
685 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
686 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
687 # library from a separate OpenLDAP installation). The most reliable
688 # way to check that is to check for a function introduced in 2.5.
690 # don't have ldap, we shouldn't check for ldap_r
691 elif cc.has_function('ldap_verify_credentials',
692 dependencies: ldap, args: test_c_args)
693 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
696 # Use ldap_r for FE if available, else assume ldap is thread-safe.
697 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
698 has_headers: 'ldap.h', header_include_directories: postgres_inc)
699 if not ldap_r.found()
702 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
703 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
706 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
707 # process. Check for OpenLDAP versions known not to tolerate doing so;
708 # assume non-OpenLDAP implementations are safe. The dblink test suite
709 # exercises the hazardous interaction directly.
710 compat_test_code = '''
712 #if !defined(LDAP_VENDOR_VERSION) || \
713 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
714 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
718 if not cc.compiles(compat_test_code,
719 name: 'LDAP implementation compatible',
720 dependencies: ldap, args: test_c_args)
722 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
723 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
724 *** also uses LDAP will crash on exit.''')
729 if ldap.found() and cc.has_function('ldap_initialize',
730 dependencies: ldap, args: test_c_args)
731 cdata.set('HAVE_LDAP_INITIALIZE', 1)
736 assert(ldap_r.found())
737 cdata.set('USE_LDAP', 1)
739 assert(not ldap_r.found())
744 ###############################################################
746 ###############################################################
748 llvmopt = get_option('llvm')
750 if add_languages('cpp', required: llvmopt, native: false)
751 llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
755 cdata.set('USE_LLVM', 1)
757 cpp = meson.get_compiler('cpp')
759 llvm_binpath = llvm.get_variable(configtool: 'bindir')
761 ccache = find_program('ccache', native: true, required: false)
762 clang = find_program(llvm_binpath / 'clang', required: true)
765 message('llvm requires a C++ compiler')
770 ###############################################################
772 ###############################################################
774 icuopt = get_option('icu')
775 if not icuopt.disabled()
776 icu = dependency('icu-uc', required: icuopt)
777 icu_i18n = dependency('icu-i18n', required: icuopt)
780 cdata.set('USE_ICU', 1)
785 icu_i18n = not_found_dep
790 ###############################################################
792 ###############################################################
794 libxmlopt = get_option('libxml')
795 if not libxmlopt.disabled()
796 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
799 cdata.set('USE_LIBXML', 1)
802 libxml = not_found_dep
807 ###############################################################
809 ###############################################################
811 libxsltopt = get_option('libxslt')
812 if not libxsltopt.disabled()
813 libxslt = dependency('libxslt', required: libxsltopt)
816 cdata.set('USE_LIBXSLT', 1)
819 libxslt = not_found_dep
824 ###############################################################
826 ###############################################################
828 lz4opt = get_option('lz4')
829 if not lz4opt.disabled()
830 lz4 = dependency('liblz4', required: lz4opt)
833 cdata.set('USE_LZ4', 1)
834 cdata.set('HAVE_LIBLZ4', 1)
843 ###############################################################
844 # Library: Tcl (for pltcl)
846 # NB: tclConfig.sh is used in autoconf build for getting
847 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
848 # variables. For now we have not seen a need to copy
849 # that behaviour to the meson build.
850 ###############################################################
852 tclopt = get_option('pltcl')
853 tcl_version = get_option('tcl_version')
854 tcl_dep = not_found_dep
855 if not tclopt.disabled()
858 tcl_dep = dependency(tcl_version, required: false)
860 if not tcl_dep.found()
861 tcl_dep = cc.find_library(tcl_version,
866 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
867 tcl_dep = not_found_dep
873 ###############################################################
875 ###############################################################
877 pamopt = get_option('pam')
878 if not pamopt.disabled()
879 pam = dependency('pam', required: false)
882 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
886 pam_header_found = false
888 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
889 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
890 args: test_c_args, include_directories: postgres_inc)
891 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
892 pam_header_found = true
893 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
894 args: test_c_args, include_directories: postgres_inc)
895 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
896 pam_header_found = true
900 cdata.set('USE_PAM', 1)
911 ###############################################################
912 # Library: Perl (for plperl)
913 ###############################################################
915 perlopt = get_option('plperl')
916 perl_dep = not_found_dep
917 if not perlopt.disabled()
920 # First verify that perl has the necessary dependencies installed
921 perl_mods = run_command(
923 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
926 if perl_mods.returncode() != 0
927 perl_may_work = false
928 perl_msg = 'perl installation does not have the required modules'
931 # Then inquire perl about its configuration
933 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
934 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
935 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
936 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
937 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
939 perl_inc_dir = '@0@/CORE'.format(archlibexp)
941 if perlversion.version_compare('< 5.14')
942 perl_may_work = false
943 perl_msg = 'Perl version 5.14 or later is required, but this is @0@'.format(perlversion)
944 elif useshrplib != 'true'
945 perl_may_work = false
946 perl_msg = 'need a shared perl'
951 # On most platforms, archlibexp is also where the Perl include files live ...
952 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
953 # ... but on newer macOS versions, we must use -iwithsysroot to look
955 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
956 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
957 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
960 # check compiler finds header
961 if not cc.has_header('perl.h', required: false,
962 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
963 perl_may_work = false
964 perl_msg = 'missing perl.h'
969 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
971 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
972 foreach flag : perl_ccflags_r.split(' ')
973 if flag.startswith('-D') and \
974 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
979 if host_system == 'windows'
980 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
982 if cc.get_id() == 'msvc'
983 # prevent binary mismatch between MSVC built plperl and Strawberry or
984 # msys ucrt perl libraries
985 perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE']
989 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
990 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
992 # We are after Embed's ldopts, but without the subset mentioned in
993 # Config's ccdlflags and ldflags. (Those are the choices of those who
994 # built the Perl installation, which are not necessarily appropriate
995 # for building PostgreSQL.)
996 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
997 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
998 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
1001 foreach ldopt : ldopts.split(' ')
1002 if ldopt == '' or ldopt in undesired
1006 perl_ldopts += ldopt.strip('"')
1009 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
1010 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
1012 perl_dep_int = declare_dependency(
1013 compile_args: perl_ccflags,
1014 link_args: perl_ldopts,
1015 version: perlversion,
1018 # While we're at it, check that we can link to libperl.
1019 # On most platforms, if perl.h is there then libperl.so will be too, but
1020 # at this writing Debian packages them separately.
1021 perl_link_test = '''
1024 #define __inline__ inline
1032 if not cc.links(perl_link_test, name: 'libperl',
1033 args: test_c_args + perl_ccflags + perl_ldopts,
1034 include_directories: postgres_inc)
1035 perl_may_work = false
1036 perl_msg = 'missing libperl'
1039 endif # perl_may_work
1042 perl_dep = perl_dep_int
1044 if perlopt.enabled()
1045 error('dependency plperl failed: @0@'.format(perl_msg))
1047 message('disabling optional dependency plperl: @0@'.format(perl_msg))
1054 ###############################################################
1055 # Library: Python (for plpython)
1056 ###############################################################
1058 pyopt = get_option('plpython')
1059 python3_dep = not_found_dep
1060 if not pyopt.disabled()
1061 pm = import('python')
1062 python3_inst = pm.find_installation(required: pyopt)
1063 if python3_inst.found()
1064 python3_dep = python3_inst.dependency(embed: true, required: pyopt)
1065 # Remove this check after we depend on Meson >= 1.1.0
1066 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt)
1067 python3_dep = not_found_dep
1074 ###############################################################
1076 ###############################################################
1078 if not get_option('readline').disabled()
1079 libedit_preferred = get_option('libedit_preferred')
1080 # Set the order of readline dependencies
1081 check_readline_deps = libedit_preferred ? \
1082 ['libedit', 'readline'] : ['readline', 'libedit']
1084 foreach readline_dep : check_readline_deps
1085 readline = dependency(readline_dep, required: false)
1086 if not readline.found()
1087 readline = cc.find_library(readline_dep,
1088 required: get_option('readline'),
1097 cdata.set('HAVE_LIBREADLINE', 1)
1100 'header_prefix': 'editline/',
1101 'flag_prefix': 'EDITLINE_',
1104 'header_prefix': 'readline/',
1105 'flag_prefix': 'READLINE_',
1108 'header_prefix': '',
1112 # Set the order of prefixes
1113 prefixes = libedit_preferred ? \
1114 [editline_prefix, default_prefix, readline_prefix] : \
1115 [readline_prefix, default_prefix, editline_prefix]
1117 at_least_one_header_found = false
1118 foreach header : ['history', 'readline']
1120 foreach prefix : prefixes
1121 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1122 # Check history.h and readline.h
1123 if not is_found and cc.has_header(header_file,
1124 args: test_c_args, include_directories: postgres_inc,
1125 dependencies: [readline], required: false)
1126 if header == 'readline'
1127 readline_h = header_file
1129 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1131 at_least_one_header_found = true
1136 if not at_least_one_header_found
1137 error('''readline header not found
1138 If you have @0@ already installed, see meson-log/meson-log.txt for details on the
1139 failure. It is possible the compiler isn't looking in the proper directory.
1140 Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
1145 'history_truncate_file',
1146 'rl_completion_matches',
1147 'rl_filename_completion_function',
1148 'rl_reset_screen_size',
1152 foreach func : check_funcs
1153 found = cc.has_function(func, dependencies: [readline],
1154 args: test_c_args, include_directories: postgres_inc)
1155 cdata.set('HAVE_' + func.to_upper(), found ? 1 : false)
1159 'rl_completion_suppress_quote',
1160 'rl_filename_quote_characters',
1161 'rl_filename_quoting_function',
1164 foreach var : check_vars
1165 cdata.set('HAVE_' + var.to_upper(),
1166 cc.has_header_symbol(readline_h, var,
1167 args: test_c_args, include_directories: postgres_inc,
1168 prefix: '#include <stdio.h>',
1169 dependencies: [readline]) ? 1 : false)
1172 # If found via cc.find_library() ensure headers are found when using the
1173 # dependency. On meson < 0.57 one cannot do compiler checks using the
1174 # dependency returned by declare_dependency(), so we can't do this above.
1175 if readline.type_name() == 'library'
1176 readline = declare_dependency(dependencies: readline,
1177 include_directories: postgres_inc)
1180 # On windows with mingw readline requires auto-import to successfully
1181 # link, as the headers don't use declspec(dllimport)
1182 if host_system == 'windows' and cc.get_id() != 'msvc'
1183 readline = declare_dependency(dependencies: readline,
1184 link_args: '-Wl,--enable-auto-import')
1188 # XXX: Figure out whether to implement mingw warning equivalent
1190 readline = not_found_dep
1195 ###############################################################
1197 ###############################################################
1199 selinux = not_found_dep
1200 selinuxopt = get_option('selinux')
1201 if meson.version().version_compare('>=0.59')
1202 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1204 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1205 cdata.set('HAVE_LIBSELINUX',
1206 selinux.found() ? 1 : false)
1210 ###############################################################
1212 ###############################################################
1214 systemd = not_found_dep
1215 systemdopt = get_option('systemd')
1216 if meson.version().version_compare('>=0.59')
1217 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1219 systemd = dependency('libsystemd', required: systemdopt)
1220 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1224 ###############################################################
1226 ###############################################################
1229 ssl_library = 'none'
1230 sslopt = get_option('ssl')
1232 if sslopt == 'auto' and auto_features.disabled()
1236 if sslopt in ['auto', 'openssl']
1237 openssl_required = (sslopt == 'openssl')
1239 # Try to find openssl via pkg-config et al, if that doesn't work
1240 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1241 # the library names that we know about.
1243 # via pkg-config et al
1244 ssl = dependency('openssl', required: false)
1245 # only meson >= 0.57 supports declare_dependency() in cc.has_function(), so
1246 # we pass cc.find_library() results if necessary
1249 # via library + headers
1251 ssl_lib = cc.find_library('ssl',
1253 header_include_directories: postgres_inc,
1254 has_headers: ['openssl/ssl.h', 'openssl/err.h'],
1255 required: openssl_required)
1256 crypto_lib = cc.find_library('crypto',
1258 required: openssl_required)
1259 if ssl_lib.found() and crypto_lib.found()
1260 ssl_int = [ssl_lib, crypto_lib]
1261 ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc)
1263 elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \
1264 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required)
1272 ['CRYPTO_new_ex_data', {'required': true}],
1273 ['SSL_new', {'required': true}],
1275 # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
1276 ['SSL_CTX_set_cert_cb'],
1278 # Functions introduced in OpenSSL 1.1.0. We used to check for
1279 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1280 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1281 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1283 ['OPENSSL_init_ssl'],
1286 ['ASN1_STRING_get0_data'],
1290 # OpenSSL versions before 1.1.0 required setting callback functions, for
1291 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1292 # function was removed.
1295 # Function introduced in OpenSSL 1.1.1
1296 ['X509_get_signature_info'],
1299 are_openssl_funcs_complete = true
1300 foreach c : check_funcs
1302 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1303 required = c.get(1, {}).get('required', false)
1304 if required and not val
1305 are_openssl_funcs_complete = false
1307 error('openssl function @0@ is required'.format(func))
1311 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1315 if are_openssl_funcs_complete
1316 cdata.set('USE_OPENSSL', 1,
1317 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1318 cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
1319 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
1320 ssl_library = 'openssl'
1327 if sslopt == 'auto' and auto_features.enabled() and not ssl.found()
1328 error('no SSL library found')
1333 ###############################################################
1335 ###############################################################
1337 uuidopt = get_option('uuid')
1338 if uuidopt != 'none'
1339 uuidname = uuidopt.to_upper()
1340 if uuidopt == 'e2fs'
1341 uuid = dependency('uuid', required: true)
1342 uuidfunc = 'uuid_generate'
1343 uuidheader = 'uuid/uuid.h'
1344 elif uuidopt == 'bsd'
1345 # libc should have uuid function
1346 uuid = declare_dependency()
1347 uuidfunc = 'uuid_to_string'
1348 uuidheader = 'uuid.h'
1349 elif uuidopt == 'ossp'
1350 uuid = dependency('ossp-uuid', required: true)
1351 uuidfunc = 'uuid_export'
1352 uuidheader = 'uuid.h'
1354 error('unknown uuid build option value: @0@'.format(uuidopt))
1357 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1358 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1360 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1362 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1363 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1365 uuid = not_found_dep
1370 ###############################################################
1372 ###############################################################
1374 zlibopt = get_option('zlib')
1375 zlib = not_found_dep
1376 if not zlibopt.disabled()
1377 zlib_t = dependency('zlib', required: zlibopt)
1379 if zlib_t.type_name() == 'internal'
1380 # if fallback was used, we don't need to test if headers are present (they
1381 # aren't built yet, so we can't test)
1383 elif not zlib_t.found()
1384 warning('did not find zlib')
1385 elif not cc.has_header('zlib.h',
1386 args: test_c_args, include_directories: postgres_inc,
1387 dependencies: [zlib_t], required: zlibopt)
1388 warning('zlib header not found')
1394 cdata.set('HAVE_LIBZ', 1)
1400 ###############################################################
1401 # Library: tap test dependencies
1402 ###############################################################
1404 # Check whether tap tests are enabled or not
1405 tap_tests_enabled = false
1406 tapopt = get_option('tap_tests')
1407 if not tapopt.disabled()
1408 # Checking for perl modules for tap tests
1409 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1410 if perl_ipc_run_check.returncode() != 0
1411 message(perl_ipc_run_check.stderr().strip())
1413 error('Additional Perl modules are required to run TAP tests.')
1415 warning('Additional Perl modules are required to run TAP tests.')
1418 tap_tests_enabled = true
1424 ###############################################################
1426 ###############################################################
1428 zstdopt = get_option('zstd')
1429 if not zstdopt.disabled()
1430 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1433 cdata.set('USE_ZSTD', 1)
1434 cdata.set('HAVE_LIBZSTD', 1)
1438 zstd = not_found_dep
1443 ###############################################################
1445 ###############################################################
1447 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1448 # unnecessarily, because we optionally rely on newer features.
1450 #include <stdbool.h>
1451 #include <complex.h>
1453 #include <inttypes.h>
1455 struct named_init_test {
1460 extern void structfunc(struct named_init_test);
1462 int main(int argc, char **argv)
1464 struct named_init_test nit = {
1469 for (int loop_var = 0; loop_var < 3; loop_var++)
1474 structfunc((struct named_init_test){1, 0});
1480 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1481 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1482 args: test_c_args + ['-std=c99'])
1483 test_c_args += '-std=c99'
1484 cflags += '-std=c99'
1486 error('C compiler does not support C99')
1490 sizeof_long = cc.sizeof('long', args: test_c_args)
1491 cdata.set('SIZEOF_LONG', sizeof_long)
1493 cdata.set('HAVE_LONG_INT_64', 1)
1494 cdata.set('PG_INT64_TYPE', 'long int')
1495 cdata.set_quoted('INT64_MODIFIER', 'l')
1496 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1497 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1498 cdata.set('PG_INT64_TYPE', 'long long int')
1499 cdata.set_quoted('INT64_MODIFIER', 'll')
1501 error('do not know how to get a 64bit int')
1504 if host_machine.endian() == 'big'
1505 cdata.set('WORDS_BIGENDIAN', 1)
1508 alignof_types = ['short', 'int', 'long', 'double']
1510 foreach t : alignof_types
1511 align = cc.alignment(t, args: test_c_args)
1515 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1517 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1519 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1520 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1523 # Check if __int128 is a working 128 bit integer type, and if so
1524 # define PG_INT128_TYPE to that typename.
1526 # This currently only detects a GCC/clang extension, but support for other
1527 # environments may be added in the future.
1529 # For the moment we only test for support for 128bit math; support for
1530 # 128bit literals and snprintf is not required.
1533 * We don't actually run this test, just link it to verify that any support
1534 * functions needed for __int128 are present.
1536 * These are globals to discourage the compiler from folding all the
1537 * arithmetic tests down to compile-time constants. We do not have
1538 * convenient support for 128bit literals at this point...
1540 __int128 a = 48828125;
1541 __int128 b = 97656250;
1546 a = (a << 12) + 1; /* 200000000001 */
1547 b = (b << 12) + 5; /* 400000000005 */
1548 /* try the most relevant arithmetic ops */
1551 /* must use the results, else compiler may optimize arithmetic away */
1557 buggy_int128 = false
1559 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1560 # If not cross-compiling, we can test for bugs and disable use of __int128
1561 # with buggy compilers. If cross-compiling, hope for the best.
1562 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1563 if not meson.is_cross_build()
1565 /* This must match the corresponding code in c.h: */
1566 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1567 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1568 #elif defined(_MSC_VER)
1569 #define pg_attribute_aligned(a) __declspec(align(a))
1571 typedef __int128 int128a
1572 #if defined(pg_attribute_aligned)
1573 pg_attribute_aligned(8)
1578 void pass_by_val(void *buffer, int128a par) { holder = par; }
1582 long int i64 = 97656225L << 12;
1584 pass_by_val(main, (int128a) i64);
1588 name: '__int128 alignment bug',
1590 assert(r.compiled())
1591 if r.returncode() != 0
1593 message('__int128 support present but buggy and thus disabled')
1598 cdata.set('PG_INT128_TYPE', '__int128')
1599 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.alignment('__int128', args: test_c_args))
1604 # Check if the C compiler knows computed gotos (gcc extension, also
1605 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1607 # Checking whether computed gotos are supported syntax-wise ought to
1608 # be enough, as the syntax is otherwise illegal.
1610 static inline int foo(void)
1612 void *labeladdrs[] = {&&my_label};
1613 goto *labeladdrs[0];
1618 cdata.set('HAVE_COMPUTED_GOTO', 1)
1622 # Check if the C compiler understands _Static_assert(),
1623 # and define HAVE__STATIC_ASSERT if so.
1625 # We actually check the syntax ({ _Static_assert(...) }), because we need
1626 # gcc-style compound expressions to be able to wrap the thing into macros.
1628 int main(int arg, char **argv)
1630 ({ _Static_assert(1, "foo"); });
1634 cdata.set('HAVE__STATIC_ASSERT', 1)
1638 # We use <stdbool.h> if we have it and it declares type bool as having
1639 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1640 if cc.has_type('_Bool', args: test_c_args) \
1641 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1642 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1643 cdata.set('HAVE__BOOL', 1)
1644 cdata.set('PG_USE_STDBOOL', 1)
1648 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1649 # warning for each use of %m.
1650 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1652 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1653 static void call_log(void)
1655 emit_log(0, "error: %s: %m", "foo");
1658 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1659 foreach a : printf_attributes
1660 if cc.compiles(testsrc.format(a),
1661 args: test_c_args + attrib_error_args, name: 'format ' + a)
1662 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1668 if cc.has_function_attribute('visibility:default') and \
1669 cc.has_function_attribute('visibility:hidden')
1670 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1672 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1673 # inlineshidden to C code as well... And either way, we want to put these
1674 # flags into exported files (pgxs, .pc files).
1675 cflags_mod += '-fvisibility=hidden'
1676 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1677 ldflags_mod += '-fvisibility=hidden'
1681 # Check if various builtins exist. Some builtins are tested separately,
1682 # because we want to test something more complicated than the generic case.
1695 foreach builtin : builtins
1696 fname = '__builtin_@0@'.format(builtin)
1697 if cc.has_function(fname, args: test_c_args)
1698 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1703 # Check if the C compiler understands __builtin_types_compatible_p,
1704 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1706 # We check usage with __typeof__, though it's unlikely any compiler would
1707 # have the former and not the latter.
1710 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1712 name: '__builtin_types_compatible_p',
1714 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1718 # Check if the C compiler understands __builtin_$op_overflow(),
1719 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1721 # Check for the most complicated case, 64 bit multiplication, as a
1722 # proxy for all of the operations. To detect the case where the compiler
1723 # knows the function but library support is missing, we must link not just
1724 # compile, and store the results in global variables so the compiler doesn't
1725 # optimize away the call.
1733 return __builtin_mul_overflow(a, b, &result);
1735 name: '__builtin_mul_overflow',
1736 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1738 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1742 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1743 # here. To prevent problems due to two detection methods working, stop
1744 # checking after one.
1747 int main(int arg, char **argv)
1749 unsigned int exx[4] = {0, 0, 0, 0};
1750 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1752 ''', name: '__get_cpuid',
1754 cdata.set('HAVE__GET_CPUID', 1)
1757 int main(int arg, char **argv)
1759 unsigned int exx[4] = {0, 0, 0, 0};
1762 ''', name: '__cpuid',
1764 cdata.set('HAVE__CPUID', 1)
1768 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1769 # versions of clang do not understand -fexcess-precision=standard, the use of
1770 # x87 floating point operations leads to problems like isinf possibly returning
1771 # false for a value that is infinite when converted from the 80bit register to
1772 # the 8byte memory representation.
1774 # Only perform the test if the compiler doesn't understand
1775 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1777 if '-fexcess-precision=standard' not in cflags
1778 if not cc.compiles('''
1779 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1782 name: '', args: test_c_args)
1783 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1789 ###############################################################
1791 ###############################################################
1793 common_functional_flags = [
1794 # Disable strict-aliasing rules; needed for gcc 3.3+
1795 '-fno-strict-aliasing',
1796 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1798 '-fexcess-precision=standard',
1801 cflags += cc.get_supported_arguments(common_functional_flags)
1803 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1806 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1807 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1809 common_warning_flags = [
1810 '-Wmissing-prototypes',
1812 # Really don't want VLAs to be used in our dialect of C
1814 # On macOS, complain about usage of symbols newer than the deployment target
1815 '-Werror=unguarded-availability-new',
1817 '-Wmissing-format-attribute',
1818 '-Wimplicit-fallthrough=3',
1819 '-Wcast-function-type',
1820 '-Wshadow=compatible-local',
1821 # This was included in -Wall/-Wformat in older GCC versions
1822 '-Wformat-security',
1825 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1827 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1830 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1831 # the result for them
1832 cflags_no_decl_after_statement = []
1833 if cc.has_argument('-Wdeclaration-after-statement')
1834 cflags_warn += '-Wdeclaration-after-statement'
1835 cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
1839 # The following tests want to suppress various unhelpful warnings by adding
1840 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1841 # switches, so we have to test for the positive form and if that works,
1842 # add the negative form.
1844 negative_warning_flags = [
1845 # Suppress clang's unhelpful unused-command-line-argument warnings.
1846 'unused-command-line-argument',
1848 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1849 # of warnings when building plperl because of usages in the Perl headers.
1850 'compound-token-split-by-macro',
1852 # Similarly disable useless truncation warnings from gcc 8+
1853 'format-truncation',
1854 'stringop-truncation',
1856 # Suppress clang 16's strict warnings about function casts
1857 'cast-function-type-strict',
1859 # To make warning_level=2 / -Wextra work, we'd need at least the following
1861 # 'missing-field-initializers',
1863 # 'unused-parameter',
1866 foreach w : negative_warning_flags
1867 if cc.has_argument('-W' + w)
1868 cflags_warn += '-Wno-' + w
1870 if llvm.found() and cpp.has_argument('-W' + w)
1871 cxxflags_warn += '-Wno-' + w
1877 if cc.get_id() == 'msvc'
1879 '/wd4018', # signed/unsigned mismatch
1880 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1881 '/wd4273', # inconsistent DLL linkage
1882 '/wd4101', # unreferenced local variable
1883 '/wd4102', # unreferenced label
1884 '/wd4090', # different 'modifier' qualifiers
1885 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1893 '/D_CRT_SECURE_NO_DEPRECATE',
1894 '/D_CRT_NONSTDC_NO_DEPRECATE',
1897 # We never need export libraries. As link.exe reports their creation, they
1898 # are unnecessarily noisy. Similarly, we don't need import library for
1899 # modules, we only import them dynamically, and they're also noisy.
1901 ldflags_mod += '/NOIMPLIB'
1906 ###############################################################
1908 ###############################################################
1910 if not get_option('spinlocks')
1911 warning('Not using spinlocks will cause poor performance')
1913 cdata.set('HAVE_SPINLOCKS', 1)
1916 if not get_option('atomics')
1917 warning('Not using atomics will cause poor performance')
1919 # XXX: perhaps we should require some atomics support in this case these
1921 cdata.set('HAVE_ATOMICS', 1)
1924 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
1925 'desc': '__sync_lock_test_and_set(char)',
1928 __sync_lock_test_and_set(&lock, 1);
1929 __sync_lock_release(&lock);'''},
1931 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
1932 'desc': '__sync_lock_test_and_set(int32)',
1935 __sync_lock_test_and_set(&lock, 1);
1936 __sync_lock_release(&lock);'''},
1938 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
1939 'desc': '__sync_val_compare_and_swap(int32)',
1942 __sync_val_compare_and_swap(&val, 0, 37);'''},
1944 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
1945 'desc': '__sync_val_compare_and_swap(int64)',
1948 __sync_val_compare_and_swap(&val, 0, 37);'''},
1950 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
1951 'desc': ' __atomic_compare_exchange_n(int32)',
1955 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1957 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
1958 'desc': ' __atomic_compare_exchange_n(int64)',
1962 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1965 foreach check : atomic_checks
1970 }'''.format(check['test'])
1972 cdata.set(check['name'],
1974 name: check['desc'],
1975 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
1983 ###############################################################
1984 # Select CRC-32C implementation.
1986 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
1987 # use the special CRC instructions for calculating CRC-32C. If we're not
1988 # targeting such a processor, but we can nevertheless produce code that uses
1989 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
1990 # implementations and select which one to use at runtime, depending on whether
1991 # SSE 4.2 is supported by the processor we're running on.
1993 # Similarly, if we are targeting an ARM processor that has the CRC
1994 # instructions that are part of the ARMv8 CRC Extension, use them. And if
1995 # we're not targeting such a processor, but can nevertheless produce code that
1996 # uses the CRC instructions, compile both, and select at runtime.
1997 ###############################################################
1999 have_optimized_crc = false
2001 if host_cpu == 'x86' or host_cpu == 'x86_64'
2003 if cc.get_id() == 'msvc'
2004 cdata.set('USE_SSE42_CRC32C', false)
2005 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2006 have_optimized_crc = true
2010 #include <nmmintrin.h>
2014 unsigned int crc = 0;
2015 crc = _mm_crc32_u8(crc, 0);
2016 crc = _mm_crc32_u32(crc, 0);
2017 /* return computed value, to prevent the above being optimized away */
2022 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
2024 # Use Intel SSE 4.2 unconditionally.
2025 cdata.set('USE_SSE42_CRC32C', 1)
2026 have_optimized_crc = true
2027 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
2028 args: test_c_args + ['-msse4.2'])
2029 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
2030 # the runtime check.
2031 cflags_crc += '-msse4.2'
2032 cdata.set('USE_SSE42_CRC32C', false)
2033 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2034 have_optimized_crc = true
2039 elif host_cpu == 'arm' or host_cpu == 'aarch64'
2042 #include <arm_acle.h>
2046 unsigned int crc = 0;
2047 crc = __crc32cb(crc, 0);
2048 crc = __crc32ch(crc, 0);
2049 crc = __crc32cw(crc, 0);
2050 crc = __crc32cd(crc, 0);
2052 /* return computed value, to prevent the above being optimized away */
2057 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
2059 # Use ARM CRC Extension unconditionally
2060 cdata.set('USE_ARMV8_CRC32C', 1)
2061 have_optimized_crc = true
2062 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
2063 args: test_c_args + ['-march=armv8-a+crc'])
2064 # Use ARM CRC Extension, with runtime check
2065 cflags_crc += '-march=armv8-a+crc'
2066 cdata.set('USE_ARMV8_CRC32C', false)
2067 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
2068 have_optimized_crc = true
2071 elif host_cpu == 'loongarch64'
2076 unsigned int crc = 0;
2077 crc = __builtin_loongarch_crcc_w_b_w(0, crc);
2078 crc = __builtin_loongarch_crcc_w_h_w(0, crc);
2079 crc = __builtin_loongarch_crcc_w_w_w(0, crc);
2080 crc = __builtin_loongarch_crcc_w_d_w(0, crc);
2082 /* return computed value, to prevent the above being optimized away */
2087 if cc.links(prog, name: '__builtin_loongarch_crcc_w_b_w, __builtin_loongarch_crcc_w_h_w, __builtin_loongarch_crcc_w_w_w, and __builtin_loongarch_crcc_w_d_w',
2089 # Use LoongArch CRC instruction unconditionally
2090 cdata.set('USE_LOONGARCH_CRC32C', 1)
2091 have_optimized_crc = true
2096 if not have_optimized_crc
2097 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
2099 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
2104 ###############################################################
2105 # Other CPU specific stuff
2106 ###############################################################
2108 if host_cpu == 'x86_64'
2113 long long x = 1; long long r;
2114 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
2116 name: '@0@: popcntq instruction'.format(host_cpu),
2118 cdata.set('HAVE_X86_64_POPCNTQ', 1)
2121 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
2122 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
2123 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
2126 addi(int ra, int si)
2129 if (__builtin_constant_p(si))
2130 __asm__ __volatile__(
2131 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
2134 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2137 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2144 ###############################################################
2145 # Library / OS tests
2146 ###############################################################
2148 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2149 # unnecessary checks over and over, particularly on windows.
2163 'sys/personality.h',
2172 foreach header : header_checks
2173 varname = 'HAVE_' + header.underscorify().to_upper()
2175 # Emulate autoconf behaviour of not-found->undef, found->1
2176 found = cc.has_header(header,
2177 include_directories: postgres_inc, args: test_c_args)
2178 cdata.set(varname, found ? 1 : false,
2179 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2184 ['F_FULLFSYNC', 'fcntl.h'],
2185 ['fdatasync', 'unistd.h'],
2186 ['posix_fadvise', 'fcntl.h'],
2187 ['strlcat', 'string.h'],
2188 ['strlcpy', 'string.h'],
2189 ['strnlen', 'string.h'],
2192 # Need to check for function declarations for these functions, because
2193 # checking for library symbols wouldn't handle deployment target
2194 # restrictions on macOS
2196 ['preadv', 'sys/uio.h'],
2197 ['pwritev', 'sys/uio.h'],
2200 foreach c : decl_checks
2204 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2206 found = cc.has_header_symbol(header, func,
2207 args: test_c_args, include_directories: postgres_inc,
2209 cdata.set10(varname, found, description:
2210 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2211 don't.'''.format(func))
2215 if cc.has_type('struct option',
2216 args: test_c_args, include_directories: postgres_inc,
2217 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2218 cdata.set('HAVE_STRUCT_OPTION', 1)
2222 foreach c : ['opterr', 'optreset']
2223 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2232 '''.format(c), name: c, args: test_c_args)
2233 cdata.set(varname, 1)
2235 cdata.set(varname, false)
2239 if cc.has_type('socklen_t',
2240 args: test_c_args, include_directories: postgres_inc,
2242 #include <sys/socket.h>''')
2243 cdata.set('HAVE_SOCKLEN_T', 1)
2246 if cc.has_member('struct sockaddr', 'sa_len',
2247 args: test_c_args, include_directories: postgres_inc,
2249 #include <sys/types.h>
2250 #include <sys/socket.h>''')
2251 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2254 if cc.has_member('struct tm', 'tm_zone',
2255 args: test_c_args, include_directories: postgres_inc,
2257 #include <sys/types.h>
2260 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2265 extern int foo(void);
2268 return timezone / 60;
2271 name: 'global variable `timezone\' exists',
2272 args: test_c_args, include_directories: postgres_inc)
2273 cdata.set('HAVE_INT_TIMEZONE', 1)
2275 cdata.set('HAVE_INT_TIMEZONE', false)
2278 if cc.has_type('union semun',
2280 include_directories: postgres_inc,
2282 #include <sys/types.h>
2283 #include <sys/ipc.h>
2284 #include <sys/sem.h>
2286 cdata.set('HAVE_UNION_SEMUN', 1)
2294 switch (strerror_r(1, buf, sizeof(buf)))
2295 { case 0: break; default: break; }
2298 args: test_c_args, include_directories: postgres_inc)
2299 cdata.set('STRERROR_R_INT', 1)
2301 cdata.set('STRERROR_R_INT', false)
2304 # Find the right header file for the locale_t type. macOS needs xlocale.h;
2305 # standard is locale.h, but glibc <= 2.25 also had an xlocale.h file that
2306 # we should not use so we check the standard header first. MSVC has a
2307 # replacement defined in src/include/port/win32_port.h.
2308 if not cc.has_type('locale_t', prefix: '#include <locale.h>') and \
2309 cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2310 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2313 # Check if the C compiler understands typeof or a variant. Define
2314 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2315 foreach kw : ['typeof', '__typeof__', 'decltype']
2326 args: test_c_args, include_directories: postgres_inc)
2328 cdata.set('HAVE_TYPEOF', 1)
2330 cdata.set('typeof', kw)
2338 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2339 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2340 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2341 wcstombs_l_test = '''
2353 if (not cc.compiles(wcstombs_l_test.format(''),
2354 name: 'wcstombs_l') and
2355 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2356 name: 'wcstombs_l in xlocale.h'))
2357 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2361 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2362 # understands, because it conflicts with __declspec(restrict). Therefore we
2363 # define pg_restrict to the appropriate definition, which presumably won't
2366 # We assume C99 support, so we don't need to make this conditional.
2368 # XXX: Historically we allowed platforms to disable restrict in template
2369 # files, but that was only added for AIX when building with XLC, which we
2370 # don't support yet.
2371 cdata.set('pg_restrict', '__restrict')
2374 # Most libraries are included only if they demonstrably provide a function we
2375 # need, but libm is an exception: always include it, because there are too
2376 # many compilers that play cute optimization games that will break probes for
2377 # standard functions such as pow().
2378 os_deps += cc.find_library('m', required: false)
2380 rt_dep = cc.find_library('rt', required: false)
2382 dl_dep = cc.find_library('dl', required: false)
2384 util_dep = cc.find_library('util', required: false)
2386 getopt_dep = cc.find_library('getopt', required: false)
2387 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2388 # Check if we want to replace getopt/getopt_long even if provided by the system
2389 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2390 # so always use our version on Windows
2391 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2392 # (i.e., allow '-' as a flag character), so use our version on those platforms
2393 # - We want to use system's getopt_long() only if the system provides struct
2395 always_replace_getopt = host_system in ['windows', 'cygwin', 'openbsd', 'solaris']
2396 always_replace_getopt_long = host_system in ['windows', 'cygwin'] or not cdata.has('HAVE_STRUCT_OPTION')
2399 execinfo_dep = cc.find_library('execinfo', required: false)
2401 if host_system == 'cygwin'
2402 cygipc_dep = cc.find_library('cygipc', required: false)
2404 cygipc_dep = not_found_dep
2407 if host_system == 'sunos'
2408 socket_dep = cc.find_library('socket', required: false)
2410 socket_dep = not_found_dep
2413 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2414 # unnecessary checks over and over, particularly on windows.
2416 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2417 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2418 ['clock_gettime', {'dependencies': [rt_dep], 'define': false}],
2420 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2421 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2422 # required. Just checking for dlsym() ought to suffice.
2423 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2426 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2427 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2437 ['posix_fallocate'],
2440 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2441 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2442 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2443 ['setproctitle', {'dependencies': [util_dep]}],
2444 ['setproctitle_fast'],
2445 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2446 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2447 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2448 ['socket', {'dependencies': [socket_dep], 'define': false}],
2450 ['strerror_r', {'dependencies': [thread_dep]}],
2455 ['sync_file_range'],
2461 func_check_results = {}
2462 foreach c : func_checks
2464 kwargs = c.get(1, {})
2465 deps = kwargs.get('dependencies', [])
2467 if kwargs.get('skip', false)
2471 found = cc.has_function(func, args: test_c_args)
2478 found = cc.has_function(func, args: test_c_args,
2479 dependencies: [dep])
2487 func_check_results += {func: found}
2489 if kwargs.get('define', true)
2490 # Emulate autoconf behaviour of not-found->undef, found->1
2491 cdata.set('HAVE_' + func.underscorify().to_upper(),
2493 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2498 if cc.has_function('syslog', args: test_c_args) and \
2499 cc.check_header('syslog.h', args: test_c_args)
2500 cdata.set('HAVE_SYSLOG', 1)
2504 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2506 if sema_kind == 'unnamed_posix' and \
2507 not func_check_results.get('sem_init', false)
2511 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2512 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2514 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2515 cdata.set_quoted('DLSUFFIX', dlsuffix)
2518 # built later than the rest of the version metadata, we need SIZEOF_VOID_P
2519 cdata.set_quoted('PG_VERSION_STR',
2520 'PostgreSQL @0@ on @1@-@2@, compiled by @3@-@4@, @5@-bit'.format(
2521 pg_version, host_machine.cpu_family(), host_system,
2522 cc.get_id(), cc.version(), cdata.get('SIZEOF_VOID_P') * 8,
2527 ###############################################################
2529 ###############################################################
2531 nlsopt = get_option('nls')
2532 libintl = not_found_dep
2534 if not nlsopt.disabled()
2535 # otherwise there'd be lots of
2536 # "Gettext not found, all translation (po) targets will be ignored."
2537 # warnings if not found.
2538 msgfmt = find_program('msgfmt', required: nlsopt, native: true)
2540 # meson 0.59 has this wrapped in dependency('intl')
2541 if (msgfmt.found() and
2542 cc.check_header('libintl.h', required: nlsopt,
2543 args: test_c_args, include_directories: postgres_inc))
2546 if cc.has_function('ngettext')
2547 libintl = declare_dependency()
2549 libintl = cc.find_library('intl',
2550 has_headers: ['libintl.h'], required: nlsopt,
2551 header_include_directories: postgres_inc,
2557 i18n = import('i18n')
2558 cdata.set('ENABLE_NLS', 1)
2564 ###############################################################
2566 ###############################################################
2568 # Set up compiler / linker arguments to be used everywhere, individual targets
2569 # can add further args directly, or indirectly via dependencies
2570 add_project_arguments(cflags, language: ['c'])
2571 add_project_arguments(cppflags, language: ['c'])
2572 add_project_arguments(cflags_warn, language: ['c'])
2573 add_project_arguments(cxxflags, language: ['cpp'])
2574 add_project_arguments(cppflags, language: ['cpp'])
2575 add_project_arguments(cxxflags_warn, language: ['cpp'])
2576 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2579 # Collect a number of lists of things while recursing through the source
2580 # tree. Later steps then can use those.
2582 # list of targets for various alias targets
2583 backend_targets = []
2586 contrib_targets = []
2587 testprep_targets = []
2591 # Define the tests to distribute them to the correct test styles later
2596 # Default options for targets
2598 # First identify rpaths
2599 bin_install_rpaths = []
2600 lib_install_rpaths = []
2601 mod_install_rpaths = []
2604 # Don't add rpaths on darwin for now - as long as only absolute references to
2605 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2606 # their final destination.
2607 if host_system != 'darwin'
2608 # Add absolute path to libdir to rpath. This ensures installed binaries /
2609 # libraries find our libraries (mainly libpq).
2610 bin_install_rpaths += dir_prefix / dir_lib
2611 lib_install_rpaths += dir_prefix / dir_lib
2612 mod_install_rpaths += dir_prefix / dir_lib
2614 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2616 # Not needed on darwin even if we use relative rpaths for our own libraries,
2617 # as the install_name of libraries in extra_lib_dirs will point to their
2619 bin_install_rpaths += postgres_lib_d
2620 lib_install_rpaths += postgres_lib_d
2621 mod_install_rpaths += postgres_lib_d
2625 # Define arguments for default targets
2627 default_target_args = {
2628 'implicit_include_directories': false,
2632 default_lib_args = default_target_args + {
2636 internal_lib_args = default_lib_args + {
2637 'build_by_default': false,
2641 default_mod_args = default_lib_args + {
2643 'install_dir': dir_lib_pkg,
2646 default_bin_args = default_target_args + {
2647 'install_dir': dir_bin,
2650 if get_option('rpath')
2651 default_lib_args += {
2652 'install_rpath': ':'.join(lib_install_rpaths),
2655 default_mod_args += {
2656 'install_rpath': ':'.join(mod_install_rpaths),
2659 default_bin_args += {
2660 'install_rpath': ':'.join(bin_install_rpaths),
2665 # Helper for exporting a limited number of symbols
2666 gen_export_kwargs = {
2667 'input': 'exports.txt',
2668 'output': '@BASENAME@.'+export_file_suffix,
2669 'command': [perl, files('src/tools/gen_export.pl'),
2670 '--format', export_file_format,
2671 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2672 'build_by_default': false,
2679 ### Helpers for custom targets used across the tree
2682 catalog_pm = files('src/backend/catalog/Catalog.pm')
2683 perfect_hash_pm = files('src/tools/PerfectHash.pm')
2684 gen_kwlist_deps = [perfect_hash_pm]
2686 perl, '-I', '@SOURCE_ROOT@/src/tools',
2687 files('src/tools/gen_keywordlist.pl'),
2688 '--output', '@OUTDIR@', '@INPUT@']
2693 ### windows resources related stuff
2696 if host_system == 'windows'
2697 pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico'
2698 win32ver_rc = files('src/port/win32ver.rc')
2699 rcgen = find_program('src/tools/rcgen', native: true)
2702 '--srcdir', '@SOURCE_DIR@',
2703 '--builddir', meson.build_root(),
2704 '--rcout', '@OUTPUT0@',
2705 '--out', '@OUTPUT1@',
2706 '--input', '@INPUT@',
2710 if cc.get_argument_syntax() == 'msvc'
2711 rc = find_program('rc', required: true)
2712 rcgen_base_args += ['--rc', rc.path()]
2713 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.res']
2715 windres = find_program('windres', required: true)
2716 rcgen_base_args += ['--windres', windres.path()]
2717 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.obj']
2720 # msbuild backend doesn't support this atm
2721 if meson.backend() == 'ninja'
2722 rcgen_base_args += ['--depfile', '@DEPFILE@']
2725 rcgen_bin_args = rcgen_base_args + [
2726 '--VFT_TYPE', 'VFT_APP',
2727 '--FILEENDING', 'exe',
2731 rcgen_lib_args = rcgen_base_args + [
2732 '--VFT_TYPE', 'VFT_DLL',
2733 '--FILEENDING', 'dll',
2736 rc_bin_gen = generator(rcgen,
2737 depfile: '@BASENAME@.d',
2738 arguments: rcgen_bin_args,
2739 output: rcgen_outputs,
2742 rc_lib_gen = generator(rcgen,
2743 depfile: '@BASENAME@.d',
2744 arguments: rcgen_lib_args,
2745 output: rcgen_outputs,
2751 # headers that the whole build tree depends on
2752 generated_headers = []
2753 # headers that the backend build depends on
2754 generated_backend_headers = []
2755 # configure_files() output, needs a way of converting to file names
2756 configure_files = []
2758 # generated files that might conflict with a partial in-tree autoconf build
2759 generated_sources = []
2760 # same, for paths that differ between autoconf / meson builds
2761 # elements are [dir, [files]]
2762 generated_sources_ac = {}
2765 # First visit src/include - all targets creating headers are defined
2766 # within. That makes it easy to add the necessary dependencies for the
2767 # subsequent build steps.
2769 subdir('src/include')
2773 # Then through src/port and src/common, as most other things depend on them
2775 frontend_port_code = declare_dependency(
2776 compile_args: ['-DFRONTEND'],
2777 include_directories: [postgres_inc],
2778 dependencies: os_deps,
2781 backend_port_code = declare_dependency(
2782 compile_args: ['-DBUILDING_DLL'],
2783 include_directories: [postgres_inc],
2784 sources: [errcodes], # errcodes.h is needed due to use of ereport
2785 dependencies: os_deps,
2790 frontend_common_code = declare_dependency(
2791 compile_args: ['-DFRONTEND'],
2792 include_directories: [postgres_inc],
2793 sources: generated_headers,
2794 dependencies: [os_deps, zlib, zstd],
2797 backend_common_code = declare_dependency(
2798 compile_args: ['-DBUILDING_DLL'],
2799 include_directories: [postgres_inc],
2800 sources: generated_headers,
2801 dependencies: [os_deps, zlib, zstd],
2804 subdir('src/common')
2806 # all shared libraries should depend on shlib_code
2807 shlib_code = declare_dependency(
2808 link_args: ldflags_sl,
2811 # all static libraries not part of the backend should depend on this
2812 frontend_stlib_code = declare_dependency(
2813 include_directories: [postgres_inc],
2814 link_with: [common_static, pgport_static],
2815 sources: generated_headers,
2816 dependencies: [os_deps, libintl],
2819 # all shared libraries not part of the backend should depend on this
2820 frontend_shlib_code = declare_dependency(
2821 include_directories: [postgres_inc],
2822 link_with: [common_shlib, pgport_shlib],
2823 sources: generated_headers,
2824 dependencies: [shlib_code, os_deps, libintl],
2827 # Dependencies both for static and shared libpq
2837 subdir('src/interfaces/libpq')
2838 # fe_utils depends on libpq
2839 subdir('src/fe_utils')
2841 # for frontend binaries
2842 frontend_code = declare_dependency(
2843 include_directories: [postgres_inc],
2844 link_with: [fe_utils, common_static, pgport_static],
2845 sources: generated_headers,
2846 dependencies: [os_deps, libintl],
2849 backend_both_deps += [
2866 backend_mod_deps = backend_both_deps + os_deps
2868 backend_code = declare_dependency(
2869 compile_args: ['-DBUILDING_DLL'],
2870 include_directories: [postgres_inc],
2871 link_args: ldflags_be,
2873 sources: generated_headers + generated_backend_headers,
2874 dependencies: os_deps + backend_both_deps + backend_deps,
2877 # install these files only during test, not main install
2878 test_install_data = []
2879 test_install_libs = []
2881 # src/backend/meson.build defines backend_mod_code used for extension
2885 # Then through the main sources. That way contrib can have dependencies on
2886 # main sources. Note that this explicitly doesn't enter src/test, right now a
2887 # few regression tests depend on contrib files.
2894 subdir('src/interfaces/libpq/test')
2895 subdir('src/interfaces/ecpg/test')
2897 subdir('doc/src/sgml')
2899 generated_sources_ac += {'': ['GNUmakefile']}
2901 # After processing src/test, add test_install_libs to the testprep_targets
2903 testprep_targets += test_install_libs
2906 # If there are any files in the source directory that we also generate in the
2907 # build directory, they might get preferred over the newly generated files,
2908 # e.g. because of a #include "file", which always will search in the current
2910 message('checking for file conflicts between source and build directory')
2911 conflicting_files = []
2912 potentially_conflicting_files_t = []
2913 potentially_conflicting_files_t += generated_headers
2914 potentially_conflicting_files_t += generated_backend_headers
2915 potentially_conflicting_files_t += generated_backend_sources
2916 potentially_conflicting_files_t += generated_sources
2918 potentially_conflicting_files = []
2920 # convert all sources of potentially conflicting files into uniform shape
2921 foreach t : potentially_conflicting_files_t
2922 potentially_conflicting_files += t.full_path()
2924 foreach t : configure_files
2926 potentially_conflicting_files += meson.current_build_dir() / t
2928 foreach sub, fnames : generated_sources_ac
2929 sub = meson.build_root() / sub
2930 foreach fname : fnames
2931 potentially_conflicting_files += sub / fname
2935 # find and report conflicting files
2936 foreach build_path : potentially_conflicting_files
2937 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
2938 # str.replace is in 0.56
2939 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
2940 if fs.exists(src_path) or fs.is_symlink(src_path)
2941 conflicting_files += src_path
2944 # XXX: Perhaps we should generate a file that would clean these up? The list
2946 if conflicting_files.length() > 0
2947 errmsg_cleanup = '''
2948 Conflicting files in source directory:
2951 The conflicting files need to be removed, either by removing the files listed
2952 above, or by running configure and then make maintainer-clean.
2954 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
2955 error(errmsg_nonclean_base.format(errmsg_cleanup))
2960 ###############################################################
2962 ###############################################################
2965 # We want to define additional install targets beyond what meson provides. For
2966 # that we need to define targets depending on nearly everything. We collected
2967 # the results of i18n.gettext() invocations into nls_targets, that also
2968 # includes maintainer targets though. Collect the ones we want as a dependency.
2970 # i18n.gettext() doesn't return the dependencies before 0.60 - but the gettext
2971 # generation happens during install, so that's not a real issue.
2973 if libintl.found() and meson.version().version_compare('>=0.60')
2974 # use range() to avoid the flattening of the list that foreach() would do
2975 foreach off : range(0, nls_targets.length())
2976 # i18n.gettext() list containing 1) list of built .mo files 2) maintainer
2977 # -pot target 3) maintainer -pot target
2978 nls_mo_targets += nls_targets[off][0]
2980 alias_target('nls', nls_mo_targets)
2995 # Meson's default install target is quite verbose. Provide one that is quiet.
2996 install_quiet = custom_target('install-quiet',
2997 output: 'install-quiet',
2998 build_always_stale: true,
2999 build_by_default: false,
3000 command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'],
3004 # Target to install files used for tests, which aren't installed by default
3005 install_test_files_args = [
3007 '--prefix', dir_prefix,
3008 '--install', contrib_data_dir, test_install_data,
3009 '--install', dir_lib_pkg, test_install_libs,
3011 run_target('install-test-files',
3012 command: [python] + install_test_files_args,
3013 depends: testprep_targets,
3018 ###############################################################
3020 ###############################################################
3022 # DESTDIR for the installation we'll run tests in
3023 test_install_destdir = meson.build_root() / 'tmp_install/'
3025 # DESTDIR + prefix appropriately munged
3026 if build_system != 'windows'
3027 # On unixoid systems this is trivial, we just prepend the destdir
3028 assert(dir_prefix.startswith('/')) # enforced by meson
3029 test_install_location = '@0@@1@'.format(test_install_destdir, dir_prefix)
3031 # drives, drive-relative paths, etc make this complicated on windows, call
3032 # into a copy of meson's logic for it
3035 'import sys; from pathlib import PurePath; d1=sys.argv[1]; d2=sys.argv[2]; print(str(PurePath(d1, *PurePath(d2).parts[1:])))',
3036 test_install_destdir, dir_prefix]
3037 test_install_location = run_command(command, check: true).stdout().strip()
3040 meson_install_args = meson_args + ['install'] + {
3041 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
3045 # setup tests should be run first,
3046 # so define priority for these
3047 setup_tests_priority = 100
3049 meson_bin, args: meson_install_args ,
3050 env: {'DESTDIR':test_install_destdir},
3051 priority: setup_tests_priority,
3056 test('install_test_files',
3058 args: install_test_files_args + ['--destdir', test_install_destdir],
3059 priority: setup_tests_priority,
3063 test_result_dir = meson.build_root() / 'testrun'
3066 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
3067 # inevitable conflicts from running tests in parallel, hackishly assign
3068 # different ports for different tests.
3072 test_env = environment()
3074 temp_install_bindir = test_install_location / get_option('bindir')
3075 test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template'
3076 test_env.set('PG_REGRESS', pg_regress.full_path())
3077 test_env.set('REGRESS_SHLIB', regress_module.full_path())
3078 test_env.set('INITDB_TEMPLATE', test_initdb_template)
3080 # Test suites that are not safe by default but can be run if selected
3081 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
3082 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
3083 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
3085 # Add the temporary installation to the library search path on platforms where
3086 # that works (everything but windows, basically). On windows everything
3087 # library-like gets installed into bindir, solving that issue.
3088 if library_path_var != ''
3089 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
3093 # Create (and remove old) initdb template directory. Tests use that, where
3094 # possible, to make it cheaper to run tests.
3096 # Use python to remove the old cached initdb, as we cannot rely on a working
3097 # 'rm' binary on windows.
3098 test('initdb_cache',
3106 shutil.rmtree(sys.argv[1], ignore_errors=True)
3107 sp = subprocess.run(sys.argv[2:] + [sys.argv[1]])
3108 sys.exit(sp.returncode)
3110 test_initdb_template,
3111 temp_install_bindir / 'initdb',
3112 '-A', 'trust', '-N', '--no-instructions', '--no-locale'
3114 priority: setup_tests_priority - 1,
3122 ###############################################################
3124 ###############################################################
3126 # When using a meson version understanding exclude_suites, define a
3127 # 'tmp_install' test setup (the default) that excludes tests running against a
3128 # pre-existing install and a 'running' setup that conflicts with creation of
3129 # the temporary installation and tap tests (which don't support running
3130 # against a running server).
3134 if meson.version().version_compare('>=0.57')
3137 runningcheck = false
3140 testwrap = files('src/tools/testwrap')
3142 foreach test_dir : tests
3145 '--basedir', meson.build_root(),
3146 '--srcdir', test_dir['sd'],
3149 foreach kind, v : test_dir
3150 if kind in ['sd', 'bd', 'name']
3156 if kind in ['regress', 'isolation', 'ecpg']
3157 if kind == 'regress'
3159 fallback_dbname = 'regression_@0@'
3160 elif kind == 'isolation'
3161 runner = pg_isolation_regress
3162 fallback_dbname = 'isolation_regression_@0@'
3164 runner = pg_regress_ecpg
3165 fallback_dbname = 'ecpg_regression_@0@'
3168 test_group = test_dir['name']
3169 test_group_running = test_dir['name'] + '-running'
3171 test_output = test_result_dir / test_group / kind
3172 test_output_running = test_result_dir / test_group_running/ kind
3174 # Unless specified by the test, choose a non-conflicting database name,
3175 # to avoid conflicts when running against existing server.
3176 dbname = t.get('dbname',
3177 fallback_dbname.format(test_dir['name']))
3179 test_command_base = [
3181 '--inputdir', t.get('inputdir', test_dir['sd']),
3182 '--expecteddir', t.get('expecteddir', test_dir['sd']),
3184 '--dlpath', test_dir['bd'],
3185 '--max-concurrent-tests=20',
3187 ] + t.get('regress_args', [])
3190 if t.has_key('schedule')
3191 test_selection += ['--schedule', t['schedule'],]
3194 if kind == 'isolation'
3195 test_selection += t.get('specs', [])
3197 test_selection += t.get('sql', [])
3201 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
3207 'depends': test_deps + t.get('deps', []),
3209 } + t.get('test_kwargs', {})
3211 test(test_group / kind,
3215 '--testgroup', test_group,
3219 '--outputdir', test_output,
3220 '--temp-instance', test_output / 'tmp_check',
3221 '--port', testport.to_string(),
3225 kwargs: test_kwargs,
3227 install_suites += test_group
3229 # some tests can't support running against running DB
3230 if runningcheck and t.get('runningcheck', true)
3231 test(test_group_running / kind,
3235 '--testgroup', test_group_running,
3239 '--outputdir', test_output_running,
3242 is_parallel: t.get('runningcheck-parallel', true),
3243 suite: test_group_running,
3244 kwargs: test_kwargs,
3246 running_suites += test_group_running
3251 if not tap_tests_enabled
3257 '-I', meson.source_root() / 'src/test/perl',
3258 '-I', test_dir['sd'],
3261 # Add temporary install, the build directory for non-installed binaries and
3262 # also test/ for non-installed test binaries built separately.
3264 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
3266 foreach name, value : t.get('env', {})
3267 env.set(name, value)
3270 test_group = test_dir['name']
3273 'suite': test_group,
3275 'depends': test_deps + t.get('deps', []),
3277 } + t.get('test_kwargs', {})
3279 foreach onetap : t['tests']
3280 # Make tap test names prettier, remove t/ and .pl
3282 if onetap_p.startswith('t/')
3283 onetap_p = onetap.split('t/')[1]
3285 if onetap_p.endswith('.pl')
3286 onetap_p = fs.stem(onetap_p)
3289 test(test_dir['name'] / onetap_p,
3291 kwargs: test_kwargs,
3292 args: testwrap_base + [
3293 '--testgroup', test_dir['name'],
3294 '--testname', onetap_p,
3296 test_dir['sd'] / onetap,
3300 install_suites += test_group
3302 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
3305 endforeach # kinds of tests
3307 endforeach # directories with tests
3309 # repeat condition so meson realizes version dependency
3310 if meson.version().version_compare('>=0.57')
3311 add_test_setup('tmp_install',
3313 exclude_suites: running_suites)
3314 add_test_setup('running',
3315 exclude_suites: ['setup'] + install_suites)
3320 ###############################################################
3322 ###############################################################
3324 alias_target('backend', backend_targets)
3325 alias_target('bin', bin_targets + [libpq_st])
3326 alias_target('pl', pl_targets)
3327 alias_target('contrib', contrib_targets)
3328 alias_target('testprep', testprep_targets)
3329 alias_target('install-world', install_quiet, installdocs)
3333 ###############################################################
3334 # The End, The End, My Friend
3335 ###############################################################
3337 if meson.version().version_compare('>=0.57')
3341 'data block size': '@0@ kB'.format(cdata.get('BLCKSZ') / 1024),
3342 'WAL block size': '@0@ kB'.format(cdata.get('XLOG_BLCKSZ') / 1024),
3343 'segment size': get_option('segsize_blocks') != 0 ?
3344 '@0@ blocks'.format(cdata.get('RELSEG_SIZE')) :
3345 '@0@ GB'.format(get_option('segsize')),
3347 section: 'Data layout',
3352 'host system': '@0@ @1@'.format(host_system, host_cpu),
3353 'build system': '@0@ @1@'.format(build_machine.system(),
3354 build_machine.cpu_family()),
3361 'linker': '@0@'.format(cc.get_linker_id()),
3362 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
3364 section: 'Compiler',
3369 'CPP FLAGS': ' '.join(cppflags),
3370 'C FLAGS, functional': ' '.join(cflags),
3371 'C FLAGS, warnings': ' '.join(cflags_warn),
3372 'C FLAGS, modules': ' '.join(cflags_mod),
3373 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3374 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3376 section: 'Compiler Flags',
3382 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3384 section: 'Compiler',
3389 'C++ FLAGS, functional': ' '.join(cxxflags),
3390 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3391 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3393 section: 'Compiler Flags',
3399 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3401 'flex': '@0@ @1@'.format(flex.full_path(), flex_version),
3403 section: 'Programs',
3409 'bsd_auth': bsd_auth,
3411 'docs_pdf': docs_pdf_dep,
3423 'plpython': python3_dep,
3425 'readline': readline,
3432 section: 'External libraries',