1 # Copyright (c) 2022-2024, 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 exesuffix = '' # overridden below where necessary
163 dlsuffix = '.so' # overridden below where necessary
164 library_path_var = 'LD_LIBRARY_PATH'
166 # Format of file to control exports from libraries, and how to pass them to
167 # the compiler. For export_fmt @0@ is the path to the file export file.
168 export_file_format = 'gnu'
169 export_file_suffix = 'list'
170 export_fmt = '-Wl,--version-script=@0@'
172 # Flags to add when linking a postgres extension, @0@ is path to
173 # the relevant object on the platform.
174 mod_link_args_fmt = []
176 memset_loop_limit = 1024
178 # Choice of shared memory and semaphore implementation
182 # We implement support for some operating systems by pretending they're
183 # another. Map here, before determining system properties below
184 if host_system == 'dragonfly'
185 # apparently the most similar
186 host_system = 'netbsd'
187 elif host_system == 'android'
188 # while android isn't quite a normal linux, it seems close enough
189 # for our purposes so far
190 host_system = 'linux'
193 # meson's system names don't quite map to our "traditional" names. In some
194 # places we need the "traditional" name, e.g., for mapping
195 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
197 portname = host_system
199 if host_system == 'aix'
200 library_path_var = 'LIBPATH'
202 export_file_format = 'aix'
203 export_fmt = '-Wl,-bE:@0@'
204 mod_link_args_fmt = ['-Wl,-bI:@0@']
205 mod_link_with_dir = 'libdir'
206 mod_link_with_name = '@0@.imp'
208 # M:SRE sets a flag indicating that an object is a shared library. Seems to
209 # work in some circumstances without, but required in others.
210 ldflags_sl += '-Wl,-bM:SRE'
211 ldflags_be += '-Wl,-brtllib'
213 # Native memset() is faster, tested on:
214 # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
215 # - AIX 5.3 ML3, gcc 4.0.1
216 memset_loop_limit = 0
218 elif host_system == 'cygwin'
219 sema_kind = 'unnamed_posix'
220 cppflags += '-D_GNU_SOURCE'
222 mod_link_args_fmt = ['@0@']
223 mod_link_with_name = 'lib@0@.exe.a'
224 mod_link_with_dir = 'libdir'
226 elif host_system == 'darwin'
228 library_path_var = 'DYLD_LIBRARY_PATH'
230 export_file_format = 'darwin'
231 export_fmt = '-Wl,-exported_symbols_list,@0@'
233 mod_link_args_fmt = ['-bundle_loader', '@0@']
234 mod_link_with_dir = 'bindir'
235 mod_link_with_name = '@0@'
237 sysroot_args = [files('src/tools/darwin_sysroot'), get_option('darwin_sysroot')]
238 pg_sysroot = run_command(sysroot_args, check:true).stdout().strip()
239 message('darwin sysroot: @0@'.format(pg_sysroot))
241 cflags += ['-isysroot', pg_sysroot]
242 ldflags += ['-isysroot', pg_sysroot]
244 # meson defaults to -Wl,-undefined,dynamic_lookup for modules, which we
245 # don't want because a) it's different from what we do for autoconf, b) it
246 # causes warnings starting in macOS Ventura
247 ldflags_mod += ['-Wl,-undefined,error']
249 elif host_system == 'freebsd'
250 sema_kind = 'unnamed_posix'
252 elif host_system == 'linux'
253 sema_kind = 'unnamed_posix'
254 cppflags += '-D_GNU_SOURCE'
256 elif host_system == 'netbsd'
257 # We must resolve all dynamic linking in the core server at program start.
258 # Otherwise the postmaster can self-deadlock due to signals interrupting
259 # resolution of calls, since NetBSD's linker takes a lock while doing that
260 # and some postmaster signal handlers do things that will also acquire that
261 # lock. As long as we need "-z now", might as well specify "-z relro" too.
262 # While there's not a hard reason to adopt these settings for our other
263 # executables, there's also little reason not to, so just add them to
265 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
267 elif host_system == 'openbsd'
270 elif host_system == 'sunos'
272 export_fmt = '-Wl,-M@0@'
273 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
275 elif host_system == 'windows'
279 library_path_var = ''
281 export_file_format = 'win'
282 export_file_suffix = 'def'
283 if cc.get_id() == 'msvc'
284 export_fmt = '/DEF:@0@'
285 mod_link_with_name = '@0@.exe.lib'
288 mod_link_with_name = 'lib@0@.exe.a'
290 mod_link_args_fmt = ['@0@']
291 mod_link_with_dir = 'libdir'
296 cdata.set('WIN32_STACK_RLIMIT', 4194304)
297 if cc.get_id() == 'msvc'
298 ldflags += '/INCREMENTAL:NO'
299 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
300 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
302 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
303 # Need to allow multiple definitions, we e.g. want to override getopt.
304 ldflags += '-Wl,--allow-multiple-definition'
305 # Ensure we get MSVC-like linking behavior.
306 ldflags += '-Wl,--disable-auto-import'
309 os_deps += cc.find_library('ws2_32', required: true)
310 secur32_dep = cc.find_library('secur32', required: true)
311 backend_deps += secur32_dep
312 libpq_deps += secur32_dep
314 postgres_inc_d += 'src/include/port/win32'
315 if cc.get_id() == 'msvc'
316 postgres_inc_d += 'src/include/port/win32_msvc'
319 windows = import('windows')
322 # XXX: Should we add an option to override the host_system as an escape
324 error('unknown host system: @0@'.format(host_system))
329 ###############################################################
331 ###############################################################
334 perl = find_program(get_option('PERL'), required: true, native: true)
335 python = find_program(get_option('PYTHON'), required: true, native: true)
336 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35')
337 bison = find_program(get_option('BISON'), native: true, version: '>= 2.3')
338 sed = find_program(get_option('SED'), 'sed', native: true, required: false)
339 prove = find_program(get_option('PROVE'), native: true, required: false)
340 tar = find_program(get_option('TAR'), native: true, required: false)
341 gzip = find_program(get_option('GZIP'), native: true, required: false)
342 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
343 openssl = find_program(get_option('OPENSSL'), native: true, required: false)
344 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
345 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
346 missing = find_program('config/missing', native: true)
347 cp = find_program('cp', required: false, native: true)
348 xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
349 xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
353 bison_version_c = run_command(bison, '--version', check: true)
354 # bison version string helpfully is something like
355 # >>bison (GNU bison) 3.8.1<<
356 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
357 if bison_version.version_compare('>=3.0')
358 bison_flags += ['-Wno-deprecated']
361 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
363 'output': ['@BASENAME@.c', '@BASENAME@.h'],
364 'command': bison_cmd,
369 flex_version_c = run_command(flex, '--version', check: true)
370 flex_version = flex_version_c.stdout().split(' ')[1].split('\n')[0]
372 flex_wrapper = files('src/tools/pgflex')
373 flex_cmd = [python, flex_wrapper,
374 '--builddir', '@BUILD_ROOT@',
375 '--srcdir', '@SOURCE_ROOT@',
376 '--privatedir', '@PRIVATE_DIR@',
377 '--flex', flex, '--perl', perl,
378 '-i', '@INPUT@', '-o', '@OUTPUT0@',
381 wget = find_program('wget', required: false, native: true)
382 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
384 install_files = files('src/tools/install_files')
388 ###############################################################
389 # Path to meson (for tests etc)
390 ###############################################################
392 # NB: this should really be part of meson, see
393 # https://github.com/mesonbuild/meson/issues/8511
394 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
396 if meson_binpath_r.stdout() == ''
397 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
398 meson_binpath_r.returncode(),
399 meson_binpath_r.stdout(),
400 meson_binpath_r.stderr()))
403 meson_binpath_s = meson_binpath_r.stdout().split('\n')
404 meson_binpath_len = meson_binpath_s.length()
406 if meson_binpath_len < 1
407 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
414 foreach e : meson_binpath_s
425 if meson_impl not in ['muon', 'meson']
426 error('unknown meson implementation "@0@"'.format(meson_impl))
429 meson_bin = find_program(meson_binpath, native: true)
433 ###############################################################
435 ###############################################################
437 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
438 cdata.set('USE_INJECTION_POINTS', get_option('injection_points') ? 1 : false)
440 blocksize = get_option('blocksize').to_int() * 1024
442 if get_option('segsize_blocks') != 0
443 if get_option('segsize') != 1
444 warning('both segsize and segsize_blocks specified, segsize_blocks wins')
447 segsize = get_option('segsize_blocks')
449 segsize = (get_option('segsize') * 1024 * 1024 * 1024) / blocksize
452 cdata.set('BLCKSZ', blocksize, description:
453 '''Size of a disk block --- this also limits the size of a tuple. You can set
454 it bigger if you need bigger tuples (although TOAST should reduce the need
455 to have large tuples, since fields can be spread across multiple tuples).
456 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
457 currently 2^15 (32768). This is determined by the 15-bit widths of the
458 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
459 Changing BLCKSZ requires an initdb.''')
461 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
462 cdata.set('RELSEG_SIZE', segsize)
463 cdata.set('DEF_PGPORT', get_option('pgport'))
464 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
465 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
466 if get_option('system_tzdata') != ''
467 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
472 ###############################################################
474 ###############################################################
476 # These are set by the equivalent --xxxdir configure options. We
477 # append "postgresql" to some of them, if the string does not already
478 # contain "pgsql" or "postgres", in order to avoid directory clutter.
482 dir_prefix = get_option('prefix')
484 dir_prefix_contains_pg = (dir_prefix.contains('pgsql') or dir_prefix.contains('postgres'))
486 dir_bin = get_option('bindir')
488 dir_data = get_option('datadir')
489 if not (dir_prefix_contains_pg or dir_data.contains('pgsql') or dir_data.contains('postgres'))
490 dir_data = dir_data / pkg
493 dir_sysconf = get_option('sysconfdir')
494 if not (dir_prefix_contains_pg or dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
495 dir_sysconf = dir_sysconf / pkg
498 dir_lib = get_option('libdir')
500 dir_lib_pkg = dir_lib
501 if not (dir_prefix_contains_pg or dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
502 dir_lib_pkg = dir_lib_pkg / pkg
505 dir_pgxs = dir_lib_pkg / 'pgxs'
507 dir_include = get_option('includedir')
509 dir_include_pkg = dir_include
510 dir_include_pkg_rel = ''
511 if not (dir_prefix_contains_pg or dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
512 dir_include_pkg = dir_include_pkg / pkg
513 dir_include_pkg_rel = pkg
516 dir_man = get_option('mandir')
518 # FIXME: These used to be separately configurable - worth adding?
519 dir_doc = get_option('datadir') / 'doc'
520 if not (dir_prefix_contains_pg or dir_doc.contains('pgsql') or dir_doc.contains('postgres'))
521 dir_doc = dir_doc / pkg
523 dir_doc_html = dir_doc / 'html'
525 dir_locale = get_option('localedir')
529 dir_bitcode = dir_lib_pkg / 'bitcode'
530 dir_include_internal = dir_include_pkg / 'internal'
531 dir_include_server = dir_include_pkg / 'server'
532 dir_include_extension = dir_include_server / 'extension'
533 dir_data_extension = dir_data / 'extension'
534 dir_doc_extension = dir_doc / 'extension'
538 ###############################################################
539 # Search paths, preparation for compiler tests
541 # NB: Arguments added later are not automatically used for subsequent
542 # configuration-time checks (so they are more isolated). If they should be
543 # used, they need to be added to test_c_args as well.
544 ###############################################################
546 postgres_inc = [include_directories(postgres_inc_d)]
547 test_lib_d = postgres_lib_d
548 test_c_args = cppflags + cflags
552 ###############################################################
554 ###############################################################
556 bsd_authopt = get_option('bsd_auth')
557 bsd_auth = not_found_dep
558 if cc.check_header('bsd_auth.h', required: bsd_authopt,
559 args: test_c_args, include_directories: postgres_inc)
560 cdata.set('USE_BSD_AUTH', 1)
561 bsd_auth = declare_dependency()
566 ###############################################################
569 # For now don't search for DNSServiceRegister in a library - only Apple's
570 # Bonjour implementation, which is always linked, works.
571 ###############################################################
573 bonjouropt = get_option('bonjour')
574 bonjour = not_found_dep
575 if cc.check_header('dns_sd.h', required: bonjouropt,
576 args: test_c_args, include_directories: postgres_inc) and \
577 cc.has_function('DNSServiceRegister',
578 args: test_c_args, include_directories: postgres_inc)
579 cdata.set('USE_BONJOUR', 1)
580 bonjour = declare_dependency()
585 ###############################################################
586 # Option: docs in HTML and man page format
587 ###############################################################
589 docs_opt = get_option('docs')
590 docs_dep = not_found_dep
591 if not docs_opt.disabled()
592 if xmllint_bin.found() and xsltproc_bin.found()
593 docs_dep = declare_dependency()
594 elif docs_opt.enabled()
595 error('missing required tools (xmllint and xsltproc needed) for docs in HTML / man page format')
601 ###############################################################
602 # Option: docs in PDF format
603 ###############################################################
605 docs_pdf_opt = get_option('docs_pdf')
606 docs_pdf_dep = not_found_dep
607 if not docs_pdf_opt.disabled()
608 fop = find_program(get_option('FOP'), native: true, required: docs_pdf_opt)
609 if xmllint_bin.found() and xsltproc_bin.found() and fop.found()
610 docs_pdf_dep = declare_dependency()
611 elif docs_pdf_opt.enabled()
612 error('missing required tools for docs in PDF format')
618 ###############################################################
620 ###############################################################
622 gssapiopt = get_option('gssapi')
625 if not gssapiopt.disabled()
626 gssapi = dependency('krb5-gssapi', required: gssapiopt)
627 have_gssapi = gssapi.found()
630 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
631 args: test_c_args, include_directories: postgres_inc)
632 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
633 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
634 cdata.set('HAVE_GSSAPI_H', 1)
640 elif cc.check_header('gssapi/gssapi_ext.h', dependencies: gssapi, required: false,
641 args: test_c_args, include_directories: postgres_inc)
642 cdata.set('HAVE_GSSAPI_GSSAPI_EXT_H', 1)
643 elif cc.check_header('gssapi_ext.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
644 cdata.set('HAVE_GSSAPI_EXT_H', 1)
650 elif cc.has_function('gss_store_cred_into', dependencies: gssapi,
651 args: test_c_args, include_directories: postgres_inc)
652 cdata.set('ENABLE_GSS', 1)
654 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
655 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
656 elif gssapiopt.enabled()
657 error('''could not find function 'gss_store_cred_into' required for GSSAPI''')
663 gssapi = not_found_dep
668 ###############################################################
670 ###############################################################
672 ldapopt = get_option('ldap')
673 if ldapopt.disabled()
675 ldap_r = not_found_dep
676 elif host_system == 'windows'
677 ldap = cc.find_library('wldap32', required: ldapopt)
680 # macos framework dependency is buggy for ldap (one can argue whether it's
681 # Apple's or meson's fault), leading to an endless recursion with ldap.h
682 # including itself. See https://github.com/mesonbuild/meson/issues/10002
683 # Luckily we only need pkg-config support, so the workaround isn't
685 ldap = dependency('ldap', method: 'pkg-config', required: false)
688 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
691 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
692 has_headers: 'ldap.h', header_include_directories: postgres_inc)
694 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
695 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
696 # library from a separate OpenLDAP installation). The most reliable
697 # way to check that is to check for a function introduced in 2.5.
699 # don't have ldap, we shouldn't check for ldap_r
700 elif cc.has_function('ldap_verify_credentials',
701 dependencies: ldap, args: test_c_args)
702 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
705 # Use ldap_r for FE if available, else assume ldap is thread-safe.
706 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
707 has_headers: 'ldap.h', header_include_directories: postgres_inc)
708 if not ldap_r.found()
711 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
712 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
715 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
716 # process. Check for OpenLDAP versions known not to tolerate doing so;
717 # assume non-OpenLDAP implementations are safe. The dblink test suite
718 # exercises the hazardous interaction directly.
719 compat_test_code = '''
721 #if !defined(LDAP_VENDOR_VERSION) || \
722 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
723 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
727 if not cc.compiles(compat_test_code,
728 name: 'LDAP implementation compatible',
729 dependencies: ldap, args: test_c_args)
731 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
732 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
733 *** also uses LDAP will crash on exit.''')
738 if ldap.found() and cc.has_function('ldap_initialize',
739 dependencies: ldap, args: test_c_args)
740 cdata.set('HAVE_LDAP_INITIALIZE', 1)
745 assert(ldap_r.found())
746 cdata.set('USE_LDAP', 1)
748 assert(not ldap_r.found())
753 ###############################################################
755 ###############################################################
757 llvmopt = get_option('llvm')
759 if add_languages('cpp', required: llvmopt, native: false)
760 llvm = dependency('llvm', version: '>=10', method: 'config-tool', required: llvmopt)
764 cdata.set('USE_LLVM', 1)
766 cpp = meson.get_compiler('cpp')
768 llvm_binpath = llvm.get_variable(configtool: 'bindir')
770 ccache = find_program('ccache', native: true, required: false)
771 clang = find_program(llvm_binpath / 'clang', required: true)
774 message('llvm requires a C++ compiler')
779 ###############################################################
781 ###############################################################
783 icuopt = get_option('icu')
784 if not icuopt.disabled()
785 icu = dependency('icu-uc', required: icuopt)
786 icu_i18n = dependency('icu-i18n', required: icuopt)
789 cdata.set('USE_ICU', 1)
794 icu_i18n = not_found_dep
799 ###############################################################
801 ###############################################################
803 libxmlopt = get_option('libxml')
804 if not libxmlopt.disabled()
805 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
808 cdata.set('USE_LIBXML', 1)
811 libxml = not_found_dep
816 ###############################################################
818 ###############################################################
820 libxsltopt = get_option('libxslt')
821 if not libxsltopt.disabled()
822 libxslt = dependency('libxslt', required: libxsltopt)
825 cdata.set('USE_LIBXSLT', 1)
828 libxslt = not_found_dep
833 ###############################################################
835 ###############################################################
837 lz4opt = get_option('lz4')
838 if not lz4opt.disabled()
839 lz4 = dependency('liblz4', required: lz4opt)
842 cdata.set('USE_LZ4', 1)
843 cdata.set('HAVE_LIBLZ4', 1)
852 ###############################################################
853 # Library: Tcl (for pltcl)
855 # NB: tclConfig.sh is used in autoconf build for getting
856 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
857 # variables. For now we have not seen a need to copy
858 # that behaviour to the meson build.
859 ###############################################################
861 tclopt = get_option('pltcl')
862 tcl_version = get_option('tcl_version')
863 tcl_dep = not_found_dep
864 if not tclopt.disabled()
867 tcl_dep = dependency(tcl_version, required: false)
869 if not tcl_dep.found()
870 tcl_dep = cc.find_library(tcl_version,
875 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
876 tcl_dep = not_found_dep
882 ###############################################################
884 ###############################################################
886 pamopt = get_option('pam')
887 if not pamopt.disabled()
888 pam = dependency('pam', required: false)
891 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
895 pam_header_found = false
897 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
898 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
899 args: test_c_args, include_directories: postgres_inc)
900 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
901 pam_header_found = true
902 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
903 args: test_c_args, include_directories: postgres_inc)
904 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
905 pam_header_found = true
909 cdata.set('USE_PAM', 1)
920 ###############################################################
921 # Library: Perl (for plperl)
922 ###############################################################
924 perlopt = get_option('plperl')
925 perl_dep = not_found_dep
926 if not perlopt.disabled()
929 # First verify that perl has the necessary dependencies installed
930 perl_mods = run_command(
932 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
935 if perl_mods.returncode() != 0
936 perl_may_work = false
937 perl_msg = 'perl installation does not have the required modules'
940 # Then inquire perl about its configuration
942 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
943 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
944 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
945 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
946 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
948 perl_inc_dir = '@0@/CORE'.format(archlibexp)
950 if perlversion.version_compare('< 5.14')
951 perl_may_work = false
952 perl_msg = 'Perl version 5.14 or later is required, but this is @0@'.format(perlversion)
953 elif useshrplib != 'true'
954 perl_may_work = false
955 perl_msg = 'need a shared perl'
960 # On most platforms, archlibexp is also where the Perl include files live ...
961 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
962 # ... but on newer macOS versions, we must use -iwithsysroot to look
964 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
965 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
966 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
969 # check compiler finds header
970 if not cc.has_header('perl.h', required: false,
971 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
972 perl_may_work = false
973 perl_msg = 'missing perl.h'
978 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
980 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
981 foreach flag : perl_ccflags_r.split(' ')
982 if flag.startswith('-D') and \
983 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
988 if host_system == 'windows'
989 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
991 if cc.get_id() == 'msvc'
992 # prevent binary mismatch between MSVC built plperl and Strawberry or
993 # msys ucrt perl libraries
994 perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE']
998 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
999 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
1001 # We are after Embed's ldopts, but without the subset mentioned in
1002 # Config's ccdlflags and ldflags. (Those are the choices of those who
1003 # built the Perl installation, which are not necessarily appropriate
1004 # for building PostgreSQL.)
1005 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
1006 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
1007 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
1010 foreach ldopt : ldopts.split(' ')
1011 if ldopt == '' or ldopt in undesired
1015 perl_ldopts += ldopt.strip('"')
1018 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
1019 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
1021 perl_dep_int = declare_dependency(
1022 compile_args: perl_ccflags,
1023 link_args: perl_ldopts,
1024 version: perlversion,
1027 # While we're at it, check that we can link to libperl.
1028 # On most platforms, if perl.h is there then libperl.so will be too, but
1029 # at this writing Debian packages them separately.
1030 perl_link_test = '''
1033 #define __inline__ inline
1041 if not cc.links(perl_link_test, name: 'libperl',
1042 args: test_c_args + perl_ccflags + perl_ldopts,
1043 include_directories: postgres_inc)
1044 perl_may_work = false
1045 perl_msg = 'missing libperl'
1048 endif # perl_may_work
1051 perl_dep = perl_dep_int
1053 if perlopt.enabled()
1054 error('dependency plperl failed: @0@'.format(perl_msg))
1056 message('disabling optional dependency plperl: @0@'.format(perl_msg))
1063 ###############################################################
1064 # Library: Python (for plpython)
1065 ###############################################################
1067 pyopt = get_option('plpython')
1068 python3_dep = not_found_dep
1069 if not pyopt.disabled()
1070 pm = import('python')
1071 python3_inst = pm.find_installation(python.path(), required: pyopt)
1072 if python3_inst.found()
1073 python3_dep = python3_inst.dependency(embed: true, required: pyopt)
1074 # Remove this check after we depend on Meson >= 1.1.0
1075 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt)
1076 python3_dep = not_found_dep
1083 ###############################################################
1085 ###############################################################
1087 if not get_option('readline').disabled()
1088 libedit_preferred = get_option('libedit_preferred')
1089 # Set the order of readline dependencies
1090 check_readline_deps = libedit_preferred ? \
1091 ['libedit', 'readline'] : ['readline', 'libedit']
1093 foreach readline_dep : check_readline_deps
1094 readline = dependency(readline_dep, required: false)
1095 if not readline.found()
1096 readline = cc.find_library(readline_dep,
1097 required: get_option('readline'),
1106 cdata.set('HAVE_LIBREADLINE', 1)
1109 'header_prefix': 'editline/',
1110 'flag_prefix': 'EDITLINE_',
1113 'header_prefix': 'readline/',
1114 'flag_prefix': 'READLINE_',
1117 'header_prefix': '',
1121 # Set the order of prefixes
1122 prefixes = libedit_preferred ? \
1123 [editline_prefix, default_prefix, readline_prefix] : \
1124 [readline_prefix, default_prefix, editline_prefix]
1126 at_least_one_header_found = false
1127 foreach header : ['history', 'readline']
1129 foreach prefix : prefixes
1130 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1131 # Check history.h and readline.h
1132 if not is_found and cc.has_header(header_file,
1133 args: test_c_args, include_directories: postgres_inc,
1134 dependencies: [readline], required: false)
1135 if header == 'readline'
1136 readline_h = header_file
1138 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1140 at_least_one_header_found = true
1145 if not at_least_one_header_found
1146 error('''readline header not found
1147 If you have @0@ already installed, see meson-logs/meson-log.txt for details on the
1148 failure. It is possible the compiler isn't looking in the proper directory.
1149 Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
1154 'history_truncate_file',
1155 'rl_completion_matches',
1156 'rl_filename_completion_function',
1157 'rl_reset_screen_size',
1161 foreach func : check_funcs
1162 found = cc.has_function(func, dependencies: [readline],
1163 args: test_c_args, include_directories: postgres_inc)
1164 cdata.set('HAVE_' + func.to_upper(), found ? 1 : false)
1168 'rl_completion_suppress_quote',
1169 'rl_filename_quote_characters',
1170 'rl_filename_quoting_function',
1173 foreach var : check_vars
1174 cdata.set('HAVE_' + var.to_upper(),
1175 cc.has_header_symbol(readline_h, var,
1176 args: test_c_args, include_directories: postgres_inc,
1177 prefix: '#include <stdio.h>',
1178 dependencies: [readline]) ? 1 : false)
1181 # If found via cc.find_library() ensure headers are found when using the
1182 # dependency. On meson < 0.57 one cannot do compiler checks using the
1183 # dependency returned by declare_dependency(), so we can't do this above.
1184 if readline.type_name() == 'library'
1185 readline = declare_dependency(dependencies: readline,
1186 include_directories: postgres_inc)
1189 # On windows with mingw readline requires auto-import to successfully
1190 # link, as the headers don't use declspec(dllimport)
1191 if host_system == 'windows' and cc.get_id() != 'msvc'
1192 readline = declare_dependency(dependencies: readline,
1193 link_args: '-Wl,--enable-auto-import')
1197 # XXX: Figure out whether to implement mingw warning equivalent
1199 readline = not_found_dep
1204 ###############################################################
1206 ###############################################################
1208 selinux = not_found_dep
1209 selinuxopt = get_option('selinux')
1210 if meson.version().version_compare('>=0.59')
1211 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1213 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1214 cdata.set('HAVE_LIBSELINUX',
1215 selinux.found() ? 1 : false)
1219 ###############################################################
1221 ###############################################################
1223 systemd = not_found_dep
1224 systemdopt = get_option('systemd')
1225 if meson.version().version_compare('>=0.59')
1226 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1228 systemd = dependency('libsystemd', required: systemdopt)
1229 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1233 ###############################################################
1235 ###############################################################
1238 ssl_library = 'none'
1239 sslopt = get_option('ssl')
1241 if sslopt == 'auto' and auto_features.disabled()
1245 if sslopt in ['auto', 'openssl']
1246 openssl_required = (sslopt == 'openssl')
1248 # Try to find openssl via pkg-config et al, if that doesn't work
1249 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1250 # the library names that we know about.
1252 # via pkg-config et al
1253 ssl = dependency('openssl', required: false)
1254 # only meson >= 0.57 supports declare_dependency() in cc.has_function(), so
1255 # we pass cc.find_library() results if necessary
1258 # via library + headers
1260 ssl_lib = cc.find_library('ssl',
1262 header_include_directories: postgres_inc,
1263 has_headers: ['openssl/ssl.h', 'openssl/err.h'],
1264 required: openssl_required)
1265 crypto_lib = cc.find_library('crypto',
1267 required: openssl_required)
1268 if ssl_lib.found() and crypto_lib.found()
1269 ssl_int = [ssl_lib, crypto_lib]
1270 ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc)
1272 elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \
1273 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required)
1281 ['CRYPTO_new_ex_data', {'required': true}],
1282 ['SSL_new', {'required': true}],
1284 # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
1285 ['SSL_CTX_set_cert_cb'],
1287 # Functions introduced in OpenSSL 1.1.0. We used to check for
1288 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1289 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1290 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1292 ['OPENSSL_init_ssl'],
1294 ['ASN1_STRING_get0_data'],
1298 # OpenSSL versions before 1.1.0 required setting callback functions, for
1299 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1300 # function was removed.
1303 # Function introduced in OpenSSL 1.1.1
1304 ['X509_get_signature_info'],
1307 are_openssl_funcs_complete = true
1308 foreach c : check_funcs
1310 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1311 required = c.get(1, {}).get('required', false)
1312 if required and not val
1313 are_openssl_funcs_complete = false
1315 error('openssl function @0@ is required'.format(func))
1319 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1323 if are_openssl_funcs_complete
1324 cdata.set('USE_OPENSSL', 1,
1325 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1326 cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
1327 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
1328 ssl_library = 'openssl'
1335 if sslopt == 'auto' and auto_features.enabled() and not ssl.found()
1336 error('no SSL library found')
1341 ###############################################################
1343 ###############################################################
1345 uuidopt = get_option('uuid')
1346 if uuidopt != 'none'
1347 uuidname = uuidopt.to_upper()
1348 if uuidopt == 'e2fs'
1349 uuid = dependency('uuid', required: true)
1350 uuidfunc = 'uuid_generate'
1351 uuidheader = 'uuid/uuid.h'
1352 elif uuidopt == 'bsd'
1353 # libc should have uuid function
1354 uuid = declare_dependency()
1355 uuidfunc = 'uuid_to_string'
1356 uuidheader = 'uuid.h'
1357 elif uuidopt == 'ossp'
1358 uuid = dependency('ossp-uuid', required: true)
1359 uuidfunc = 'uuid_export'
1360 uuidheader = 'uuid.h'
1362 error('unknown uuid build option value: @0@'.format(uuidopt))
1365 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1366 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1368 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1370 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1371 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1373 uuid = not_found_dep
1378 ###############################################################
1380 ###############################################################
1382 zlibopt = get_option('zlib')
1383 zlib = not_found_dep
1384 if not zlibopt.disabled()
1385 zlib_t = dependency('zlib', required: zlibopt)
1387 if zlib_t.type_name() == 'internal'
1388 # if fallback was used, we don't need to test if headers are present (they
1389 # aren't built yet, so we can't test)
1391 elif not zlib_t.found()
1392 warning('did not find zlib')
1393 elif not cc.has_header('zlib.h',
1394 args: test_c_args, include_directories: postgres_inc,
1395 dependencies: [zlib_t], required: zlibopt)
1396 warning('zlib header not found')
1402 cdata.set('HAVE_LIBZ', 1)
1408 ###############################################################
1409 # Library: tap test dependencies
1410 ###############################################################
1412 # Check whether tap tests are enabled or not
1413 tap_tests_enabled = false
1414 tapopt = get_option('tap_tests')
1415 if not tapopt.disabled()
1416 # Checking for perl modules for tap tests
1417 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1418 if perl_ipc_run_check.returncode() != 0
1419 message(perl_ipc_run_check.stderr().strip())
1421 error('Additional Perl modules are required to run TAP tests.')
1423 warning('Additional Perl modules are required to run TAP tests.')
1426 tap_tests_enabled = true
1432 ###############################################################
1434 ###############################################################
1436 zstdopt = get_option('zstd')
1437 if not zstdopt.disabled()
1438 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1441 cdata.set('USE_ZSTD', 1)
1442 cdata.set('HAVE_LIBZSTD', 1)
1446 zstd = not_found_dep
1451 ###############################################################
1453 ###############################################################
1455 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1456 # unnecessarily, because we optionally rely on newer features.
1458 #include <stdbool.h>
1459 #include <complex.h>
1461 #include <inttypes.h>
1463 struct named_init_test {
1468 extern void structfunc(struct named_init_test);
1470 int main(int argc, char **argv)
1472 struct named_init_test nit = {
1477 for (int loop_var = 0; loop_var < 3; loop_var++)
1482 structfunc((struct named_init_test){1, 0});
1488 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1489 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1490 args: test_c_args + ['-std=c99'])
1491 test_c_args += '-std=c99'
1492 cflags += '-std=c99'
1494 error('C compiler does not support C99')
1498 sizeof_long = cc.sizeof('long', args: test_c_args)
1499 cdata.set('SIZEOF_LONG', sizeof_long)
1501 cdata.set('HAVE_LONG_INT_64', 1)
1502 cdata.set('PG_INT64_TYPE', 'long int')
1503 cdata.set_quoted('INT64_MODIFIER', 'l')
1504 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1505 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1506 cdata.set('PG_INT64_TYPE', 'long long int')
1507 cdata.set_quoted('INT64_MODIFIER', 'll')
1509 error('do not know how to get a 64bit int')
1512 if host_machine.endian() == 'big'
1513 cdata.set('WORDS_BIGENDIAN', 1)
1516 alignof_types = ['short', 'int', 'long', 'double']
1518 foreach t : alignof_types
1519 align = cc.alignment(t, args: test_c_args)
1523 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1525 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1527 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1528 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1531 # Check if __int128 is a working 128 bit integer type, and if so
1532 # define PG_INT128_TYPE to that typename.
1534 # This currently only detects a GCC/clang extension, but support for other
1535 # environments may be added in the future.
1537 # For the moment we only test for support for 128bit math; support for
1538 # 128bit literals and snprintf is not required.
1541 * We don't actually run this test, just link it to verify that any support
1542 * functions needed for __int128 are present.
1544 * These are globals to discourage the compiler from folding all the
1545 * arithmetic tests down to compile-time constants. We do not have
1546 * convenient support for 128bit literals at this point...
1548 __int128 a = 48828125;
1549 __int128 b = 97656250;
1554 a = (a << 12) + 1; /* 200000000001 */
1555 b = (b << 12) + 5; /* 400000000005 */
1556 /* try the most relevant arithmetic ops */
1559 /* must use the results, else compiler may optimize arithmetic away */
1565 buggy_int128 = false
1567 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1568 # If not cross-compiling, we can test for bugs and disable use of __int128
1569 # with buggy compilers. If cross-compiling, hope for the best.
1570 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1571 if not meson.is_cross_build()
1573 /* This must match the corresponding code in c.h: */
1574 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1575 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1576 #elif defined(_MSC_VER)
1577 #define pg_attribute_aligned(a) __declspec(align(a))
1579 typedef __int128 int128a
1580 #if defined(pg_attribute_aligned)
1581 pg_attribute_aligned(8)
1586 void pass_by_val(void *buffer, int128a par) { holder = par; }
1590 long int i64 = 97656225L << 12;
1592 pass_by_val(main, (int128a) i64);
1596 name: '__int128 alignment bug',
1598 assert(r.compiled())
1599 if r.returncode() != 0
1601 message('__int128 support present but buggy and thus disabled')
1606 cdata.set('PG_INT128_TYPE', '__int128')
1607 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.alignment('__int128', args: test_c_args))
1612 # Check if the C compiler knows computed gotos (gcc extension, also
1613 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1615 # Checking whether computed gotos are supported syntax-wise ought to
1616 # be enough, as the syntax is otherwise illegal.
1618 static inline int foo(void)
1620 void *labeladdrs[] = {&&my_label};
1621 goto *labeladdrs[0];
1626 cdata.set('HAVE_COMPUTED_GOTO', 1)
1630 # Check if the C compiler understands _Static_assert(),
1631 # and define HAVE__STATIC_ASSERT if so.
1633 # We actually check the syntax ({ _Static_assert(...) }), because we need
1634 # gcc-style compound expressions to be able to wrap the thing into macros.
1636 int main(int arg, char **argv)
1638 ({ _Static_assert(1, "foo"); });
1642 cdata.set('HAVE__STATIC_ASSERT', 1)
1646 # We use <stdbool.h> if we have it and it declares type bool as having
1647 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1648 if cc.has_type('_Bool', args: test_c_args) \
1649 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1650 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1651 cdata.set('HAVE__BOOL', 1)
1652 cdata.set('PG_USE_STDBOOL', 1)
1656 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1657 # warning for each use of %m.
1658 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1660 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1661 static void call_log(void)
1663 emit_log(0, "error: %s: %m", "foo");
1666 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1667 foreach a : printf_attributes
1668 if cc.compiles(testsrc.format(a),
1669 args: test_c_args + attrib_error_args, name: 'format ' + a)
1670 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1676 if cc.has_function_attribute('visibility:default') and \
1677 cc.has_function_attribute('visibility:hidden')
1678 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1680 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1681 # inlineshidden to C code as well... And either way, we want to put these
1682 # flags into exported files (pgxs, .pc files).
1683 cflags_mod += '-fvisibility=hidden'
1684 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1685 ldflags_mod += '-fvisibility=hidden'
1689 # Check if various builtins exist. Some builtins are tested separately,
1690 # because we want to test something more complicated than the generic case.
1703 foreach builtin : builtins
1704 fname = '__builtin_@0@'.format(builtin)
1705 if cc.has_function(fname, args: test_c_args)
1706 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1711 # Check if the C compiler understands __builtin_types_compatible_p,
1712 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1714 # We check usage with __typeof__, though it's unlikely any compiler would
1715 # have the former and not the latter.
1718 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1720 name: '__builtin_types_compatible_p',
1722 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1726 # Check if the C compiler understands __builtin_$op_overflow(),
1727 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1729 # Check for the most complicated case, 64 bit multiplication, as a
1730 # proxy for all of the operations. To detect the case where the compiler
1731 # knows the function but library support is missing, we must link not just
1732 # compile, and store the results in global variables so the compiler doesn't
1733 # optimize away the call.
1741 return __builtin_mul_overflow(a, b, &result);
1743 name: '__builtin_mul_overflow',
1744 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1746 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1750 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1751 # here. To prevent problems due to two detection methods working, stop
1752 # checking after one.
1755 int main(int arg, char **argv)
1757 unsigned int exx[4] = {0, 0, 0, 0};
1758 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1760 ''', name: '__get_cpuid',
1762 cdata.set('HAVE__GET_CPUID', 1)
1765 int main(int arg, char **argv)
1767 unsigned int exx[4] = {0, 0, 0, 0};
1770 ''', name: '__cpuid',
1772 cdata.set('HAVE__CPUID', 1)
1776 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1777 # versions of clang do not understand -fexcess-precision=standard, the use of
1778 # x87 floating point operations leads to problems like isinf possibly returning
1779 # false for a value that is infinite when converted from the 80bit register to
1780 # the 8byte memory representation.
1782 # Only perform the test if the compiler doesn't understand
1783 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1785 if '-fexcess-precision=standard' not in cflags
1786 if not cc.compiles('''
1787 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1790 name: '', args: test_c_args)
1791 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1797 ###############################################################
1799 ###############################################################
1801 common_functional_flags = [
1802 # Disable strict-aliasing rules; needed for gcc 3.3+
1803 '-fno-strict-aliasing',
1804 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1806 '-fexcess-precision=standard',
1809 cflags += cc.get_supported_arguments(common_functional_flags)
1811 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1814 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1815 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1817 common_warning_flags = [
1818 '-Wmissing-prototypes',
1820 # Really don't want VLAs to be used in our dialect of C
1822 # On macOS, complain about usage of symbols newer than the deployment target
1823 '-Werror=unguarded-availability-new',
1825 '-Wmissing-format-attribute',
1826 '-Wimplicit-fallthrough=3',
1827 '-Wcast-function-type',
1828 '-Wshadow=compatible-local',
1829 # This was included in -Wall/-Wformat in older GCC versions
1830 '-Wformat-security',
1833 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1835 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1838 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1839 # the result for them
1840 cflags_no_decl_after_statement = []
1841 if cc.has_argument('-Wdeclaration-after-statement')
1842 cflags_warn += '-Wdeclaration-after-statement'
1843 cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
1847 # The following tests want to suppress various unhelpful warnings by adding
1848 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1849 # switches, so we have to test for the positive form and if that works,
1850 # add the negative form.
1852 negative_warning_flags = [
1853 # Suppress clang's unhelpful unused-command-line-argument warnings.
1854 'unused-command-line-argument',
1856 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1857 # of warnings when building plperl because of usages in the Perl headers.
1858 'compound-token-split-by-macro',
1860 # Similarly disable useless truncation warnings from gcc 8+
1861 'format-truncation',
1862 'stringop-truncation',
1864 # Suppress clang 16's strict warnings about function casts
1865 'cast-function-type-strict',
1867 # To make warning_level=2 / -Wextra work, we'd need at least the following
1869 # 'missing-field-initializers',
1871 # 'unused-parameter',
1874 foreach w : negative_warning_flags
1875 if cc.has_argument('-W' + w)
1876 cflags_warn += '-Wno-' + w
1878 if llvm.found() and cpp.has_argument('-W' + w)
1879 cxxflags_warn += '-Wno-' + w
1884 if cc.get_id() == 'msvc'
1886 '/wd4018', # signed/unsigned mismatch
1887 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1888 '/wd4273', # inconsistent DLL linkage
1889 '/wd4101', # unreferenced local variable
1890 '/wd4102', # unreferenced label
1891 '/wd4090', # different 'modifier' qualifiers
1892 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1900 '/D_CRT_SECURE_NO_DEPRECATE',
1901 '/D_CRT_NONSTDC_NO_DEPRECATE',
1904 # We never need export libraries. As link.exe reports their creation, they
1905 # are unnecessarily noisy. Similarly, we don't need import library for
1906 # modules, we only import them dynamically, and they're also noisy.
1908 ldflags_mod += '/NOIMPLIB'
1913 ###############################################################
1915 ###############################################################
1917 if not get_option('spinlocks')
1918 warning('Not using spinlocks will cause poor performance')
1920 cdata.set('HAVE_SPINLOCKS', 1)
1923 if not get_option('atomics')
1924 warning('Not using atomics will cause poor performance')
1926 # XXX: perhaps we should require some atomics support in this case these
1928 cdata.set('HAVE_ATOMICS', 1)
1931 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
1932 'desc': '__sync_lock_test_and_set(char)',
1935 __sync_lock_test_and_set(&lock, 1);
1936 __sync_lock_release(&lock);'''},
1938 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
1939 'desc': '__sync_lock_test_and_set(int32)',
1942 __sync_lock_test_and_set(&lock, 1);
1943 __sync_lock_release(&lock);'''},
1945 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
1946 'desc': '__sync_val_compare_and_swap(int32)',
1949 __sync_val_compare_and_swap(&val, 0, 37);'''},
1951 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
1952 'desc': '__sync_val_compare_and_swap(int64)',
1955 __sync_val_compare_and_swap(&val, 0, 37);'''},
1957 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
1958 'desc': ' __atomic_compare_exchange_n(int32)',
1962 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1964 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
1965 'desc': ' __atomic_compare_exchange_n(int64)',
1969 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1972 foreach check : atomic_checks
1977 }'''.format(check['test'])
1979 cdata.set(check['name'],
1981 name: check['desc'],
1982 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
1990 ###############################################################
1991 # Select CRC-32C implementation.
1993 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
1994 # use the special CRC instructions for calculating CRC-32C. If we're not
1995 # targeting such a processor, but we can nevertheless produce code that uses
1996 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
1997 # implementations and select which one to use at runtime, depending on whether
1998 # SSE 4.2 is supported by the processor we're running on.
2000 # Similarly, if we are targeting an ARM processor that has the CRC
2001 # instructions that are part of the ARMv8 CRC Extension, use them. And if
2002 # we're not targeting such a processor, but can nevertheless produce code that
2003 # uses the CRC instructions, compile both, and select at runtime.
2004 ###############################################################
2006 have_optimized_crc = false
2008 if host_cpu == 'x86' or host_cpu == 'x86_64'
2010 if cc.get_id() == 'msvc'
2011 cdata.set('USE_SSE42_CRC32C', false)
2012 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2013 have_optimized_crc = true
2017 #include <nmmintrin.h>
2021 unsigned int crc = 0;
2022 crc = _mm_crc32_u8(crc, 0);
2023 crc = _mm_crc32_u32(crc, 0);
2024 /* return computed value, to prevent the above being optimized away */
2029 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
2031 # Use Intel SSE 4.2 unconditionally.
2032 cdata.set('USE_SSE42_CRC32C', 1)
2033 have_optimized_crc = true
2034 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
2035 args: test_c_args + ['-msse4.2'])
2036 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
2037 # the runtime check.
2038 cflags_crc += '-msse4.2'
2039 cdata.set('USE_SSE42_CRC32C', false)
2040 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2041 have_optimized_crc = true
2046 elif host_cpu == 'arm' or host_cpu == 'aarch64'
2049 #include <arm_acle.h>
2053 unsigned int crc = 0;
2054 crc = __crc32cb(crc, 0);
2055 crc = __crc32ch(crc, 0);
2056 crc = __crc32cw(crc, 0);
2057 crc = __crc32cd(crc, 0);
2059 /* return computed value, to prevent the above being optimized away */
2064 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
2066 # Use ARM CRC Extension unconditionally
2067 cdata.set('USE_ARMV8_CRC32C', 1)
2068 have_optimized_crc = true
2069 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
2070 args: test_c_args + ['-march=armv8-a+crc'])
2071 # Use ARM CRC Extension, with runtime check
2072 cflags_crc += '-march=armv8-a+crc'
2073 cdata.set('USE_ARMV8_CRC32C', false)
2074 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
2075 have_optimized_crc = true
2078 elif host_cpu == 'loongarch64'
2083 unsigned int crc = 0;
2084 crc = __builtin_loongarch_crcc_w_b_w(0, crc);
2085 crc = __builtin_loongarch_crcc_w_h_w(0, crc);
2086 crc = __builtin_loongarch_crcc_w_w_w(0, crc);
2087 crc = __builtin_loongarch_crcc_w_d_w(0, crc);
2089 /* return computed value, to prevent the above being optimized away */
2094 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',
2096 # Use LoongArch CRC instruction unconditionally
2097 cdata.set('USE_LOONGARCH_CRC32C', 1)
2098 have_optimized_crc = true
2103 if not have_optimized_crc
2104 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
2106 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
2111 ###############################################################
2112 # Other CPU specific stuff
2113 ###############################################################
2115 if host_cpu == 'x86_64'
2120 long long x = 1; long long r;
2121 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
2123 name: '@0@: popcntq instruction'.format(host_cpu),
2125 cdata.set('HAVE_X86_64_POPCNTQ', 1)
2128 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
2129 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
2130 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
2133 addi(int ra, int si)
2136 if (__builtin_constant_p(si))
2137 __asm__ __volatile__(
2138 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
2141 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2144 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2151 ###############################################################
2152 # Library / OS tests
2153 ###############################################################
2155 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2156 # unnecessary checks over and over, particularly on windows.
2170 'sys/personality.h',
2179 foreach header : header_checks
2180 varname = 'HAVE_' + header.underscorify().to_upper()
2182 # Emulate autoconf behaviour of not-found->undef, found->1
2183 found = cc.has_header(header,
2184 include_directories: postgres_inc, args: test_c_args)
2185 cdata.set(varname, found ? 1 : false,
2186 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2191 ['F_FULLFSYNC', 'fcntl.h'],
2192 ['fdatasync', 'unistd.h'],
2193 ['posix_fadvise', 'fcntl.h'],
2194 ['strlcat', 'string.h'],
2195 ['strlcpy', 'string.h'],
2196 ['strnlen', 'string.h'],
2199 # Need to check for function declarations for these functions, because
2200 # checking for library symbols wouldn't handle deployment target
2201 # restrictions on macOS
2203 ['preadv', 'sys/uio.h'],
2204 ['pwritev', 'sys/uio.h'],
2207 foreach c : decl_checks
2211 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2213 found = cc.has_header_symbol(header, func,
2214 args: test_c_args, include_directories: postgres_inc,
2216 cdata.set10(varname, found, description:
2217 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2218 don't.'''.format(func))
2222 if cc.has_type('struct option',
2223 args: test_c_args, include_directories: postgres_inc,
2224 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2225 cdata.set('HAVE_STRUCT_OPTION', 1)
2229 foreach c : ['opterr', 'optreset']
2230 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2239 '''.format(c), name: c, args: test_c_args)
2240 cdata.set(varname, 1)
2242 cdata.set(varname, false)
2246 if cc.has_type('socklen_t',
2247 args: test_c_args, include_directories: postgres_inc,
2249 #include <sys/socket.h>''')
2250 cdata.set('HAVE_SOCKLEN_T', 1)
2253 if cc.has_member('struct sockaddr', 'sa_len',
2254 args: test_c_args, include_directories: postgres_inc,
2256 #include <sys/types.h>
2257 #include <sys/socket.h>''')
2258 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2261 if cc.has_member('struct tm', 'tm_zone',
2262 args: test_c_args, include_directories: postgres_inc,
2264 #include <sys/types.h>
2267 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2272 extern int foo(void);
2275 return timezone / 60;
2278 name: 'global variable `timezone\' exists',
2279 args: test_c_args, include_directories: postgres_inc)
2280 cdata.set('HAVE_INT_TIMEZONE', 1)
2282 cdata.set('HAVE_INT_TIMEZONE', false)
2285 if cc.has_type('union semun',
2287 include_directories: postgres_inc,
2289 #include <sys/types.h>
2290 #include <sys/ipc.h>
2291 #include <sys/sem.h>
2293 cdata.set('HAVE_UNION_SEMUN', 1)
2301 switch (strerror_r(1, buf, sizeof(buf)))
2302 { case 0: break; default: break; }
2305 args: test_c_args, include_directories: postgres_inc)
2306 cdata.set('STRERROR_R_INT', 1)
2308 cdata.set('STRERROR_R_INT', false)
2311 # Find the right header file for the locale_t type. macOS needs xlocale.h;
2312 # standard is locale.h, but glibc <= 2.25 also had an xlocale.h file that
2313 # we should not use so we check the standard header first. MSVC has a
2314 # replacement defined in src/include/port/win32_port.h.
2315 if not cc.has_type('locale_t', prefix: '#include <locale.h>') and \
2316 cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2317 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2320 # Check if the C compiler understands typeof or a variant. Define
2321 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2322 foreach kw : ['typeof', '__typeof__', 'decltype']
2333 args: test_c_args, include_directories: postgres_inc)
2335 cdata.set('HAVE_TYPEOF', 1)
2337 cdata.set('typeof', kw)
2345 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2346 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2347 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2348 wcstombs_l_test = '''
2360 if (not cc.compiles(wcstombs_l_test.format(''),
2361 name: 'wcstombs_l') and
2362 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2363 name: 'wcstombs_l in xlocale.h'))
2364 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2368 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2369 # understands, because it conflicts with __declspec(restrict). Therefore we
2370 # define pg_restrict to the appropriate definition, which presumably won't
2373 # We assume C99 support, so we don't need to make this conditional.
2375 # XXX: Historically we allowed platforms to disable restrict in template
2376 # files, but that was only added for AIX when building with XLC, which we
2377 # don't support yet.
2378 cdata.set('pg_restrict', '__restrict')
2381 # Most libraries are included only if they demonstrably provide a function we
2382 # need, but libm is an exception: always include it, because there are too
2383 # many compilers that play cute optimization games that will break probes for
2384 # standard functions such as pow().
2385 os_deps += cc.find_library('m', required: false)
2387 rt_dep = cc.find_library('rt', required: false)
2389 dl_dep = cc.find_library('dl', required: false)
2391 util_dep = cc.find_library('util', required: false)
2393 getopt_dep = cc.find_library('getopt', required: false)
2394 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2395 # Check if we want to replace getopt/getopt_long even if provided by the system
2396 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2397 # so always use our version on Windows
2398 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2399 # (i.e., allow '-' as a flag character), so use our version on those platforms
2400 # - We want to use system's getopt_long() only if the system provides struct
2402 always_replace_getopt = host_system in ['windows', 'cygwin', 'openbsd', 'solaris']
2403 always_replace_getopt_long = host_system in ['windows', 'cygwin'] or not cdata.has('HAVE_STRUCT_OPTION')
2406 execinfo_dep = cc.find_library('execinfo', required: false)
2408 if host_system == 'cygwin'
2409 cygipc_dep = cc.find_library('cygipc', required: false)
2411 cygipc_dep = not_found_dep
2414 if host_system == 'sunos'
2415 socket_dep = cc.find_library('socket', required: false)
2417 socket_dep = not_found_dep
2420 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2421 # unnecessary checks over and over, particularly on windows.
2423 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2424 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2425 ['clock_gettime', {'dependencies': [rt_dep], 'define': false}],
2427 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2428 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2429 # required. Just checking for dlsym() ought to suffice.
2430 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2433 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2434 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2444 ['posix_fallocate'],
2447 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2448 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2449 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2450 ['setproctitle', {'dependencies': [util_dep]}],
2451 ['setproctitle_fast'],
2452 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2453 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2454 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2455 ['socket', {'dependencies': [socket_dep], 'define': false}],
2457 ['strerror_r', {'dependencies': [thread_dep]}],
2462 ['sync_file_range'],
2468 func_check_results = {}
2469 foreach c : func_checks
2471 kwargs = c.get(1, {})
2472 deps = kwargs.get('dependencies', [])
2474 if kwargs.get('skip', false)
2478 found = cc.has_function(func, args: test_c_args)
2485 found = cc.has_function(func, args: test_c_args,
2486 dependencies: [dep])
2494 func_check_results += {func: found}
2496 if kwargs.get('define', true)
2497 # Emulate autoconf behaviour of not-found->undef, found->1
2498 cdata.set('HAVE_' + func.underscorify().to_upper(),
2500 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2505 if cc.has_function('syslog', args: test_c_args) and \
2506 cc.check_header('syslog.h', args: test_c_args)
2507 cdata.set('HAVE_SYSLOG', 1)
2511 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2513 if sema_kind == 'unnamed_posix' and \
2514 not func_check_results.get('sem_init', false)
2518 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2519 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2521 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2522 cdata.set_quoted('DLSUFFIX', dlsuffix)
2525 # built later than the rest of the version metadata, we need SIZEOF_VOID_P
2526 cdata.set_quoted('PG_VERSION_STR',
2527 'PostgreSQL @0@ on @1@-@2@, compiled by @3@-@4@, @5@-bit'.format(
2528 pg_version, host_machine.cpu_family(), host_system,
2529 cc.get_id(), cc.version(), cdata.get('SIZEOF_VOID_P') * 8,
2534 ###############################################################
2536 ###############################################################
2538 nlsopt = get_option('nls')
2539 libintl = not_found_dep
2541 if not nlsopt.disabled()
2542 # otherwise there'd be lots of
2543 # "Gettext not found, all translation (po) targets will be ignored."
2544 # warnings if not found.
2545 msgfmt = find_program('msgfmt', required: nlsopt, native: true)
2547 # meson 0.59 has this wrapped in dependency('intl')
2548 if (msgfmt.found() and
2549 cc.check_header('libintl.h', required: nlsopt,
2550 args: test_c_args, include_directories: postgres_inc))
2553 if cc.has_function('ngettext')
2554 libintl = declare_dependency()
2556 libintl = cc.find_library('intl',
2557 has_headers: ['libintl.h'], required: nlsopt,
2558 header_include_directories: postgres_inc,
2564 i18n = import('i18n')
2565 cdata.set('ENABLE_NLS', 1)
2571 ###############################################################
2573 ###############################################################
2575 # Set up compiler / linker arguments to be used everywhere, individual targets
2576 # can add further args directly, or indirectly via dependencies
2577 add_project_arguments(cflags, language: ['c'])
2578 add_project_arguments(cppflags, language: ['c'])
2579 add_project_arguments(cflags_warn, language: ['c'])
2580 add_project_arguments(cxxflags, language: ['cpp'])
2581 add_project_arguments(cppflags, language: ['cpp'])
2582 add_project_arguments(cxxflags_warn, language: ['cpp'])
2583 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2586 # Collect a number of lists of things while recursing through the source
2587 # tree. Later steps then can use those.
2589 # list of targets for various alias targets
2590 backend_targets = []
2593 contrib_targets = []
2594 testprep_targets = []
2598 # Define the tests to distribute them to the correct test styles later
2603 # Default options for targets
2605 # First identify rpaths
2606 bin_install_rpaths = []
2607 lib_install_rpaths = []
2608 mod_install_rpaths = []
2611 # Don't add rpaths on darwin for now - as long as only absolute references to
2612 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2613 # their final destination.
2614 if host_system != 'darwin'
2615 # Add absolute path to libdir to rpath. This ensures installed binaries /
2616 # libraries find our libraries (mainly libpq).
2617 bin_install_rpaths += dir_prefix / dir_lib
2618 lib_install_rpaths += dir_prefix / dir_lib
2619 mod_install_rpaths += dir_prefix / dir_lib
2621 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2623 # Not needed on darwin even if we use relative rpaths for our own libraries,
2624 # as the install_name of libraries in extra_lib_dirs will point to their
2626 bin_install_rpaths += postgres_lib_d
2627 lib_install_rpaths += postgres_lib_d
2628 mod_install_rpaths += postgres_lib_d
2632 # Define arguments for default targets
2634 default_target_args = {
2635 'implicit_include_directories': false,
2639 default_lib_args = default_target_args + {
2643 internal_lib_args = default_lib_args + {
2644 'build_by_default': false,
2648 default_mod_args = default_lib_args + {
2650 'install_dir': dir_lib_pkg,
2653 default_bin_args = default_target_args + {
2654 'install_dir': dir_bin,
2657 if get_option('rpath')
2658 default_lib_args += {
2659 'install_rpath': ':'.join(lib_install_rpaths),
2662 default_mod_args += {
2663 'install_rpath': ':'.join(mod_install_rpaths),
2666 default_bin_args += {
2667 'install_rpath': ':'.join(bin_install_rpaths),
2672 # Helper for exporting a limited number of symbols
2673 gen_export_kwargs = {
2674 'input': 'exports.txt',
2675 'output': '@BASENAME@.'+export_file_suffix,
2676 'command': [perl, files('src/tools/gen_export.pl'),
2677 '--format', export_file_format,
2678 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2679 'build_by_default': false,
2686 ### Helpers for custom targets used across the tree
2689 catalog_pm = files('src/backend/catalog/Catalog.pm')
2690 perfect_hash_pm = files('src/tools/PerfectHash.pm')
2691 gen_kwlist_deps = [perfect_hash_pm]
2693 perl, '-I', '@SOURCE_ROOT@/src/tools',
2694 files('src/tools/gen_keywordlist.pl'),
2695 '--output', '@OUTDIR@', '@INPUT@']
2700 ### windows resources related stuff
2703 if host_system == 'windows'
2704 pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico'
2705 win32ver_rc = files('src/port/win32ver.rc')
2706 rcgen = find_program('src/tools/rcgen', native: true)
2709 '--srcdir', '@SOURCE_DIR@',
2710 '--builddir', meson.build_root(),
2711 '--rcout', '@OUTPUT0@',
2712 '--out', '@OUTPUT1@',
2713 '--input', '@INPUT@',
2717 if cc.get_argument_syntax() == 'msvc'
2718 rc = find_program('rc', required: true)
2719 rcgen_base_args += ['--rc', rc.path()]
2720 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.res']
2722 windres = find_program('windres', required: true)
2723 rcgen_base_args += ['--windres', windres.path()]
2724 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.obj']
2727 # msbuild backend doesn't support this atm
2728 if meson.backend() == 'ninja'
2729 rcgen_base_args += ['--depfile', '@DEPFILE@']
2732 rcgen_bin_args = rcgen_base_args + [
2733 '--VFT_TYPE', 'VFT_APP',
2734 '--FILEENDING', 'exe',
2738 rcgen_lib_args = rcgen_base_args + [
2739 '--VFT_TYPE', 'VFT_DLL',
2740 '--FILEENDING', 'dll',
2743 rc_bin_gen = generator(rcgen,
2744 depfile: '@BASENAME@.d',
2745 arguments: rcgen_bin_args,
2746 output: rcgen_outputs,
2749 rc_lib_gen = generator(rcgen,
2750 depfile: '@BASENAME@.d',
2751 arguments: rcgen_lib_args,
2752 output: rcgen_outputs,
2758 # headers that the whole build tree depends on
2759 generated_headers = []
2760 # headers that the backend build depends on
2761 generated_backend_headers = []
2762 # configure_files() output, needs a way of converting to file names
2763 configure_files = []
2765 # generated files that might conflict with a partial in-tree autoconf build
2766 generated_sources = []
2767 # same, for paths that differ between autoconf / meson builds
2768 # elements are [dir, [files]]
2769 generated_sources_ac = {}
2772 # First visit src/include - all targets creating headers are defined
2773 # within. That makes it easy to add the necessary dependencies for the
2774 # subsequent build steps.
2776 subdir('src/include')
2780 # Then through src/port and src/common, as most other things depend on them
2782 frontend_port_code = declare_dependency(
2783 compile_args: ['-DFRONTEND'],
2784 include_directories: [postgres_inc],
2785 dependencies: os_deps,
2788 backend_port_code = declare_dependency(
2789 compile_args: ['-DBUILDING_DLL'],
2790 include_directories: [postgres_inc],
2791 sources: [errcodes], # errcodes.h is needed due to use of ereport
2792 dependencies: os_deps,
2797 frontend_common_code = declare_dependency(
2798 compile_args: ['-DFRONTEND'],
2799 include_directories: [postgres_inc],
2800 sources: generated_headers,
2801 dependencies: [os_deps, zlib, zstd],
2804 backend_common_code = declare_dependency(
2805 compile_args: ['-DBUILDING_DLL'],
2806 include_directories: [postgres_inc],
2807 sources: generated_headers,
2808 dependencies: [os_deps, zlib, zstd],
2811 subdir('src/common')
2813 # all shared libraries should depend on shlib_code
2814 shlib_code = declare_dependency(
2815 link_args: ldflags_sl,
2818 # all static libraries not part of the backend should depend on this
2819 frontend_stlib_code = declare_dependency(
2820 include_directories: [postgres_inc],
2821 link_with: [common_static, pgport_static],
2822 sources: generated_headers,
2823 dependencies: [os_deps, libintl],
2826 # all shared libraries not part of the backend should depend on this
2827 frontend_shlib_code = declare_dependency(
2828 include_directories: [postgres_inc],
2829 link_with: [common_shlib, pgport_shlib],
2830 sources: generated_headers,
2831 dependencies: [shlib_code, os_deps, libintl],
2834 # Dependencies both for static and shared libpq
2844 subdir('src/interfaces/libpq')
2845 # fe_utils depends on libpq
2846 subdir('src/fe_utils')
2848 # for frontend binaries
2849 frontend_code = declare_dependency(
2850 include_directories: [postgres_inc],
2851 link_with: [fe_utils, common_static, pgport_static],
2852 sources: generated_headers,
2853 dependencies: [os_deps, libintl],
2856 backend_both_deps += [
2873 backend_mod_deps = backend_both_deps + os_deps
2875 backend_code = declare_dependency(
2876 compile_args: ['-DBUILDING_DLL'],
2877 include_directories: [postgres_inc],
2878 link_args: ldflags_be,
2880 sources: generated_headers + generated_backend_headers,
2881 dependencies: os_deps + backend_both_deps + backend_deps,
2884 # install these files only during test, not main install
2885 test_install_data = []
2886 test_install_libs = []
2888 # src/backend/meson.build defines backend_mod_code used for extension
2892 # Then through the main sources. That way contrib can have dependencies on
2893 # main sources. Note that this explicitly doesn't enter src/test, right now a
2894 # few regression tests depend on contrib files.
2901 subdir('src/interfaces/libpq/test')
2902 subdir('src/interfaces/ecpg/test')
2904 subdir('doc/src/sgml')
2906 generated_sources_ac += {'': ['GNUmakefile']}
2908 # After processing src/test, add test_install_libs to the testprep_targets
2910 testprep_targets += test_install_libs
2913 # If there are any files in the source directory that we also generate in the
2914 # build directory, they might get preferred over the newly generated files,
2915 # e.g. because of a #include "file", which always will search in the current
2917 message('checking for file conflicts between source and build directory')
2918 conflicting_files = []
2919 potentially_conflicting_files_t = []
2920 potentially_conflicting_files_t += generated_headers
2921 potentially_conflicting_files_t += generated_backend_headers
2922 potentially_conflicting_files_t += generated_backend_sources
2923 potentially_conflicting_files_t += generated_sources
2925 potentially_conflicting_files = []
2927 # convert all sources of potentially conflicting files into uniform shape
2928 foreach t : potentially_conflicting_files_t
2929 potentially_conflicting_files += t.full_path()
2931 foreach t1 : configure_files
2932 if meson.version().version_compare('>=0.59')
2933 t = fs.parent(t1) / fs.name(t1)
2935 t = '@0@'.format(t1)
2937 potentially_conflicting_files += meson.current_build_dir() / t
2939 foreach sub, fnames : generated_sources_ac
2940 sub = meson.build_root() / sub
2941 foreach fname : fnames
2942 potentially_conflicting_files += sub / fname
2946 # find and report conflicting files
2947 foreach build_path : potentially_conflicting_files
2948 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
2949 # str.replace is in 0.56
2950 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
2951 if fs.exists(src_path) or fs.is_symlink(src_path)
2952 conflicting_files += src_path
2955 # XXX: Perhaps we should generate a file that would clean these up? The list
2957 if conflicting_files.length() > 0
2958 errmsg_cleanup = '''
2959 Conflicting files in source directory:
2962 The conflicting files need to be removed, either by removing the files listed
2963 above, or by running configure and then make maintainer-clean.
2965 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
2966 error(errmsg_nonclean_base.format(errmsg_cleanup))
2971 ###############################################################
2973 ###############################################################
2976 # We want to define additional install targets beyond what meson provides. For
2977 # that we need to define targets depending on nearly everything. We collected
2978 # the results of i18n.gettext() invocations into nls_targets, that also
2979 # includes maintainer targets though. Collect the ones we want as a dependency.
2981 # i18n.gettext() doesn't return the dependencies before 0.60 - but the gettext
2982 # generation happens during install, so that's not a real issue.
2984 if libintl.found() and meson.version().version_compare('>=0.60')
2985 # use range() to avoid the flattening of the list that foreach() would do
2986 foreach off : range(0, nls_targets.length())
2987 # i18n.gettext() list containing 1) list of built .mo files 2) maintainer
2988 # -pot target 3) maintainer -pot target
2989 nls_mo_targets += nls_targets[off][0]
2991 alias_target('nls', nls_mo_targets)
3006 # Meson's default install target is quite verbose. Provide one that is quiet.
3007 install_quiet = custom_target('install-quiet',
3008 output: 'install-quiet',
3009 build_always_stale: true,
3010 build_by_default: false,
3011 command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'],
3015 # Target to install files used for tests, which aren't installed by default
3016 install_test_files_args = [
3018 '--prefix', dir_prefix,
3019 '--install', contrib_data_dir, test_install_data,
3020 '--install', dir_lib_pkg, test_install_libs,
3022 run_target('install-test-files',
3023 command: [python] + install_test_files_args,
3024 depends: testprep_targets,
3029 ###############################################################
3031 ###############################################################
3033 # DESTDIR for the installation we'll run tests in
3034 test_install_destdir = meson.build_root() / 'tmp_install/'
3036 # DESTDIR + prefix appropriately munged
3037 if build_system != 'windows'
3038 # On unixoid systems this is trivial, we just prepend the destdir
3039 assert(dir_prefix.startswith('/')) # enforced by meson
3040 test_install_location = '@0@@1@'.format(test_install_destdir, dir_prefix)
3042 # drives, drive-relative paths, etc make this complicated on windows, call
3043 # into a copy of meson's logic for it
3046 'import sys; from pathlib import PurePath; d1=sys.argv[1]; d2=sys.argv[2]; print(str(PurePath(d1, *PurePath(d2).parts[1:])))',
3047 test_install_destdir, dir_prefix]
3048 test_install_location = run_command(command, check: true).stdout().strip()
3051 meson_install_args = meson_args + ['install'] + {
3052 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
3056 # setup tests should be run first,
3057 # so define priority for these
3058 setup_tests_priority = 100
3060 meson_bin, args: meson_install_args ,
3061 env: {'DESTDIR':test_install_destdir},
3062 priority: setup_tests_priority,
3067 test('install_test_files',
3069 args: install_test_files_args + ['--destdir', test_install_destdir],
3070 priority: setup_tests_priority,
3074 test_result_dir = meson.build_root() / 'testrun'
3077 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
3078 # inevitable conflicts from running tests in parallel, hackishly assign
3079 # different ports for different tests.
3083 test_env = environment()
3085 temp_install_bindir = test_install_location / get_option('bindir')
3086 test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template'
3087 test_env.set('PG_REGRESS', pg_regress.full_path())
3088 test_env.set('REGRESS_SHLIB', regress_module.full_path())
3089 test_env.set('INITDB_TEMPLATE', test_initdb_template)
3091 # Test suites that are not safe by default but can be run if selected
3092 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
3093 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
3094 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
3096 # Add the temporary installation to the library search path on platforms where
3097 # that works (everything but windows, basically). On windows everything
3098 # library-like gets installed into bindir, solving that issue.
3099 if library_path_var != ''
3100 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
3104 # Create (and remove old) initdb template directory. Tests use that, where
3105 # possible, to make it cheaper to run tests.
3107 # Use python to remove the old cached initdb, as we cannot rely on a working
3108 # 'rm' binary on windows.
3109 test('initdb_cache',
3117 shutil.rmtree(sys.argv[1], ignore_errors=True)
3118 sp = subprocess.run(sys.argv[2:] + [sys.argv[1]])
3119 sys.exit(sp.returncode)
3121 test_initdb_template,
3122 temp_install_bindir / 'initdb',
3123 '--auth', 'trust', '--no-sync', '--no-instructions', '--lc-messages=C',
3126 priority: setup_tests_priority - 1,
3134 ###############################################################
3136 ###############################################################
3138 # When using a meson version understanding exclude_suites, define a
3139 # 'tmp_install' test setup (the default) that excludes tests running against a
3140 # pre-existing install and a 'running' setup that conflicts with creation of
3141 # the temporary installation and tap tests (which don't support running
3142 # against a running server).
3146 if meson.version().version_compare('>=0.57')
3149 runningcheck = false
3152 testwrap = files('src/tools/testwrap')
3154 foreach test_dir : tests
3157 '--basedir', meson.build_root(),
3158 '--srcdir', test_dir['sd'],
3161 foreach kind, v : test_dir
3162 if kind in ['sd', 'bd', 'name']
3168 if kind in ['regress', 'isolation', 'ecpg']
3169 if kind == 'regress'
3171 fallback_dbname = 'regression_@0@'
3172 elif kind == 'isolation'
3173 runner = pg_isolation_regress
3174 fallback_dbname = 'isolation_regression_@0@'
3176 runner = pg_regress_ecpg
3177 fallback_dbname = 'ecpg_regression_@0@'
3180 test_group = test_dir['name']
3181 test_group_running = test_dir['name'] + '-running'
3183 test_output = test_result_dir / test_group / kind
3184 test_output_running = test_result_dir / test_group_running/ kind
3186 # Unless specified by the test, choose a non-conflicting database name,
3187 # to avoid conflicts when running against existing server.
3188 dbname = t.get('dbname',
3189 fallback_dbname.format(test_dir['name']))
3191 test_command_base = [
3193 '--inputdir', t.get('inputdir', test_dir['sd']),
3194 '--expecteddir', t.get('expecteddir', test_dir['sd']),
3196 '--dlpath', test_dir['bd'],
3197 '--max-concurrent-tests=20',
3199 ] + t.get('regress_args', [])
3202 if t.has_key('schedule')
3203 test_selection += ['--schedule', t['schedule'],]
3206 if kind == 'isolation'
3207 test_selection += t.get('specs', [])
3209 test_selection += t.get('sql', [])
3213 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
3219 'depends': test_deps + t.get('deps', []),
3221 } + t.get('test_kwargs', {})
3223 test(test_group / kind,
3227 '--testgroup', test_group,
3231 '--outputdir', test_output,
3232 '--temp-instance', test_output / 'tmp_check',
3233 '--port', testport.to_string(),
3237 kwargs: test_kwargs,
3239 install_suites += test_group
3241 # some tests can't support running against running DB
3242 if runningcheck and t.get('runningcheck', true)
3243 test(test_group_running / kind,
3247 '--testgroup', test_group_running,
3251 '--outputdir', test_output_running,
3254 is_parallel: t.get('runningcheck-parallel', true),
3255 suite: test_group_running,
3256 kwargs: test_kwargs,
3258 running_suites += test_group_running
3263 testwrap_tap = testwrap_base
3264 if not tap_tests_enabled
3265 testwrap_tap += ['--skip', 'TAP tests not enabled']
3270 '-I', meson.source_root() / 'src/test/perl',
3271 '-I', test_dir['sd'],
3274 # Add temporary install, the build directory for non-installed binaries and
3275 # also test/ for non-installed test binaries built separately.
3277 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
3279 foreach name, value : t.get('env', {})
3280 env.set(name, value)
3283 test_group = test_dir['name']
3286 'suite': test_group,
3288 'depends': test_deps + t.get('deps', []),
3290 } + t.get('test_kwargs', {})
3292 foreach onetap : t['tests']
3293 # Make tap test names prettier, remove t/ and .pl
3295 if onetap_p.startswith('t/')
3296 onetap_p = onetap.split('t/')[1]
3298 if onetap_p.endswith('.pl')
3299 onetap_p = fs.stem(onetap_p)
3302 test(test_dir['name'] / onetap_p,
3304 kwargs: test_kwargs,
3305 args: testwrap_tap + [
3306 '--testgroup', test_dir['name'],
3307 '--testname', onetap_p,
3309 test_dir['sd'] / onetap,
3313 install_suites += test_group
3315 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
3318 endforeach # kinds of tests
3320 endforeach # directories with tests
3322 # repeat condition so meson realizes version dependency
3323 if meson.version().version_compare('>=0.57')
3324 add_test_setup('tmp_install',
3326 exclude_suites: running_suites)
3327 add_test_setup('running',
3328 exclude_suites: ['setup'] + install_suites)
3333 ###############################################################
3335 ###############################################################
3337 alias_target('backend', backend_targets)
3338 alias_target('bin', bin_targets + [libpq_st])
3339 alias_target('pl', pl_targets)
3340 alias_target('contrib', contrib_targets)
3341 alias_target('testprep', testprep_targets)
3343 alias_target('world', all_built, docs)
3344 alias_target('install-world', install_quiet, installdocs)
3348 perl, '-ne', 'next if /^#/; print',
3349 files('doc/src/sgml/targets-meson.txt'),
3355 ###############################################################
3356 # The End, The End, My Friend
3357 ###############################################################
3359 if meson.version().version_compare('>=0.57')
3363 'data block size': '@0@ kB'.format(cdata.get('BLCKSZ') / 1024),
3364 'WAL block size': '@0@ kB'.format(cdata.get('XLOG_BLCKSZ') / 1024),
3365 'segment size': get_option('segsize_blocks') != 0 ?
3366 '@0@ blocks'.format(cdata.get('RELSEG_SIZE')) :
3367 '@0@ GB'.format(get_option('segsize')),
3369 section: 'Data layout',
3374 'host system': '@0@ @1@'.format(host_system, host_cpu),
3375 'build system': '@0@ @1@'.format(build_machine.system(),
3376 build_machine.cpu_family()),
3383 'linker': '@0@'.format(cc.get_linker_id()),
3384 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
3386 section: 'Compiler',
3391 'CPP FLAGS': ' '.join(cppflags),
3392 'C FLAGS, functional': ' '.join(cflags),
3393 'C FLAGS, warnings': ' '.join(cflags_warn),
3394 'C FLAGS, modules': ' '.join(cflags_mod),
3395 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3396 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3398 section: 'Compiler Flags',
3404 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3406 section: 'Compiler',
3411 'C++ FLAGS, functional': ' '.join(cxxflags),
3412 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3413 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3415 section: 'Compiler Flags',
3421 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3423 'flex': '@0@ @1@'.format(flex.full_path(), flex_version),
3425 section: 'Programs',
3431 'bsd_auth': bsd_auth,
3433 'docs_pdf': docs_pdf_dep,
3445 'plpython': python3_dep,
3447 'readline': readline,
3454 section: 'External libraries',