1 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
3 # Entry point for building PostgreSQL with meson
5 # Good starting points for writing meson.build files are:
6 # - https://mesonbuild.com/Syntax.html
7 # - https://mesonbuild.com/Reference-manual.html
12 license: 'PostgreSQL',
14 # We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for
15 # RHEL 7 has 0.55. < 0.54 would require replacing some uses of the fs
16 # module, < 0.53 all uses of fs. So far there's no need to go to >=0.56.
17 meson_version: '>=0.54',
19 'warning_level=1', #-Wall equivalent
21 'buildtype=debugoptimized', # -O2 + debug
22 # For compatibility with the autoconf build, set a default prefix. This
23 # works even on windows, where it's a drive-relative path (i.e. when on
24 # d:/somepath it'll install to d:/usr/local/pgsql)
25 'prefix=/usr/local/pgsql',
31 ###############################################################
33 ###############################################################
36 pkgconfig = import('pkgconfig')
38 host_system = host_machine.system()
39 build_system = build_machine.system()
40 host_cpu = host_machine.cpu_family()
42 cc = meson.get_compiler('c')
44 not_found_dep = dependency('', required: false)
45 thread_dep = dependency('threads')
46 auto_features = get_option('auto_features')
50 ###############################################################
52 ###############################################################
54 # It's very easy to get into confusing states when the source directory
55 # contains an in-place build. E.g. the wrong pg_config.h will be used. So just
56 # refuse to build in that case.
58 # There's a more elaborate check later, that checks for conflicts around all
59 # generated files. But we can only do that much further down the line, so this
60 # quick check seems worth it. Adhering to this advice should clean up the
61 # conflict, but won't protect against somebody doing make distclean or just
62 # removing pg_config.h
63 errmsg_nonclean_base = '''
65 Non-clean source code directory detected.
67 To build with meson the source tree may not have an in-place, ./configure
68 style, build configured. You can have both meson and ./configure style builds
69 for the same source tree by building out-of-source / VPATH with
70 configure. Alternatively use a separate check out for meson based builds.
74 if fs.exists(meson.current_source_dir() / 'src' / 'include' / 'pg_config.h')
75 errmsg_cleanup = 'To clean up, run make distclean in the source tree.'
76 error(errmsg_nonclean_base.format(errmsg_cleanup))
81 ###############################################################
82 # Variables to be determined
83 ###############################################################
85 postgres_inc_d = ['src/include']
86 postgres_inc_d += get_option('extra_include_dirs')
88 postgres_lib_d = get_option('extra_lib_dirs')
107 backend_both_deps = []
113 # source of data for pg_config.h etc
114 cdata = configuration_data()
118 ###############################################################
119 # Version and other metadata
120 ###############################################################
122 pg_version = meson.project_version()
124 if pg_version.endswith('devel')
125 pg_version_arr = [pg_version.split('devel')[0], '0']
126 elif pg_version.contains('beta')
127 pg_version_arr = [pg_version.split('beta')[0], '0']
128 elif pg_version.contains('rc')
129 pg_version_arr = [pg_version.split('rc')[0], '0']
131 pg_version_arr = pg_version.split('.')
134 pg_version_major = pg_version_arr[0].to_int()
135 pg_version_minor = pg_version_arr[1].to_int()
136 pg_version_num = (pg_version_major * 10000) + pg_version_minor
138 pg_url = 'https://www.postgresql.org/'
140 cdata.set_quoted('PACKAGE_NAME', 'PostgreSQL')
141 cdata.set_quoted('PACKAGE_BUGREPORT', 'pgsql-bugs@lists.postgresql.org')
142 cdata.set_quoted('PACKAGE_URL', pg_url)
143 cdata.set_quoted('PACKAGE_VERSION', pg_version)
144 cdata.set_quoted('PACKAGE_STRING', 'PostgreSQL @0@'.format(pg_version))
145 cdata.set_quoted('PACKAGE_TARNAME', 'postgresql')
147 pg_version += get_option('extra_version')
148 cdata.set_quoted('PG_VERSION', pg_version)
149 cdata.set_quoted('PG_MAJORVERSION', pg_version_major.to_string())
150 cdata.set('PG_MAJORVERSION_NUM', pg_version_major)
151 cdata.set('PG_MINORVERSION_NUM', pg_version_minor)
152 cdata.set('PG_VERSION_NUM', pg_version_num)
153 # PG_VERSION_STR is built later, it depends on compiler test results
154 cdata.set_quoted('CONFIGURE_ARGS', '')
158 ###############################################################
159 # Basic platform specific configuration
160 ###############################################################
162 exesuffix = '' # overridden below where necessary
163 dlsuffix = '.so' # overridden below where necessary
164 library_path_var = 'LD_LIBRARY_PATH'
166 # Format of file to control exports from libraries, and how to pass them to
167 # the compiler. For export_fmt @0@ is the path to the file export file.
168 export_file_format = 'gnu'
169 export_file_suffix = 'list'
170 export_fmt = '-Wl,--version-script=@0@'
172 # Flags to add when linking a postgres extension, @0@ is path to
173 # the relevant object on the platform.
174 mod_link_args_fmt = []
176 memset_loop_limit = 1024
178 # Choice of shared memory and semaphore implementation
182 # We implement support for some operating systems by pretending they're
183 # another. Map here, before determining system properties below
184 if host_system == 'dragonfly'
185 # apparently the most similar
186 host_system = 'netbsd'
187 elif host_system == 'android'
188 # while android isn't quite a normal linux, it seems close enough
189 # for our purposes so far
190 host_system = 'linux'
193 # meson's system names don't quite map to our "traditional" names. In some
194 # places we need the "traditional" name, e.g., for mapping
195 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
197 portname = host_system
199 if host_system == 'cygwin'
200 sema_kind = 'unnamed_posix'
201 cppflags += '-D_GNU_SOURCE'
203 mod_link_args_fmt = ['@0@']
204 mod_link_with_name = 'lib@0@.a'
205 mod_link_with_dir = 'libdir'
207 elif host_system == 'darwin'
209 library_path_var = 'DYLD_LIBRARY_PATH'
211 export_file_format = 'darwin'
212 export_fmt = '-Wl,-exported_symbols_list,@0@'
214 mod_link_args_fmt = ['-bundle_loader', '@0@']
215 mod_link_with_dir = 'bindir'
216 mod_link_with_name = '@0@'
218 sysroot_args = [files('src/tools/darwin_sysroot'), get_option('darwin_sysroot')]
219 pg_sysroot = run_command(sysroot_args, check:true).stdout().strip()
220 message('darwin sysroot: @0@'.format(pg_sysroot))
222 cflags += ['-isysroot', pg_sysroot]
223 ldflags += ['-isysroot', pg_sysroot]
226 # meson defaults to -Wl,-undefined,dynamic_lookup for modules, which we
227 # don't want because a) it's different from what we do for autoconf, b) it
228 # causes warnings in macOS Ventura. But using -Wl,-undefined,error causes a
229 # warning starting in Sonoma. So only add -Wl,-undefined,error if it does
230 # not cause a warning.
231 if cc.has_multi_link_arguments('-Wl,-undefined,error', '-Werror')
232 ldflags_mod += '-Wl,-undefined,error'
235 # Starting in Sonoma, the linker warns about the same library being
236 # linked twice. Which can easily happen when multiple dependencies
237 # depend on the same library. Quiesce the ill considered warning.
238 ldflags += cc.get_supported_link_arguments('-Wl,-no_warn_duplicate_libraries')
240 elif host_system == 'freebsd'
241 sema_kind = 'unnamed_posix'
243 elif host_system == 'linux'
244 sema_kind = 'unnamed_posix'
245 cppflags += '-D_GNU_SOURCE'
247 elif host_system == 'netbsd'
248 # We must resolve all dynamic linking in the core server at program start.
249 # Otherwise the postmaster can self-deadlock due to signals interrupting
250 # resolution of calls, since NetBSD's linker takes a lock while doing that
251 # and some postmaster signal handlers do things that will also acquire that
252 # lock. As long as we need "-z now", might as well specify "-z relro" too.
253 # While there's not a hard reason to adopt these settings for our other
254 # executables, there's also little reason not to, so just add them to
256 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
258 elif host_system == 'openbsd'
261 elif host_system == 'sunos'
263 export_fmt = '-Wl,-M@0@'
264 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
266 elif host_system == 'windows'
270 library_path_var = ''
272 export_file_format = 'win'
273 export_file_suffix = 'def'
274 if cc.get_id() == 'msvc'
275 export_fmt = '/DEF:@0@'
276 mod_link_with_name = '@0@.lib'
279 mod_link_with_name = 'lib@0@.a'
281 mod_link_args_fmt = ['@0@']
282 mod_link_with_dir = 'libdir'
287 cdata.set('WIN32_STACK_RLIMIT', 4194304)
288 if cc.get_id() == 'msvc'
289 ldflags += '/INCREMENTAL:NO'
290 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
291 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
293 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
294 # Need to allow multiple definitions, we e.g. want to override getopt.
295 ldflags += '-Wl,--allow-multiple-definition'
296 # Ensure we get MSVC-like linking behavior.
297 ldflags += '-Wl,--disable-auto-import'
300 os_deps += cc.find_library('ws2_32', required: true)
301 secur32_dep = cc.find_library('secur32', required: true)
302 backend_deps += secur32_dep
303 libpq_deps += secur32_dep
305 postgres_inc_d += 'src/include/port/win32'
306 if cc.get_id() == 'msvc'
307 postgres_inc_d += 'src/include/port/win32_msvc'
310 windows = import('windows')
313 # XXX: Should we add an option to override the host_system as an escape
315 error('unknown host system: @0@'.format(host_system))
320 ###############################################################
322 ###############################################################
325 perl = find_program(get_option('PERL'), required: true, native: true)
326 python = find_program(get_option('PYTHON'), required: true, native: true)
327 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35')
328 bison = find_program(get_option('BISON'), native: true, version: '>= 2.3')
329 sed = find_program(get_option('SED'), 'sed', native: true, required: false)
330 prove = find_program(get_option('PROVE'), native: true, required: false)
331 tar = find_program(get_option('TAR'), native: true, required: false)
332 gzip = find_program(get_option('GZIP'), native: true, required: false)
333 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
334 openssl = find_program(get_option('OPENSSL'), native: true, required: false)
335 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
336 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
337 missing = find_program('config/missing', native: true)
338 cp = find_program('cp', required: false, native: true)
339 xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
340 xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
344 bison_version_c = run_command(bison, '--version', check: true)
345 # bison version string helpfully is something like
346 # >>bison (GNU bison) 3.8.1<<
347 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
348 if bison_version.version_compare('>=3.0')
349 bison_flags += ['-Wno-deprecated']
352 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
354 'output': ['@BASENAME@.c', '@BASENAME@.h'],
355 'command': bison_cmd,
360 flex_version_c = run_command(flex, '--version', check: true)
361 flex_version = flex_version_c.stdout().split(' ')[1].split('\n')[0]
363 flex_wrapper = files('src/tools/pgflex')
364 flex_cmd = [python, flex_wrapper,
365 '--builddir', '@BUILD_ROOT@',
366 '--srcdir', '@SOURCE_ROOT@',
367 '--privatedir', '@PRIVATE_DIR@',
368 '--flex', flex, '--perl', perl,
369 '-i', '@INPUT@', '-o', '@OUTPUT0@',
372 wget = find_program('wget', required: false, native: true)
373 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
375 install_files = files('src/tools/install_files')
379 ###############################################################
380 # Path to meson (for tests etc)
381 ###############################################################
383 # NB: this should really be part of meson, see
384 # https://github.com/mesonbuild/meson/issues/8511
385 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
387 if meson_binpath_r.stdout() == ''
388 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
389 meson_binpath_r.returncode(),
390 meson_binpath_r.stdout(),
391 meson_binpath_r.stderr()))
394 meson_binpath_s = meson_binpath_r.stdout().split('\n')
395 meson_binpath_len = meson_binpath_s.length()
397 if meson_binpath_len < 1
398 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
405 foreach e : meson_binpath_s
416 if meson_impl not in ['muon', 'meson']
417 error('unknown meson implementation "@0@"'.format(meson_impl))
420 meson_bin = find_program(meson_binpath, native: true)
424 ###############################################################
426 ###############################################################
428 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
429 cdata.set('USE_INJECTION_POINTS', get_option('injection_points') ? 1 : false)
431 blocksize = get_option('blocksize').to_int() * 1024
433 if get_option('segsize_blocks') != 0
434 if get_option('segsize') != 1
435 warning('both segsize and segsize_blocks specified, segsize_blocks wins')
438 segsize = get_option('segsize_blocks')
440 segsize = (get_option('segsize') * 1024 * 1024 * 1024) / blocksize
443 cdata.set('BLCKSZ', blocksize, description:
444 '''Size of a disk block --- this also limits the size of a tuple. You can set
445 it bigger if you need bigger tuples (although TOAST should reduce the need
446 to have large tuples, since fields can be spread across multiple tuples).
447 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
448 currently 2^15 (32768). This is determined by the 15-bit widths of the
449 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
450 Changing BLCKSZ requires an initdb.''')
452 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
453 cdata.set('RELSEG_SIZE', segsize)
454 cdata.set('DEF_PGPORT', get_option('pgport'))
455 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
456 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
457 if get_option('system_tzdata') != ''
458 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
463 ###############################################################
465 ###############################################################
467 # These are set by the equivalent --xxxdir configure options. We
468 # append "postgresql" to some of them, if the string does not already
469 # contain "pgsql" or "postgres", in order to avoid directory clutter.
473 dir_prefix = get_option('prefix')
475 dir_prefix_contains_pg = (dir_prefix.contains('pgsql') or dir_prefix.contains('postgres'))
477 dir_bin = get_option('bindir')
479 dir_data = get_option('datadir')
480 if not (dir_prefix_contains_pg or dir_data.contains('pgsql') or dir_data.contains('postgres'))
481 dir_data = dir_data / pkg
484 dir_sysconf = get_option('sysconfdir')
485 if not (dir_prefix_contains_pg or dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
486 dir_sysconf = dir_sysconf / pkg
489 dir_lib = get_option('libdir')
491 dir_lib_pkg = dir_lib
492 if not (dir_prefix_contains_pg or dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
493 dir_lib_pkg = dir_lib_pkg / pkg
496 dir_pgxs = dir_lib_pkg / 'pgxs'
498 dir_include = get_option('includedir')
500 dir_include_pkg = dir_include
501 dir_include_pkg_rel = ''
502 if not (dir_prefix_contains_pg or dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
503 dir_include_pkg = dir_include_pkg / pkg
504 dir_include_pkg_rel = pkg
507 dir_man = get_option('mandir')
509 # FIXME: These used to be separately configurable - worth adding?
510 dir_doc = get_option('datadir') / 'doc'
511 if not (dir_prefix_contains_pg or dir_doc.contains('pgsql') or dir_doc.contains('postgres'))
512 dir_doc = dir_doc / pkg
514 dir_doc_html = dir_doc / 'html'
516 dir_locale = get_option('localedir')
520 dir_bitcode = dir_lib_pkg / 'bitcode'
521 dir_include_internal = dir_include_pkg / 'internal'
522 dir_include_server = dir_include_pkg / 'server'
523 dir_include_extension = dir_include_server / 'extension'
524 dir_data_extension = dir_data / 'extension'
525 dir_doc_extension = dir_doc / 'extension'
529 ###############################################################
530 # Search paths, preparation for compiler tests
532 # NB: Arguments added later are not automatically used for subsequent
533 # configuration-time checks (so they are more isolated). If they should be
534 # used, they need to be added to test_c_args as well.
535 ###############################################################
537 postgres_inc = [include_directories(postgres_inc_d)]
538 test_lib_d = postgres_lib_d
539 test_c_args = cppflags + cflags
543 ###############################################################
545 ###############################################################
547 bsd_authopt = get_option('bsd_auth')
548 bsd_auth = not_found_dep
549 if cc.check_header('bsd_auth.h', required: bsd_authopt,
550 args: test_c_args, include_directories: postgres_inc)
551 cdata.set('USE_BSD_AUTH', 1)
552 bsd_auth = declare_dependency()
557 ###############################################################
560 # For now don't search for DNSServiceRegister in a library - only Apple's
561 # Bonjour implementation, which is always linked, works.
562 ###############################################################
564 bonjouropt = get_option('bonjour')
565 bonjour = not_found_dep
566 if cc.check_header('dns_sd.h', required: bonjouropt,
567 args: test_c_args, include_directories: postgres_inc) and \
568 cc.has_function('DNSServiceRegister',
569 args: test_c_args, include_directories: postgres_inc)
570 cdata.set('USE_BONJOUR', 1)
571 bonjour = declare_dependency()
576 ###############################################################
577 # Option: docs in HTML and man page format
578 ###############################################################
580 docs_opt = get_option('docs')
581 docs_dep = not_found_dep
582 if not docs_opt.disabled()
583 if xmllint_bin.found() and xsltproc_bin.found()
584 docs_dep = declare_dependency()
585 elif docs_opt.enabled()
586 error('missing required tools (xmllint and xsltproc needed) for docs in HTML / man page format')
592 ###############################################################
593 # Option: docs in PDF format
594 ###############################################################
596 docs_pdf_opt = get_option('docs_pdf')
597 docs_pdf_dep = not_found_dep
598 if not docs_pdf_opt.disabled()
599 fop = find_program(get_option('FOP'), native: true, required: docs_pdf_opt)
600 if xmllint_bin.found() and xsltproc_bin.found() and fop.found()
601 docs_pdf_dep = declare_dependency()
602 elif docs_pdf_opt.enabled()
603 error('missing required tools for docs in PDF format')
609 ###############################################################
611 ###############################################################
613 gssapiopt = get_option('gssapi')
616 if not gssapiopt.disabled()
617 gssapi = dependency('krb5-gssapi', required: gssapiopt)
618 have_gssapi = gssapi.found()
621 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
622 args: test_c_args, include_directories: postgres_inc)
623 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
624 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
625 cdata.set('HAVE_GSSAPI_H', 1)
631 elif cc.check_header('gssapi/gssapi_ext.h', dependencies: gssapi, required: false,
632 args: test_c_args, include_directories: postgres_inc)
633 cdata.set('HAVE_GSSAPI_GSSAPI_EXT_H', 1)
634 elif cc.check_header('gssapi_ext.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
635 cdata.set('HAVE_GSSAPI_EXT_H', 1)
641 elif cc.has_function('gss_store_cred_into', dependencies: gssapi,
642 args: test_c_args, include_directories: postgres_inc)
643 cdata.set('ENABLE_GSS', 1)
645 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
646 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
647 elif gssapiopt.enabled()
648 error('''could not find function 'gss_store_cred_into' required for GSSAPI''')
654 gssapi = not_found_dep
659 ###############################################################
661 ###############################################################
663 ldapopt = get_option('ldap')
664 if ldapopt.disabled()
666 ldap_r = not_found_dep
667 elif host_system == 'windows'
668 ldap = cc.find_library('wldap32', required: ldapopt)
671 # macos framework dependency is buggy for ldap (one can argue whether it's
672 # Apple's or meson's fault), leading to an endless recursion with ldap.h
673 # including itself. See https://github.com/mesonbuild/meson/issues/10002
674 # Luckily we only need pkg-config support, so the workaround isn't
676 ldap = dependency('ldap', method: 'pkg-config', required: false)
679 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
682 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
683 has_headers: 'ldap.h', header_include_directories: postgres_inc)
685 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
686 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
687 # library from a separate OpenLDAP installation). The most reliable
688 # way to check that is to check for a function introduced in 2.5.
690 # don't have ldap, we shouldn't check for ldap_r
691 elif cc.has_function('ldap_verify_credentials',
692 dependencies: ldap, args: test_c_args)
693 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
696 # Use ldap_r for FE if available, else assume ldap is thread-safe.
697 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
698 has_headers: 'ldap.h', header_include_directories: postgres_inc)
699 if not ldap_r.found()
702 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
703 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
706 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
707 # process. Check for OpenLDAP versions known not to tolerate doing so;
708 # assume non-OpenLDAP implementations are safe. The dblink test suite
709 # exercises the hazardous interaction directly.
710 compat_test_code = '''
712 #if !defined(LDAP_VENDOR_VERSION) || \
713 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
714 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
718 if not cc.compiles(compat_test_code,
719 name: 'LDAP implementation compatible',
720 dependencies: ldap, args: test_c_args)
722 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
723 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
724 *** also uses LDAP will crash on exit.''')
729 if ldap.found() and cc.has_function('ldap_initialize',
730 dependencies: ldap, args: test_c_args)
731 cdata.set('HAVE_LDAP_INITIALIZE', 1)
736 assert(ldap_r.found())
737 cdata.set('USE_LDAP', 1)
739 assert(not ldap_r.found())
744 ###############################################################
746 ###############################################################
748 llvmopt = get_option('llvm')
750 if add_languages('cpp', required: llvmopt, native: false)
751 llvm = dependency('llvm', version: '>=10', method: 'config-tool', required: llvmopt)
755 cdata.set('USE_LLVM', 1)
757 cpp = meson.get_compiler('cpp')
759 llvm_binpath = llvm.get_variable(configtool: 'bindir')
761 ccache = find_program('ccache', native: true, required: false)
762 clang = find_program(llvm_binpath / 'clang', required: true)
765 message('llvm requires a C++ compiler')
770 ###############################################################
772 ###############################################################
774 icuopt = get_option('icu')
775 if not icuopt.disabled()
776 icu = dependency('icu-uc', required: icuopt)
777 icu_i18n = dependency('icu-i18n', required: icuopt)
780 cdata.set('USE_ICU', 1)
785 icu_i18n = not_found_dep
790 ###############################################################
792 ###############################################################
794 libxmlopt = get_option('libxml')
795 if not libxmlopt.disabled()
796 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
799 cdata.set('USE_LIBXML', 1)
802 libxml = not_found_dep
807 ###############################################################
809 ###############################################################
811 libxsltopt = get_option('libxslt')
812 if not libxsltopt.disabled()
813 libxslt = dependency('libxslt', required: libxsltopt)
816 cdata.set('USE_LIBXSLT', 1)
819 libxslt = not_found_dep
824 ###############################################################
826 ###############################################################
828 lz4opt = get_option('lz4')
829 if not lz4opt.disabled()
830 lz4 = dependency('liblz4', required: lz4opt)
833 cdata.set('USE_LZ4', 1)
834 cdata.set('HAVE_LIBLZ4', 1)
843 ###############################################################
844 # Library: Tcl (for pltcl)
846 # NB: tclConfig.sh is used in autoconf build for getting
847 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
848 # variables. For now we have not seen a need to copy
849 # that behaviour to the meson build.
850 ###############################################################
852 tclopt = get_option('pltcl')
853 tcl_version = get_option('tcl_version')
854 tcl_dep = not_found_dep
855 if not tclopt.disabled()
858 tcl_dep = dependency(tcl_version, required: false)
860 if not tcl_dep.found()
861 tcl_dep = cc.find_library(tcl_version,
866 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
867 tcl_dep = not_found_dep
873 ###############################################################
875 ###############################################################
877 pamopt = get_option('pam')
878 if not pamopt.disabled()
879 pam = dependency('pam', required: false)
882 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
886 pam_header_found = false
888 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
889 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
890 args: test_c_args, include_directories: postgres_inc)
891 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
892 pam_header_found = true
893 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
894 args: test_c_args, include_directories: postgres_inc)
895 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
896 pam_header_found = true
900 cdata.set('USE_PAM', 1)
911 ###############################################################
912 # Library: Perl (for plperl)
913 ###############################################################
915 perlopt = get_option('plperl')
916 perl_dep = not_found_dep
917 if not perlopt.disabled()
920 # First verify that perl has the necessary dependencies installed
921 perl_mods = run_command(
923 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
926 if perl_mods.returncode() != 0
927 perl_may_work = false
928 perl_msg = 'perl installation does not have the required modules'
931 # Then inquire perl about its configuration
933 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
934 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
935 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
936 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
937 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
939 perl_inc_dir = '@0@/CORE'.format(archlibexp)
941 if perlversion.version_compare('< 5.14')
942 perl_may_work = false
943 perl_msg = 'Perl version 5.14 or later is required, but this is @0@'.format(perlversion)
944 elif useshrplib != 'true'
945 perl_may_work = false
946 perl_msg = 'need a shared perl'
951 # On most platforms, archlibexp is also where the Perl include files live ...
952 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
953 # ... but on newer macOS versions, we must use -iwithsysroot to look
955 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
956 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
957 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
960 # check compiler finds header
961 if not cc.has_header('perl.h', required: false,
962 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
963 perl_may_work = false
964 perl_msg = 'missing perl.h'
969 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
971 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
972 foreach flag : perl_ccflags_r.split(' ')
973 if flag.startswith('-D') and \
974 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
979 if host_system == 'windows'
980 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
982 if cc.get_id() == 'msvc'
983 # prevent binary mismatch between MSVC built plperl and Strawberry or
984 # msys ucrt perl libraries
985 perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE']
989 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
990 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
992 # We are after Embed's ldopts, but without the subset mentioned in
993 # Config's ccdlflags and ldflags. (Those are the choices of those who
994 # built the Perl installation, which are not necessarily appropriate
995 # for building PostgreSQL.)
996 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
997 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
998 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
1001 foreach ldopt : ldopts.split(' ')
1002 if ldopt == '' or ldopt in undesired
1006 perl_ldopts += ldopt.strip('"')
1009 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
1010 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
1012 perl_dep_int = declare_dependency(
1013 compile_args: perl_ccflags,
1014 link_args: perl_ldopts,
1015 version: perlversion,
1018 # While we're at it, check that we can link to libperl.
1019 # On most platforms, if perl.h is there then libperl.so will be too, but
1020 # at this writing Debian packages them separately.
1021 perl_link_test = '''
1024 #define __inline__ inline
1032 if not cc.links(perl_link_test, name: 'libperl',
1033 args: test_c_args + perl_ccflags + perl_ldopts,
1034 include_directories: postgres_inc)
1035 perl_may_work = false
1036 perl_msg = 'missing libperl'
1039 endif # perl_may_work
1042 perl_dep = perl_dep_int
1044 if perlopt.enabled()
1045 error('dependency plperl failed: @0@'.format(perl_msg))
1047 message('disabling optional dependency plperl: @0@'.format(perl_msg))
1054 ###############################################################
1055 # Library: Python (for plpython)
1056 ###############################################################
1058 pyopt = get_option('plpython')
1059 python3_dep = not_found_dep
1060 if not pyopt.disabled()
1061 pm = import('python')
1062 python3_inst = pm.find_installation(python.path(), required: pyopt)
1063 if python3_inst.found()
1064 python3_dep = python3_inst.dependency(embed: true, required: pyopt)
1065 # Remove this check after we depend on Meson >= 1.1.0
1066 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt, include_directories: postgres_inc)
1067 python3_dep = not_found_dep
1074 ###############################################################
1076 ###############################################################
1078 if not get_option('readline').disabled()
1079 libedit_preferred = get_option('libedit_preferred')
1080 # Set the order of readline dependencies
1081 check_readline_deps = libedit_preferred ? \
1082 ['libedit', 'readline'] : ['readline', 'libedit']
1084 foreach readline_dep : check_readline_deps
1085 readline = dependency(readline_dep, required: false)
1086 if not readline.found()
1087 readline = cc.find_library(readline_dep,
1088 required: get_option('readline'),
1097 cdata.set('HAVE_LIBREADLINE', 1)
1100 'header_prefix': 'editline/',
1101 'flag_prefix': 'EDITLINE_',
1104 'header_prefix': 'readline/',
1105 'flag_prefix': 'READLINE_',
1108 'header_prefix': '',
1112 # Set the order of prefixes
1113 prefixes = libedit_preferred ? \
1114 [editline_prefix, default_prefix, readline_prefix] : \
1115 [readline_prefix, default_prefix, editline_prefix]
1117 at_least_one_header_found = false
1118 foreach header : ['history', 'readline']
1120 foreach prefix : prefixes
1121 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1122 # Check history.h and readline.h
1123 if not is_found and cc.has_header(header_file,
1124 args: test_c_args, include_directories: postgres_inc,
1125 dependencies: [readline], required: false)
1126 if header == 'readline'
1127 readline_h = header_file
1129 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1131 at_least_one_header_found = true
1136 if not at_least_one_header_found
1137 error('''readline header not found
1138 If you have @0@ already installed, see meson-logs/meson-log.txt for details on the
1139 failure. It is possible the compiler isn't looking in the proper directory.
1140 Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
1145 'history_truncate_file',
1146 'rl_completion_matches',
1147 'rl_filename_completion_function',
1148 'rl_reset_screen_size',
1152 foreach func : check_funcs
1153 found = cc.has_function(func, dependencies: [readline],
1154 args: test_c_args, include_directories: postgres_inc)
1155 cdata.set('HAVE_' + func.to_upper(), found ? 1 : false)
1159 'rl_completion_suppress_quote',
1160 'rl_filename_quote_characters',
1161 'rl_filename_quoting_function',
1164 foreach var : check_vars
1165 cdata.set('HAVE_' + var.to_upper(),
1166 cc.has_header_symbol(readline_h, var,
1167 args: test_c_args, include_directories: postgres_inc,
1168 prefix: '#include <stdio.h>',
1169 dependencies: [readline]) ? 1 : false)
1172 # If found via cc.find_library() ensure headers are found when using the
1173 # dependency. On meson < 0.57 one cannot do compiler checks using the
1174 # dependency returned by declare_dependency(), so we can't do this above.
1175 if readline.type_name() == 'library'
1176 readline = declare_dependency(dependencies: readline,
1177 include_directories: postgres_inc)
1180 # On windows with mingw readline requires auto-import to successfully
1181 # link, as the headers don't use declspec(dllimport)
1182 if host_system == 'windows' and cc.get_id() != 'msvc'
1183 readline = declare_dependency(dependencies: readline,
1184 link_args: '-Wl,--enable-auto-import')
1188 # XXX: Figure out whether to implement mingw warning equivalent
1190 readline = not_found_dep
1195 ###############################################################
1197 ###############################################################
1199 selinux = not_found_dep
1200 selinuxopt = get_option('selinux')
1201 if meson.version().version_compare('>=0.59')
1202 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1204 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1205 cdata.set('HAVE_LIBSELINUX',
1206 selinux.found() ? 1 : false)
1210 ###############################################################
1212 ###############################################################
1214 systemd = not_found_dep
1215 systemdopt = get_option('systemd')
1216 if meson.version().version_compare('>=0.59')
1217 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1219 systemd = dependency('libsystemd', required: systemdopt)
1220 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1224 ###############################################################
1226 ###############################################################
1229 ssl_library = 'none'
1230 sslopt = get_option('ssl')
1232 if sslopt == 'auto' and auto_features.disabled()
1236 if sslopt in ['auto', 'openssl']
1237 openssl_required = (sslopt == 'openssl')
1239 # Try to find openssl via pkg-config et al, if that doesn't work
1240 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1241 # the library names that we know about.
1243 # via pkg-config et al
1244 ssl = dependency('openssl', required: false)
1245 # only meson >= 0.57 supports declare_dependency() in cc.has_function(), so
1246 # we pass cc.find_library() results if necessary
1249 # via library + headers
1251 ssl_lib = cc.find_library('ssl',
1253 header_include_directories: postgres_inc,
1254 has_headers: ['openssl/ssl.h', 'openssl/err.h'],
1255 required: openssl_required)
1256 crypto_lib = cc.find_library('crypto',
1258 required: openssl_required)
1259 if ssl_lib.found() and crypto_lib.found()
1260 ssl_int = [ssl_lib, crypto_lib]
1261 ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc)
1263 elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \
1264 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required)
1272 ['CRYPTO_new_ex_data', {'required': true}],
1273 ['SSL_new', {'required': true}],
1275 # Function introduced in OpenSSL 1.0.2, not in LibreSSL.
1276 ['SSL_CTX_set_cert_cb'],
1278 # Functions introduced in OpenSSL 1.1.0. We used to check for
1279 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1280 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1281 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1283 ['OPENSSL_init_ssl'],
1285 ['ASN1_STRING_get0_data'],
1289 # OpenSSL versions before 1.1.0 required setting callback functions, for
1290 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1291 # function was removed.
1294 # Function introduced in OpenSSL 1.1.1
1295 ['X509_get_signature_info'],
1298 are_openssl_funcs_complete = true
1299 foreach c : check_funcs
1301 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1302 required = c.get(1, {}).get('required', false)
1303 if required and not val
1304 are_openssl_funcs_complete = false
1306 error('openssl function @0@ is required'.format(func))
1310 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1314 if are_openssl_funcs_complete
1315 cdata.set('USE_OPENSSL', 1,
1316 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1317 cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
1318 description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
1319 ssl_library = 'openssl'
1326 if sslopt == 'auto' and auto_features.enabled() and not ssl.found()
1327 error('no SSL library found')
1332 ###############################################################
1334 ###############################################################
1336 uuidopt = get_option('uuid')
1337 if uuidopt != 'none'
1338 uuidname = uuidopt.to_upper()
1339 if uuidopt == 'e2fs'
1340 uuid = dependency('uuid', required: true)
1341 uuidfunc = 'uuid_generate'
1342 uuidheader = 'uuid/uuid.h'
1343 elif uuidopt == 'bsd'
1344 # libc should have uuid function
1345 uuid = declare_dependency()
1346 uuidfunc = 'uuid_to_string'
1347 uuidheader = 'uuid.h'
1348 elif uuidopt == 'ossp'
1349 uuid = dependency('ossp-uuid', required: true)
1350 uuidfunc = 'uuid_export'
1351 uuidheader = 'uuid.h'
1353 error('unknown uuid build option value: @0@'.format(uuidopt))
1356 if not cc.has_header_symbol(uuidheader, uuidfunc,
1358 include_directories: postgres_inc,
1360 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1362 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1364 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1365 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1367 uuid = not_found_dep
1372 ###############################################################
1374 ###############################################################
1376 zlibopt = get_option('zlib')
1377 zlib = not_found_dep
1378 if not zlibopt.disabled()
1379 zlib_t = dependency('zlib', required: zlibopt)
1381 if zlib_t.type_name() == 'internal'
1382 # if fallback was used, we don't need to test if headers are present (they
1383 # aren't built yet, so we can't test)
1385 elif not zlib_t.found()
1386 warning('did not find zlib')
1387 elif not cc.has_header('zlib.h',
1388 args: test_c_args, include_directories: postgres_inc,
1389 dependencies: [zlib_t], required: zlibopt)
1390 warning('zlib header not found')
1396 cdata.set('HAVE_LIBZ', 1)
1402 ###############################################################
1403 # Library: tap test dependencies
1404 ###############################################################
1406 # Check whether tap tests are enabled or not
1407 tap_tests_enabled = false
1408 tapopt = get_option('tap_tests')
1409 if not tapopt.disabled()
1410 # Checking for perl modules for tap tests
1411 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1412 if perl_ipc_run_check.returncode() != 0
1413 message(perl_ipc_run_check.stderr().strip())
1415 error('Additional Perl modules are required to run TAP tests.')
1417 warning('Additional Perl modules are required to run TAP tests.')
1420 tap_tests_enabled = true
1426 ###############################################################
1428 ###############################################################
1430 zstdopt = get_option('zstd')
1431 if not zstdopt.disabled()
1432 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1435 cdata.set('USE_ZSTD', 1)
1436 cdata.set('HAVE_LIBZSTD', 1)
1440 zstd = not_found_dep
1445 ###############################################################
1447 ###############################################################
1449 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1450 # unnecessarily, because we optionally rely on newer features.
1452 #include <stdbool.h>
1453 #include <complex.h>
1455 #include <inttypes.h>
1457 struct named_init_test {
1462 extern void structfunc(struct named_init_test);
1464 int main(int argc, char **argv)
1466 struct named_init_test nit = {
1471 for (int loop_var = 0; loop_var < 3; loop_var++)
1476 structfunc((struct named_init_test){1, 0});
1482 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1483 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1484 args: test_c_args + ['-std=c99'])
1485 test_c_args += '-std=c99'
1486 cflags += '-std=c99'
1488 error('C compiler does not support C99')
1492 sizeof_long = cc.sizeof('long', args: test_c_args)
1493 cdata.set('SIZEOF_LONG', sizeof_long)
1495 cdata.set('HAVE_LONG_INT_64', 1)
1496 pg_int64_type = 'long int'
1497 cdata.set_quoted('INT64_MODIFIER', 'l')
1498 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1499 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1500 pg_int64_type = 'long long int'
1501 cdata.set_quoted('INT64_MODIFIER', 'll')
1503 error('do not know how to get a 64bit int')
1505 cdata.set('PG_INT64_TYPE', pg_int64_type)
1507 if host_machine.endian() == 'big'
1508 cdata.set('WORDS_BIGENDIAN', 1)
1511 # Determine memory alignment requirements for the basic C data types.
1513 alignof_types = ['short', 'int', 'long', 'double']
1514 foreach t : alignof_types
1515 align = cc.alignment(t, args: test_c_args)
1516 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1519 # Compute maximum alignment of any basic type.
1521 # We require 'double' to have the strictest alignment among the basic types,
1522 # because otherwise the C ABI might impose 8-byte alignment on some of the
1523 # other C types that correspond to TYPALIGN_DOUBLE SQL types. That could
1524 # cause a mismatch between the tuple layout and the C struct layout of a
1525 # catalog tuple. We used to carefully order catalog columns such that any
1526 # fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
1527 # of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
1528 # where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
1530 # We assume without checking that int64's alignment is at least as strong
1531 # as long, char, short, or int. Note that we intentionally do not consider
1532 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
1533 # would be too much of a penalty for disk and memory space.
1534 alignof_double = cdata.get('ALIGNOF_DOUBLE')
1535 if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
1536 error('alignment of int64 is greater than the alignment of double')
1538 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
1540 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1541 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1544 # Check if __int128 is a working 128 bit integer type, and if so
1545 # define PG_INT128_TYPE to that typename.
1547 # This currently only detects a GCC/clang extension, but support for other
1548 # environments may be added in the future.
1550 # For the moment we only test for support for 128bit math; support for
1551 # 128bit literals and snprintf is not required.
1554 * We don't actually run this test, just link it to verify that any support
1555 * functions needed for __int128 are present.
1557 * These are globals to discourage the compiler from folding all the
1558 * arithmetic tests down to compile-time constants. We do not have
1559 * convenient support for 128bit literals at this point...
1561 __int128 a = 48828125;
1562 __int128 b = 97656250;
1567 a = (a << 12) + 1; /* 200000000001 */
1568 b = (b << 12) + 5; /* 400000000005 */
1569 /* try the most relevant arithmetic ops */
1572 /* must use the results, else compiler may optimize arithmetic away */
1578 buggy_int128 = false
1580 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1581 # If not cross-compiling, we can test for bugs and disable use of __int128
1582 # with buggy compilers. If cross-compiling, hope for the best.
1583 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1584 if not meson.is_cross_build()
1586 /* This must match the corresponding code in c.h: */
1587 #if defined(__GNUC__) || defined(__SUNPRO_C)
1588 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1589 #elif defined(_MSC_VER)
1590 #define pg_attribute_aligned(a) __declspec(align(a))
1592 typedef __int128 int128a
1593 #if defined(pg_attribute_aligned)
1594 pg_attribute_aligned(8)
1599 void pass_by_val(void *buffer, int128a par) { holder = par; }
1603 long int i64 = 97656225L << 12;
1605 pass_by_val(main, (int128a) i64);
1609 name: '__int128 alignment bug',
1611 assert(r.compiled())
1612 if r.returncode() != 0
1614 message('__int128 support present but buggy and thus disabled')
1619 cdata.set('PG_INT128_TYPE', '__int128')
1620 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.alignment('__int128', args: test_c_args))
1625 # Check if the C compiler knows computed gotos (gcc extension, also
1626 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1628 # Checking whether computed gotos are supported syntax-wise ought to
1629 # be enough, as the syntax is otherwise illegal.
1631 static inline int foo(void)
1633 void *labeladdrs[] = {&&my_label};
1634 goto *labeladdrs[0];
1639 cdata.set('HAVE_COMPUTED_GOTO', 1)
1643 # Check if the C compiler understands _Static_assert(),
1644 # and define HAVE__STATIC_ASSERT if so.
1646 # We actually check the syntax ({ _Static_assert(...) }), because we need
1647 # gcc-style compound expressions to be able to wrap the thing into macros.
1649 int main(int arg, char **argv)
1651 ({ _Static_assert(1, "foo"); });
1655 cdata.set('HAVE__STATIC_ASSERT', 1)
1659 # We use <stdbool.h> if we have it and it declares type bool as having
1660 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1661 if cc.has_type('_Bool', args: test_c_args) \
1662 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1663 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1664 cdata.set('HAVE__BOOL', 1)
1665 cdata.set('PG_USE_STDBOOL', 1)
1669 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1670 # warning for each use of %m.
1671 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1673 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1674 static void call_log(void)
1676 emit_log(0, "error: %s: %m", "foo");
1679 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1680 foreach a : printf_attributes
1681 if cc.compiles(testsrc.format(a),
1682 args: test_c_args + attrib_error_args, name: 'format ' + a)
1683 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1689 if cc.has_function_attribute('visibility:default') and \
1690 cc.has_function_attribute('visibility:hidden')
1691 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1693 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1694 # inlineshidden to C code as well... And either way, we want to put these
1695 # flags into exported files (pgxs, .pc files).
1696 cflags_mod += '-fvisibility=hidden'
1697 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1698 ldflags_mod += '-fvisibility=hidden'
1702 # Check if various builtins exist. Some builtins are tested separately,
1703 # because we want to test something more complicated than the generic case.
1716 foreach builtin : builtins
1717 fname = '__builtin_@0@'.format(builtin)
1718 if cc.has_function(fname, args: test_c_args)
1719 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1724 # Check if the C compiler understands __builtin_types_compatible_p,
1725 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1727 # We check usage with __typeof__, though it's unlikely any compiler would
1728 # have the former and not the latter.
1731 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1733 name: '__builtin_types_compatible_p',
1735 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1739 # Check if the C compiler understands __builtin_$op_overflow(),
1740 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1742 # Check for the most complicated case, 64 bit multiplication, as a
1743 # proxy for all of the operations. To detect the case where the compiler
1744 # knows the function but library support is missing, we must link not just
1745 # compile, and store the results in global variables so the compiler doesn't
1746 # optimize away the call.
1754 return __builtin_mul_overflow(a, b, &result);
1756 name: '__builtin_mul_overflow',
1757 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1759 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1763 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1764 # here. To prevent problems due to two detection methods working, stop
1765 # checking after one.
1768 int main(int arg, char **argv)
1770 unsigned int exx[4] = {0, 0, 0, 0};
1771 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1773 ''', name: '__get_cpuid',
1775 cdata.set('HAVE__GET_CPUID', 1)
1778 int main(int arg, char **argv)
1780 unsigned int exx[4] = {0, 0, 0, 0};
1783 ''', name: '__cpuid',
1785 cdata.set('HAVE__CPUID', 1)
1789 # Check for __get_cpuid_count() and __cpuidex() in a similar fashion.
1792 int main(int arg, char **argv)
1794 unsigned int exx[4] = {0, 0, 0, 0};
1795 __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
1797 ''', name: '__get_cpuid_count',
1799 cdata.set('HAVE__GET_CPUID_COUNT', 1)
1802 int main(int arg, char **argv)
1804 unsigned int exx[4] = {0, 0, 0, 0};
1805 __cpuidex(exx, 7, 0);
1807 ''', name: '__cpuidex',
1809 cdata.set('HAVE__CPUIDEX', 1)
1813 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1814 # versions of clang do not understand -fexcess-precision=standard, the use of
1815 # x87 floating point operations leads to problems like isinf possibly returning
1816 # false for a value that is infinite when converted from the 80bit register to
1817 # the 8byte memory representation.
1819 # Only perform the test if the compiler doesn't understand
1820 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1822 if '-fexcess-precision=standard' not in cflags
1823 if not cc.compiles('''
1824 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1827 name: '', args: test_c_args)
1828 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1834 ###############################################################
1836 ###############################################################
1838 common_functional_flags = [
1839 # Disable strict-aliasing rules; needed for gcc 3.3+
1840 '-fno-strict-aliasing',
1841 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1843 '-fexcess-precision=standard',
1846 cflags += cc.get_supported_arguments(common_functional_flags)
1848 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1851 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1852 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1854 common_warning_flags = [
1855 '-Wmissing-prototypes',
1857 # Really don't want VLAs to be used in our dialect of C
1859 # On macOS, complain about usage of symbols newer than the deployment target
1860 '-Werror=unguarded-availability-new',
1862 '-Wmissing-format-attribute',
1863 '-Wimplicit-fallthrough=3',
1864 '-Wcast-function-type',
1865 '-Wshadow=compatible-local',
1866 # This was included in -Wall/-Wformat in older GCC versions
1867 '-Wformat-security',
1870 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1872 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1875 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1876 # the result for them
1877 cflags_no_decl_after_statement = []
1878 if cc.has_argument('-Wdeclaration-after-statement')
1879 cflags_warn += '-Wdeclaration-after-statement'
1880 cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
1884 # The following tests want to suppress various unhelpful warnings by adding
1885 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1886 # switches, so we have to test for the positive form and if that works,
1887 # add the negative form.
1889 negative_warning_flags = [
1890 # Suppress clang's unhelpful unused-command-line-argument warnings.
1891 'unused-command-line-argument',
1893 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1894 # of warnings when building plperl because of usages in the Perl headers.
1895 'compound-token-split-by-macro',
1897 # Similarly disable useless truncation warnings from gcc 8+
1898 'format-truncation',
1899 'stringop-truncation',
1901 # Suppress clang 16's strict warnings about function casts
1902 'cast-function-type-strict',
1904 # To make warning_level=2 / -Wextra work, we'd need at least the following
1906 # 'missing-field-initializers',
1908 # 'unused-parameter',
1911 foreach w : negative_warning_flags
1912 if cc.has_argument('-W' + w)
1913 cflags_warn += '-Wno-' + w
1915 if llvm.found() and cpp.has_argument('-W' + w)
1916 cxxflags_warn += '-Wno-' + w
1921 if cc.get_id() == 'msvc'
1923 '/wd4018', # signed/unsigned mismatch
1924 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1925 '/wd4273', # inconsistent DLL linkage
1926 '/wd4101', # unreferenced local variable
1927 '/wd4102', # unreferenced label
1928 '/wd4090', # different 'modifier' qualifiers
1929 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1937 '/D_CRT_SECURE_NO_DEPRECATE',
1938 '/D_CRT_NONSTDC_NO_DEPRECATE',
1941 # We never need export libraries. As link.exe reports their creation, they
1942 # are unnecessarily noisy. Similarly, we don't need import library for
1943 # modules, we only import them dynamically, and they're also noisy.
1945 ldflags_mod += '/NOIMPLIB'
1949 # Compute flags that are built into Meson. We need these to
1950 # substitute into Makefile.global and for pg_config. We only compute
1951 # the flags for Unix-style compilers, since that's the only style that
1952 # would use Makefile.global or pg_config.
1954 # We don't use get_option('warning_level') here, because the other
1955 # warning levels are not useful with PostgreSQL source code.
1956 common_builtin_flags = ['-Wall']
1958 if get_option('debug')
1959 common_builtin_flags += ['-g']
1962 optimization = get_option('optimization')
1963 if optimization == '0'
1964 common_builtin_flags += ['-O0']
1965 elif optimization == '1'
1966 common_builtin_flags += ['-O1']
1967 elif optimization == '2'
1968 common_builtin_flags += ['-O2']
1969 elif optimization == '3'
1970 common_builtin_flags += ['-O3']
1971 elif optimization == 's'
1972 common_builtin_flags += ['-Os']
1975 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
1977 cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
1982 ###############################################################
1984 ###############################################################
1986 if not get_option('spinlocks')
1987 warning('Not using spinlocks will cause poor performance')
1989 cdata.set('HAVE_SPINLOCKS', 1)
1992 if not get_option('atomics')
1993 warning('Not using atomics will cause poor performance')
1995 # XXX: perhaps we should require some atomics support in this case these
1997 cdata.set('HAVE_ATOMICS', 1)
2000 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
2001 'desc': '__sync_lock_test_and_set(char)',
2004 __sync_lock_test_and_set(&lock, 1);
2005 __sync_lock_release(&lock);'''},
2007 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
2008 'desc': '__sync_lock_test_and_set(int32)',
2011 __sync_lock_test_and_set(&lock, 1);
2012 __sync_lock_release(&lock);'''},
2014 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
2015 'desc': '__sync_val_compare_and_swap(int32)',
2018 __sync_val_compare_and_swap(&val, 0, 37);'''},
2020 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
2021 'desc': '__sync_val_compare_and_swap(int64)',
2024 __sync_val_compare_and_swap(&val, 0, 37);'''},
2026 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
2027 'desc': ' __atomic_compare_exchange_n(int32)',
2031 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
2033 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
2034 'desc': ' __atomic_compare_exchange_n(int64)',
2038 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
2041 foreach check : atomic_checks
2046 }'''.format(check['test'])
2048 cdata.set(check['name'],
2050 name: check['desc'],
2051 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
2058 ###############################################################
2059 # Check for the availability of XSAVE intrinsics.
2060 ###############################################################
2063 if host_cpu == 'x86' or host_cpu == 'x86_64'
2066 #include <immintrin.h>
2070 return _xgetbv(0) & 0xe0;
2074 if cc.links(prog, name: 'XSAVE intrinsics without -mxsave',
2076 cdata.set('HAVE_XSAVE_INTRINSICS', 1)
2077 elif cc.links(prog, name: 'XSAVE intrinsics with -mxsave',
2078 args: test_c_args + ['-mxsave'])
2079 cdata.set('HAVE_XSAVE_INTRINSICS', 1)
2080 cflags_xsave += '-mxsave'
2086 ###############################################################
2087 # Check for the availability of AVX-512 popcount intrinsics.
2088 ###############################################################
2091 if host_cpu == 'x86_64'
2094 #include <immintrin.h>
2098 const char buf[sizeof(__m512i)];
2100 __m512i accum = _mm512_setzero_si512();
2101 const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
2102 const __m512i cnt = _mm512_popcnt_epi64(val);
2103 accum = _mm512_add_epi64(accum, cnt);
2104 popcnt = _mm512_reduce_add_epi64(accum);
2105 /* return computed value, to prevent the above being optimized away */
2110 if cc.links(prog, name: 'AVX-512 popcount without -mavx512vpopcntdq -mavx512bw',
2111 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
2112 cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
2113 elif cc.links(prog, name: 'AVX-512 popcount with -mavx512vpopcntdq -mavx512bw',
2114 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))] + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
2115 cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
2116 cflags_popcnt += ['-mavx512vpopcntdq'] + ['-mavx512bw']
2122 ###############################################################
2123 # Select CRC-32C implementation.
2125 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
2126 # use the special CRC instructions for calculating CRC-32C. If we're not
2127 # targeting such a processor, but we can nevertheless produce code that uses
2128 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
2129 # implementations and select which one to use at runtime, depending on whether
2130 # SSE 4.2 is supported by the processor we're running on.
2132 # Similarly, if we are targeting an ARM processor that has the CRC
2133 # instructions that are part of the ARMv8 CRC Extension, use them. And if
2134 # we're not targeting such a processor, but can nevertheless produce code that
2135 # uses the CRC instructions, compile both, and select at runtime.
2136 ###############################################################
2138 have_optimized_crc = false
2140 if host_cpu == 'x86' or host_cpu == 'x86_64'
2142 if cc.get_id() == 'msvc'
2143 cdata.set('USE_SSE42_CRC32C', false)
2144 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2145 have_optimized_crc = true
2149 #include <nmmintrin.h>
2153 unsigned int crc = 0;
2154 crc = _mm_crc32_u8(crc, 0);
2155 crc = _mm_crc32_u32(crc, 0);
2156 /* return computed value, to prevent the above being optimized away */
2161 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
2163 # Use Intel SSE 4.2 unconditionally.
2164 cdata.set('USE_SSE42_CRC32C', 1)
2165 have_optimized_crc = true
2166 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
2167 args: test_c_args + ['-msse4.2'])
2168 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
2169 # the runtime check.
2170 cflags_crc += '-msse4.2'
2171 cdata.set('USE_SSE42_CRC32C', false)
2172 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
2173 have_optimized_crc = true
2178 elif host_cpu == 'arm' or host_cpu == 'aarch64'
2181 #include <arm_acle.h>
2185 unsigned int crc = 0;
2186 crc = __crc32cb(crc, 0);
2187 crc = __crc32ch(crc, 0);
2188 crc = __crc32cw(crc, 0);
2189 crc = __crc32cd(crc, 0);
2191 /* return computed value, to prevent the above being optimized away */
2196 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
2198 # Use ARM CRC Extension unconditionally
2199 cdata.set('USE_ARMV8_CRC32C', 1)
2200 have_optimized_crc = true
2201 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
2202 args: test_c_args + ['-march=armv8-a+crc'])
2203 # Use ARM CRC Extension, with runtime check
2204 cflags_crc += '-march=armv8-a+crc'
2205 cdata.set('USE_ARMV8_CRC32C', false)
2206 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
2207 have_optimized_crc = true
2210 elif host_cpu == 'loongarch64'
2215 unsigned int crc = 0;
2216 crc = __builtin_loongarch_crcc_w_b_w(0, crc);
2217 crc = __builtin_loongarch_crcc_w_h_w(0, crc);
2218 crc = __builtin_loongarch_crcc_w_w_w(0, crc);
2219 crc = __builtin_loongarch_crcc_w_d_w(0, crc);
2221 /* return computed value, to prevent the above being optimized away */
2226 if cc.links(prog, name: '__builtin_loongarch_crcc_w_b_w, __builtin_loongarch_crcc_w_h_w, __builtin_loongarch_crcc_w_w_w, and __builtin_loongarch_crcc_w_d_w',
2228 # Use LoongArch CRC instruction unconditionally
2229 cdata.set('USE_LOONGARCH_CRC32C', 1)
2230 have_optimized_crc = true
2235 if not have_optimized_crc
2236 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
2238 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
2243 ###############################################################
2244 # Other CPU specific stuff
2245 ###############################################################
2247 if host_cpu == 'x86_64'
2252 long long x = 1; long long r;
2253 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
2255 name: '@0@: popcntq instruction'.format(host_cpu),
2257 cdata.set('HAVE_X86_64_POPCNTQ', 1)
2260 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
2261 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
2262 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
2265 addi(int ra, int si)
2268 if (__builtin_constant_p(si))
2269 __asm__ __volatile__(
2270 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
2273 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2276 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2283 ###############################################################
2284 # Library / OS tests
2285 ###############################################################
2287 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2288 # unnecessary checks over and over, particularly on windows.
2302 'sys/personality.h',
2311 foreach header : header_checks
2312 varname = 'HAVE_' + header.underscorify().to_upper()
2314 # Emulate autoconf behaviour of not-found->undef, found->1
2315 found = cc.has_header(header,
2316 include_directories: postgres_inc, args: test_c_args)
2317 cdata.set(varname, found ? 1 : false,
2318 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2323 ['F_FULLFSYNC', 'fcntl.h'],
2324 ['fdatasync', 'unistd.h'],
2325 ['posix_fadvise', 'fcntl.h'],
2326 ['strlcat', 'string.h'],
2327 ['strlcpy', 'string.h'],
2328 ['strnlen', 'string.h'],
2331 # Need to check for function declarations for these functions, because
2332 # checking for library symbols wouldn't handle deployment target
2333 # restrictions on macOS
2335 ['preadv', 'sys/uio.h'],
2336 ['pwritev', 'sys/uio.h'],
2339 # Check presence of some optional LLVM functions.
2342 ['LLVMCreateGDBRegistrationListener', 'llvm-c/ExecutionEngine.h'],
2343 ['LLVMCreatePerfJITEventListener', 'llvm-c/ExecutionEngine.h'],
2347 foreach c : decl_checks
2351 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2353 found = cc.has_header_symbol(header, func,
2354 args: test_c_args, include_directories: postgres_inc,
2356 cdata.set10(varname, found, description:
2357 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2358 don't.'''.format(func))
2362 if cc.has_type('struct option',
2363 args: test_c_args, include_directories: postgres_inc,
2364 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2365 cdata.set('HAVE_STRUCT_OPTION', 1)
2369 foreach c : ['opterr', 'optreset']
2370 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2379 '''.format(c), name: c, args: test_c_args)
2380 cdata.set(varname, 1)
2382 cdata.set(varname, false)
2386 if cc.has_type('socklen_t',
2387 args: test_c_args, include_directories: postgres_inc,
2389 #include <sys/socket.h>''')
2390 cdata.set('HAVE_SOCKLEN_T', 1)
2393 if cc.has_member('struct sockaddr', 'sa_len',
2394 args: test_c_args, include_directories: postgres_inc,
2396 #include <sys/types.h>
2397 #include <sys/socket.h>''')
2398 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2401 if cc.has_member('struct tm', 'tm_zone',
2402 args: test_c_args, include_directories: postgres_inc,
2404 #include <sys/types.h>
2407 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2412 extern int foo(void);
2415 return timezone / 60;
2418 name: 'global variable `timezone\' exists',
2419 args: test_c_args, include_directories: postgres_inc)
2420 cdata.set('HAVE_INT_TIMEZONE', 1)
2422 cdata.set('HAVE_INT_TIMEZONE', false)
2425 if cc.has_type('union semun',
2427 include_directories: postgres_inc,
2429 #include <sys/types.h>
2430 #include <sys/ipc.h>
2431 #include <sys/sem.h>
2433 cdata.set('HAVE_UNION_SEMUN', 1)
2441 switch (strerror_r(1, buf, sizeof(buf)))
2442 { case 0: break; default: break; }
2445 args: test_c_args, include_directories: postgres_inc)
2446 cdata.set('STRERROR_R_INT', 1)
2448 cdata.set('STRERROR_R_INT', false)
2451 # Find the right header file for the locale_t type. macOS needs xlocale.h;
2452 # standard is locale.h, but glibc <= 2.25 also had an xlocale.h file that
2453 # we should not use so we check the standard header first. MSVC has a
2454 # replacement defined in src/include/port/win32_port.h.
2455 if not cc.has_type('locale_t', prefix: '#include <locale.h>') and \
2456 cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2457 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2460 # Check if the C compiler understands typeof or a variant. Define
2461 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2462 foreach kw : ['typeof', '__typeof__', 'decltype']
2473 args: test_c_args, include_directories: postgres_inc)
2475 cdata.set('HAVE_TYPEOF', 1)
2477 cdata.set('typeof', kw)
2485 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2486 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2487 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2488 wcstombs_l_test = '''
2500 if (not cc.compiles(wcstombs_l_test.format(''),
2501 name: 'wcstombs_l') and
2502 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2503 name: 'wcstombs_l in xlocale.h'))
2504 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2508 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2509 # understands, because it conflicts with __declspec(restrict). Therefore we
2510 # define pg_restrict to the appropriate definition, which presumably won't
2513 # We assume C99 support, so we don't need to make this conditional.
2514 cdata.set('pg_restrict', '__restrict')
2517 # Most libraries are included only if they demonstrably provide a function we
2518 # need, but libm is an exception: always include it, because there are too
2519 # many compilers that play cute optimization games that will break probes for
2520 # standard functions such as pow().
2521 os_deps += cc.find_library('m', required: false)
2523 rt_dep = cc.find_library('rt', required: false)
2525 dl_dep = cc.find_library('dl', required: false)
2527 util_dep = cc.find_library('util', required: false)
2529 getopt_dep = cc.find_library('getopt', required: false)
2530 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2531 # Check if we want to replace getopt/getopt_long even if provided by the system
2532 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2533 # so always use our version on Windows
2534 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2535 # (i.e., allow '-' as a flag character), so use our version on those platforms
2536 # - We want to use system's getopt_long() only if the system provides struct
2538 always_replace_getopt = host_system in ['windows', 'cygwin', 'openbsd', 'solaris']
2539 always_replace_getopt_long = host_system in ['windows', 'cygwin'] or not cdata.has('HAVE_STRUCT_OPTION')
2542 execinfo_dep = cc.find_library('execinfo', required: false)
2544 if host_system == 'cygwin'
2545 cygipc_dep = cc.find_library('cygipc', required: false)
2547 cygipc_dep = not_found_dep
2550 if host_system == 'sunos'
2551 socket_dep = cc.find_library('socket', required: false)
2553 socket_dep = not_found_dep
2556 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2557 # unnecessary checks over and over, particularly on windows.
2559 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2560 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2561 ['clock_gettime', {'dependencies': [rt_dep], 'define': false}],
2563 ['copy_file_range'],
2564 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2565 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2566 # required. Just checking for dlsym() ought to suffice.
2567 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2570 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2571 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2581 ['posix_fallocate'],
2583 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2584 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2585 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2586 ['setproctitle', {'dependencies': [util_dep]}],
2587 ['setproctitle_fast'],
2588 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2589 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2590 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2591 ['socket', {'dependencies': [socket_dep], 'define': false}],
2593 ['strerror_r', {'dependencies': [thread_dep]}],
2598 ['sync_file_range'],
2604 func_check_results = {}
2605 foreach c : func_checks
2607 kwargs = c.get(1, {})
2608 deps = kwargs.get('dependencies', [])
2610 if kwargs.get('skip', false)
2614 found = cc.has_function(func, args: test_c_args)
2621 found = cc.has_function(func, args: test_c_args,
2622 dependencies: [dep])
2630 func_check_results += {func: found}
2632 if kwargs.get('define', true)
2633 # Emulate autoconf behaviour of not-found->undef, found->1
2634 cdata.set('HAVE_' + func.underscorify().to_upper(),
2636 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2641 if cc.has_function('syslog', args: test_c_args) and \
2642 cc.check_header('syslog.h', args: test_c_args)
2643 cdata.set('HAVE_SYSLOG', 1)
2647 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2649 if sema_kind == 'unnamed_posix' and \
2650 not func_check_results.get('sem_init', false)
2654 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2655 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2657 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2658 cdata.set_quoted('DLSUFFIX', dlsuffix)
2661 # built later than the rest of the version metadata, we need SIZEOF_VOID_P
2662 cdata.set_quoted('PG_VERSION_STR',
2663 'PostgreSQL @0@ on @1@-@2@, compiled by @3@-@4@, @5@-bit'.format(
2664 pg_version, host_machine.cpu_family(), host_system,
2665 cc.get_id(), cc.version(), cdata.get('SIZEOF_VOID_P') * 8,
2670 ###############################################################
2672 ###############################################################
2674 nlsopt = get_option('nls')
2675 libintl = not_found_dep
2677 if not nlsopt.disabled()
2678 # otherwise there'd be lots of
2679 # "Gettext not found, all translation (po) targets will be ignored."
2680 # warnings if not found.
2681 msgfmt = find_program('msgfmt', required: nlsopt, native: true)
2683 # meson 0.59 has this wrapped in dependency('intl')
2684 if (msgfmt.found() and
2685 cc.check_header('libintl.h', required: nlsopt,
2686 args: test_c_args, include_directories: postgres_inc))
2689 if cc.has_function('ngettext')
2690 libintl = declare_dependency()
2692 libintl = cc.find_library('intl',
2693 has_headers: ['libintl.h'], required: nlsopt,
2694 header_include_directories: postgres_inc,
2700 i18n = import('i18n')
2701 cdata.set('ENABLE_NLS', 1)
2707 ###############################################################
2709 ###############################################################
2711 # Set up compiler / linker arguments to be used everywhere, individual targets
2712 # can add further args directly, or indirectly via dependencies
2713 add_project_arguments(cflags, language: ['c'])
2714 add_project_arguments(cppflags, language: ['c'])
2715 add_project_arguments(cflags_warn, language: ['c'])
2716 add_project_arguments(cxxflags, language: ['cpp'])
2717 add_project_arguments(cppflags, language: ['cpp'])
2718 add_project_arguments(cxxflags_warn, language: ['cpp'])
2719 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2722 # Collect a number of lists of things while recursing through the source
2723 # tree. Later steps then can use those.
2725 # list of targets for various alias targets
2726 backend_targets = []
2729 contrib_targets = []
2730 testprep_targets = []
2734 # Define the tests to distribute them to the correct test styles later
2739 # Default options for targets
2741 # First identify rpaths
2742 bin_install_rpaths = []
2743 lib_install_rpaths = []
2744 mod_install_rpaths = []
2747 # Don't add rpaths on darwin for now - as long as only absolute references to
2748 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2749 # their final destination.
2750 if host_system != 'darwin'
2751 # Add absolute path to libdir to rpath. This ensures installed binaries /
2752 # libraries find our libraries (mainly libpq).
2753 bin_install_rpaths += dir_prefix / dir_lib
2754 lib_install_rpaths += dir_prefix / dir_lib
2755 mod_install_rpaths += dir_prefix / dir_lib
2757 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2759 # Not needed on darwin even if we use relative rpaths for our own libraries,
2760 # as the install_name of libraries in extra_lib_dirs will point to their
2762 bin_install_rpaths += postgres_lib_d
2763 lib_install_rpaths += postgres_lib_d
2764 mod_install_rpaths += postgres_lib_d
2768 # Define arguments for default targets
2770 default_target_args = {
2771 'implicit_include_directories': false,
2775 default_lib_args = default_target_args + {
2779 internal_lib_args = default_lib_args + {
2780 'build_by_default': false,
2784 default_mod_args = default_lib_args + {
2786 'install_dir': dir_lib_pkg,
2789 default_bin_args = default_target_args + {
2790 'install_dir': dir_bin,
2793 if get_option('rpath')
2794 default_lib_args += {
2795 'install_rpath': ':'.join(lib_install_rpaths),
2798 default_mod_args += {
2799 'install_rpath': ':'.join(mod_install_rpaths),
2802 default_bin_args += {
2803 'install_rpath': ':'.join(bin_install_rpaths),
2808 # Helper for exporting a limited number of symbols
2809 gen_export_kwargs = {
2810 'input': 'exports.txt',
2811 'output': '@BASENAME@.'+export_file_suffix,
2812 'command': [perl, files('src/tools/gen_export.pl'),
2813 '--format', export_file_format,
2814 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2815 'build_by_default': false,
2822 ### Helpers for custom targets used across the tree
2825 catalog_pm = files('src/backend/catalog/Catalog.pm')
2826 perfect_hash_pm = files('src/tools/PerfectHash.pm')
2827 gen_kwlist_deps = [perfect_hash_pm]
2829 perl, '-I', '@SOURCE_ROOT@/src/tools',
2830 files('src/tools/gen_keywordlist.pl'),
2831 '--output', '@OUTDIR@', '@INPUT@']
2836 ### windows resources related stuff
2839 if host_system == 'windows'
2840 pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico'
2841 win32ver_rc = files('src/port/win32ver.rc')
2842 rcgen = find_program('src/tools/rcgen', native: true)
2845 '--srcdir', '@SOURCE_DIR@',
2846 '--builddir', meson.build_root(),
2847 '--rcout', '@OUTPUT0@',
2848 '--out', '@OUTPUT1@',
2849 '--input', '@INPUT@',
2853 if cc.get_argument_syntax() == 'msvc'
2854 rc = find_program('rc', required: true)
2855 rcgen_base_args += ['--rc', rc.path()]
2856 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.res']
2858 windres = find_program('windres', required: true)
2859 rcgen_base_args += ['--windres', windres.path()]
2860 rcgen_outputs = ['@BASENAME@.rc', '@BASENAME@.obj']
2863 # msbuild backend doesn't support this atm
2864 if meson.backend() == 'ninja'
2865 rcgen_base_args += ['--depfile', '@DEPFILE@']
2868 rcgen_bin_args = rcgen_base_args + [
2869 '--VFT_TYPE', 'VFT_APP',
2870 '--FILEENDING', 'exe',
2874 rcgen_lib_args = rcgen_base_args + [
2875 '--VFT_TYPE', 'VFT_DLL',
2876 '--FILEENDING', 'dll',
2879 rc_bin_gen = generator(rcgen,
2880 depfile: '@BASENAME@.d',
2881 arguments: rcgen_bin_args,
2882 output: rcgen_outputs,
2885 rc_lib_gen = generator(rcgen,
2886 depfile: '@BASENAME@.d',
2887 arguments: rcgen_lib_args,
2888 output: rcgen_outputs,
2894 # headers that the whole build tree depends on
2895 generated_headers = []
2896 # headers that the backend build depends on
2897 generated_backend_headers = []
2898 # configure_files() output, needs a way of converting to file names
2899 configure_files = []
2901 # generated files that might conflict with a partial in-tree autoconf build
2902 generated_sources = []
2903 # same, for paths that differ between autoconf / meson builds
2904 # elements are [dir, [files]]
2905 generated_sources_ac = {}
2908 # First visit src/include - all targets creating headers are defined
2909 # within. That makes it easy to add the necessary dependencies for the
2910 # subsequent build steps.
2912 subdir('src/include')
2916 # Then through src/port and src/common, as most other things depend on them
2918 frontend_port_code = declare_dependency(
2919 compile_args: ['-DFRONTEND'],
2920 include_directories: [postgres_inc],
2921 dependencies: os_deps,
2924 backend_port_code = declare_dependency(
2925 compile_args: ['-DBUILDING_DLL'],
2926 include_directories: [postgres_inc],
2927 sources: [errcodes], # errcodes.h is needed due to use of ereport
2928 dependencies: os_deps,
2933 frontend_common_code = declare_dependency(
2934 compile_args: ['-DFRONTEND'],
2935 include_directories: [postgres_inc],
2936 sources: generated_headers,
2937 dependencies: [os_deps, zlib, zstd],
2940 backend_common_code = declare_dependency(
2941 compile_args: ['-DBUILDING_DLL'],
2942 include_directories: [postgres_inc],
2943 sources: generated_headers,
2944 dependencies: [os_deps, zlib, zstd],
2947 subdir('src/common')
2949 # all shared libraries should depend on shlib_code
2950 shlib_code = declare_dependency(
2951 link_args: ldflags_sl,
2954 # all static libraries not part of the backend should depend on this
2955 frontend_stlib_code = declare_dependency(
2956 include_directories: [postgres_inc],
2957 link_with: [common_static, pgport_static],
2958 sources: generated_headers,
2959 dependencies: [os_deps, libintl],
2962 # all shared libraries not part of the backend should depend on this
2963 frontend_shlib_code = declare_dependency(
2964 include_directories: [postgres_inc],
2965 link_with: [common_shlib, pgport_shlib],
2966 sources: generated_headers,
2967 dependencies: [shlib_code, os_deps, libintl],
2970 # Dependencies both for static and shared libpq
2980 subdir('src/interfaces/libpq')
2981 # fe_utils depends on libpq
2982 subdir('src/fe_utils')
2984 # for frontend binaries
2985 frontend_code = declare_dependency(
2986 include_directories: [postgres_inc],
2987 link_with: [fe_utils, common_static, pgport_static],
2988 sources: generated_headers,
2989 dependencies: [os_deps, libintl],
2992 backend_both_deps += [
3009 backend_mod_deps = backend_both_deps + os_deps
3011 backend_code = declare_dependency(
3012 compile_args: ['-DBUILDING_DLL'],
3013 include_directories: [postgres_inc],
3014 link_args: ldflags_be,
3016 sources: generated_headers + generated_backend_headers,
3017 dependencies: os_deps + backend_both_deps + backend_deps,
3020 # install these files only during test, not main install
3021 test_install_data = []
3022 test_install_libs = []
3024 # src/backend/meson.build defines backend_mod_code used for extension
3028 # Then through the main sources. That way contrib can have dependencies on
3029 # main sources. Note that this explicitly doesn't enter src/test, right now a
3030 # few regression tests depend on contrib files.
3037 subdir('src/interfaces/libpq/test')
3038 subdir('src/interfaces/ecpg/test')
3040 subdir('doc/src/sgml')
3042 generated_sources_ac += {'': ['GNUmakefile']}
3044 # After processing src/test, add test_install_libs to the testprep_targets
3046 testprep_targets += test_install_libs
3049 # If there are any files in the source directory that we also generate in the
3050 # build directory, they might get preferred over the newly generated files,
3051 # e.g. because of a #include "file", which always will search in the current
3053 message('checking for file conflicts between source and build directory')
3054 conflicting_files = []
3055 potentially_conflicting_files_t = []
3056 potentially_conflicting_files_t += generated_headers
3057 potentially_conflicting_files_t += generated_backend_headers
3058 potentially_conflicting_files_t += generated_backend_sources
3059 potentially_conflicting_files_t += generated_sources
3061 potentially_conflicting_files = []
3063 # convert all sources of potentially conflicting files into uniform shape
3064 foreach t : potentially_conflicting_files_t
3065 potentially_conflicting_files += t.full_path()
3067 foreach t1 : configure_files
3068 if meson.version().version_compare('>=0.59')
3069 t = fs.parent(t1) / fs.name(t1)
3071 t = '@0@'.format(t1)
3073 potentially_conflicting_files += meson.current_build_dir() / t
3075 foreach sub, fnames : generated_sources_ac
3076 sub = meson.build_root() / sub
3077 foreach fname : fnames
3078 potentially_conflicting_files += sub / fname
3082 # find and report conflicting files
3083 foreach build_path : potentially_conflicting_files
3084 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
3085 # str.replace is in 0.56
3086 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
3087 if fs.exists(src_path) or fs.is_symlink(src_path)
3088 conflicting_files += src_path
3091 # XXX: Perhaps we should generate a file that would clean these up? The list
3093 if conflicting_files.length() > 0
3094 errmsg_cleanup = '''
3095 Conflicting files in source directory:
3098 The conflicting files need to be removed, either by removing the files listed
3099 above, or by running configure and then make maintainer-clean.
3101 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
3102 error(errmsg_nonclean_base.format(errmsg_cleanup))
3107 ###############################################################
3109 ###############################################################
3112 # We want to define additional install targets beyond what meson provides. For
3113 # that we need to define targets depending on nearly everything. We collected
3114 # the results of i18n.gettext() invocations into nls_targets, that also
3115 # includes maintainer targets though. Collect the ones we want as a dependency.
3117 # i18n.gettext() doesn't return the dependencies before 0.60 - but the gettext
3118 # generation happens during install, so that's not a real issue.
3120 if libintl.found() and meson.version().version_compare('>=0.60')
3121 # use range() to avoid the flattening of the list that foreach() would do
3122 foreach off : range(0, nls_targets.length())
3123 # i18n.gettext() list containing 1) list of built .mo files 2) maintainer
3124 # -pot target 3) maintainer -pot target
3125 nls_mo_targets += nls_targets[off][0]
3127 alias_target('nls', nls_mo_targets)
3142 # Meson's default install target is quite verbose. Provide one that is quiet.
3143 install_quiet = custom_target('install-quiet',
3144 output: 'install-quiet',
3145 build_always_stale: true,
3146 build_by_default: false,
3147 command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'],
3151 # Target to install files used for tests, which aren't installed by default
3152 install_test_files_args = [
3154 '--prefix', dir_prefix,
3155 '--install', contrib_data_dir, test_install_data,
3156 '--install', dir_lib_pkg, test_install_libs,
3158 run_target('install-test-files',
3159 command: [python] + install_test_files_args,
3160 depends: testprep_targets,
3165 ###############################################################
3167 ###############################################################
3169 # DESTDIR for the installation we'll run tests in
3170 test_install_destdir = meson.build_root() / 'tmp_install/'
3172 # DESTDIR + prefix appropriately munged
3173 if build_system != 'windows'
3174 # On unixoid systems this is trivial, we just prepend the destdir
3175 assert(dir_prefix.startswith('/')) # enforced by meson
3176 test_install_location = '@0@@1@'.format(test_install_destdir, dir_prefix)
3178 # drives, drive-relative paths, etc make this complicated on windows, call
3179 # into a copy of meson's logic for it
3182 'import sys; from pathlib import PurePath; d1=sys.argv[1]; d2=sys.argv[2]; print(str(PurePath(d1, *PurePath(d2).parts[1:])))',
3183 test_install_destdir, dir_prefix]
3184 test_install_location = run_command(command, check: true).stdout().strip()
3187 meson_install_args = meson_args + ['install'] + {
3188 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
3192 # setup tests should be run first,
3193 # so define priority for these
3194 setup_tests_priority = 100
3196 meson_bin, args: meson_install_args ,
3197 env: {'DESTDIR':test_install_destdir},
3198 priority: setup_tests_priority,
3203 test('install_test_files',
3205 args: install_test_files_args + ['--destdir', test_install_destdir],
3206 priority: setup_tests_priority,
3210 test_result_dir = meson.build_root() / 'testrun'
3213 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
3214 # inevitable conflicts from running tests in parallel, hackishly assign
3215 # different ports for different tests.
3219 test_env = environment()
3221 temp_install_bindir = test_install_location / get_option('bindir')
3222 test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template'
3223 test_env.set('PG_REGRESS', pg_regress.full_path())
3224 test_env.set('REGRESS_SHLIB', regress_module.full_path())
3225 test_env.set('INITDB_TEMPLATE', test_initdb_template)
3227 # Test suites that are not safe by default but can be run if selected
3228 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
3229 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
3230 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
3232 # Add the temporary installation to the library search path on platforms where
3233 # that works (everything but windows, basically). On windows everything
3234 # library-like gets installed into bindir, solving that issue.
3235 if library_path_var != ''
3236 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
3240 # Create (and remove old) initdb template directory. Tests use that, where
3241 # possible, to make it cheaper to run tests.
3243 # Use python to remove the old cached initdb, as we cannot rely on a working
3244 # 'rm' binary on windows.
3245 test('initdb_cache',
3253 shutil.rmtree(sys.argv[1], ignore_errors=True)
3254 sp = subprocess.run(sys.argv[2:] + [sys.argv[1]])
3255 sys.exit(sp.returncode)
3257 test_initdb_template,
3258 temp_install_bindir / 'initdb',
3259 '--auth', 'trust', '--no-sync', '--no-instructions', '--lc-messages=C',
3262 priority: setup_tests_priority - 1,
3270 ###############################################################
3272 ###############################################################
3274 # When using a meson version understanding exclude_suites, define a
3275 # 'tmp_install' test setup (the default) that excludes tests running against a
3276 # pre-existing install and a 'running' setup that conflicts with creation of
3277 # the temporary installation and tap tests (which don't support running
3278 # against a running server).
3282 if meson.version().version_compare('>=0.57')
3285 runningcheck = false
3288 testwrap = files('src/tools/testwrap')
3290 foreach test_dir : tests
3293 '--basedir', meson.build_root(),
3294 '--srcdir', test_dir['sd'],
3297 foreach kind, v : test_dir
3298 if kind in ['sd', 'bd', 'name']
3304 if kind in ['regress', 'isolation', 'ecpg']
3305 if kind == 'regress'
3307 fallback_dbname = 'regression_@0@'
3308 elif kind == 'isolation'
3309 runner = pg_isolation_regress
3310 fallback_dbname = 'isolation_regression_@0@'
3312 runner = pg_regress_ecpg
3313 fallback_dbname = 'ecpg_regression_@0@'
3316 test_group = test_dir['name']
3317 test_group_running = test_dir['name'] + '-running'
3319 test_output = test_result_dir / test_group / kind
3320 test_output_running = test_result_dir / test_group_running/ kind
3322 # Unless specified by the test, choose a non-conflicting database name,
3323 # to avoid conflicts when running against existing server.
3324 dbname = t.get('dbname',
3325 fallback_dbname.format(test_dir['name']))
3327 test_command_base = [
3329 '--inputdir', t.get('inputdir', test_dir['sd']),
3330 '--expecteddir', t.get('expecteddir', test_dir['sd']),
3332 '--dlpath', test_dir['bd'],
3333 '--max-concurrent-tests=20',
3335 ] + t.get('regress_args', [])
3338 if t.has_key('schedule')
3339 test_selection += ['--schedule', t['schedule'],]
3342 if kind == 'isolation'
3343 test_selection += t.get('specs', [])
3345 test_selection += t.get('sql', [])
3349 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
3355 'depends': test_deps + t.get('deps', []),
3357 } + t.get('test_kwargs', {})
3359 test(test_group / kind,
3363 '--testgroup', test_group,
3367 '--outputdir', test_output,
3368 '--temp-instance', test_output / 'tmp_check',
3369 '--port', testport.to_string(),
3373 kwargs: test_kwargs,
3375 install_suites += test_group
3377 # some tests can't support running against running DB
3378 if runningcheck and t.get('runningcheck', true)
3379 test(test_group_running / kind,
3383 '--testgroup', test_group_running,
3387 '--outputdir', test_output_running,
3390 is_parallel: t.get('runningcheck-parallel', true),
3391 suite: test_group_running,
3392 kwargs: test_kwargs,
3394 running_suites += test_group_running
3399 testwrap_tap = testwrap_base
3400 if not tap_tests_enabled
3401 testwrap_tap += ['--skip', 'TAP tests not enabled']
3406 '-I', meson.source_root() / 'src/test/perl',
3407 '-I', test_dir['sd'],
3410 # Add temporary install, the build directory for non-installed binaries and
3411 # also test/ for non-installed test binaries built separately.
3413 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
3415 foreach name, value : t.get('env', {})
3416 env.set(name, value)
3419 test_group = test_dir['name']
3422 'suite': test_group,
3424 'depends': test_deps + t.get('deps', []),
3426 } + t.get('test_kwargs', {})
3428 foreach onetap : t['tests']
3429 # Make tap test names prettier, remove t/ and .pl
3431 if onetap_p.startswith('t/')
3432 onetap_p = onetap.split('t/')[1]
3434 if onetap_p.endswith('.pl')
3435 onetap_p = fs.stem(onetap_p)
3438 test(test_dir['name'] / onetap_p,
3440 kwargs: test_kwargs,
3441 args: testwrap_tap + [
3442 '--testgroup', test_dir['name'],
3443 '--testname', onetap_p,
3445 test_dir['sd'] / onetap,
3449 install_suites += test_group
3451 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
3454 endforeach # kinds of tests
3456 endforeach # directories with tests
3458 # repeat condition so meson realizes version dependency
3459 if meson.version().version_compare('>=0.57')
3460 add_test_setup('tmp_install',
3462 exclude_suites: running_suites)
3463 add_test_setup('running',
3464 exclude_suites: ['setup'] + install_suites)
3469 ###############################################################
3471 ###############################################################
3473 alias_target('backend', backend_targets)
3474 alias_target('bin', bin_targets + [libpq_st])
3475 alias_target('pl', pl_targets)
3476 alias_target('contrib', contrib_targets)
3477 alias_target('testprep', testprep_targets)
3479 alias_target('world', all_built, docs)
3480 alias_target('install-world', install_quiet, installdocs)
3484 perl, '-ne', 'next if /^#/; print',
3485 files('doc/src/sgml/targets-meson.txt'),
3491 ###############################################################
3492 # Distribution archive
3493 ###############################################################
3495 # Meson has its own distribution building command (meson dist), but we
3496 # are not using that at this point. The main problem is that, the way
3497 # they have implemented it, it is not deterministic. Also, we want it
3498 # to be equivalent to the "make" version for the time being. But the
3499 # target name "dist" in meson is reserved for that reason, so we call
3500 # the custom target "pgdist".
3502 git = find_program('git', required: false, native: true, disabler: true)
3503 bzip2 = find_program('bzip2', required: false, native: true)
3505 distdir = meson.project_name() + '-' + meson.project_version()
3507 pg_git_revision = get_option('PG_GIT_REVISION')
3509 # Note: core.autocrlf=false is needed to avoid line-ending conversion
3510 # in case the environment has a different setting. Without this, a
3511 # tarball created on Windows might be different than on, and unusable
3512 # on, Unix machines.
3514 tar_gz = custom_target('tar.gz',
3515 build_always_stale: true,
3516 command: [git, '-C', '@SOURCE_ROOT@',
3517 '-c', 'core.autocrlf=false',
3519 '--format', 'tar.gz',
3521 '--prefix', distdir + '/',
3522 '-o', join_paths(meson.build_root(), '@OUTPUT@'),
3524 output: distdir + '.tar.gz',
3528 tar_bz2 = custom_target('tar.bz2',
3529 build_always_stale: true,
3530 command: [git, '-C', '@SOURCE_ROOT@',
3531 '-c', 'core.autocrlf=false',
3532 '-c', 'tar.tar.bz2.command="@0@" -c'.format(bzip2.path()),
3534 '--format', 'tar.bz2',
3535 '--prefix', distdir + '/',
3536 '-o', join_paths(meson.build_root(), '@OUTPUT@'),
3538 output: distdir + '.tar.bz2',
3541 tar_bz2 = custom_target('tar.bz2',
3542 command: [perl, '-e', 'exit 1'],
3543 output: distdir + '.tar.bz2',
3547 alias_target('pgdist', [tar_gz, tar_bz2])
3549 # Make the standard "dist" command fail, to prevent accidental use.
3550 # But not if we are in a subproject, in case the parent project wants to
3551 # create a dist using the standard Meson command.
3552 if not meson.is_subproject()
3553 # We can only pass the identifier perl here when we depend on >= 0.55
3554 if meson.version().version_compare('>=0.55')
3555 meson.add_dist_script(perl, '-e', 'exit 1')
3561 ###############################################################
3562 # The End, The End, My Friend
3563 ###############################################################
3565 if meson.version().version_compare('>=0.57')
3569 'data block size': '@0@ kB'.format(cdata.get('BLCKSZ') / 1024),
3570 'WAL block size': '@0@ kB'.format(cdata.get('XLOG_BLCKSZ') / 1024),
3571 'segment size': get_option('segsize_blocks') != 0 ?
3572 '@0@ blocks'.format(cdata.get('RELSEG_SIZE')) :
3573 '@0@ GB'.format(get_option('segsize')),
3575 section: 'Data layout',
3580 'host system': '@0@ @1@'.format(host_system, host_cpu),
3581 'build system': '@0@ @1@'.format(build_machine.system(),
3582 build_machine.cpu_family()),
3589 'linker': '@0@'.format(cc.get_linker_id()),
3590 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
3592 section: 'Compiler',
3597 'CPP FLAGS': ' '.join(cppflags),
3598 'C FLAGS, functional': ' '.join(cflags),
3599 'C FLAGS, warnings': ' '.join(cflags_warn),
3600 'C FLAGS, modules': ' '.join(cflags_mod),
3601 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3602 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3604 section: 'Compiler Flags',
3610 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3612 section: 'Compiler',
3617 'C++ FLAGS, functional': ' '.join(cxxflags),
3618 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3619 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3621 section: 'Compiler Flags',
3627 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3629 'flex': '@0@ @1@'.format(flex.full_path(), flex_version),
3631 section: 'Programs',
3637 'bsd_auth': bsd_auth,
3639 'docs_pdf': docs_pdf_dep,
3651 'plpython': python3_dep,
3653 'readline': readline,
3660 section: 'External libraries',