1 # Copyright (c) 2022-2023, PostgreSQL Global Development Group
3 # Entry point for building PostgreSQL with meson
5 # Good starting points for writing meson.build files are:
6 # - https://mesonbuild.com/Syntax.html
7 # - https://mesonbuild.com/Reference-manual.html
12 license: 'PostgreSQL',
14 # We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for
15 # RHEL 7 has 0.55. < 0.54 would require replacing some uses of the fs
16 # module, < 0.53 all uses of fs. So far there's no need to go to >=0.56.
17 meson_version: '>=0.54',
19 'warning_level=1', #-Wall equivalent
21 'buildtype=debugoptimized', # -O2 + debug
22 # For compatibility with the autoconf build, set a default prefix. This
23 # works even on windows, where it's a drive-relative path (i.e. when on
24 # d:/somepath it'll install to d:/usr/local/pgsql)
25 'prefix=/usr/local/pgsql',
31 ###############################################################
33 ###############################################################
36 pkgconfig = import('pkgconfig')
38 host_system = host_machine.system()
39 build_system = build_machine.system()
40 host_cpu = host_machine.cpu_family()
42 cc = meson.get_compiler('c')
44 not_found_dep = dependency('', required: false)
45 thread_dep = dependency('threads')
46 auto_features = get_option('auto_features')
50 ###############################################################
52 ###############################################################
54 # It's very easy to get into confusing states when the source directory
55 # contains an in-place build. E.g. the wrong pg_config.h will be used. So just
56 # refuse to build in that case.
58 # There's a more elaborate check later, that checks for conflicts around all
59 # generated files. But we can only do that much further down the line, so this
60 # quick check seems worth it. Adhering to this advice should clean up the
61 # conflict, but won't protect against somebody doing make distclean or just
62 # removing pg_config.h
63 errmsg_nonclean_base = '''
65 Non-clean source code directory detected.
67 To build with meson the source tree may not have an in-place, ./configure
68 style, build configured. You can have both meson and ./configure style builds
69 for the same source tree by building out-of-source / VPATH with
70 configure. Alternatively use a separate check out for meson based builds.
74 if fs.exists(meson.current_source_dir() / 'src' / 'include' / 'pg_config.h')
75 errmsg_cleanup = 'To clean up, run make maintainer-clean in the source tree.'
76 error(errmsg_nonclean_base.format(errmsg_cleanup))
81 ###############################################################
82 # Variables to be determined
83 ###############################################################
85 postgres_inc_d = ['src/include']
86 postgres_inc_d += get_option('extra_include_dirs')
88 postgres_lib_d = get_option('extra_lib_dirs')
107 backend_both_deps = []
113 # source of data for pg_config.h etc
114 cdata = configuration_data()
118 ###############################################################
119 # Version and other metadata
120 ###############################################################
122 pg_version = meson.project_version()
124 if pg_version.endswith('devel')
125 pg_version_arr = [pg_version.split('devel')[0], '0']
126 elif pg_version.contains('beta')
127 pg_version_arr = [pg_version.split('beta')[0], '0']
128 elif pg_version.contains('rc')
129 pg_version_arr = [pg_version.split('rc')[0], '0']
131 pg_version_arr = pg_version.split('.')
134 pg_version_major = pg_version_arr[0].to_int()
135 pg_version_minor = pg_version_arr[1].to_int()
136 pg_version_num = (pg_version_major * 10000) + pg_version_minor
138 pg_url = 'https://www.postgresql.org/'
140 cdata.set_quoted('PACKAGE_NAME', 'PostgreSQL')
141 cdata.set_quoted('PACKAGE_BUGREPORT', 'pgsql-bugs@lists.postgresql.org')
142 cdata.set_quoted('PACKAGE_URL', pg_url)
143 cdata.set_quoted('PACKAGE_VERSION', pg_version)
144 cdata.set_quoted('PACKAGE_STRING', 'PostgreSQL @0@'.format(pg_version))
145 cdata.set_quoted('PACKAGE_TARNAME', 'postgresql')
147 pg_version += get_option('extra_version')
148 cdata.set_quoted('PG_VERSION', pg_version)
149 cdata.set_quoted('PG_MAJORVERSION', pg_version_major.to_string())
150 cdata.set('PG_MAJORVERSION_NUM', pg_version_major)
151 cdata.set('PG_MINORVERSION_NUM', pg_version_minor)
152 cdata.set('PG_VERSION_NUM', pg_version_num)
153 # PG_VERSION_STR is built later, it depends on compiler test results
154 cdata.set_quoted('CONFIGURE_ARGS', '')
158 ###############################################################
159 # Basic platform specific configuration
160 ###############################################################
162 exesuffix = '' # overridden below where necessary
163 dlsuffix = '.so' # overridden below where necessary
164 library_path_var = 'LD_LIBRARY_PATH'
166 # Format of file to control exports from libraries, and how to pass them to
167 # the compiler. For export_fmt @0@ is the path to the file export file.
168 export_file_format = 'gnu'
169 export_file_suffix = 'list'
170 export_fmt = '-Wl,--version-script=@0@'
172 # Flags to add when linking a postgres extension, @0@ is path to
173 # the relevant object on the platform.
174 mod_link_args_fmt = []
176 memset_loop_limit = 1024
178 # Choice of shared memory and semaphore implementation
182 # We implement support for some operating systems by pretending they're
183 # another. Map here, before determining system properties below
184 if host_system == 'dragonfly'
185 # apparently the most similar
186 host_system = 'netbsd'
189 # meson's system names don't quite map to our "traditional" names. In some
190 # places we need the "traditional" name, e.g., for mapping
191 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
193 portname = host_system
195 if host_system == 'aix'
196 library_path_var = 'LIBPATH'
198 export_file_format = 'aix'
199 export_fmt = '-Wl,-bE:@0@'
200 mod_link_args_fmt = ['-Wl,-bI:@0@']
201 mod_link_with_dir = 'libdir'
202 mod_link_with_name = '@0@.imp'
204 # M:SRE sets a flag indicating that an object is a shared library. Seems to
205 # work in some circumstances without, but required in others.
206 ldflags_sl += '-Wl,-bM:SRE'
207 ldflags_be += '-Wl,-brtllib'
209 # Native memset() is faster, tested on:
210 # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
211 # - AIX 5.3 ML3, gcc 4.0.1
212 memset_loop_limit = 0
214 elif host_system == 'cygwin'
215 sema_kind = 'unnamed_posix'
216 cppflags += '-D_GNU_SOURCE'
218 mod_link_args_fmt = ['@0@']
219 mod_link_with_name = 'lib@0@.exe.a'
220 mod_link_with_dir = 'libdir'
222 elif host_system == 'darwin'
224 library_path_var = 'DYLD_LIBRARY_PATH'
226 export_file_format = 'darwin'
227 export_fmt = '-Wl,-exported_symbols_list,@0@'
229 mod_link_args_fmt = ['-bundle_loader', '@0@']
230 mod_link_with_dir = 'bindir'
231 mod_link_with_name = '@0@'
233 sysroot_args = [files('src/tools/darwin_sysroot'), get_option('darwin_sysroot')]
234 pg_sysroot = run_command(sysroot_args, check:true).stdout().strip()
235 message('darwin sysroot: @0@'.format(pg_sysroot))
237 cflags += ['-isysroot', pg_sysroot]
238 ldflags += ['-isysroot', pg_sysroot]
241 # meson defaults to -Wl,-undefined,dynamic_lookup for modules, which we
242 # don't want because a) it's different from what we do for autoconf, b) it
243 # causes warnings in macOS Ventura. But using -Wl,-undefined,error causes a
244 # warning starting in Sonoma. So only add -Wl,-undefined,error if it does
245 # not cause a warning.
246 if cc.has_multi_link_arguments('-Wl,-undefined,error', '-Werror')
247 ldflags_mod += '-Wl,-undefined,error'
250 # Starting in Sonoma, the linker warns about the same library being
251 # linked twice. Which can easily happen when multiple dependencies
252 # depend on the same library. Quiesce the ill considered warning.
253 ldflags += cc.get_supported_link_arguments('-Wl,-no_warn_duplicate_libraries')
255 elif host_system == 'freebsd'
256 sema_kind = 'unnamed_posix'
258 elif host_system == 'linux'
259 sema_kind = 'unnamed_posix'
260 cppflags += '-D_GNU_SOURCE'
262 elif host_system == 'netbsd'
263 # We must resolve all dynamic linking in the core server at program start.
264 # Otherwise the postmaster can self-deadlock due to signals interrupting
265 # resolution of calls, since NetBSD's linker takes a lock while doing that
266 # and some postmaster signal handlers do things that will also acquire that
267 # lock. As long as we need "-z now", might as well specify "-z relro" too.
268 # While there's not a hard reason to adopt these settings for our other
269 # executables, there's also little reason not to, so just add them to
271 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
273 elif host_system == 'openbsd'
276 elif host_system == 'sunos'
278 export_fmt = '-Wl,-M@0@'
279 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
281 elif host_system == 'windows'
285 library_path_var = ''
287 export_file_format = 'win'
288 export_file_suffix = 'def'
289 if cc.get_id() == 'msvc'
290 export_fmt = '/DEF:@0@'
291 mod_link_with_name = '@0@.exe.lib'
294 mod_link_with_name = 'lib@0@.exe.a'
296 mod_link_args_fmt = ['@0@']
297 mod_link_with_dir = 'libdir'
302 cdata.set('WIN32_STACK_RLIMIT', 4194304)
303 if cc.get_id() == 'msvc'
304 ldflags += '/INCREMENTAL:NO'
305 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
306 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
308 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
309 # Need to allow multiple definitions, we e.g. want to override getopt.
310 ldflags += '-Wl,--allow-multiple-definition'
311 # Ensure we get MSVC-like linking behavior.
312 ldflags += '-Wl,--disable-auto-import'
315 os_deps += cc.find_library('ws2_32', required: true)
316 secur32_dep = cc.find_library('secur32', required: true)
317 backend_deps += secur32_dep
318 libpq_deps += secur32_dep
320 postgres_inc_d += 'src/include/port/win32'
321 if cc.get_id() == 'msvc'
322 postgres_inc_d += 'src/include/port/win32_msvc'
325 windows = import('windows')
328 # XXX: Should we add an option to override the host_system as an escape
330 error('unknown host system: @0@'.format(host_system))
335 ###############################################################
337 ###############################################################
340 perl = find_program(get_option('PERL'), required: true, native: true)
341 python = find_program(get_option('PYTHON'), required: true, native: true)
342 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35')
343 bison = find_program(get_option('BISON'), native: true, version: '>= 2.3')
344 sed = find_program(get_option('SED'), 'sed', native: true)
345 prove = find_program(get_option('PROVE'), native: true, required: false)
346 tar = find_program(get_option('TAR'), native: true)
347 gzip = find_program(get_option('GZIP'), native: true)
348 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
349 openssl = find_program(get_option('OPENSSL'), native: true, required: false)
350 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
351 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
352 missing = find_program('config/missing', native: true)
353 cp = find_program('cp', required: false, native: true)
354 xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
355 xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
359 bison_version_c = run_command(bison, '--version', check: true)
360 # bison version string helpfully is something like
361 # >>bison (GNU bison) 3.8.1<<
362 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
363 if bison_version.version_compare('>=3.0')
364 bison_flags += ['-Wno-deprecated']
367 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
369 'output': ['@BASENAME@.c', '@BASENAME@.h'],
370 'command': bison_cmd,
374 flex_wrapper = files('src/tools/pgflex')
375 flex_cmd = [python, flex_wrapper,
376 '--builddir', '@BUILD_ROOT@',
377 '--srcdir', '@SOURCE_ROOT@',
378 '--privatedir', '@PRIVATE_DIR@',
379 '--flex', flex, '--perl', perl,
380 '-i', '@INPUT@', '-o', '@OUTPUT0@',
383 wget = find_program('wget', required: false, native: true)
384 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
386 install_files = files('src/tools/install_files')
390 ###############################################################
391 # Path to meson (for tests etc)
392 ###############################################################
394 # NB: this should really be part of meson, see
395 # https://github.com/mesonbuild/meson/issues/8511
396 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
398 if meson_binpath_r.stdout() == ''
399 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
400 meson_binpath_r.returncode(),
401 meson_binpath_r.stdout(),
402 meson_binpath_r.stderr()))
405 meson_binpath_s = meson_binpath_r.stdout().split('\n')
406 meson_binpath_len = meson_binpath_s.length()
408 if meson_binpath_len < 1
409 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
416 foreach e : meson_binpath_s
427 if meson_impl not in ['muon', 'meson']
428 error('unknown meson implementation "@0@"'.format(meson_impl))
431 meson_bin = find_program(meson_binpath, native: true)
435 ###############################################################
437 ###############################################################
439 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
441 blocksize = get_option('blocksize').to_int() * 1024
443 if get_option('segsize_blocks') != 0
444 if get_option('segsize') != 1
445 warning('both segsize and segsize_blocks specified, segsize_blocks wins')
448 segsize = get_option('segsize_blocks')
450 segsize = (get_option('segsize') * 1024 * 1024 * 1024) / blocksize
453 cdata.set('BLCKSZ', blocksize, description:
454 '''Size of a disk block --- this also limits the size of a tuple. You can set
455 it bigger if you need bigger tuples (although TOAST should reduce the need
456 to have large tuples, since fields can be spread across multiple tuples).
457 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
458 currently 2^15 (32768). This is determined by the 15-bit widths of the
459 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
460 Changing BLCKSZ requires an initdb.''')
462 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
463 cdata.set('RELSEG_SIZE', segsize)
464 cdata.set('DEF_PGPORT', get_option('pgport'))
465 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
466 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
467 if get_option('system_tzdata') != ''
468 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
473 ###############################################################
475 ###############################################################
477 # These are set by the equivalent --xxxdir configure options. We
478 # append "postgresql" to some of them, if the string does not already
479 # contain "pgsql" or "postgres", in order to avoid directory clutter.
483 dir_prefix = get_option('prefix')
485 dir_prefix_contains_pg = (dir_prefix.contains('pgsql') or dir_prefix.contains('postgres'))
487 dir_bin = get_option('bindir')
489 dir_data = get_option('datadir')
490 if not (dir_prefix_contains_pg or dir_data.contains('pgsql') or dir_data.contains('postgres'))
491 dir_data = dir_data / pkg
494 dir_sysconf = get_option('sysconfdir')
495 if not (dir_prefix_contains_pg or dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
496 dir_sysconf = dir_sysconf / pkg
499 dir_lib = get_option('libdir')
501 dir_lib_pkg = dir_lib
502 if not (dir_prefix_contains_pg or dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
503 dir_lib_pkg = dir_lib_pkg / pkg
506 dir_pgxs = dir_lib_pkg / 'pgxs'
508 dir_include = get_option('includedir')
510 dir_include_pkg = dir_include
511 dir_include_pkg_rel = ''
512 if not (dir_prefix_contains_pg or dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
513 dir_include_pkg = dir_include_pkg / pkg
514 dir_include_pkg_rel = pkg
517 dir_man = get_option('mandir')
519 # FIXME: These used to be separately configurable - worth adding?
520 dir_doc = get_option('datadir') / 'doc' / 'postgresql'
521 dir_doc_html = dir_doc / 'html'
523 dir_locale = get_option('localedir')
527 dir_bitcode = dir_lib_pkg / 'bitcode'
528 dir_include_internal = dir_include_pkg / 'internal'
529 dir_include_server = dir_include_pkg / 'server'
530 dir_include_extension = dir_include_server / 'extension'
531 dir_data_extension = dir_data / 'extension'
535 ###############################################################
536 # Search paths, preparation for compiler tests
538 # NB: Arguments added later are not automatically used for subsequent
539 # configuration-time checks (so they are more isolated). If they should be
540 # used, they need to be added to test_c_args as well.
541 ###############################################################
543 postgres_inc = [include_directories(postgres_inc_d)]
544 test_lib_d = postgres_lib_d
545 test_c_args = cppflags + cflags
549 ###############################################################
551 ###############################################################
553 bsd_authopt = get_option('bsd_auth')
554 bsd_auth = not_found_dep
555 if cc.check_header('bsd_auth.h', required: bsd_authopt,
556 args: test_c_args, include_directories: postgres_inc)
557 cdata.set('USE_BSD_AUTH', 1)
558 bsd_auth = declare_dependency()
563 ###############################################################
566 # For now don't search for DNSServiceRegister in a library - only Apple's
567 # Bonjour implementation, which is always linked, works.
568 ###############################################################
570 bonjouropt = get_option('bonjour')
571 bonjour = not_found_dep
572 if cc.check_header('dns_sd.h', required: bonjouropt,
573 args: test_c_args, include_directories: postgres_inc) and \
574 cc.has_function('DNSServiceRegister',
575 args: test_c_args, include_directories: postgres_inc)
576 cdata.set('USE_BONJOUR', 1)
577 bonjour = declare_dependency()
582 ###############################################################
583 # Option: docs in HTML and man page format
584 ###############################################################
586 docs_opt = get_option('docs')
587 docs_dep = not_found_dep
588 if not docs_opt.disabled()
589 if xmllint_bin.found() and xsltproc_bin.found()
590 docs_dep = declare_dependency()
591 elif docs_opt.enabled()
592 error('missing required tools for docs in HTML / man page format')
598 ###############################################################
599 # Option: docs in PDF format
600 ###############################################################
602 docs_pdf_opt = get_option('docs_pdf')
603 docs_pdf_dep = not_found_dep
604 if not docs_pdf_opt.disabled()
605 fop = find_program(get_option('FOP'), native: true, required: docs_pdf_opt)
606 if xmllint_bin.found() and xsltproc_bin.found() and fop.found()
607 docs_pdf_dep = declare_dependency()
608 elif docs_pdf_opt.enabled()
609 error('missing required tools for docs in PDF format')
615 ###############################################################
617 ###############################################################
619 gssapiopt = get_option('gssapi')
622 if not gssapiopt.disabled()
623 gssapi = dependency('krb5-gssapi', required: false)
624 have_gssapi = gssapi.found()
627 gssapi_deps = [gssapi]
629 # Hardcoded lookup for gssapi. This is necessary as gssapi on windows does
630 # not install neither pkg-config nor cmake dependency information.
631 if host_system == 'windows'
632 is_64 = cc.sizeof('void *', args: test_c_args) == 8
634 gssapi_search_libs = ['gssapi64', 'krb5_64', 'comerr64']
636 gssapi_search_libs = ['gssapi32', 'krb5_32', 'comerr32']
639 gssapi_search_libs = ['gssapi_krb5']
643 foreach libname : gssapi_search_libs
644 lib = cc.find_library(libname, dirs: test_lib_d, required: false)
652 # Meson before 0.57.0 did not support using check_header() etc with
653 # declare_dependency(). Thus the tests below use the library looked up
654 # above. Once we require a newer meson version, we can simplify.
655 gssapi = declare_dependency(dependencies: gssapi_deps)
660 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi_deps, required: false,
661 args: test_c_args, include_directories: postgres_inc)
662 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
663 elif cc.check_header('gssapi.h', dependencies: gssapi_deps, required: gssapiopt,
664 args: test_c_args, include_directories: postgres_inc)
665 cdata.set('HAVE_GSSAPI_H', 1)
671 elif cc.check_header('gssapi/gssapi_ext.h', dependencies: gssapi_deps, required: false,
672 args: test_c_args, include_directories: postgres_inc)
673 cdata.set('HAVE_GSSAPI_GSSAPI_EXT_H', 1)
674 elif cc.check_header('gssapi_ext.h', dependencies: gssapi_deps, required: gssapiopt,
675 args: test_c_args, include_directories: postgres_inc)
676 cdata.set('HAVE_GSSAPI_EXT_H', 1)
682 elif cc.has_function('gss_store_cred_into', dependencies: gssapi_deps,
683 args: test_c_args, include_directories: postgres_inc)
684 cdata.set('ENABLE_GSS', 1)
686 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
687 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
688 elif gssapiopt.enabled()
689 error('''could not find function 'gss_store_cred_into' required for GSSAPI''')
694 if not have_gssapi and gssapiopt.enabled()
695 error('dependency lookup for gssapi failed')
700 gssapi = not_found_dep
705 ###############################################################
707 ###############################################################
709 ldapopt = get_option('ldap')
710 if ldapopt.disabled()
712 ldap_r = not_found_dep
713 elif host_system == 'windows'
714 ldap = cc.find_library('wldap32', required: ldapopt)
717 # macos framework dependency is buggy for ldap (one can argue whether it's
718 # Apple's or meson's fault), leading to an endless recursion with ldap.h
719 # including itself. See https://github.com/mesonbuild/meson/issues/10002
720 # Luckily we only need pkg-config support, so the workaround isn't
722 ldap = dependency('ldap', method: 'pkg-config', required: false)
725 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
728 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
729 has_headers: 'ldap.h', header_include_directories: postgres_inc)
731 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
732 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
733 # library from a separate OpenLDAP installation). The most reliable
734 # way to check that is to check for a function introduced in 2.5.
736 # don't have ldap, we shouldn't check for ldap_r
737 elif cc.has_function('ldap_verify_credentials',
738 dependencies: ldap, args: test_c_args)
739 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
742 # Use ldap_r for FE if available, else assume ldap is thread-safe.
743 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
744 has_headers: 'ldap.h', header_include_directories: postgres_inc)
745 if not ldap_r.found()
748 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
749 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
752 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
753 # process. Check for OpenLDAP versions known not to tolerate doing so;
754 # assume non-OpenLDAP implementations are safe. The dblink test suite
755 # exercises the hazardous interaction directly.
756 compat_test_code = '''
758 #if !defined(LDAP_VENDOR_VERSION) || \
759 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
760 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
764 if not cc.compiles(compat_test_code,
765 name: 'LDAP implementation compatible',
766 dependencies: ldap, args: test_c_args)
768 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
769 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
770 *** also uses LDAP will crash on exit.''')
775 if ldap.found() and cc.has_function('ldap_initialize',
776 dependencies: ldap, args: test_c_args)
777 cdata.set('HAVE_LDAP_INITIALIZE', 1)
782 assert(ldap_r.found())
783 cdata.set('USE_LDAP', 1)
785 assert(not ldap_r.found())
790 ###############################################################
792 ###############################################################
794 llvmopt = get_option('llvm')
796 if add_languages('cpp', required: llvmopt, native: false)
797 llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
801 cdata.set('USE_LLVM', 1)
803 cpp = meson.get_compiler('cpp')
805 llvm_binpath = llvm.get_variable(configtool: 'bindir')
807 ccache = find_program('ccache', native: true, required: false)
809 # Some distros put LLVM and clang in different paths, so fallback to
810 # find via PATH, too.
811 clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
814 message('llvm requires a C++ compiler')
819 ###############################################################
821 ###############################################################
823 icuopt = get_option('icu')
824 if not icuopt.disabled()
825 icu = dependency('icu-uc', required: false)
827 icu_i18n = dependency('icu-i18n', required: true)
830 # Unfortunately the dependency is named differently with cmake
831 if not icu.found() # combine with above once meson 0.60.0 is required
832 icu = dependency('ICU', required: icuopt,
833 components: ['uc'], modules: ['ICU::uc'], method: 'cmake')
835 icu_i18n = dependency('ICU', required: true,
836 components: ['i18n'], modules: ['ICU::i18n'])
841 cdata.set('USE_ICU', 1)
843 icu_i18n = not_found_dep
848 icu_i18n = not_found_dep
853 ###############################################################
855 ###############################################################
857 libxmlopt = get_option('libxml')
858 if not libxmlopt.disabled()
859 libxml = dependency('libxml-2.0', required: false, version: '>= 2.6.23')
860 # Unfortunately the dependency is named differently with cmake
861 if not libxml.found() # combine with above once meson 0.60.0 is required
862 libxml = dependency('LibXml2', required: libxmlopt, version: '>= 2.6.23',
867 cdata.set('USE_LIBXML', 1)
870 libxml = not_found_dep
875 ###############################################################
877 ###############################################################
879 libxsltopt = get_option('libxslt')
880 if not libxsltopt.disabled()
881 libxslt = dependency('libxslt', required: false)
882 # Unfortunately the dependency is named differently with cmake
883 if not libxslt.found() # combine with above once meson 0.60.0 is required
884 libxslt = dependency('LibXslt', required: libxsltopt, method: 'cmake')
888 cdata.set('USE_LIBXSLT', 1)
891 libxslt = not_found_dep
896 ###############################################################
898 ###############################################################
900 lz4opt = get_option('lz4')
901 if not lz4opt.disabled()
902 lz4 = dependency('liblz4', required: false)
903 # Unfortunately the dependency is named differently with cmake
904 if not lz4.found() # combine with above once meson 0.60.0 is required
905 lz4 = dependency('lz4', required: lz4opt,
906 method: 'cmake', modules: ['LZ4::lz4_shared'],
911 cdata.set('USE_LZ4', 1)
912 cdata.set('HAVE_LIBLZ4', 1)
921 ###############################################################
922 # Library: Tcl (for pltcl)
924 # NB: tclConfig.sh is used in autoconf build for getting
925 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
926 # variables. For now we have not seen a need to copy
927 # that behaviour to the meson build.
928 ###############################################################
930 tclopt = get_option('pltcl')
931 tcl_version = get_option('tcl_version')
932 tcl_dep = not_found_dep
933 if not tclopt.disabled()
936 tcl_dep = dependency(tcl_version, required: false)
938 if not tcl_dep.found()
939 tcl_dep = cc.find_library(tcl_version,
944 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
945 tcl_dep = not_found_dep
951 ###############################################################
953 ###############################################################
955 pamopt = get_option('pam')
956 if not pamopt.disabled()
957 pam = dependency('pam', required: false)
960 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
964 pam_header_found = false
966 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
967 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
968 args: test_c_args, include_directories: postgres_inc)
969 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
970 pam_header_found = true
971 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
972 args: test_c_args, include_directories: postgres_inc)
973 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
974 pam_header_found = true
978 cdata.set('USE_PAM', 1)
989 ###############################################################
990 # Library: Perl (for plperl)
991 ###############################################################
993 perlopt = get_option('plperl')
994 perl_dep = not_found_dep
995 if not perlopt.disabled()
998 # First verify that perl has the necessary dependencies installed
999 perl_mods = run_command(
1001 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
1004 if perl_mods.returncode() != 0
1005 perl_may_work = false
1006 perl_msg = 'perl installation does not have the required modules'
1009 # Then inquire perl about its configuration
1011 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
1012 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
1013 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
1014 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
1015 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
1017 perl_inc_dir = '@0@/CORE'.format(archlibexp)
1019 if perlversion.version_compare('< 5.14')
1020 perl_may_work = false
1021 perl_msg = 'Perl version 5.14 or later is required, but this is @0@'.format(perlversion)
1022 elif useshrplib != 'true'
1023 perl_may_work = false
1024 perl_msg = 'need a shared perl'
1029 # On most platforms, archlibexp is also where the Perl include files live ...
1030 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
1031 # ... but on newer macOS versions, we must use -iwithsysroot to look
1033 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
1034 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
1035 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
1038 # check compiler finds header
1039 if not cc.has_header('perl.h', required: false,
1040 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
1041 perl_may_work = false
1042 perl_msg = 'missing perl.h'
1047 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
1049 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
1050 foreach flag : perl_ccflags_r.split(' ')
1051 if flag.startswith('-D') and \
1052 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
1053 perl_ccflags += flag
1057 if host_system == 'windows'
1058 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
1060 if cc.get_id() == 'msvc'
1061 # prevent binary mismatch between MSVC built plperl and Strawberry or
1062 # msys ucrt perl libraries
1063 perl_v = run_command(perl, '-V').stdout()
1064 if not perl_v.contains('USE_THREAD_SAFE_LOCALE')
1065 perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE']
1070 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
1071 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
1073 # We are after Embed's ldopts, but without the subset mentioned in
1074 # Config's ccdlflags and ldflags. (Those are the choices of those who
1075 # built the Perl installation, which are not necessarily appropriate
1076 # for building PostgreSQL.)
1077 perl_ldopts = run_command(perl, '-e', '''
1078 use ExtUtils::Embed;
1079 use Text::ParseWords;
1080 # tell perl to suppress including these in ldopts
1081 *ExtUtils::Embed::_ldflags =*ExtUtils::Embed::_ccdlflags = sub { return ""; };
1082 # adding an argument to ldopts makes it return a value instead of printing
1083 # print one of these per line so splitting will preserve spaces in file names.
1084 # shellwords eats backslashes, so we need to escape them.
1085 (my $opts = ldopts(undef)) =~ s!\\!\\\\!g;
1086 print "$_\n" foreach shellwords($opts);
1088 check: true).stdout().strip().split('\n')
1090 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
1092 perl_dep_int = declare_dependency(
1093 compile_args: perl_ccflags,
1094 link_args: perl_ldopts,
1095 version: perlversion,
1098 # While we're at it, check that we can link to libperl.
1099 # On most platforms, if perl.h is there then libperl.so will be too, but
1100 # at this writing Debian packages them separately.
1101 perl_link_test = '''
1104 #define __inline__ inline
1112 if not cc.links(perl_link_test, name: 'libperl',
1113 args: test_c_args + perl_ccflags + perl_ldopts,
1114 include_directories: postgres_inc)
1115 perl_may_work = false
1116 perl_msg = 'missing libperl'
1119 endif # perl_may_work
1122 perl_dep = perl_dep_int
1124 if perlopt.enabled()
1125 error('dependency plperl failed: @0@'.format(perl_msg))
1127 message('disabling optional dependency plperl: @0@'.format(perl_msg))
1134 ###############################################################
1135 # Library: Python (for plpython)
1136 ###############################################################
1138 pyopt = get_option('plpython')
1139 python3_dep = not_found_dep
1140 if not pyopt.disabled()
1141 pm = import('python')
1142 python3_inst = pm.find_installation(python.path(), required: pyopt)
1143 if python3_inst.found()
1144 python3_dep = python3_inst.dependency(embed: true, required: pyopt)
1145 # Remove this check after we depend on Meson >= 1.1.0
1146 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt, include_directories: postgres_inc)
1147 python3_dep = not_found_dep
1154 ###############################################################
1156 ###############################################################
1158 if not get_option('readline').disabled()
1159 libedit_preferred = get_option('libedit_preferred')
1160 # Set the order of readline dependencies.
1161 # cc.find_library breaks and throws on the first dependency which
1162 # is marked as required=true and can't be found. Thus, we only mark
1163 # the last dependency to look up as required, to not throw too early.
1164 check_readline_deps = [
1166 'name': libedit_preferred ? 'libedit' : 'readline',
1170 'name': libedit_preferred ? 'readline' : 'libedit',
1171 'required': get_option('readline')
1175 foreach readline_dep : check_readline_deps
1176 readline = dependency(readline_dep['name'], required: false)
1177 if not readline.found()
1178 readline = cc.find_library(readline_dep['name'],
1179 required: readline_dep['required'],
1188 cdata.set('HAVE_LIBREADLINE', 1)
1191 'header_prefix': 'editline/',
1192 'flag_prefix': 'EDITLINE_',
1195 'header_prefix': 'readline/',
1196 'flag_prefix': 'READLINE_',
1199 'header_prefix': '',
1203 # Set the order of prefixes
1204 prefixes = libedit_preferred ? \
1205 [editline_prefix, default_prefix, readline_prefix] : \
1206 [readline_prefix, default_prefix, editline_prefix]
1208 at_least_one_header_found = false
1209 foreach header : ['history', 'readline']
1211 foreach prefix : prefixes
1212 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1213 # Check history.h and readline.h
1214 if not is_found and cc.has_header(header_file,
1215 args: test_c_args, include_directories: postgres_inc,
1216 dependencies: [readline], required: false)
1217 if header == 'readline'
1218 readline_h = header_file
1220 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1222 at_least_one_header_found = true
1227 if not at_least_one_header_found
1228 error('''readline header not found
1229 If you have @0@ already installed, see meson-logs/meson-log.txt for details on the
1230 failure. It is possible the compiler isn't looking in the proper directory.
1231 Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
1236 'history_truncate_file',
1237 'rl_completion_matches',
1238 'rl_filename_completion_function',
1239 'rl_reset_screen_size',
1243 foreach func : check_funcs
1244 found = cc.has_function(func, dependencies: [readline],
1245 args: test_c_args, include_directories: postgres_inc)
1246 cdata.set('HAVE_' + func.to_upper(), found ? 1 : false)
1250 'rl_completion_suppress_quote',
1251 'rl_filename_quote_characters',
1252 'rl_filename_quoting_function',
1255 foreach var : check_vars
1256 cdata.set('HAVE_' + var.to_upper(),
1257 cc.has_header_symbol(readline_h, var,
1258 args: test_c_args, include_directories: postgres_inc,
1259 prefix: '#include <stdio.h>',
1260 dependencies: [readline]) ? 1 : false)
1263 # If found via cc.find_library() ensure headers are found when using the
1264 # dependency. On meson < 0.57 one cannot do compiler checks using the
1265 # dependency returned by declare_dependency(), so we can't do this above.
1266 if readline.type_name() == 'library'
1267 readline = declare_dependency(dependencies: readline,
1268 include_directories: postgres_inc)
1271 # On windows with mingw readline requires auto-import to successfully
1272 # link, as the headers don't use declspec(dllimport)
1273 if host_system == 'windows' and cc.get_id() != 'msvc'
1274 readline = declare_dependency(dependencies: readline,
1275 link_args: '-Wl,--enable-auto-import')
1279 # XXX: Figure out whether to implement mingw warning equivalent
1281 readline = not_found_dep
1286 ###############################################################
1288 ###############################################################
1290 selinux = not_found_dep
1291 selinuxopt = get_option('selinux')
1292 if meson.version().version_compare('>=0.59')
1293 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1295 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1296 cdata.set('HAVE_LIBSELINUX',
1297 selinux.found() ? 1 : false)
1301 ###############################################################
1303 ###############################################################
1305 systemd = not_found_dep
1306 systemdopt = get_option('systemd')
1307 if meson.version().version_compare('>=0.59')
1308 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1310 systemd = dependency('libsystemd', required: systemdopt)
1311 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1315 ###############################################################
1317 ###############################################################
1320 ssl_library = 'none'
1321 sslopt = get_option('ssl')
1323 if sslopt == 'auto' and auto_features.disabled()
1327 if sslopt in ['auto', 'openssl']
1328 openssl_required = (sslopt == 'openssl')
1330 # Try to find openssl via pkg-config et al, if that doesn't work
1331 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1332 # the library names that we know about.
1334 # via pkg-config et al
1335 ssl = dependency('openssl', required: false)
1336 # only meson >= 0.57 supports declare_dependency() in cc.has_function(), so
1337 # we pass cc.find_library() results if necessary
1340 # via library + headers
1342 ssl_lib = cc.find_library('ssl',
1344 header_include_directories: postgres_inc,
1345 has_headers: ['openssl/ssl.h', 'openssl/err.h'],
1346 required: openssl_required)
1347 crypto_lib = cc.find_library('crypto',
1349 required: openssl_required)
1350 if ssl_lib.found() and crypto_lib.found()
1351 ssl_int = [ssl_lib, crypto_lib]
1352 ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc)
1354 elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \
1355 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required)
1363 ['CRYPTO_new_ex_data', {'required': true}],
1364 ['SSL_new', {'required': true}],
1366 # Functions introduced in OpenSSL 1.0.2.
1367 ['X509_get_signature_nid'],
1368 ['SSL_CTX_set_cert_cb'], # not in LibreSSL
1370 # Functions introduced in OpenSSL 1.1.0. We used to check for
1371 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1372 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1373 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1375 ['OPENSSL_init_ssl'],
1377 ['ASN1_STRING_get0_data'],
1381 # OpenSSL versions before 1.1.0 required setting callback functions, for
1382 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1383 # function was removed.
1386 # Function introduced in OpenSSL 1.1.1
1387 ['X509_get_signature_info'],
1388 ['SSL_CTX_set_num_tickets'],
1391 are_openssl_funcs_complete = true
1392 foreach c : check_funcs
1394 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1395 required = c.get(1, {}).get('required', false)
1396 if required and not val
1397 are_openssl_funcs_complete = false
1399 error('openssl function @0@ is required'.format(func))
1403 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1407 if are_openssl_funcs_complete
1408 cdata.set('USE_OPENSSL', 1,
1409 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1410 cdata.set('OPENSSL_API_COMPAT', '0x10001000L',
1411 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
1412 ssl_library = 'openssl'
1419 if sslopt == 'auto' and auto_features.enabled() and not ssl.found()
1420 error('no SSL library found')
1425 ###############################################################
1427 ###############################################################
1429 uuidopt = get_option('uuid')
1430 if uuidopt != 'none'
1431 uuidname = uuidopt.to_upper()
1432 if uuidopt == 'e2fs'
1433 uuid = dependency('uuid', required: true)
1434 uuidfunc = 'uuid_generate'
1435 uuidheader = 'uuid/uuid.h'
1436 elif uuidopt == 'bsd'
1437 # libc should have uuid function
1438 uuid = declare_dependency()
1439 uuidfunc = 'uuid_to_string'
1440 uuidheader = 'uuid.h'
1441 elif uuidopt == 'ossp'
1442 # In upstream, the package and library is called just 'uuid', but many
1443 # distros change it to 'ossp-uuid'.
1444 uuid = dependency('ossp-uuid', 'uuid', required: false)
1445 uuidfunc = 'uuid_export'
1446 uuidheader = 'uuid.h'
1448 # Hardcoded lookup for ossp-uuid. This is necessary as ossp-uuid on
1449 # windows installs neither a pkg-config nor a cmake dependency
1450 # information. Nor is there another supported uuid implementation
1451 # available on windows.
1453 uuid = cc.find_library('ossp-uuid',
1454 required: false, dirs: test_lib_d,
1455 has_headers: uuidheader, header_include_directories: postgres_inc)
1458 uuid = cc.find_library('uuid',
1459 required: true, dirs: test_lib_d,
1460 has_headers: uuidheader, header_include_directories: postgres_inc)
1463 error('unknown uuid build option value: @0@'.format(uuidopt))
1466 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1467 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1469 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1471 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1472 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1474 uuid = not_found_dep
1479 ###############################################################
1481 ###############################################################
1483 zlibopt = get_option('zlib')
1484 zlib = not_found_dep
1485 if not zlibopt.disabled()
1486 zlib_t = dependency('zlib', required: zlibopt)
1488 if zlib_t.type_name() == 'internal'
1489 # if fallback was used, we don't need to test if headers are present (they
1490 # aren't built yet, so we can't test)
1492 elif not zlib_t.found()
1493 warning('did not find zlib')
1494 elif not cc.has_header('zlib.h',
1495 args: test_c_args, include_directories: postgres_inc,
1496 dependencies: [zlib_t], required: zlibopt)
1497 warning('zlib header not found')
1498 elif not cc.has_type('z_streamp',
1499 dependencies: [zlib_t], prefix: '#include <zlib.h>',
1500 args: test_c_args, include_directories: postgres_inc)
1501 if zlibopt.enabled()
1502 error('zlib version is too old')
1504 warning('zlib version is too old')
1511 cdata.set('HAVE_LIBZ', 1)
1517 ###############################################################
1518 # Library: tap test dependencies
1519 ###############################################################
1521 # Check whether tap tests are enabled or not
1522 tap_tests_enabled = false
1523 tapopt = get_option('tap_tests')
1524 if not tapopt.disabled()
1525 # Checking for perl modules for tap tests
1526 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1527 if perl_ipc_run_check.returncode() != 0
1528 message(perl_ipc_run_check.stderr().strip())
1530 error('Additional Perl modules are required to run TAP tests.')
1532 warning('Additional Perl modules are required to run TAP tests.')
1535 tap_tests_enabled = true
1541 ###############################################################
1543 ###############################################################
1545 zstdopt = get_option('zstd')
1546 if not zstdopt.disabled()
1547 zstd = dependency('libzstd', required: false, version: '>=1.4.0')
1548 # Unfortunately the dependency is named differently with cmake
1549 if not zstd.found() # combine with above once meson 0.60.0 is required
1550 zstd = dependency('zstd', required: zstdopt, version: '>=1.4.0',
1551 method: 'cmake', modules: ['zstd::libzstd_shared'])
1555 cdata.set('USE_ZSTD', 1)
1556 cdata.set('HAVE_LIBZSTD', 1)
1560 zstd = not_found_dep
1565 ###############################################################
1567 ###############################################################
1569 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1570 # unnecessarily, because we optionally rely on newer features.
1572 #include <stdbool.h>
1573 #include <complex.h>
1575 #include <inttypes.h>
1577 struct named_init_test {
1582 extern void structfunc(struct named_init_test);
1584 int main(int argc, char **argv)
1586 struct named_init_test nit = {
1591 for (int loop_var = 0; loop_var < 3; loop_var++)
1596 structfunc((struct named_init_test){1, 0});
1602 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1603 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1604 args: test_c_args + ['-std=c99'])
1605 test_c_args += '-std=c99'
1606 cflags += '-std=c99'
1608 error('C compiler does not support C99')
1612 sizeof_long = cc.sizeof('long', args: test_c_args)
1613 cdata.set('SIZEOF_LONG', sizeof_long)
1615 cdata.set('HAVE_LONG_INT_64', 1)
1616 cdata.set('PG_INT64_TYPE', 'long int')
1617 cdata.set_quoted('INT64_MODIFIER', 'l')
1618 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1619 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1620 cdata.set('PG_INT64_TYPE', 'long long int')
1621 cdata.set_quoted('INT64_MODIFIER', 'll')
1623 error('do not know how to get a 64bit int')
1626 if host_machine.endian() == 'big'
1627 cdata.set('WORDS_BIGENDIAN', 1)
1630 alignof_types = ['short', 'int', 'long', 'double']
1632 foreach t : alignof_types
1633 align = cc.alignment(t, args: test_c_args)
1637 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1639 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1641 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1642 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1645 # Check if __int128 is a working 128 bit integer type, and if so
1646 # define PG_INT128_TYPE to that typename.
1648 # This currently only detects a GCC/clang extension, but support for other
1649 # environments may be added in the future.
1651 # For the moment we only test for support for 128bit math; support for
1652 # 128bit literals and snprintf is not required.
1655 * We don't actually run this test, just link it to verify that any support
1656 * functions needed for __int128 are present.
1658 * These are globals to discourage the compiler from folding all the
1659 * arithmetic tests down to compile-time constants. We do not have
1660 * convenient support for 128bit literals at this point...
1662 __int128 a = 48828125;
1663 __int128 b = 97656250;
1668 a = (a << 12) + 1; /* 200000000001 */
1669 b = (b << 12) + 5; /* 400000000005 */
1670 /* try the most relevant arithmetic ops */
1673 /* must use the results, else compiler may optimize arithmetic away */
1679 buggy_int128 = false
1681 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1682 # If not cross-compiling, we can test for bugs and disable use of __int128
1683 # with buggy compilers. If cross-compiling, hope for the best.
1684 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1685 if not meson.is_cross_build()
1687 /* This must match the corresponding code in c.h: */
1688 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1689 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1690 #elif defined(_MSC_VER)
1691 #define pg_attribute_aligned(a) __declspec(align(a))
1693 typedef __int128 int128a
1694 #if defined(pg_attribute_aligned)
1695 pg_attribute_aligned(8)
1700 void pass_by_val(void *buffer, int128a par) { holder = par; }
1704 long int i64 = 97656225L << 12;
1706 pass_by_val(main, (int128a) i64);
1710 name: '__int128 alignment bug',
1712 assert(r.compiled())
1713 if r.returncode() != 0
1715 message('__int128 support present but buggy and thus disabled')
1720 cdata.set('PG_INT128_TYPE', '__int128')
1721 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.alignment('__int128', args: test_c_args))
1726 # Check if the C compiler knows computed gotos (gcc extension, also
1727 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1729 # Checking whether computed gotos are supported syntax-wise ought to
1730 # be enough, as the syntax is otherwise illegal.
1732 static inline int foo(void)
1734 void *labeladdrs[] = {&&my_label};
1735 goto *labeladdrs[0];
1740 cdata.set('HAVE_COMPUTED_GOTO', 1)
1744 # Check if the C compiler understands _Static_assert(),
1745 # and define HAVE__STATIC_ASSERT if so.
1747 # We actually check the syntax ({ _Static_assert(...) }), because we need
1748 # gcc-style compound expressions to be able to wrap the thing into macros.
1750 int main(int arg, char **argv)
1752 ({ _Static_assert(1, "foo"); });
1756 cdata.set('HAVE__STATIC_ASSERT', 1)
1760 # We use <stdbool.h> if we have it and it declares type bool as having
1761 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1762 if cc.has_type('_Bool', args: test_c_args) \
1763 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1764 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1765 cdata.set('HAVE__BOOL', 1)
1766 cdata.set('PG_USE_STDBOOL', 1)
1770 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1771 # warning for each use of %m.
1772 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1774 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1775 static void call_log(void)
1777 emit_log(0, "error: %s: %m", "foo");
1780 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1781 foreach a : printf_attributes
1782 if cc.compiles(testsrc.format(a),
1783 args: test_c_args + attrib_error_args, name: 'format ' + a)
1784 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1790 if cc.has_function_attribute('visibility:default') and \
1791 cc.has_function_attribute('visibility:hidden')
1792 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1794 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1795 # inlineshidden to C code as well... And either way, we want to put these
1796 # flags into exported files (pgxs, .pc files).
1797 cflags_mod += '-fvisibility=hidden'
1798 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1799 ldflags_mod += '-fvisibility=hidden'
1803 # Check if various builtins exist. Some builtins are tested separately,
1804 # because we want to test something more complicated than the generic case.
1817 foreach builtin : builtins
1818 fname = '__builtin_@0@'.format(builtin)
1819 if cc.has_function(fname, args: test_c_args)
1820 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1825 # Check if the C compiler understands __builtin_types_compatible_p,
1826 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1828 # We check usage with __typeof__, though it's unlikely any compiler would
1829 # have the former and not the latter.
1832 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1834 name: '__builtin_types_compatible_p',
1836 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1840 # Check if the C compiler understands __builtin_$op_overflow(),
1841 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1843 # Check for the most complicated case, 64 bit multiplication, as a
1844 # proxy for all of the operations. To detect the case where the compiler
1845 # knows the function but library support is missing, we must link not just
1846 # compile, and store the results in global variables so the compiler doesn't
1847 # optimize away the call.
1855 return __builtin_mul_overflow(a, b, &result);
1857 name: '__builtin_mul_overflow',
1858 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1860 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1864 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1865 # here. To prevent problems due to two detection methods working, stop
1866 # checking after one.
1869 int main(int arg, char **argv)
1871 unsigned int exx[4] = {0, 0, 0, 0};
1872 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1874 ''', name: '__get_cpuid',
1876 cdata.set('HAVE__GET_CPUID', 1)
1879 int main(int arg, char **argv)
1881 unsigned int exx[4] = {0, 0, 0, 0};
1884 ''', name: '__cpuid',
1886 cdata.set('HAVE__CPUID', 1)
1890 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1891 # versions of clang do not understand -fexcess-precision=standard, the use of
1892 # x87 floating point operations leads to problems like isinf possibly returning
1893 # false for a value that is infinite when converted from the 80bit register to
1894 # the 8byte memory representation.
1896 # Only perform the test if the compiler doesn't understand
1897 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1899 if '-fexcess-precision=standard' not in cflags
1900 if not cc.compiles('''
1901 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1904 name: '', args: test_c_args)
1905 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1911 ###############################################################
1913 ###############################################################
1915 common_functional_flags = [
1916 # Disable strict-aliasing rules; needed for gcc 3.3+
1917 '-fno-strict-aliasing',
1918 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1920 '-fexcess-precision=standard',
1923 cflags += cc.get_supported_arguments(common_functional_flags)
1925 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1928 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1929 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1931 common_warning_flags = [
1932 '-Wmissing-prototypes',
1934 # Really don't want VLAs to be used in our dialect of C
1936 # On macOS, complain about usage of symbols newer than the deployment target
1937 '-Werror=unguarded-availability-new',
1939 '-Wmissing-format-attribute',
1940 '-Wimplicit-fallthrough=3',
1941 '-Wcast-function-type',
1942 '-Wshadow=compatible-local',
1943 # This was included in -Wall/-Wformat in older GCC versions
1944 '-Wformat-security',
1947 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1949 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1952 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1953 # the result for them
1954 cflags_no_decl_after_statement = []
1955 if cc.has_argument('-Wdeclaration-after-statement')
1956 cflags_warn += '-Wdeclaration-after-statement'
1957 cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
1961 # The following tests want to suppress various unhelpful warnings by adding
1962 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1963 # switches, so we have to test for the positive form and if that works,
1964 # add the negative form.
1966 negative_warning_flags = [
1967 # Suppress clang's unhelpful unused-command-line-argument warnings.
1968 'unused-command-line-argument',
1970 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1971 # of warnings when building plperl because of usages in the Perl headers.
1972 'compound-token-split-by-macro',
1974 # Similarly disable useless truncation warnings from gcc 8+
1975 'format-truncation',
1976 'stringop-truncation',
1978 # Suppress clang 16's strict warnings about function casts
1979 'cast-function-type-strict',
1981 # To make warning_level=2 / -Wextra work, we'd need at least the following
1983 # 'missing-field-initializers',
1985 # 'unused-parameter',
1988 foreach w : negative_warning_flags
1989 if cc.has_argument('-W' + w)
1990 cflags_warn += '-Wno-' + w
1992 if llvm.found() and cpp.has_argument('-W' + w)
1993 cxxflags_warn += '-Wno-' + w
1999 if cc.get_id() == 'msvc'
2001 '/wd4018', # signed/unsigned mismatch
2002 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
2003 '/wd4273', # inconsistent DLL linkage
2004 '/wd4101', # unreferenced local variable
2005 '/wd4102', # unreferenced label
2006 '/wd4090', # different 'modifier' qualifiers
2007 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
2015 '/D_CRT_SECURE_NO_DEPRECATE',
2016 '/D_CRT_NONSTDC_NO_DEPRECATE',
2019 # We never need export libraries. As link.exe reports their creation, they
2020 # are unnecessarily noisy. Similarly, we don't need import library for
2021 # modules, we only import them dynamically, and they're also noisy.
2023 ldflags_mod += '/NOIMPLIB'
2028 ###############################################################
2030 ###############################################################
2032 if not get_option('spinlocks')
2033 warning('Not using spinlocks will cause poor performance')
2035 cdata.set('HAVE_SPINLOCKS', 1)
2038 if not get_option('atomics')
2039 warning('Not using atomics will cause poor performance')
2041 # XXX: perhaps we should require some atomics support in this case these
2043 cdata.set('HAVE_ATOMICS', 1)
2046 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
2047 'desc': '__sync_lock_test_and_set(char)',
2050 __sync_lock_test_and_set(&lock, 1);
2051 __sync_lock_release(&lock);'''},
2053 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
2054 'desc': '__sync_lock_test_and_set(int32)',
2057 __sync_lock_test_and_set(&lock, 1);
2058 __sync_lock_release(&lock);'''},
2060 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
2061 'desc': '__sync_val_compare_and_swap(int32)',
2064 __sync_val_compare_and_swap(&val, 0, 37);'''},
2066 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
2067 'desc': '__sync_val_compare_and_swap(int64)',
2070 __sync_val_compare_and_swap(&val, 0, 37);'''},
2072 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
2073 'desc': ' __atomic_compare_exchange_n(int32)',
2077 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
2079 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
2080 'desc': ' __atomic_compare_exchange_n(int64)',
2084 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
2087 foreach check : atomic_checks
2092 }'''.format(check['test'])
2094 cdata.set(check['name'],
2096 name: check['desc'],
2097 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
2105 ###############################################################
2106 # Select CRC-32C implementation.
2108 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
2109 # use the special CRC instructions for calculating CRC-32C. If we're not
2110 # targeting such a processor, but we can nevertheless produce code that uses
2111 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
2112 # implementations and select which one to use at runtime, depending on whether
2113 # SSE 4.2 is supported by the processor we're running on.
2115 # Similarly, if we are targeting an ARM processor that has the CRC
2116 # instructions that are part of the ARMv8 CRC Extension, use them. And if
2117 # we're not targeting such a processor, but can nevertheless produce code that
2118 # uses the CRC instructions, compile both, and select at runtime.
2119 ###############################################################
2121 have_optimized_crc = false
2123 if host_cpu == 'x86' or host_cpu == 'x86_64'
2125 if cc.get_id() == 'msvc'
2126 cdata.set('USE_SSE42_CRC32C', false)
2127 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2128 have_optimized_crc = true
2132 #include <nmmintrin.h>
2136 unsigned int crc = 0;
2137 crc = _mm_crc32_u8(crc, 0);
2138 crc = _mm_crc32_u32(crc, 0);
2139 /* return computed value, to prevent the above being optimized away */
2144 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
2146 # Use Intel SSE 4.2 unconditionally.
2147 cdata.set('USE_SSE42_CRC32C', 1)
2148 have_optimized_crc = true
2149 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
2150 args: test_c_args + ['-msse4.2'])
2151 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
2152 # the runtime check.
2153 cflags_crc += '-msse4.2'
2154 cdata.set('USE_SSE42_CRC32C', false)
2155 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2156 have_optimized_crc = true
2161 elif host_cpu == 'arm' or host_cpu == 'aarch64'
2164 #include <arm_acle.h>
2168 unsigned int crc = 0;
2169 crc = __crc32cb(crc, 0);
2170 crc = __crc32ch(crc, 0);
2171 crc = __crc32cw(crc, 0);
2172 crc = __crc32cd(crc, 0);
2174 /* return computed value, to prevent the above being optimized away */
2179 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
2181 # Use ARM CRC Extension unconditionally
2182 cdata.set('USE_ARMV8_CRC32C', 1)
2183 have_optimized_crc = true
2184 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
2185 args: test_c_args + ['-march=armv8-a+crc'])
2186 # Use ARM CRC Extension, with runtime check
2187 cflags_crc += '-march=armv8-a+crc'
2188 cdata.set('USE_ARMV8_CRC32C', false)
2189 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
2190 have_optimized_crc = true
2194 if not have_optimized_crc
2195 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
2197 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
2202 ###############################################################
2203 # Other CPU specific stuff
2204 ###############################################################
2206 if host_cpu == 'x86_64'
2211 long long x = 1; long long r;
2212 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
2214 name: '@0@: popcntq instruction'.format(host_cpu),
2216 cdata.set('HAVE_X86_64_POPCNTQ', 1)
2219 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
2220 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
2221 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
2224 addi(int ra, int si)
2227 if (__builtin_constant_p(si))
2228 __asm__ __volatile__(
2229 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
2232 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2235 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2242 ###############################################################
2243 # Library / OS tests
2244 ###############################################################
2246 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2247 # unnecessary checks over and over, particularly on windows.
2261 'sys/personality.h',
2270 foreach header : header_checks
2271 varname = 'HAVE_' + header.underscorify().to_upper()
2273 # Emulate autoconf behaviour of not-found->undef, found->1
2274 found = cc.has_header(header,
2275 include_directories: postgres_inc, args: test_c_args)
2276 cdata.set(varname, found ? 1 : false,
2277 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2282 ['F_FULLFSYNC', 'fcntl.h'],
2283 ['fdatasync', 'unistd.h'],
2284 ['posix_fadvise', 'fcntl.h'],
2285 ['strlcat', 'string.h'],
2286 ['strlcpy', 'string.h'],
2287 ['strnlen', 'string.h'],
2290 # Need to check for function declarations for these functions, because
2291 # checking for library symbols wouldn't handle deployment target
2292 # restrictions on macOS
2294 ['preadv', 'sys/uio.h'],
2295 ['pwritev', 'sys/uio.h'],
2298 foreach c : decl_checks
2302 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2304 found = cc.has_header_symbol(header, func,
2305 args: test_c_args, include_directories: postgres_inc,
2307 cdata.set10(varname, found, description:
2308 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2309 don't.'''.format(func))
2313 if cc.has_type('struct option',
2314 args: test_c_args, include_directories: postgres_inc,
2315 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2316 cdata.set('HAVE_STRUCT_OPTION', 1)
2320 foreach c : ['opterr', 'optreset']
2321 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2330 '''.format(c), name: c, args: test_c_args)
2331 cdata.set(varname, 1)
2333 cdata.set(varname, false)
2337 if cc.has_type('socklen_t',
2338 args: test_c_args, include_directories: postgres_inc,
2340 #include <sys/socket.h>''')
2341 cdata.set('HAVE_SOCKLEN_T', 1)
2344 if cc.has_member('struct sockaddr', 'sa_len',
2345 args: test_c_args, include_directories: postgres_inc,
2347 #include <sys/types.h>
2348 #include <sys/socket.h>''')
2349 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2352 if cc.has_member('struct tm', 'tm_zone',
2353 args: test_c_args, include_directories: postgres_inc,
2355 #include <sys/types.h>
2358 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2363 extern int foo(void);
2366 return timezone / 60;
2369 name: 'global variable `timezone\' exists',
2370 args: test_c_args, include_directories: postgres_inc)
2371 cdata.set('HAVE_INT_TIMEZONE', 1)
2373 cdata.set('HAVE_INT_TIMEZONE', false)
2376 if cc.has_type('union semun',
2378 include_directories: postgres_inc,
2380 #include <sys/types.h>
2381 #include <sys/ipc.h>
2382 #include <sys/sem.h>
2384 cdata.set('HAVE_UNION_SEMUN', 1)
2392 switch (strerror_r(1, buf, sizeof(buf)))
2393 { case 0: break; default: break; }
2396 args: test_c_args, include_directories: postgres_inc)
2397 cdata.set('STRERROR_R_INT', 1)
2399 cdata.set('STRERROR_R_INT', false)
2402 # Check for the locale_t type and find the right header file. macOS
2403 # needs xlocale.h; standard is locale.h, but glibc also has an
2404 # xlocale.h file that we should not use. MSVC has a replacement
2405 # defined in src/include/port/win32_port.h.
2406 if cc.has_type('locale_t', prefix: '#include <locale.h>')
2407 cdata.set('HAVE_LOCALE_T', 1)
2408 elif cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2409 cdata.set('HAVE_LOCALE_T', 1)
2410 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2411 elif cc.get_id() == 'msvc'
2412 cdata.set('HAVE_LOCALE_T', 1)
2415 # Check if the C compiler understands typeof or a variant. Define
2416 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2417 foreach kw : ['typeof', '__typeof__', 'decltype']
2428 args: test_c_args, include_directories: postgres_inc)
2430 cdata.set('HAVE_TYPEOF', 1)
2432 cdata.set('typeof', kw)
2440 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2441 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2442 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2443 wcstombs_l_test = '''
2455 if (not cc.compiles(wcstombs_l_test.format(''),
2456 name: 'wcstombs_l') and
2457 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2458 name: 'wcstombs_l in xlocale.h'))
2459 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2463 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2464 # understands, because it conflicts with __declspec(restrict). Therefore we
2465 # define pg_restrict to the appropriate definition, which presumably won't
2468 # We assume C99 support, so we don't need to make this conditional.
2470 # XXX: Historically we allowed platforms to disable restrict in template
2471 # files, but that was only added for AIX when building with XLC, which we
2472 # don't support yet.
2473 cdata.set('pg_restrict', '__restrict')
2476 # Most libraries are included only if they demonstrably provide a function we
2477 # need, but libm is an exception: always include it, because there are too
2478 # many compilers that play cute optimization games that will break probes for
2479 # standard functions such as pow().
2480 os_deps += cc.find_library('m', required: false)
2482 rt_dep = cc.find_library('rt', required: false)
2484 dl_dep = cc.find_library('dl', required: false)
2486 util_dep = cc.find_library('util', required: false)
2487 posix4_dep = cc.find_library('posix4', required: false)
2489 getopt_dep = cc.find_library('getopt', required: false)
2490 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2491 # Check if we want to replace getopt/getopt_long even if provided by the system
2492 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2493 # so always use our version on Windows
2494 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2495 # (i.e., allow '-' as a flag character), so use our version on those platforms
2496 # - We want to use system's getopt_long() only if the system provides struct
2498 always_replace_getopt = host_system in ['windows', 'cygwin', 'openbsd', 'solaris']
2499 always_replace_getopt_long = host_system in ['windows', 'cygwin'] or not cdata.has('HAVE_STRUCT_OPTION')
2502 execinfo_dep = cc.find_library('execinfo', required: false)
2504 if host_system == 'cygwin'
2505 cygipc_dep = cc.find_library('cygipc', required: false)
2507 cygipc_dep = not_found_dep
2510 if host_system == 'sunos'
2511 socket_dep = cc.find_library('socket', required: false)
2513 socket_dep = not_found_dep
2516 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2517 # unnecessary checks over and over, particularly on windows.
2519 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2520 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2521 ['clock_gettime', {'dependencies': [rt_dep, posix4_dep], 'define': false}],
2523 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2524 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2525 # required. Just checking for dlsym() ought to suffice.
2526 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2528 ['fdatasync', {'dependencies': [rt_dep, posix4_dep], 'define': false}], # Solaris
2530 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2531 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2541 ['posix_fallocate'],
2543 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2544 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2545 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2546 ['setproctitle', {'dependencies': [util_dep]}],
2547 ['setproctitle_fast'],
2548 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2549 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2550 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2551 ['socket', {'dependencies': [socket_dep], 'define': false}],
2553 ['strerror_r', {'dependencies': [thread_dep]}],
2558 ['sync_file_range'],
2564 func_check_results = {}
2565 foreach c : func_checks
2567 kwargs = c.get(1, {})
2568 deps = kwargs.get('dependencies', [])
2570 if kwargs.get('skip', false)
2574 found = cc.has_function(func, args: test_c_args)
2581 found = cc.has_function(func, args: test_c_args,
2582 dependencies: [dep])
2590 func_check_results += {func: found}
2592 if kwargs.get('define', true)
2593 # Emulate autoconf behaviour of not-found->undef, found->1
2594 cdata.set('HAVE_' + func.underscorify().to_upper(),
2596 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2601 if cc.has_function('syslog', args: test_c_args) and \
2602 cc.check_header('syslog.h', args: test_c_args)
2603 cdata.set('HAVE_SYSLOG', 1)
2607 # MSVC has replacements defined in src/include/port/win32_port.h.
2608 if cc.get_id() == 'msvc'
2609 cdata.set('HAVE_WCSTOMBS_L', 1)
2610 cdata.set('HAVE_MBSTOWCS_L', 1)
2614 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2616 if sema_kind == 'unnamed_posix' and \
2617 not func_check_results.get('sem_init', false)
2621 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2622 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2624 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2625 cdata.set_quoted('DLSUFFIX', dlsuffix)
2628 # built later than the rest of the version metadata, we need SIZEOF_VOID_P
2629 cdata.set_quoted('PG_VERSION_STR',
2630 'PostgreSQL @0@ on @1@-@2@, compiled by @3@-@4@, @5@-bit'.format(
2631 pg_version, host_machine.cpu_family(), host_system,
2632 cc.get_id(), cc.version(), cdata.get('SIZEOF_VOID_P') * 8,
2638 ###############################################################
2640 ###############################################################
2642 # XXX: About to rely on thread safety in the autoconf build, so not worth
2643 # implementing a fallback.
2644 cdata.set('ENABLE_THREAD_SAFETY', 1)
2648 ###############################################################
2650 ###############################################################
2652 nlsopt = get_option('nls')
2653 libintl = not_found_dep
2655 if not nlsopt.disabled()
2656 # otherwise there'd be lots of
2657 # "Gettext not found, all translation (po) targets will be ignored."
2658 # warnings if not found.
2659 msgfmt = find_program('msgfmt', required: nlsopt, native: true)
2661 # meson 0.59 has this wrapped in dependency('intl')
2662 if (msgfmt.found() and
2663 cc.check_header('libintl.h', required: nlsopt,
2664 args: test_c_args, include_directories: postgres_inc))
2667 if cc.has_function('ngettext')
2668 libintl = declare_dependency()
2670 libintl = cc.find_library('intl',
2671 has_headers: ['libintl.h'], required: nlsopt,
2672 header_include_directories: postgres_inc,
2678 i18n = import('i18n')
2679 cdata.set('ENABLE_NLS', 1)
2685 ###############################################################
2687 ###############################################################
2689 # Set up compiler / linker arguments to be used everywhere, individual targets
2690 # can add further args directly, or indirectly via dependencies
2691 add_project_arguments(cflags, language: ['c'])
2692 add_project_arguments(cppflags, language: ['c'])
2693 add_project_arguments(cflags_warn, language: ['c'])
2694 add_project_arguments(cxxflags, language: ['cpp'])
2695 add_project_arguments(cppflags, language: ['cpp'])
2696 add_project_arguments(cxxflags_warn, language: ['cpp'])
2697 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2700 # Collect a number of lists of things while recursing through the source
2701 # tree. Later steps then can use those.
2703 # list of targets for various alias targets
2704 backend_targets = []
2707 contrib_targets = []
2708 testprep_targets = []
2712 # Define the tests to distribute them to the correct test styles later
2717 # Default options for targets
2719 # First identify rpaths
2720 bin_install_rpaths = []
2721 lib_install_rpaths = []
2722 mod_install_rpaths = []
2725 # Don't add rpaths on darwin for now - as long as only absolute references to
2726 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2727 # their final destination.
2728 if host_system != 'darwin'
2729 # Add absolute path to libdir to rpath. This ensures installed binaries /
2730 # libraries find our libraries (mainly libpq).
2731 bin_install_rpaths += dir_prefix / dir_lib
2732 lib_install_rpaths += dir_prefix / dir_lib
2733 mod_install_rpaths += dir_prefix / dir_lib
2735 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2737 # Not needed on darwin even if we use relative rpaths for our own libraries,
2738 # as the install_name of libraries in extra_lib_dirs will point to their
2740 bin_install_rpaths += postgres_lib_d
2741 lib_install_rpaths += postgres_lib_d
2742 mod_install_rpaths += postgres_lib_d
2746 # Define arguments for default targets
2748 default_target_args = {
2749 'implicit_include_directories': false,
2753 default_lib_args = default_target_args + {
2757 internal_lib_args = default_lib_args + {
2758 'build_by_default': false,
2762 default_mod_args = default_lib_args + {
2764 'install_dir': dir_lib_pkg,
2767 default_bin_args = default_target_args + {
2768 'install_dir': dir_bin,
2771 if get_option('rpath')
2772 default_lib_args += {
2773 'install_rpath': ':'.join(lib_install_rpaths),
2776 default_mod_args += {
2777 'install_rpath': ':'.join(mod_install_rpaths),
2780 default_bin_args += {
2781 'install_rpath': ':'.join(bin_install_rpaths),
2786 # Helper for exporting a limited number of symbols
2787 gen_export_kwargs = {
2788 'input': 'exports.txt',
2789 'output': '@BASENAME@.'+export_file_suffix,
2790 'command': [perl, files('src/tools/gen_export.pl'),
2791 '--format', export_file_format,
2792 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2793 'build_by_default': false,
2800 ### Helpers for custom targets used across the tree
2803 catalog_pm = files('src/backend/catalog/Catalog.pm')
2804 perfect_hash_pm = files('src/tools/PerfectHash.pm')
2805 gen_kwlist_deps = [perfect_hash_pm]
2807 perl, '-I', '@SOURCE_ROOT@/src/tools',
2808 files('src/tools/gen_keywordlist.pl'),
2809 '--output', '@OUTDIR@', '@INPUT@']
2814 ### windows resources related stuff
2817 if host_system == 'windows'
2818 pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico'
2819 win32ver_rc = files('src/port/win32ver.rc')
2820 rcgen = find_program('src/tools/rcgen', native: true)
2823 '--srcdir', '@SOURCE_DIR@',
2824 '--builddir', meson.build_root(),
2825 '--rcout', '@OUTPUT0@',
2826 '--out', '@OUTPUT1@',
2827 '--input', '@INPUT@',
2831 if cc.get_argument_syntax() == 'msvc'
2832 rc = find_program('rc', required: true)
2833 rcgen_base_args += ['--rc', rc.path()]
2834 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.res']
2836 windres = find_program('windres', required: true)
2837 rcgen_base_args += ['--windres', windres.path()]
2838 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.obj']
2841 # msbuild backend doesn't support this atm
2842 if meson.backend() == 'ninja'
2843 rcgen_base_args += ['--depfile', '@DEPFILE@']
2846 rcgen_bin_args = rcgen_base_args + [
2847 '--VFT_TYPE', 'VFT_APP',
2848 '--FILEENDING', 'exe',
2852 rcgen_lib_args = rcgen_base_args + [
2853 '--VFT_TYPE', 'VFT_DLL',
2854 '--FILEENDING', 'dll',
2857 rc_bin_gen = generator(rcgen,
2858 depfile: '@BASENAME@.d',
2859 arguments: rcgen_bin_args,
2860 output: rcgen_outputs,
2863 rc_lib_gen = generator(rcgen,
2864 depfile: '@BASENAME@.d',
2865 arguments: rcgen_lib_args,
2866 output: rcgen_outputs,
2872 # headers that the whole build tree depends on
2873 generated_headers = []
2874 # headers that the backend build depends on
2875 generated_backend_headers = []
2876 # configure_files() output, needs a way of converting to file names
2877 configure_files = []
2879 # generated files that might conflict with a partial in-tree autoconf build
2880 generated_sources = []
2881 # same, for paths that differ between autoconf / meson builds
2882 # elements are [dir, [files]]
2883 generated_sources_ac = {}
2886 # First visit src/include - all targets creating headers are defined
2887 # within. That makes it easy to add the necessary dependencies for the
2888 # subsequent build steps.
2890 subdir('src/include')
2894 # Then through src/port and src/common, as most other things depend on them
2896 frontend_port_code = declare_dependency(
2897 compile_args: ['-DFRONTEND'],
2898 include_directories: [postgres_inc],
2899 dependencies: os_deps,
2902 backend_port_code = declare_dependency(
2903 compile_args: ['-DBUILDING_DLL'],
2904 include_directories: [postgres_inc],
2905 sources: [errcodes], # errcodes.h is needed due to use of ereport
2906 dependencies: os_deps,
2911 frontend_common_code = declare_dependency(
2912 compile_args: ['-DFRONTEND'],
2913 include_directories: [postgres_inc],
2914 sources: generated_headers,
2915 dependencies: [os_deps, zlib, zstd],
2918 backend_common_code = declare_dependency(
2919 compile_args: ['-DBUILDING_DLL'],
2920 include_directories: [postgres_inc],
2921 sources: generated_headers,
2922 dependencies: [os_deps, zlib, zstd],
2925 subdir('src/common')
2927 # all shared libraries should depend on shlib_code
2928 shlib_code = declare_dependency(
2929 link_args: ldflags_sl,
2932 # all static libraries not part of the backend should depend on this
2933 frontend_stlib_code = declare_dependency(
2934 include_directories: [postgres_inc],
2935 link_with: [common_static, pgport_static],
2936 sources: generated_headers,
2937 dependencies: [os_deps, libintl],
2940 # all shared libraries not part of the backend should depend on this
2941 frontend_shlib_code = declare_dependency(
2942 include_directories: [postgres_inc],
2943 link_with: [common_shlib, pgport_shlib],
2944 sources: generated_headers,
2945 dependencies: [shlib_code, os_deps, libintl],
2948 # Dependencies both for static and shared libpq
2958 subdir('src/interfaces/libpq')
2959 # fe_utils depends on libpq
2960 subdir('src/fe_utils')
2962 # for frontend binaries
2963 frontend_code = declare_dependency(
2964 include_directories: [postgres_inc],
2965 link_with: [fe_utils, common_static, pgport_static],
2966 sources: generated_headers,
2967 dependencies: [os_deps, libintl],
2970 backend_both_deps += [
2987 backend_mod_deps = backend_both_deps + os_deps
2989 backend_code = declare_dependency(
2990 compile_args: ['-DBUILDING_DLL'],
2991 include_directories: [postgres_inc],
2992 link_args: ldflags_be,
2994 sources: generated_headers + generated_backend_headers,
2995 dependencies: os_deps + backend_both_deps + backend_deps,
2998 # install these files only during test, not main install
2999 test_install_data = []
3000 test_install_libs = []
3002 # src/backend/meson.build defines backend_mod_code used for extension
3006 # Then through the main sources. That way contrib can have dependencies on
3007 # main sources. Note that this explicitly doesn't enter src/test, right now a
3008 # few regression tests depend on contrib files.
3015 subdir('src/interfaces/libpq/test')
3016 subdir('src/interfaces/ecpg/test')
3018 subdir('doc/src/sgml')
3020 generated_sources_ac += {'': ['GNUmakefile']}
3022 # After processing src/test, add test_install_libs to the testprep_targets
3024 testprep_targets += test_install_libs
3027 # If there are any files in the source directory that we also generate in the
3028 # build directory, they might get preferred over the newly generated files,
3029 # e.g. because of a #include "file", which always will search in the current
3031 message('checking for file conflicts between source and build directory')
3032 conflicting_files = []
3033 potentially_conflicting_files_t = []
3034 potentially_conflicting_files_t += generated_headers
3035 potentially_conflicting_files_t += generated_backend_headers
3036 potentially_conflicting_files_t += generated_backend_sources
3037 potentially_conflicting_files_t += generated_sources
3039 potentially_conflicting_files = []
3041 # convert all sources of potentially conflicting files into uniform shape
3042 foreach t : potentially_conflicting_files_t
3043 potentially_conflicting_files += t.full_path()
3045 foreach t1 : configure_files
3046 if meson.version().version_compare('>=0.59')
3047 t = fs.parent(t1) / fs.name(t1)
3049 t = '@0@'.format(t1)
3051 potentially_conflicting_files += meson.current_build_dir() / t
3053 foreach sub, fnames : generated_sources_ac
3054 sub = meson.build_root() / sub
3055 foreach fname : fnames
3056 potentially_conflicting_files += sub / fname
3060 # find and report conflicting files
3061 foreach build_path : potentially_conflicting_files
3062 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
3063 # str.replace is in 0.56
3064 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
3065 if fs.exists(src_path) or fs.is_symlink(src_path)
3066 conflicting_files += src_path
3069 # XXX: Perhaps we should generate a file that would clean these up? The list
3071 if conflicting_files.length() > 0
3072 errmsg_cleanup = '''
3073 Conflicting files in source directory:
3076 The conflicting files need to be removed, either by removing the files listed
3077 above, or by running configure and then make maintainer-clean.
3079 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
3080 error(errmsg_nonclean_base.format(errmsg_cleanup))
3085 ###############################################################
3087 ###############################################################
3090 # We want to define additional install targets beyond what meson provides. For
3091 # that we need to define targets depending on nearly everything. We collected
3092 # the results of i18n.gettext() invocations into nls_targets, that also
3093 # includes maintainer targets though. Collect the ones we want as a dependency.
3095 # i18n.gettext() doesn't return the dependencies before 0.60 - but the gettext
3096 # generation happens during install, so that's not a real issue.
3098 if libintl.found() and meson.version().version_compare('>=0.60')
3099 # use range() to avoid the flattening of the list that foreach() would do
3100 foreach off : range(0, nls_targets.length())
3101 # i18n.gettext() list containing 1) list of built .mo files 2) maintainer
3102 # -pot target 3) maintainer -pot target
3103 nls_mo_targets += nls_targets[off][0]
3105 alias_target('nls', nls_mo_targets)
3120 # Meson's default install target is quite verbose. Provide one that is quiet.
3121 install_quiet = custom_target('install-quiet',
3122 output: 'install-quiet',
3123 build_always_stale: true,
3124 build_by_default: false,
3125 command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'],
3129 # Target to install files used for tests, which aren't installed by default
3130 install_test_files_args = [
3132 '--prefix', dir_prefix,
3133 '--install', contrib_data_dir, test_install_data,
3134 '--install', dir_lib_pkg, test_install_libs,
3136 run_target('install-test-files',
3137 command: [python] + install_test_files_args,
3138 depends: testprep_targets,
3143 ###############################################################
3145 ###############################################################
3147 # DESTDIR for the installation we'll run tests in
3148 test_install_destdir = meson.build_root() / 'tmp_install/'
3150 # DESTDIR + prefix appropriately munged
3151 if build_system != 'windows'
3152 # On unixoid systems this is trivial, we just prepend the destdir
3153 assert(dir_prefix.startswith('/')) # enforced by meson
3154 temp_install_bindir = '@0@@1@'.format(test_install_destdir, dir_prefix / dir_bin)
3155 temp_install_libdir = '@0@@1@'.format(test_install_destdir, dir_prefix / dir_lib)
3157 # drives, drive-relative paths, etc make this complicated on windows, call
3158 # into a copy of meson's logic for it
3161 'import sys; from pathlib import PurePath; d1=sys.argv[1]; d2=sys.argv[2]; print(str(PurePath(d1, *PurePath(d2).parts[1:])))',
3162 test_install_destdir]
3163 temp_install_bindir = run_command(command, dir_prefix / dir_bin, check: true).stdout().strip()
3164 temp_install_libdir = run_command(command, dir_prefix / dir_lib, check: true).stdout().strip()
3167 meson_install_args = meson_args + ['install'] + {
3168 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
3172 # setup tests should be run first,
3173 # so define priority for these
3174 setup_tests_priority = 100
3176 meson_bin, args: meson_install_args ,
3177 env: {'DESTDIR':test_install_destdir},
3178 priority: setup_tests_priority,
3183 test('install_test_files',
3185 args: install_test_files_args + ['--destdir', test_install_destdir],
3186 priority: setup_tests_priority,
3190 test_result_dir = meson.build_root() / 'testrun'
3193 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
3194 # inevitable conflicts from running tests in parallel, hackishly assign
3195 # different ports for different tests.
3199 test_env = environment()
3201 test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template'
3202 test_env.set('PG_REGRESS', pg_regress.full_path())
3203 test_env.set('REGRESS_SHLIB', regress_module.full_path())
3205 # Test suites that are not safe by default but can be run if selected
3206 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
3207 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
3208 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
3210 # Add the temporary installation to the library search path on platforms where
3211 # that works (everything but windows, basically). On windows everything
3212 # library-like gets installed into bindir, solving that issue.
3213 if library_path_var != ''
3214 test_env.prepend(library_path_var, temp_install_libdir)
3219 ###############################################################
3221 ###############################################################
3223 # When using a meson version understanding exclude_suites, define a
3224 # 'tmp_install' test setup (the default) that excludes tests running against a
3225 # pre-existing install and a 'running' setup that conflicts with creation of
3226 # the temporary installation and tap tests (which don't support running
3227 # against a running server).
3231 if meson.version().version_compare('>=0.57')
3234 runningcheck = false
3237 testwrap = files('src/tools/testwrap')
3239 foreach test_dir : tests
3242 '--basedir', meson.build_root(),
3243 '--srcdir', test_dir['sd'],
3246 foreach kind, v : test_dir
3247 if kind in ['sd', 'bd', 'name']
3253 if kind in ['regress', 'isolation', 'ecpg']
3254 if kind == 'regress'
3256 fallback_dbname = 'regression_@0@'
3257 elif kind == 'isolation'
3258 runner = pg_isolation_regress
3259 fallback_dbname = 'isolation_regression_@0@'
3261 runner = pg_regress_ecpg
3262 fallback_dbname = 'ecpg_regression_@0@'
3265 test_group = test_dir['name']
3266 test_group_running = test_dir['name'] + '-running'
3268 test_output = test_result_dir / test_group / kind
3269 test_output_running = test_result_dir / test_group_running/ kind
3271 # Unless specified by the test, choose a non-conflicting database name,
3272 # to avoid conflicts when running against existing server.
3273 dbname = t.get('dbname',
3274 fallback_dbname.format(test_dir['name']))
3276 test_command_base = [
3278 '--inputdir', t.get('inputdir', test_dir['sd']),
3279 '--expecteddir', t.get('expecteddir', test_dir['sd']),
3281 '--dlpath', test_dir['bd'],
3282 '--max-concurrent-tests=20',
3284 ] + t.get('regress_args', [])
3287 if t.has_key('schedule')
3288 test_selection += ['--schedule', t['schedule'],]
3291 if kind == 'isolation'
3292 test_selection += t.get('specs', [])
3294 test_selection += t.get('sql', [])
3298 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
3304 'depends': test_deps + t.get('deps', []),
3306 } + t.get('test_kwargs', {})
3308 test(test_group / kind,
3312 '--testgroup', test_group,
3316 '--outputdir', test_output,
3317 '--temp-instance', test_output / 'tmp_check',
3318 '--port', testport.to_string(),
3322 kwargs: test_kwargs,
3324 install_suites += test_group
3326 # some tests can't support running against running DB
3327 if runningcheck and t.get('runningcheck', true)
3328 test(test_group_running / kind,
3332 '--testgroup', test_group_running,
3336 '--outputdir', test_output_running,
3339 is_parallel: t.get('runningcheck-parallel', true),
3340 suite: test_group_running,
3341 kwargs: test_kwargs,
3343 running_suites += test_group_running
3348 if not tap_tests_enabled
3354 '-I', meson.source_root() / 'src/test/perl',
3355 '-I', test_dir['sd'],
3358 # Add temporary install, the build directory for non-installed binaries and
3359 # also test/ for non-installed test binaries built separately.
3361 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
3363 foreach name, value : t.get('env', {})
3364 env.set(name, value)
3367 test_group = test_dir['name']
3370 'suite': test_group,
3372 'depends': test_deps + t.get('deps', []),
3374 } + t.get('test_kwargs', {})
3376 foreach onetap : t['tests']
3377 # Make tap test names prettier, remove t/ and .pl
3379 if onetap_p.startswith('t/')
3380 onetap_p = onetap.split('t/')[1]
3382 if onetap_p.endswith('.pl')
3383 onetap_p = fs.stem(onetap_p)
3386 test(test_dir['name'] / onetap_p,
3388 kwargs: test_kwargs,
3389 args: testwrap_base + [
3390 '--testgroup', test_dir['name'],
3391 '--testname', onetap_p,
3393 test_dir['sd'] / onetap,
3397 install_suites += test_group
3399 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
3402 endforeach # kinds of tests
3404 endforeach # directories with tests
3406 # repeat condition so meson realizes version dependency
3407 if meson.version().version_compare('>=0.57')
3408 add_test_setup('tmp_install',
3410 exclude_suites: running_suites)
3411 add_test_setup('running',
3412 exclude_suites: ['setup'] + install_suites)
3417 ###############################################################
3419 ###############################################################
3421 alias_target('backend', backend_targets)
3422 alias_target('bin', bin_targets + [libpq_st])
3423 alias_target('pl', pl_targets)
3424 alias_target('contrib', contrib_targets)
3425 alias_target('testprep', testprep_targets)
3426 alias_target('install-world', install_quiet, installdocs)
3430 ###############################################################
3431 # The End, The End, My Friend
3432 ###############################################################
3434 if meson.version().version_compare('>=0.57')
3438 'data block size': '@0@ kB'.format(cdata.get('BLCKSZ') / 1024),
3439 'WAL block size': '@0@ kB'.format(cdata.get('XLOG_BLCKSZ') / 1024),
3440 'segment size': get_option('segsize_blocks') != 0 ?
3441 '@0@ blocks'.format(cdata.get('RELSEG_SIZE')) :
3442 '@0@ GB'.format(get_option('segsize')),
3444 section: 'Data layout',
3449 'host system': '@0@ @1@'.format(host_system, host_cpu),
3450 'build system': '@0@ @1@'.format(build_machine.system(),
3451 build_machine.cpu_family()),
3458 'linker': '@0@'.format(cc.get_linker_id()),
3459 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
3461 section: 'Compiler',
3466 'CPP FLAGS': ' '.join(cppflags),
3467 'C FLAGS, functional': ' '.join(cflags),
3468 'C FLAGS, warnings': ' '.join(cflags_warn),
3469 'C FLAGS, modules': ' '.join(cflags_mod),
3470 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3471 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3473 section: 'Compiler Flags',
3479 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3481 section: 'Compiler',
3486 'C++ FLAGS, functional': ' '.join(cxxflags),
3487 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3488 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3490 section: 'Compiler Flags',
3496 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3499 section: 'Programs',
3505 'bsd_auth': bsd_auth,
3507 'docs_pdf': docs_pdf_dep,
3519 'plpython': python3_dep,
3521 'readline': readline,
3528 section: 'External libraries',