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 distclean 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, required: false)
335 prove = find_program(get_option('PROVE'), native: true, required: false)
336 tar = find_program(get_option('TAR'), native: true, required: false)
337 gzip = find_program(get_option('GZIP'), native: true, required: false)
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'
515 if not (dir_prefix_contains_pg or dir_doc.contains('pgsql') or dir_doc.contains('postgres'))
516 dir_doc = dir_doc / pkg
518 dir_doc_html = dir_doc / 'html'
520 dir_locale = get_option('localedir')
524 dir_bitcode = dir_lib_pkg / 'bitcode'
525 dir_include_internal = dir_include_pkg / 'internal'
526 dir_include_server = dir_include_pkg / 'server'
527 dir_include_extension = dir_include_server / 'extension'
528 dir_data_extension = dir_data / 'extension'
529 dir_doc_extension = dir_doc / 'extension'
533 ###############################################################
534 # Search paths, preparation for compiler tests
536 # NB: Arguments added later are not automatically used for subsequent
537 # configuration-time checks (so they are more isolated). If they should be
538 # used, they need to be added to test_c_args as well.
539 ###############################################################
541 postgres_inc = [include_directories(postgres_inc_d)]
542 test_lib_d = postgres_lib_d
543 test_c_args = cppflags + cflags
547 ###############################################################
549 ###############################################################
551 bsd_authopt = get_option('bsd_auth')
552 bsd_auth = not_found_dep
553 if cc.check_header('bsd_auth.h', required: bsd_authopt,
554 args: test_c_args, include_directories: postgres_inc)
555 cdata.set('USE_BSD_AUTH', 1)
556 bsd_auth = declare_dependency()
561 ###############################################################
564 # For now don't search for DNSServiceRegister in a library - only Apple's
565 # Bonjour implementation, which is always linked, works.
566 ###############################################################
568 bonjouropt = get_option('bonjour')
569 bonjour = not_found_dep
570 if cc.check_header('dns_sd.h', required: bonjouropt,
571 args: test_c_args, include_directories: postgres_inc) and \
572 cc.has_function('DNSServiceRegister',
573 args: test_c_args, include_directories: postgres_inc)
574 cdata.set('USE_BONJOUR', 1)
575 bonjour = declare_dependency()
580 ###############################################################
581 # Option: docs in HTML and man page format
582 ###############################################################
584 docs_opt = get_option('docs')
585 docs_dep = not_found_dep
586 if not docs_opt.disabled()
587 if xmllint_bin.found() and xsltproc_bin.found()
588 docs_dep = declare_dependency()
589 elif docs_opt.enabled()
590 error('missing required tools for docs in HTML / man page format')
596 ###############################################################
597 # Option: docs in PDF format
598 ###############################################################
600 docs_pdf_opt = get_option('docs_pdf')
601 docs_pdf_dep = not_found_dep
602 if not docs_pdf_opt.disabled()
603 fop = find_program(get_option('FOP'), native: true, required: docs_pdf_opt)
604 if xmllint_bin.found() and xsltproc_bin.found() and fop.found()
605 docs_pdf_dep = declare_dependency()
606 elif docs_pdf_opt.enabled()
607 error('missing required tools for docs in PDF format')
613 ###############################################################
615 ###############################################################
617 gssapiopt = get_option('gssapi')
620 if not gssapiopt.disabled()
621 gssapi = dependency('krb5-gssapi', required: gssapiopt)
622 have_gssapi = gssapi.found()
625 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
626 args: test_c_args, include_directories: postgres_inc)
627 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
628 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
629 cdata.set('HAVE_GSSAPI_H', 1)
635 elif cc.check_header('gssapi/gssapi_ext.h', dependencies: gssapi, required: false,
636 args: test_c_args, include_directories: postgres_inc)
637 cdata.set('HAVE_GSSAPI_GSSAPI_EXT_H', 1)
638 elif cc.check_header('gssapi_ext.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
639 cdata.set('HAVE_GSSAPI_EXT_H', 1)
645 elif cc.has_function('gss_store_cred_into', dependencies: gssapi,
646 args: test_c_args, include_directories: postgres_inc)
647 cdata.set('ENABLE_GSS', 1)
649 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
650 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
651 elif gssapiopt.enabled()
652 error('''could not find function 'gss_store_cred_into' required for GSSAPI''')
658 gssapi = not_found_dep
663 ###############################################################
665 ###############################################################
667 ldapopt = get_option('ldap')
668 if ldapopt.disabled()
670 ldap_r = not_found_dep
671 elif host_system == 'windows'
672 ldap = cc.find_library('wldap32', required: ldapopt)
675 # macos framework dependency is buggy for ldap (one can argue whether it's
676 # Apple's or meson's fault), leading to an endless recursion with ldap.h
677 # including itself. See https://github.com/mesonbuild/meson/issues/10002
678 # Luckily we only need pkg-config support, so the workaround isn't
680 ldap = dependency('ldap', method: 'pkg-config', required: false)
683 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
686 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
687 has_headers: 'ldap.h', header_include_directories: postgres_inc)
689 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
690 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
691 # library from a separate OpenLDAP installation). The most reliable
692 # way to check that is to check for a function introduced in 2.5.
694 # don't have ldap, we shouldn't check for ldap_r
695 elif cc.has_function('ldap_verify_credentials',
696 dependencies: ldap, args: test_c_args)
697 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
700 # Use ldap_r for FE if available, else assume ldap is thread-safe.
701 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
702 has_headers: 'ldap.h', header_include_directories: postgres_inc)
703 if not ldap_r.found()
706 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
707 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
710 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
711 # process. Check for OpenLDAP versions known not to tolerate doing so;
712 # assume non-OpenLDAP implementations are safe. The dblink test suite
713 # exercises the hazardous interaction directly.
714 compat_test_code = '''
716 #if !defined(LDAP_VENDOR_VERSION) || \
717 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
718 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
722 if not cc.compiles(compat_test_code,
723 name: 'LDAP implementation compatible',
724 dependencies: ldap, args: test_c_args)
726 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
727 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
728 *** also uses LDAP will crash on exit.''')
733 if ldap.found() and cc.has_function('ldap_initialize',
734 dependencies: ldap, args: test_c_args)
735 cdata.set('HAVE_LDAP_INITIALIZE', 1)
740 assert(ldap_r.found())
741 cdata.set('USE_LDAP', 1)
743 assert(not ldap_r.found())
748 ###############################################################
750 ###############################################################
752 llvmopt = get_option('llvm')
754 if add_languages('cpp', required: llvmopt, native: false)
755 llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
759 cdata.set('USE_LLVM', 1)
761 cpp = meson.get_compiler('cpp')
763 llvm_binpath = llvm.get_variable(configtool: 'bindir')
765 ccache = find_program('ccache', native: true, required: false)
766 clang = find_program(llvm_binpath / 'clang', required: true)
769 message('llvm requires a C++ compiler')
774 ###############################################################
776 ###############################################################
778 icuopt = get_option('icu')
779 if not icuopt.disabled()
780 icu = dependency('icu-uc', required: icuopt)
781 icu_i18n = dependency('icu-i18n', required: icuopt)
784 cdata.set('USE_ICU', 1)
789 icu_i18n = not_found_dep
794 ###############################################################
796 ###############################################################
798 libxmlopt = get_option('libxml')
799 if not libxmlopt.disabled()
800 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
803 cdata.set('USE_LIBXML', 1)
806 libxml = not_found_dep
811 ###############################################################
813 ###############################################################
815 libxsltopt = get_option('libxslt')
816 if not libxsltopt.disabled()
817 libxslt = dependency('libxslt', required: libxsltopt)
820 cdata.set('USE_LIBXSLT', 1)
823 libxslt = not_found_dep
828 ###############################################################
830 ###############################################################
832 lz4opt = get_option('lz4')
833 if not lz4opt.disabled()
834 lz4 = dependency('liblz4', required: lz4opt)
837 cdata.set('USE_LZ4', 1)
838 cdata.set('HAVE_LIBLZ4', 1)
847 ###############################################################
848 # Library: Tcl (for pltcl)
850 # NB: tclConfig.sh is used in autoconf build for getting
851 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
852 # variables. For now we have not seen a need to copy
853 # that behaviour to the meson build.
854 ###############################################################
856 tclopt = get_option('pltcl')
857 tcl_version = get_option('tcl_version')
858 tcl_dep = not_found_dep
859 if not tclopt.disabled()
862 tcl_dep = dependency(tcl_version, required: false)
864 if not tcl_dep.found()
865 tcl_dep = cc.find_library(tcl_version,
870 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
871 tcl_dep = not_found_dep
877 ###############################################################
879 ###############################################################
881 pamopt = get_option('pam')
882 if not pamopt.disabled()
883 pam = dependency('pam', required: false)
886 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
890 pam_header_found = false
892 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
893 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
894 args: test_c_args, include_directories: postgres_inc)
895 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
896 pam_header_found = true
897 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
898 args: test_c_args, include_directories: postgres_inc)
899 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
900 pam_header_found = true
904 cdata.set('USE_PAM', 1)
915 ###############################################################
916 # Library: Perl (for plperl)
917 ###############################################################
919 perlopt = get_option('plperl')
920 perl_dep = not_found_dep
921 if not perlopt.disabled()
924 # First verify that perl has the necessary dependencies installed
925 perl_mods = run_command(
927 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
930 if perl_mods.returncode() != 0
931 perl_may_work = false
932 perl_msg = 'perl installation does not have the required modules'
935 # Then inquire perl about its configuration
937 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
938 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
939 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
940 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
941 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
943 perl_inc_dir = '@0@/CORE'.format(archlibexp)
945 if perlversion.version_compare('< 5.14')
946 perl_may_work = false
947 perl_msg = 'Perl version 5.14 or later is required, but this is @0@'.format(perlversion)
948 elif useshrplib != 'true'
949 perl_may_work = false
950 perl_msg = 'need a shared perl'
955 # On most platforms, archlibexp is also where the Perl include files live ...
956 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
957 # ... but on newer macOS versions, we must use -iwithsysroot to look
959 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
960 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
961 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
964 # check compiler finds header
965 if not cc.has_header('perl.h', required: false,
966 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
967 perl_may_work = false
968 perl_msg = 'missing perl.h'
973 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
975 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
976 foreach flag : perl_ccflags_r.split(' ')
977 if flag.startswith('-D') and \
978 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
983 if host_system == 'windows'
984 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
986 if cc.get_id() == 'msvc'
987 # prevent binary mismatch between MSVC built plperl and Strawberry or
988 # msys ucrt perl libraries
989 perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE']
993 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
994 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
996 # We are after Embed's ldopts, but without the subset mentioned in
997 # Config's ccdlflags and ldflags. (Those are the choices of those who
998 # built the Perl installation, which are not necessarily appropriate
999 # for building PostgreSQL.)
1000 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
1001 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
1002 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
1005 foreach ldopt : ldopts.split(' ')
1006 if ldopt == '' or ldopt in undesired
1010 perl_ldopts += ldopt.strip('"')
1013 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
1014 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
1016 perl_dep_int = declare_dependency(
1017 compile_args: perl_ccflags,
1018 link_args: perl_ldopts,
1019 version: perlversion,
1022 # While we're at it, check that we can link to libperl.
1023 # On most platforms, if perl.h is there then libperl.so will be too, but
1024 # at this writing Debian packages them separately.
1025 perl_link_test = '''
1028 #define __inline__ inline
1036 if not cc.links(perl_link_test, name: 'libperl',
1037 args: test_c_args + perl_ccflags + perl_ldopts,
1038 include_directories: postgres_inc)
1039 perl_may_work = false
1040 perl_msg = 'missing libperl'
1043 endif # perl_may_work
1046 perl_dep = perl_dep_int
1048 if perlopt.enabled()
1049 error('dependency plperl failed: @0@'.format(perl_msg))
1051 message('disabling optional dependency plperl: @0@'.format(perl_msg))
1058 ###############################################################
1059 # Library: Python (for plpython)
1060 ###############################################################
1062 pyopt = get_option('plpython')
1063 python3_dep = not_found_dep
1064 if not pyopt.disabled()
1065 pm = import('python')
1066 python3_inst = pm.find_installation(python.path(), required: pyopt)
1067 if python3_inst.found()
1068 python3_dep = python3_inst.dependency(embed: true, required: pyopt)
1069 # Remove this check after we depend on Meson >= 1.1.0
1070 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt)
1071 python3_dep = not_found_dep
1078 ###############################################################
1080 ###############################################################
1082 if not get_option('readline').disabled()
1083 libedit_preferred = get_option('libedit_preferred')
1084 # Set the order of readline dependencies
1085 check_readline_deps = libedit_preferred ? \
1086 ['libedit', 'readline'] : ['readline', 'libedit']
1088 foreach readline_dep : check_readline_deps
1089 readline = dependency(readline_dep, required: false)
1090 if not readline.found()
1091 readline = cc.find_library(readline_dep,
1092 required: get_option('readline'),
1101 cdata.set('HAVE_LIBREADLINE', 1)
1104 'header_prefix': 'editline/',
1105 'flag_prefix': 'EDITLINE_',
1108 'header_prefix': 'readline/',
1109 'flag_prefix': 'READLINE_',
1112 'header_prefix': '',
1116 # Set the order of prefixes
1117 prefixes = libedit_preferred ? \
1118 [editline_prefix, default_prefix, readline_prefix] : \
1119 [readline_prefix, default_prefix, editline_prefix]
1121 at_least_one_header_found = false
1122 foreach header : ['history', 'readline']
1124 foreach prefix : prefixes
1125 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1126 # Check history.h and readline.h
1127 if not is_found and cc.has_header(header_file,
1128 args: test_c_args, include_directories: postgres_inc,
1129 dependencies: [readline], required: false)
1130 if header == 'readline'
1131 readline_h = header_file
1133 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1135 at_least_one_header_found = true
1140 if not at_least_one_header_found
1141 error('''readline header not found
1142 If you have @0@ already installed, see meson-logs/meson-log.txt for details on the
1143 failure. It is possible the compiler isn't looking in the proper directory.
1144 Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
1149 'history_truncate_file',
1150 'rl_completion_matches',
1151 'rl_filename_completion_function',
1152 'rl_reset_screen_size',
1156 foreach func : check_funcs
1157 found = cc.has_function(func, dependencies: [readline],
1158 args: test_c_args, include_directories: postgres_inc)
1159 cdata.set('HAVE_' + func.to_upper(), found ? 1 : false)
1163 'rl_completion_suppress_quote',
1164 'rl_filename_quote_characters',
1165 'rl_filename_quoting_function',
1168 foreach var : check_vars
1169 cdata.set('HAVE_' + var.to_upper(),
1170 cc.has_header_symbol(readline_h, var,
1171 args: test_c_args, include_directories: postgres_inc,
1172 prefix: '#include <stdio.h>',
1173 dependencies: [readline]) ? 1 : false)
1176 # If found via cc.find_library() ensure headers are found when using the
1177 # dependency. On meson < 0.57 one cannot do compiler checks using the
1178 # dependency returned by declare_dependency(), so we can't do this above.
1179 if readline.type_name() == 'library'
1180 readline = declare_dependency(dependencies: readline,
1181 include_directories: postgres_inc)
1184 # On windows with mingw readline requires auto-import to successfully
1185 # link, as the headers don't use declspec(dllimport)
1186 if host_system == 'windows' and cc.get_id() != 'msvc'
1187 readline = declare_dependency(dependencies: readline,
1188 link_args: '-Wl,--enable-auto-import')
1192 # XXX: Figure out whether to implement mingw warning equivalent
1194 readline = not_found_dep
1199 ###############################################################
1201 ###############################################################
1203 selinux = not_found_dep
1204 selinuxopt = get_option('selinux')
1205 if meson.version().version_compare('>=0.59')
1206 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1208 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1209 cdata.set('HAVE_LIBSELINUX',
1210 selinux.found() ? 1 : false)
1214 ###############################################################
1216 ###############################################################
1218 systemd = not_found_dep
1219 systemdopt = get_option('systemd')
1220 if meson.version().version_compare('>=0.59')
1221 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1223 systemd = dependency('libsystemd', required: systemdopt)
1224 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1228 ###############################################################
1230 ###############################################################
1233 ssl_library = 'none'
1234 sslopt = get_option('ssl')
1236 if sslopt == 'auto' and auto_features.disabled()
1240 if sslopt in ['auto', 'openssl']
1241 openssl_required = (sslopt == 'openssl')
1243 # Try to find openssl via pkg-config et al, if that doesn't work
1244 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1245 # the library names that we know about.
1247 # via pkg-config et al
1248 ssl = dependency('openssl', required: false)
1249 # only meson >= 0.57 supports declare_dependency() in cc.has_function(), so
1250 # we pass cc.find_library() results if necessary
1253 # via library + headers
1255 ssl_lib = cc.find_library('ssl',
1257 header_include_directories: postgres_inc,
1258 has_headers: ['openssl/ssl.h', 'openssl/err.h'],
1259 required: openssl_required)
1260 crypto_lib = cc.find_library('crypto',
1262 required: openssl_required)
1263 if ssl_lib.found() and crypto_lib.found()
1264 ssl_int = [ssl_lib, crypto_lib]
1265 ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc)
1267 elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \
1268 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required)
1276 ['CRYPTO_new_ex_data', {'required': true}],
1277 ['SSL_new', {'required': true}],
1279 # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
1280 ['SSL_CTX_set_cert_cb'],
1282 # Functions introduced in OpenSSL 1.1.0. We used to check for
1283 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1284 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1285 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1287 ['OPENSSL_init_ssl'],
1289 ['ASN1_STRING_get0_data'],
1293 # OpenSSL versions before 1.1.0 required setting callback functions, for
1294 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1295 # function was removed.
1298 # Function introduced in OpenSSL 1.1.1
1299 ['X509_get_signature_info'],
1302 are_openssl_funcs_complete = true
1303 foreach c : check_funcs
1305 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1306 required = c.get(1, {}).get('required', false)
1307 if required and not val
1308 are_openssl_funcs_complete = false
1310 error('openssl function @0@ is required'.format(func))
1314 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1318 if are_openssl_funcs_complete
1319 cdata.set('USE_OPENSSL', 1,
1320 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1321 cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
1322 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
1323 ssl_library = 'openssl'
1330 if sslopt == 'auto' and auto_features.enabled() and not ssl.found()
1331 error('no SSL library found')
1336 ###############################################################
1338 ###############################################################
1340 uuidopt = get_option('uuid')
1341 if uuidopt != 'none'
1342 uuidname = uuidopt.to_upper()
1343 if uuidopt == 'e2fs'
1344 uuid = dependency('uuid', required: true)
1345 uuidfunc = 'uuid_generate'
1346 uuidheader = 'uuid/uuid.h'
1347 elif uuidopt == 'bsd'
1348 # libc should have uuid function
1349 uuid = declare_dependency()
1350 uuidfunc = 'uuid_to_string'
1351 uuidheader = 'uuid.h'
1352 elif uuidopt == 'ossp'
1353 uuid = dependency('ossp-uuid', required: true)
1354 uuidfunc = 'uuid_export'
1355 uuidheader = 'uuid.h'
1357 error('unknown uuid build option value: @0@'.format(uuidopt))
1360 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1361 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1363 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1365 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1366 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1368 uuid = not_found_dep
1373 ###############################################################
1375 ###############################################################
1377 zlibopt = get_option('zlib')
1378 zlib = not_found_dep
1379 if not zlibopt.disabled()
1380 zlib_t = dependency('zlib', required: zlibopt)
1382 if zlib_t.type_name() == 'internal'
1383 # if fallback was used, we don't need to test if headers are present (they
1384 # aren't built yet, so we can't test)
1386 elif not zlib_t.found()
1387 warning('did not find zlib')
1388 elif not cc.has_header('zlib.h',
1389 args: test_c_args, include_directories: postgres_inc,
1390 dependencies: [zlib_t], required: zlibopt)
1391 warning('zlib header not found')
1397 cdata.set('HAVE_LIBZ', 1)
1403 ###############################################################
1404 # Library: tap test dependencies
1405 ###############################################################
1407 # Check whether tap tests are enabled or not
1408 tap_tests_enabled = false
1409 tapopt = get_option('tap_tests')
1410 if not tapopt.disabled()
1411 # Checking for perl modules for tap tests
1412 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1413 if perl_ipc_run_check.returncode() != 0
1414 message(perl_ipc_run_check.stderr().strip())
1416 error('Additional Perl modules are required to run TAP tests.')
1418 warning('Additional Perl modules are required to run TAP tests.')
1421 tap_tests_enabled = true
1427 ###############################################################
1429 ###############################################################
1431 zstdopt = get_option('zstd')
1432 if not zstdopt.disabled()
1433 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1436 cdata.set('USE_ZSTD', 1)
1437 cdata.set('HAVE_LIBZSTD', 1)
1441 zstd = not_found_dep
1446 ###############################################################
1448 ###############################################################
1450 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1451 # unnecessarily, because we optionally rely on newer features.
1453 #include <stdbool.h>
1454 #include <complex.h>
1456 #include <inttypes.h>
1458 struct named_init_test {
1463 extern void structfunc(struct named_init_test);
1465 int main(int argc, char **argv)
1467 struct named_init_test nit = {
1472 for (int loop_var = 0; loop_var < 3; loop_var++)
1477 structfunc((struct named_init_test){1, 0});
1483 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1484 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1485 args: test_c_args + ['-std=c99'])
1486 test_c_args += '-std=c99'
1487 cflags += '-std=c99'
1489 error('C compiler does not support C99')
1493 sizeof_long = cc.sizeof('long', args: test_c_args)
1494 cdata.set('SIZEOF_LONG', sizeof_long)
1496 cdata.set('HAVE_LONG_INT_64', 1)
1497 cdata.set('PG_INT64_TYPE', 'long int')
1498 cdata.set_quoted('INT64_MODIFIER', 'l')
1499 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1500 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1501 cdata.set('PG_INT64_TYPE', 'long long int')
1502 cdata.set_quoted('INT64_MODIFIER', 'll')
1504 error('do not know how to get a 64bit int')
1507 if host_machine.endian() == 'big'
1508 cdata.set('WORDS_BIGENDIAN', 1)
1511 alignof_types = ['short', 'int', 'long', 'double']
1513 foreach t : alignof_types
1514 align = cc.alignment(t, args: test_c_args)
1518 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1520 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1522 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1523 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1526 # Check if __int128 is a working 128 bit integer type, and if so
1527 # define PG_INT128_TYPE to that typename.
1529 # This currently only detects a GCC/clang extension, but support for other
1530 # environments may be added in the future.
1532 # For the moment we only test for support for 128bit math; support for
1533 # 128bit literals and snprintf is not required.
1536 * We don't actually run this test, just link it to verify that any support
1537 * functions needed for __int128 are present.
1539 * These are globals to discourage the compiler from folding all the
1540 * arithmetic tests down to compile-time constants. We do not have
1541 * convenient support for 128bit literals at this point...
1543 __int128 a = 48828125;
1544 __int128 b = 97656250;
1549 a = (a << 12) + 1; /* 200000000001 */
1550 b = (b << 12) + 5; /* 400000000005 */
1551 /* try the most relevant arithmetic ops */
1554 /* must use the results, else compiler may optimize arithmetic away */
1560 buggy_int128 = false
1562 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1563 # If not cross-compiling, we can test for bugs and disable use of __int128
1564 # with buggy compilers. If cross-compiling, hope for the best.
1565 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1566 if not meson.is_cross_build()
1568 /* This must match the corresponding code in c.h: */
1569 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1570 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1571 #elif defined(_MSC_VER)
1572 #define pg_attribute_aligned(a) __declspec(align(a))
1574 typedef __int128 int128a
1575 #if defined(pg_attribute_aligned)
1576 pg_attribute_aligned(8)
1581 void pass_by_val(void *buffer, int128a par) { holder = par; }
1585 long int i64 = 97656225L << 12;
1587 pass_by_val(main, (int128a) i64);
1591 name: '__int128 alignment bug',
1593 assert(r.compiled())
1594 if r.returncode() != 0
1596 message('__int128 support present but buggy and thus disabled')
1601 cdata.set('PG_INT128_TYPE', '__int128')
1602 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.alignment('__int128', args: test_c_args))
1607 # Check if the C compiler knows computed gotos (gcc extension, also
1608 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1610 # Checking whether computed gotos are supported syntax-wise ought to
1611 # be enough, as the syntax is otherwise illegal.
1613 static inline int foo(void)
1615 void *labeladdrs[] = {&&my_label};
1616 goto *labeladdrs[0];
1621 cdata.set('HAVE_COMPUTED_GOTO', 1)
1625 # Check if the C compiler understands _Static_assert(),
1626 # and define HAVE__STATIC_ASSERT if so.
1628 # We actually check the syntax ({ _Static_assert(...) }), because we need
1629 # gcc-style compound expressions to be able to wrap the thing into macros.
1631 int main(int arg, char **argv)
1633 ({ _Static_assert(1, "foo"); });
1637 cdata.set('HAVE__STATIC_ASSERT', 1)
1641 # We use <stdbool.h> if we have it and it declares type bool as having
1642 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1643 if cc.has_type('_Bool', args: test_c_args) \
1644 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1645 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1646 cdata.set('HAVE__BOOL', 1)
1647 cdata.set('PG_USE_STDBOOL', 1)
1651 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1652 # warning for each use of %m.
1653 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1655 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1656 static void call_log(void)
1658 emit_log(0, "error: %s: %m", "foo");
1661 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1662 foreach a : printf_attributes
1663 if cc.compiles(testsrc.format(a),
1664 args: test_c_args + attrib_error_args, name: 'format ' + a)
1665 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1671 if cc.has_function_attribute('visibility:default') and \
1672 cc.has_function_attribute('visibility:hidden')
1673 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1675 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1676 # inlineshidden to C code as well... And either way, we want to put these
1677 # flags into exported files (pgxs, .pc files).
1678 cflags_mod += '-fvisibility=hidden'
1679 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1680 ldflags_mod += '-fvisibility=hidden'
1684 # Check if various builtins exist. Some builtins are tested separately,
1685 # because we want to test something more complicated than the generic case.
1698 foreach builtin : builtins
1699 fname = '__builtin_@0@'.format(builtin)
1700 if cc.has_function(fname, args: test_c_args)
1701 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1706 # Check if the C compiler understands __builtin_types_compatible_p,
1707 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1709 # We check usage with __typeof__, though it's unlikely any compiler would
1710 # have the former and not the latter.
1713 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1715 name: '__builtin_types_compatible_p',
1717 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1721 # Check if the C compiler understands __builtin_$op_overflow(),
1722 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1724 # Check for the most complicated case, 64 bit multiplication, as a
1725 # proxy for all of the operations. To detect the case where the compiler
1726 # knows the function but library support is missing, we must link not just
1727 # compile, and store the results in global variables so the compiler doesn't
1728 # optimize away the call.
1736 return __builtin_mul_overflow(a, b, &result);
1738 name: '__builtin_mul_overflow',
1739 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1741 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1745 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1746 # here. To prevent problems due to two detection methods working, stop
1747 # checking after one.
1750 int main(int arg, char **argv)
1752 unsigned int exx[4] = {0, 0, 0, 0};
1753 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1755 ''', name: '__get_cpuid',
1757 cdata.set('HAVE__GET_CPUID', 1)
1760 int main(int arg, char **argv)
1762 unsigned int exx[4] = {0, 0, 0, 0};
1765 ''', name: '__cpuid',
1767 cdata.set('HAVE__CPUID', 1)
1771 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1772 # versions of clang do not understand -fexcess-precision=standard, the use of
1773 # x87 floating point operations leads to problems like isinf possibly returning
1774 # false for a value that is infinite when converted from the 80bit register to
1775 # the 8byte memory representation.
1777 # Only perform the test if the compiler doesn't understand
1778 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1780 if '-fexcess-precision=standard' not in cflags
1781 if not cc.compiles('''
1782 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1785 name: '', args: test_c_args)
1786 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1792 ###############################################################
1794 ###############################################################
1796 common_functional_flags = [
1797 # Disable strict-aliasing rules; needed for gcc 3.3+
1798 '-fno-strict-aliasing',
1799 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1801 '-fexcess-precision=standard',
1804 cflags += cc.get_supported_arguments(common_functional_flags)
1806 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1809 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1810 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1812 common_warning_flags = [
1813 '-Wmissing-prototypes',
1815 # Really don't want VLAs to be used in our dialect of C
1817 # On macOS, complain about usage of symbols newer than the deployment target
1818 '-Werror=unguarded-availability-new',
1820 '-Wmissing-format-attribute',
1821 '-Wimplicit-fallthrough=3',
1822 '-Wcast-function-type',
1823 '-Wshadow=compatible-local',
1824 # This was included in -Wall/-Wformat in older GCC versions
1825 '-Wformat-security',
1828 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1830 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1833 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1834 # the result for them
1835 cflags_no_decl_after_statement = []
1836 if cc.has_argument('-Wdeclaration-after-statement')
1837 cflags_warn += '-Wdeclaration-after-statement'
1838 cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
1842 # The following tests want to suppress various unhelpful warnings by adding
1843 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1844 # switches, so we have to test for the positive form and if that works,
1845 # add the negative form.
1847 negative_warning_flags = [
1848 # Suppress clang's unhelpful unused-command-line-argument warnings.
1849 'unused-command-line-argument',
1851 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1852 # of warnings when building plperl because of usages in the Perl headers.
1853 'compound-token-split-by-macro',
1855 # Similarly disable useless truncation warnings from gcc 8+
1856 'format-truncation',
1857 'stringop-truncation',
1859 # Suppress clang 16's strict warnings about function casts
1860 'cast-function-type-strict',
1862 # To make warning_level=2 / -Wextra work, we'd need at least the following
1864 # 'missing-field-initializers',
1866 # 'unused-parameter',
1869 foreach w : negative_warning_flags
1870 if cc.has_argument('-W' + w)
1871 cflags_warn += '-Wno-' + w
1873 if llvm.found() and cpp.has_argument('-W' + w)
1874 cxxflags_warn += '-Wno-' + w
1879 if cc.get_id() == 'msvc'
1881 '/wd4018', # signed/unsigned mismatch
1882 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1883 '/wd4273', # inconsistent DLL linkage
1884 '/wd4101', # unreferenced local variable
1885 '/wd4102', # unreferenced label
1886 '/wd4090', # different 'modifier' qualifiers
1887 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1895 '/D_CRT_SECURE_NO_DEPRECATE',
1896 '/D_CRT_NONSTDC_NO_DEPRECATE',
1899 # We never need export libraries. As link.exe reports their creation, they
1900 # are unnecessarily noisy. Similarly, we don't need import library for
1901 # modules, we only import them dynamically, and they're also noisy.
1903 ldflags_mod += '/NOIMPLIB'
1908 ###############################################################
1910 ###############################################################
1912 if not get_option('spinlocks')
1913 warning('Not using spinlocks will cause poor performance')
1915 cdata.set('HAVE_SPINLOCKS', 1)
1918 if not get_option('atomics')
1919 warning('Not using atomics will cause poor performance')
1921 # XXX: perhaps we should require some atomics support in this case these
1923 cdata.set('HAVE_ATOMICS', 1)
1926 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
1927 'desc': '__sync_lock_test_and_set(char)',
1930 __sync_lock_test_and_set(&lock, 1);
1931 __sync_lock_release(&lock);'''},
1933 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
1934 'desc': '__sync_lock_test_and_set(int32)',
1937 __sync_lock_test_and_set(&lock, 1);
1938 __sync_lock_release(&lock);'''},
1940 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
1941 'desc': '__sync_val_compare_and_swap(int32)',
1944 __sync_val_compare_and_swap(&val, 0, 37);'''},
1946 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
1947 'desc': '__sync_val_compare_and_swap(int64)',
1950 __sync_val_compare_and_swap(&val, 0, 37);'''},
1952 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
1953 'desc': ' __atomic_compare_exchange_n(int32)',
1957 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1959 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
1960 'desc': ' __atomic_compare_exchange_n(int64)',
1964 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1967 foreach check : atomic_checks
1972 }'''.format(check['test'])
1974 cdata.set(check['name'],
1976 name: check['desc'],
1977 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
1985 ###############################################################
1986 # Select CRC-32C implementation.
1988 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
1989 # use the special CRC instructions for calculating CRC-32C. If we're not
1990 # targeting such a processor, but we can nevertheless produce code that uses
1991 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
1992 # implementations and select which one to use at runtime, depending on whether
1993 # SSE 4.2 is supported by the processor we're running on.
1995 # Similarly, if we are targeting an ARM processor that has the CRC
1996 # instructions that are part of the ARMv8 CRC Extension, use them. And if
1997 # we're not targeting such a processor, but can nevertheless produce code that
1998 # uses the CRC instructions, compile both, and select at runtime.
1999 ###############################################################
2001 have_optimized_crc = false
2003 if host_cpu == 'x86' or host_cpu == 'x86_64'
2005 if cc.get_id() == 'msvc'
2006 cdata.set('USE_SSE42_CRC32C', false)
2007 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2008 have_optimized_crc = true
2012 #include <nmmintrin.h>
2016 unsigned int crc = 0;
2017 crc = _mm_crc32_u8(crc, 0);
2018 crc = _mm_crc32_u32(crc, 0);
2019 /* return computed value, to prevent the above being optimized away */
2024 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
2026 # Use Intel SSE 4.2 unconditionally.
2027 cdata.set('USE_SSE42_CRC32C', 1)
2028 have_optimized_crc = true
2029 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
2030 args: test_c_args + ['-msse4.2'])
2031 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
2032 # the runtime check.
2033 cflags_crc += '-msse4.2'
2034 cdata.set('USE_SSE42_CRC32C', false)
2035 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2036 have_optimized_crc = true
2041 elif host_cpu == 'arm' or host_cpu == 'aarch64'
2044 #include <arm_acle.h>
2048 unsigned int crc = 0;
2049 crc = __crc32cb(crc, 0);
2050 crc = __crc32ch(crc, 0);
2051 crc = __crc32cw(crc, 0);
2052 crc = __crc32cd(crc, 0);
2054 /* return computed value, to prevent the above being optimized away */
2059 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
2061 # Use ARM CRC Extension unconditionally
2062 cdata.set('USE_ARMV8_CRC32C', 1)
2063 have_optimized_crc = true
2064 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
2065 args: test_c_args + ['-march=armv8-a+crc'])
2066 # Use ARM CRC Extension, with runtime check
2067 cflags_crc += '-march=armv8-a+crc'
2068 cdata.set('USE_ARMV8_CRC32C', false)
2069 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
2070 have_optimized_crc = true
2073 elif host_cpu == 'loongarch64'
2078 unsigned int crc = 0;
2079 crc = __builtin_loongarch_crcc_w_b_w(0, crc);
2080 crc = __builtin_loongarch_crcc_w_h_w(0, crc);
2081 crc = __builtin_loongarch_crcc_w_w_w(0, crc);
2082 crc = __builtin_loongarch_crcc_w_d_w(0, crc);
2084 /* return computed value, to prevent the above being optimized away */
2089 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',
2091 # Use LoongArch CRC instruction unconditionally
2092 cdata.set('USE_LOONGARCH_CRC32C', 1)
2093 have_optimized_crc = true
2098 if not have_optimized_crc
2099 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
2101 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
2106 ###############################################################
2107 # Other CPU specific stuff
2108 ###############################################################
2110 if host_cpu == 'x86_64'
2115 long long x = 1; long long r;
2116 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
2118 name: '@0@: popcntq instruction'.format(host_cpu),
2120 cdata.set('HAVE_X86_64_POPCNTQ', 1)
2123 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
2124 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
2125 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
2128 addi(int ra, int si)
2131 if (__builtin_constant_p(si))
2132 __asm__ __volatile__(
2133 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
2136 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2139 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2146 ###############################################################
2147 # Library / OS tests
2148 ###############################################################
2150 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2151 # unnecessary checks over and over, particularly on windows.
2165 'sys/personality.h',
2174 foreach header : header_checks
2175 varname = 'HAVE_' + header.underscorify().to_upper()
2177 # Emulate autoconf behaviour of not-found->undef, found->1
2178 found = cc.has_header(header,
2179 include_directories: postgres_inc, args: test_c_args)
2180 cdata.set(varname, found ? 1 : false,
2181 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2186 ['F_FULLFSYNC', 'fcntl.h'],
2187 ['fdatasync', 'unistd.h'],
2188 ['posix_fadvise', 'fcntl.h'],
2189 ['strlcat', 'string.h'],
2190 ['strlcpy', 'string.h'],
2191 ['strnlen', 'string.h'],
2194 # Need to check for function declarations for these functions, because
2195 # checking for library symbols wouldn't handle deployment target
2196 # restrictions on macOS
2198 ['preadv', 'sys/uio.h'],
2199 ['pwritev', 'sys/uio.h'],
2202 foreach c : decl_checks
2206 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2208 found = cc.has_header_symbol(header, func,
2209 args: test_c_args, include_directories: postgres_inc,
2211 cdata.set10(varname, found, description:
2212 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2213 don't.'''.format(func))
2217 if cc.has_type('struct option',
2218 args: test_c_args, include_directories: postgres_inc,
2219 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2220 cdata.set('HAVE_STRUCT_OPTION', 1)
2224 foreach c : ['opterr', 'optreset']
2225 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2234 '''.format(c), name: c, args: test_c_args)
2235 cdata.set(varname, 1)
2237 cdata.set(varname, false)
2241 if cc.has_type('socklen_t',
2242 args: test_c_args, include_directories: postgres_inc,
2244 #include <sys/socket.h>''')
2245 cdata.set('HAVE_SOCKLEN_T', 1)
2248 if cc.has_member('struct sockaddr', 'sa_len',
2249 args: test_c_args, include_directories: postgres_inc,
2251 #include <sys/types.h>
2252 #include <sys/socket.h>''')
2253 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2256 if cc.has_member('struct tm', 'tm_zone',
2257 args: test_c_args, include_directories: postgres_inc,
2259 #include <sys/types.h>
2262 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2267 extern int foo(void);
2270 return timezone / 60;
2273 name: 'global variable `timezone\' exists',
2274 args: test_c_args, include_directories: postgres_inc)
2275 cdata.set('HAVE_INT_TIMEZONE', 1)
2277 cdata.set('HAVE_INT_TIMEZONE', false)
2280 if cc.has_type('union semun',
2282 include_directories: postgres_inc,
2284 #include <sys/types.h>
2285 #include <sys/ipc.h>
2286 #include <sys/sem.h>
2288 cdata.set('HAVE_UNION_SEMUN', 1)
2296 switch (strerror_r(1, buf, sizeof(buf)))
2297 { case 0: break; default: break; }
2300 args: test_c_args, include_directories: postgres_inc)
2301 cdata.set('STRERROR_R_INT', 1)
2303 cdata.set('STRERROR_R_INT', false)
2306 # Find the right header file for the locale_t type. macOS needs xlocale.h;
2307 # standard is locale.h, but glibc <= 2.25 also had an xlocale.h file that
2308 # we should not use so we check the standard header first. MSVC has a
2309 # replacement defined in src/include/port/win32_port.h.
2310 if not cc.has_type('locale_t', prefix: '#include <locale.h>') and \
2311 cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2312 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2315 # Check if the C compiler understands typeof or a variant. Define
2316 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2317 foreach kw : ['typeof', '__typeof__', 'decltype']
2328 args: test_c_args, include_directories: postgres_inc)
2330 cdata.set('HAVE_TYPEOF', 1)
2332 cdata.set('typeof', kw)
2340 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2341 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2342 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2343 wcstombs_l_test = '''
2355 if (not cc.compiles(wcstombs_l_test.format(''),
2356 name: 'wcstombs_l') and
2357 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2358 name: 'wcstombs_l in xlocale.h'))
2359 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2363 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2364 # understands, because it conflicts with __declspec(restrict). Therefore we
2365 # define pg_restrict to the appropriate definition, which presumably won't
2368 # We assume C99 support, so we don't need to make this conditional.
2370 # XXX: Historically we allowed platforms to disable restrict in template
2371 # files, but that was only added for AIX when building with XLC, which we
2372 # don't support yet.
2373 cdata.set('pg_restrict', '__restrict')
2376 # Most libraries are included only if they demonstrably provide a function we
2377 # need, but libm is an exception: always include it, because there are too
2378 # many compilers that play cute optimization games that will break probes for
2379 # standard functions such as pow().
2380 os_deps += cc.find_library('m', required: false)
2382 rt_dep = cc.find_library('rt', required: false)
2384 dl_dep = cc.find_library('dl', required: false)
2386 util_dep = cc.find_library('util', required: false)
2388 getopt_dep = cc.find_library('getopt', required: false)
2389 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2390 # Check if we want to replace getopt/getopt_long even if provided by the system
2391 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2392 # so always use our version on Windows
2393 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2394 # (i.e., allow '-' as a flag character), so use our version on those platforms
2395 # - We want to use system's getopt_long() only if the system provides struct
2397 always_replace_getopt = host_system in ['windows', 'cygwin', 'openbsd', 'solaris']
2398 always_replace_getopt_long = host_system in ['windows', 'cygwin'] or not cdata.has('HAVE_STRUCT_OPTION')
2401 execinfo_dep = cc.find_library('execinfo', required: false)
2403 if host_system == 'cygwin'
2404 cygipc_dep = cc.find_library('cygipc', required: false)
2406 cygipc_dep = not_found_dep
2409 if host_system == 'sunos'
2410 socket_dep = cc.find_library('socket', required: false)
2412 socket_dep = not_found_dep
2415 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2416 # unnecessary checks over and over, particularly on windows.
2418 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2419 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2420 ['clock_gettime', {'dependencies': [rt_dep], 'define': false}],
2422 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2423 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2424 # required. Just checking for dlsym() ought to suffice.
2425 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2428 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2429 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2439 ['posix_fallocate'],
2442 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2443 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2444 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2445 ['setproctitle', {'dependencies': [util_dep]}],
2446 ['setproctitle_fast'],
2447 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2448 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2449 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2450 ['socket', {'dependencies': [socket_dep], 'define': false}],
2452 ['strerror_r', {'dependencies': [thread_dep]}],
2457 ['sync_file_range'],
2463 func_check_results = {}
2464 foreach c : func_checks
2466 kwargs = c.get(1, {})
2467 deps = kwargs.get('dependencies', [])
2469 if kwargs.get('skip', false)
2473 found = cc.has_function(func, args: test_c_args)
2480 found = cc.has_function(func, args: test_c_args,
2481 dependencies: [dep])
2489 func_check_results += {func: found}
2491 if kwargs.get('define', true)
2492 # Emulate autoconf behaviour of not-found->undef, found->1
2493 cdata.set('HAVE_' + func.underscorify().to_upper(),
2495 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2500 if cc.has_function('syslog', args: test_c_args) and \
2501 cc.check_header('syslog.h', args: test_c_args)
2502 cdata.set('HAVE_SYSLOG', 1)
2506 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2508 if sema_kind == 'unnamed_posix' and \
2509 not func_check_results.get('sem_init', false)
2513 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2514 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2516 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2517 cdata.set_quoted('DLSUFFIX', dlsuffix)
2520 # built later than the rest of the version metadata, we need SIZEOF_VOID_P
2521 cdata.set_quoted('PG_VERSION_STR',
2522 'PostgreSQL @0@ on @1@-@2@, compiled by @3@-@4@, @5@-bit'.format(
2523 pg_version, host_machine.cpu_family(), host_system,
2524 cc.get_id(), cc.version(), cdata.get('SIZEOF_VOID_P') * 8,
2529 ###############################################################
2531 ###############################################################
2533 nlsopt = get_option('nls')
2534 libintl = not_found_dep
2536 if not nlsopt.disabled()
2537 # otherwise there'd be lots of
2538 # "Gettext not found, all translation (po) targets will be ignored."
2539 # warnings if not found.
2540 msgfmt = find_program('msgfmt', required: nlsopt, native: true)
2542 # meson 0.59 has this wrapped in dependency('intl')
2543 if (msgfmt.found() and
2544 cc.check_header('libintl.h', required: nlsopt,
2545 args: test_c_args, include_directories: postgres_inc))
2548 if cc.has_function('ngettext')
2549 libintl = declare_dependency()
2551 libintl = cc.find_library('intl',
2552 has_headers: ['libintl.h'], required: nlsopt,
2553 header_include_directories: postgres_inc,
2559 i18n = import('i18n')
2560 cdata.set('ENABLE_NLS', 1)
2566 ###############################################################
2568 ###############################################################
2570 # Set up compiler / linker arguments to be used everywhere, individual targets
2571 # can add further args directly, or indirectly via dependencies
2572 add_project_arguments(cflags, language: ['c'])
2573 add_project_arguments(cppflags, language: ['c'])
2574 add_project_arguments(cflags_warn, language: ['c'])
2575 add_project_arguments(cxxflags, language: ['cpp'])
2576 add_project_arguments(cppflags, language: ['cpp'])
2577 add_project_arguments(cxxflags_warn, language: ['cpp'])
2578 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2581 # Collect a number of lists of things while recursing through the source
2582 # tree. Later steps then can use those.
2584 # list of targets for various alias targets
2585 backend_targets = []
2588 contrib_targets = []
2589 testprep_targets = []
2593 # Define the tests to distribute them to the correct test styles later
2598 # Default options for targets
2600 # First identify rpaths
2601 bin_install_rpaths = []
2602 lib_install_rpaths = []
2603 mod_install_rpaths = []
2606 # Don't add rpaths on darwin for now - as long as only absolute references to
2607 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2608 # their final destination.
2609 if host_system != 'darwin'
2610 # Add absolute path to libdir to rpath. This ensures installed binaries /
2611 # libraries find our libraries (mainly libpq).
2612 bin_install_rpaths += dir_prefix / dir_lib
2613 lib_install_rpaths += dir_prefix / dir_lib
2614 mod_install_rpaths += dir_prefix / dir_lib
2616 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2618 # Not needed on darwin even if we use relative rpaths for our own libraries,
2619 # as the install_name of libraries in extra_lib_dirs will point to their
2621 bin_install_rpaths += postgres_lib_d
2622 lib_install_rpaths += postgres_lib_d
2623 mod_install_rpaths += postgres_lib_d
2627 # Define arguments for default targets
2629 default_target_args = {
2630 'implicit_include_directories': false,
2634 default_lib_args = default_target_args + {
2638 internal_lib_args = default_lib_args + {
2639 'build_by_default': false,
2643 default_mod_args = default_lib_args + {
2645 'install_dir': dir_lib_pkg,
2648 default_bin_args = default_target_args + {
2649 'install_dir': dir_bin,
2652 if get_option('rpath')
2653 default_lib_args += {
2654 'install_rpath': ':'.join(lib_install_rpaths),
2657 default_mod_args += {
2658 'install_rpath': ':'.join(mod_install_rpaths),
2661 default_bin_args += {
2662 'install_rpath': ':'.join(bin_install_rpaths),
2667 # Helper for exporting a limited number of symbols
2668 gen_export_kwargs = {
2669 'input': 'exports.txt',
2670 'output': '@BASENAME@.'+export_file_suffix,
2671 'command': [perl, files('src/tools/gen_export.pl'),
2672 '--format', export_file_format,
2673 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2674 'build_by_default': false,
2681 ### Helpers for custom targets used across the tree
2684 catalog_pm = files('src/backend/catalog/Catalog.pm')
2685 perfect_hash_pm = files('src/tools/PerfectHash.pm')
2686 gen_kwlist_deps = [perfect_hash_pm]
2688 perl, '-I', '@SOURCE_ROOT@/src/tools',
2689 files('src/tools/gen_keywordlist.pl'),
2690 '--output', '@OUTDIR@', '@INPUT@']
2695 ### windows resources related stuff
2698 if host_system == 'windows'
2699 pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico'
2700 win32ver_rc = files('src/port/win32ver.rc')
2701 rcgen = find_program('src/tools/rcgen', native: true)
2704 '--srcdir', '@SOURCE_DIR@',
2705 '--builddir', meson.build_root(),
2706 '--rcout', '@OUTPUT0@',
2707 '--out', '@OUTPUT1@',
2708 '--input', '@INPUT@',
2712 if cc.get_argument_syntax() == 'msvc'
2713 rc = find_program('rc', required: true)
2714 rcgen_base_args += ['--rc', rc.path()]
2715 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.res']
2717 windres = find_program('windres', required: true)
2718 rcgen_base_args += ['--windres', windres.path()]
2719 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.obj']
2722 # msbuild backend doesn't support this atm
2723 if meson.backend() == 'ninja'
2724 rcgen_base_args += ['--depfile', '@DEPFILE@']
2727 rcgen_bin_args = rcgen_base_args + [
2728 '--VFT_TYPE', 'VFT_APP',
2729 '--FILEENDING', 'exe',
2733 rcgen_lib_args = rcgen_base_args + [
2734 '--VFT_TYPE', 'VFT_DLL',
2735 '--FILEENDING', 'dll',
2738 rc_bin_gen = generator(rcgen,
2739 depfile: '@BASENAME@.d',
2740 arguments: rcgen_bin_args,
2741 output: rcgen_outputs,
2744 rc_lib_gen = generator(rcgen,
2745 depfile: '@BASENAME@.d',
2746 arguments: rcgen_lib_args,
2747 output: rcgen_outputs,
2753 # headers that the whole build tree depends on
2754 generated_headers = []
2755 # headers that the backend build depends on
2756 generated_backend_headers = []
2757 # configure_files() output, needs a way of converting to file names
2758 configure_files = []
2760 # generated files that might conflict with a partial in-tree autoconf build
2761 generated_sources = []
2762 # same, for paths that differ between autoconf / meson builds
2763 # elements are [dir, [files]]
2764 generated_sources_ac = {}
2767 # First visit src/include - all targets creating headers are defined
2768 # within. That makes it easy to add the necessary dependencies for the
2769 # subsequent build steps.
2771 subdir('src/include')
2775 # Then through src/port and src/common, as most other things depend on them
2777 frontend_port_code = declare_dependency(
2778 compile_args: ['-DFRONTEND'],
2779 include_directories: [postgres_inc],
2780 dependencies: os_deps,
2783 backend_port_code = declare_dependency(
2784 compile_args: ['-DBUILDING_DLL'],
2785 include_directories: [postgres_inc],
2786 sources: [errcodes], # errcodes.h is needed due to use of ereport
2787 dependencies: os_deps,
2792 frontend_common_code = declare_dependency(
2793 compile_args: ['-DFRONTEND'],
2794 include_directories: [postgres_inc],
2795 sources: generated_headers,
2796 dependencies: [os_deps, zlib, zstd],
2799 backend_common_code = declare_dependency(
2800 compile_args: ['-DBUILDING_DLL'],
2801 include_directories: [postgres_inc],
2802 sources: generated_headers,
2803 dependencies: [os_deps, zlib, zstd],
2806 subdir('src/common')
2808 # all shared libraries should depend on shlib_code
2809 shlib_code = declare_dependency(
2810 link_args: ldflags_sl,
2813 # all static libraries not part of the backend should depend on this
2814 frontend_stlib_code = declare_dependency(
2815 include_directories: [postgres_inc],
2816 link_with: [common_static, pgport_static],
2817 sources: generated_headers,
2818 dependencies: [os_deps, libintl],
2821 # all shared libraries not part of the backend should depend on this
2822 frontend_shlib_code = declare_dependency(
2823 include_directories: [postgres_inc],
2824 link_with: [common_shlib, pgport_shlib],
2825 sources: generated_headers,
2826 dependencies: [shlib_code, os_deps, libintl],
2829 # Dependencies both for static and shared libpq
2839 subdir('src/interfaces/libpq')
2840 # fe_utils depends on libpq
2841 subdir('src/fe_utils')
2843 # for frontend binaries
2844 frontend_code = declare_dependency(
2845 include_directories: [postgres_inc],
2846 link_with: [fe_utils, common_static, pgport_static],
2847 sources: generated_headers,
2848 dependencies: [os_deps, libintl],
2851 backend_both_deps += [
2868 backend_mod_deps = backend_both_deps + os_deps
2870 backend_code = declare_dependency(
2871 compile_args: ['-DBUILDING_DLL'],
2872 include_directories: [postgres_inc],
2873 link_args: ldflags_be,
2875 sources: generated_headers + generated_backend_headers,
2876 dependencies: os_deps + backend_both_deps + backend_deps,
2879 # install these files only during test, not main install
2880 test_install_data = []
2881 test_install_libs = []
2883 # src/backend/meson.build defines backend_mod_code used for extension
2887 # Then through the main sources. That way contrib can have dependencies on
2888 # main sources. Note that this explicitly doesn't enter src/test, right now a
2889 # few regression tests depend on contrib files.
2896 subdir('src/interfaces/libpq/test')
2897 subdir('src/interfaces/ecpg/test')
2899 subdir('doc/src/sgml')
2901 generated_sources_ac += {'': ['GNUmakefile']}
2903 # After processing src/test, add test_install_libs to the testprep_targets
2905 testprep_targets += test_install_libs
2908 # If there are any files in the source directory that we also generate in the
2909 # build directory, they might get preferred over the newly generated files,
2910 # e.g. because of a #include "file", which always will search in the current
2912 message('checking for file conflicts between source and build directory')
2913 conflicting_files = []
2914 potentially_conflicting_files_t = []
2915 potentially_conflicting_files_t += generated_headers
2916 potentially_conflicting_files_t += generated_backend_headers
2917 potentially_conflicting_files_t += generated_backend_sources
2918 potentially_conflicting_files_t += generated_sources
2920 potentially_conflicting_files = []
2922 # convert all sources of potentially conflicting files into uniform shape
2923 foreach t : potentially_conflicting_files_t
2924 potentially_conflicting_files += t.full_path()
2926 foreach t1 : configure_files
2927 if meson.version().version_compare('>=0.59')
2928 t = fs.parent(t1) / fs.name(t1)
2930 t = '@0@'.format(t1)
2932 potentially_conflicting_files += meson.current_build_dir() / t
2934 foreach sub, fnames : generated_sources_ac
2935 sub = meson.build_root() / sub
2936 foreach fname : fnames
2937 potentially_conflicting_files += sub / fname
2941 # find and report conflicting files
2942 foreach build_path : potentially_conflicting_files
2943 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
2944 # str.replace is in 0.56
2945 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
2946 if fs.exists(src_path) or fs.is_symlink(src_path)
2947 conflicting_files += src_path
2950 # XXX: Perhaps we should generate a file that would clean these up? The list
2952 if conflicting_files.length() > 0
2953 errmsg_cleanup = '''
2954 Conflicting files in source directory:
2957 The conflicting files need to be removed, either by removing the files listed
2958 above, or by running configure and then make maintainer-clean.
2960 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
2961 error(errmsg_nonclean_base.format(errmsg_cleanup))
2966 ###############################################################
2968 ###############################################################
2971 # We want to define additional install targets beyond what meson provides. For
2972 # that we need to define targets depending on nearly everything. We collected
2973 # the results of i18n.gettext() invocations into nls_targets, that also
2974 # includes maintainer targets though. Collect the ones we want as a dependency.
2976 # i18n.gettext() doesn't return the dependencies before 0.60 - but the gettext
2977 # generation happens during install, so that's not a real issue.
2979 if libintl.found() and meson.version().version_compare('>=0.60')
2980 # use range() to avoid the flattening of the list that foreach() would do
2981 foreach off : range(0, nls_targets.length())
2982 # i18n.gettext() list containing 1) list of built .mo files 2) maintainer
2983 # -pot target 3) maintainer -pot target
2984 nls_mo_targets += nls_targets[off][0]
2986 alias_target('nls', nls_mo_targets)
3001 # Meson's default install target is quite verbose. Provide one that is quiet.
3002 install_quiet = custom_target('install-quiet',
3003 output: 'install-quiet',
3004 build_always_stale: true,
3005 build_by_default: false,
3006 command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'],
3010 # Target to install files used for tests, which aren't installed by default
3011 install_test_files_args = [
3013 '--prefix', dir_prefix,
3014 '--install', contrib_data_dir, test_install_data,
3015 '--install', dir_lib_pkg, test_install_libs,
3017 run_target('install-test-files',
3018 command: [python] + install_test_files_args,
3019 depends: testprep_targets,
3024 ###############################################################
3026 ###############################################################
3028 # DESTDIR for the installation we'll run tests in
3029 test_install_destdir = meson.build_root() / 'tmp_install/'
3031 # DESTDIR + prefix appropriately munged
3032 if build_system != 'windows'
3033 # On unixoid systems this is trivial, we just prepend the destdir
3034 assert(dir_prefix.startswith('/')) # enforced by meson
3035 test_install_location = '@0@@1@'.format(test_install_destdir, dir_prefix)
3037 # drives, drive-relative paths, etc make this complicated on windows, call
3038 # into a copy of meson's logic for it
3041 'import sys; from pathlib import PurePath; d1=sys.argv[1]; d2=sys.argv[2]; print(str(PurePath(d1, *PurePath(d2).parts[1:])))',
3042 test_install_destdir, dir_prefix]
3043 test_install_location = run_command(command, check: true).stdout().strip()
3046 meson_install_args = meson_args + ['install'] + {
3047 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
3051 # setup tests should be run first,
3052 # so define priority for these
3053 setup_tests_priority = 100
3055 meson_bin, args: meson_install_args ,
3056 env: {'DESTDIR':test_install_destdir},
3057 priority: setup_tests_priority,
3062 test('install_test_files',
3064 args: install_test_files_args + ['--destdir', test_install_destdir],
3065 priority: setup_tests_priority,
3069 test_result_dir = meson.build_root() / 'testrun'
3072 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
3073 # inevitable conflicts from running tests in parallel, hackishly assign
3074 # different ports for different tests.
3078 test_env = environment()
3080 temp_install_bindir = test_install_location / get_option('bindir')
3081 test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template'
3082 test_env.set('PG_REGRESS', pg_regress.full_path())
3083 test_env.set('REGRESS_SHLIB', regress_module.full_path())
3084 test_env.set('INITDB_TEMPLATE', test_initdb_template)
3086 # Test suites that are not safe by default but can be run if selected
3087 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
3088 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
3089 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
3091 # Add the temporary installation to the library search path on platforms where
3092 # that works (everything but windows, basically). On windows everything
3093 # library-like gets installed into bindir, solving that issue.
3094 if library_path_var != ''
3095 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
3099 # Create (and remove old) initdb template directory. Tests use that, where
3100 # possible, to make it cheaper to run tests.
3102 # Use python to remove the old cached initdb, as we cannot rely on a working
3103 # 'rm' binary on windows.
3104 test('initdb_cache',
3112 shutil.rmtree(sys.argv[1], ignore_errors=True)
3113 sp = subprocess.run(sys.argv[2:] + [sys.argv[1]])
3114 sys.exit(sp.returncode)
3116 test_initdb_template,
3117 temp_install_bindir / 'initdb',
3118 '--auth', 'trust', '--no-sync', '--no-instructions', '--no-locale',
3121 priority: setup_tests_priority - 1,
3129 ###############################################################
3131 ###############################################################
3133 # When using a meson version understanding exclude_suites, define a
3134 # 'tmp_install' test setup (the default) that excludes tests running against a
3135 # pre-existing install and a 'running' setup that conflicts with creation of
3136 # the temporary installation and tap tests (which don't support running
3137 # against a running server).
3141 if meson.version().version_compare('>=0.57')
3144 runningcheck = false
3147 testwrap = files('src/tools/testwrap')
3149 foreach test_dir : tests
3152 '--basedir', meson.build_root(),
3153 '--srcdir', test_dir['sd'],
3156 foreach kind, v : test_dir
3157 if kind in ['sd', 'bd', 'name']
3163 if kind in ['regress', 'isolation', 'ecpg']
3164 if kind == 'regress'
3166 fallback_dbname = 'regression_@0@'
3167 elif kind == 'isolation'
3168 runner = pg_isolation_regress
3169 fallback_dbname = 'isolation_regression_@0@'
3171 runner = pg_regress_ecpg
3172 fallback_dbname = 'ecpg_regression_@0@'
3175 test_group = test_dir['name']
3176 test_group_running = test_dir['name'] + '-running'
3178 test_output = test_result_dir / test_group / kind
3179 test_output_running = test_result_dir / test_group_running/ kind
3181 # Unless specified by the test, choose a non-conflicting database name,
3182 # to avoid conflicts when running against existing server.
3183 dbname = t.get('dbname',
3184 fallback_dbname.format(test_dir['name']))
3186 test_command_base = [
3188 '--inputdir', t.get('inputdir', test_dir['sd']),
3189 '--expecteddir', t.get('expecteddir', test_dir['sd']),
3191 '--dlpath', test_dir['bd'],
3192 '--max-concurrent-tests=20',
3194 ] + t.get('regress_args', [])
3197 if t.has_key('schedule')
3198 test_selection += ['--schedule', t['schedule'],]
3201 if kind == 'isolation'
3202 test_selection += t.get('specs', [])
3204 test_selection += t.get('sql', [])
3208 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
3214 'depends': test_deps + t.get('deps', []),
3216 } + t.get('test_kwargs', {})
3218 test(test_group / kind,
3222 '--testgroup', test_group,
3226 '--outputdir', test_output,
3227 '--temp-instance', test_output / 'tmp_check',
3228 '--port', testport.to_string(),
3232 kwargs: test_kwargs,
3234 install_suites += test_group
3236 # some tests can't support running against running DB
3237 if runningcheck and t.get('runningcheck', true)
3238 test(test_group_running / kind,
3242 '--testgroup', test_group_running,
3246 '--outputdir', test_output_running,
3249 is_parallel: t.get('runningcheck-parallel', true),
3250 suite: test_group_running,
3251 kwargs: test_kwargs,
3253 running_suites += test_group_running
3258 testwrap_tap = testwrap_base
3259 if not tap_tests_enabled
3260 testwrap_tap += ['--skip', 'TAP tests not enabled']
3265 '-I', meson.source_root() / 'src/test/perl',
3266 '-I', test_dir['sd'],
3269 # Add temporary install, the build directory for non-installed binaries and
3270 # also test/ for non-installed test binaries built separately.
3272 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
3274 foreach name, value : t.get('env', {})
3275 env.set(name, value)
3278 test_group = test_dir['name']
3281 'suite': test_group,
3283 'depends': test_deps + t.get('deps', []),
3285 } + t.get('test_kwargs', {})
3287 foreach onetap : t['tests']
3288 # Make tap test names prettier, remove t/ and .pl
3290 if onetap_p.startswith('t/')
3291 onetap_p = onetap.split('t/')[1]
3293 if onetap_p.endswith('.pl')
3294 onetap_p = fs.stem(onetap_p)
3297 test(test_dir['name'] / onetap_p,
3299 kwargs: test_kwargs,
3300 args: testwrap_tap + [
3301 '--testgroup', test_dir['name'],
3302 '--testname', onetap_p,
3304 test_dir['sd'] / onetap,
3308 install_suites += test_group
3310 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
3313 endforeach # kinds of tests
3315 endforeach # directories with tests
3317 # repeat condition so meson realizes version dependency
3318 if meson.version().version_compare('>=0.57')
3319 add_test_setup('tmp_install',
3321 exclude_suites: running_suites)
3322 add_test_setup('running',
3323 exclude_suites: ['setup'] + install_suites)
3328 ###############################################################
3330 ###############################################################
3332 alias_target('backend', backend_targets)
3333 alias_target('bin', bin_targets + [libpq_st])
3334 alias_target('pl', pl_targets)
3335 alias_target('contrib', contrib_targets)
3336 alias_target('testprep', testprep_targets)
3338 alias_target('world', all_built, docs)
3339 alias_target('install-world', install_quiet, installdocs)
3343 perl, '-ne', 'next if /^#/; print',
3344 files('doc/src/sgml/targets-meson.txt'),
3350 ###############################################################
3351 # The End, The End, My Friend
3352 ###############################################################
3354 if meson.version().version_compare('>=0.57')
3358 'data block size': '@0@ kB'.format(cdata.get('BLCKSZ') / 1024),
3359 'WAL block size': '@0@ kB'.format(cdata.get('XLOG_BLCKSZ') / 1024),
3360 'segment size': get_option('segsize_blocks') != 0 ?
3361 '@0@ blocks'.format(cdata.get('RELSEG_SIZE')) :
3362 '@0@ GB'.format(get_option('segsize')),
3364 section: 'Data layout',
3369 'host system': '@0@ @1@'.format(host_system, host_cpu),
3370 'build system': '@0@ @1@'.format(build_machine.system(),
3371 build_machine.cpu_family()),
3378 'linker': '@0@'.format(cc.get_linker_id()),
3379 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
3381 section: 'Compiler',
3386 'CPP FLAGS': ' '.join(cppflags),
3387 'C FLAGS, functional': ' '.join(cflags),
3388 'C FLAGS, warnings': ' '.join(cflags_warn),
3389 'C FLAGS, modules': ' '.join(cflags_mod),
3390 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3391 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3393 section: 'Compiler Flags',
3399 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3401 section: 'Compiler',
3406 'C++ FLAGS, functional': ' '.join(cxxflags),
3407 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3408 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3410 section: 'Compiler Flags',
3416 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3418 'flex': '@0@ @1@'.format(flex.full_path(), flex_version),
3420 section: 'Programs',
3426 'bsd_auth': bsd_auth,
3428 'docs_pdf': docs_pdf_dep,
3440 'plpython': python3_dep,
3442 'readline': readline,
3449 section: 'External libraries',