1 # Entry point for building PostgreSQL with meson
3 # Good starting points for writing meson.build files are:
4 # - https://mesonbuild.com/Syntax.html
5 # - https://mesonbuild.com/Reference-manual.html
10 license: 'PostgreSQL',
12 # We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for
13 # RHEL 7 has 0.55. < 0.54 would require replacing some uses of the fs
14 # module, < 0.53 all uses of fs. So far there's no need to go to >=0.56.
15 meson_version: '>=0.54',
17 'warning_level=1', #-Wall equivalent
19 # For compatibility with the autoconf build, set a default prefix. This
20 # works even on windows, where it's a drive-relative path (i.e. when on
21 # d:/sompath it'll install to d:/usr/local/pgsql)
22 'prefix=/usr/local/pgsql',
28 ###############################################################
30 ###############################################################
33 pkgconfig = import('pkgconfig')
35 host_system = host_machine.system()
36 build_system = build_machine.system()
37 host_cpu = host_machine.cpu_family()
39 cc = meson.get_compiler('c')
41 not_found_dep = dependency('', required: false)
42 thread_dep = dependency('threads')
46 ###############################################################
48 ###############################################################
50 # It's very easy to get into confusing states when the source directory
51 # contains an in-place build. E.g. the wrong pg_config.h will be used. So just
52 # refuse to build in that case.
54 # There's a more elaborate check later, that checks for conflicts around all
55 # generated files. But we can only do that much further down the line, so this
56 # quick check seems worth it. Adhering to this advice should clean up the
57 # conflict, but won't protect against somebody doing make distclean or just
58 # removing pg_config.h
59 errmsg_nonclean_base = '''
61 Non-clean source code directory detected.
63 To build with meson the source tree may not have an in-place, ./configure
64 style, build configured. You can have both meson and ./configure style builds
65 for the same source tree by building out-of-source / VPATH with
66 configure. Alternatively use a separate check out for meson based builds.
70 if fs.exists(meson.current_source_dir() / 'src' / 'include' / 'pg_config.h')
71 errmsg_cleanup = 'To clean up, run make maintainer-clean in the source tree.'
72 error(errmsg_nonclean_base.format(errmsg_cleanup))
77 ###############################################################
78 # Variables to be determined
79 ###############################################################
81 postgres_inc_d = ['src/include']
82 postgres_inc_d += get_option('extra_include_dirs')
84 postgres_lib_d = get_option('extra_lib_dirs')
103 backend_both_deps = []
109 # source of data for pg_config.h etc
110 cdata = configuration_data()
114 ###############################################################
115 # Version and other metadata
116 ###############################################################
118 pg_version = meson.project_version()
120 if pg_version.endswith('devel')
121 pg_version_arr = [pg_version.split('devel')[0], '0']
122 elif pg_version.contains('beta')
123 pg_version_arr = [pg_version.split('beta')[0], '0']
124 elif pg_version.contains('rc')
125 pg_version_arr = [pg_version.split('rc')[0], '0']
127 pg_version_arr = pg_version.split('.')
130 pg_version_major = pg_version_arr[0].to_int()
131 pg_version_minor = pg_version_arr[1].to_int()
132 pg_version_num = (pg_version_major * 10000) + pg_version_minor
134 pg_url = 'https://www.postgresql.org/'
136 cdata.set_quoted('PACKAGE_NAME', 'PostgreSQL')
137 cdata.set_quoted('PACKAGE_BUGREPORT', 'pgsql-bugs@lists.postgresql.org')
138 cdata.set_quoted('PACKAGE_URL', pg_url)
139 cdata.set_quoted('PACKAGE_VERSION', pg_version)
140 cdata.set_quoted('PACKAGE_STRING', 'PostgreSQL @0@'.format(pg_version))
141 cdata.set_quoted('PACKAGE_TARNAME', 'postgresql')
143 pg_version += get_option('extra_version')
144 cdata.set_quoted('PG_VERSION', pg_version)
145 cdata.set_quoted('PG_VERSION_STR', 'PostgreSQL @0@ on @1@, compiled by @2@-@3@'.format(
146 pg_version, build_machine.cpu_family(), cc.get_id(), cc.version()))
147 cdata.set_quoted('PG_MAJORVERSION', pg_version_major.to_string())
148 cdata.set('PG_MAJORVERSION_NUM', pg_version_major)
149 cdata.set('PG_MINORVERSION_NUM', pg_version_minor)
150 cdata.set('PG_VERSION_NUM', pg_version_num)
151 cdata.set_quoted('CONFIGURE_ARGS', '')
155 ###############################################################
156 # Basic platform specific configuration
157 ###############################################################
159 # meson's system names don't quite map to our "traditional" names. In some
160 # places we need the "traditional" name, e.g., for mapping
161 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
163 portname = host_system
165 exesuffix = '' # overridden below where necessary
166 dlsuffix = '.so' # overridden below where necessary
167 library_path_var = 'LD_LIBRARY_PATH'
169 # Format of file to control exports from libraries, and how to pass them to
170 # the compiler. For export_fmt @0@ is the path to the file export file.
171 export_file_format = 'gnu'
172 export_file_suffix = 'list'
173 export_fmt = '-Wl,--version-script=@0@'
175 # Flags to add when linking a postgres extension, @0@ is path to
176 # the relevant object on the platform.
177 mod_link_args_fmt = []
179 memset_loop_limit = 1024
181 # Choice of shared memory and semaphore implementation
185 # We implement support for some operating systems by pretending they're
186 # another. Map here, before determining system properties below
187 if host_system == 'dragonfly'
188 # apparently the most similar
189 host_system = 'netbsd'
192 if host_system == 'aix'
193 library_path_var = 'LIBPATH'
195 export_file_format = 'aix'
196 export_fmt = '-Wl,-bE:@0@'
197 mod_link_args_fmt = ['-Wl,-bI:@0@']
198 mod_link_with_dir = 'libdir'
199 mod_link_with_name = '@0@.imp'
201 # M:SRE sets a flag indicating that an object is a shared library. Seems to
202 # work in some circumstances without, but required in others.
203 ldflags_sl += '-Wl,-bM:SRE'
204 ldflags_be += '-Wl,-brtllib'
206 # Native memset() is faster, tested on:
207 # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
208 # - AIX 5.3 ML3, gcc 4.0.1
209 memset_loop_limit = 0
211 elif host_system == 'cygwin'
212 cppflags += '-D_GNU_SOURCE'
214 elif host_system == 'darwin'
216 library_path_var = 'DYLD_LIBRARY_PATH'
218 export_file_format = 'darwin'
219 export_fmt = '-exported_symbols_list=@0@'
221 mod_link_args_fmt = ['-bundle_loader', '@0@']
222 mod_link_with_dir = 'bindir'
223 mod_link_with_name = '@0@'
225 sysroot_args = [files('src/tools/darwin_sysroot'), get_option('darwin_sysroot')]
226 pg_sysroot = run_command(sysroot_args, check:true).stdout().strip()
227 message('darwin sysroot: @0@'.format(pg_sysroot))
228 cflags += ['-isysroot', pg_sysroot]
229 ldflags += ['-isysroot', pg_sysroot]
231 elif host_system == 'freebsd'
232 sema_kind = 'unnamed_posix'
234 elif host_system == 'linux'
235 sema_kind = 'unnamed_posix'
236 cppflags += '-D_GNU_SOURCE'
238 elif host_system == 'netbsd'
239 # We must resolve all dynamic linking in the core server at program start.
240 # Otherwise the postmaster can self-deadlock due to signals interrupting
241 # resolution of calls, since NetBSD's linker takes a lock while doing that
242 # and some postmaster signal handlers do things that will also acquire that
243 # lock. As long as we need "-z now", might as well specify "-z relro" too.
244 # While there's not a hard reason to adopt these settings for our other
245 # executables, there's also little reason not to, so just add them to
247 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
249 elif host_system == 'openbsd'
252 elif host_system == 'sunos'
254 export_fmt = '-Wl,-M@0@'
255 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
257 elif host_system == 'windows'
261 library_path_var = ''
263 export_file_format = 'win'
264 export_file_suffix = 'def'
265 if cc.get_id() == 'msvc'
266 export_fmt = '/DEF:@0@'
267 mod_link_with_name = '@0@.exe.lib'
270 mod_link_with_name = 'lib@0@.exe.a'
272 mod_link_args_fmt = ['@0@']
273 mod_link_with_dir = 'libdir'
278 cdata.set('WIN32_STACK_RLIMIT', 4194304)
279 if cc.get_id() == 'msvc'
280 ldflags += '/INCREMENTAL:NO'
281 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
282 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
284 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
285 # Need to allow multiple definitions, we e.g. want to override getopt.
286 ldflags += '-Wl,--allow-multiple-definition'
287 # Ensure we get MSVC-like linking behavior.
288 ldflags += '-Wl,--disable-auto-import'
291 os_deps += cc.find_library('ws2_32', required: true)
292 secur32_dep = cc.find_library('secur32', required: true)
293 backend_deps += secur32_dep
294 libpq_deps += secur32_dep
296 postgres_inc_d += 'src/include/port/win32'
297 if cc.get_id() == 'msvc'
298 postgres_inc_d += 'src/include/port/win32_msvc'
301 windows = import('windows')
304 # XXX: Should we add an option to override the host_system as an escape
306 error('unknown host system: @0@'.format(host_system))
311 ###############################################################
313 ###############################################################
316 perl = find_program(get_option('PERL'), required: true, native: true)
317 python = find_program(get_option('PYTHON'), required: true, native: true)
318 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.31')
319 bison = find_program(get_option('BISON'), native: true, version: '>= 1.875')
320 sed = find_program(get_option('SED'), 'sed', native: true)
321 prove = find_program(get_option('PROVE'), native: true)
322 tar = find_program(get_option('TAR'), native: true)
323 gzip = find_program(get_option('GZIP'), native: true)
324 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
325 touch = find_program('touch', native: true)
326 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
327 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
328 missing = find_program('config/missing', native: true)
331 install_sh = find_program('config/install-sh', native: true)
335 bison_version_c = run_command(bison, '--version', check: true)
336 # bison version string helpfully is something like
337 # >>bison (GNU bison) 3.8.1<<
338 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
339 if bison_version.version_compare('>=3.0')
340 bison_flags += ['-Wno-deprecated']
343 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
345 'output': ['@BASENAME@.c', '@BASENAME@.h'],
346 'command': bison_cmd,
350 flex_wrapper = files('src/tools/pgflex')
351 flex_cmd = [python, flex_wrapper,
352 '--builddir', '@BUILD_ROOT@',
353 '--srcdir', '@SOURCE_ROOT@',
354 '--privatedir', '@PRIVATE_DIR@',
355 '--flex', flex, '--perl', perl,
356 '-i', '@INPUT@', '-o', '@OUTPUT0@',
359 wget = find_program('wget', required: false, native: true)
360 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
364 ###############################################################
365 # Path to meson (for tests etc)
366 ###############################################################
368 # NB: this should really be part of meson, see
369 # https://github.com/mesonbuild/meson/issues/8511
370 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
372 if meson_binpath_r.returncode() != 0 or meson_binpath_r.stdout() == ''
373 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
374 meson_binpath_r.returncode(),
375 meson_binpath_r.stdout(),
376 meson_binpath_r.stderr()))
379 meson_binpath_s = meson_binpath_r.stdout().split('\n')
380 meson_binpath_len = meson_binpath_s.length()
382 if meson_binpath_len < 1
383 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
390 foreach e : meson_binpath_s
401 if meson_impl not in ['muon', 'meson']
402 error('unknown meson implementation "@0@"'.format(meson_impl))
405 meson_bin = find_program(meson_binpath, native: true)
409 ###############################################################
411 ###############################################################
413 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
415 cdata.set('BLCKSZ', get_option('blocksize').to_int() * 1024, description:
416 '''Size of a disk block --- this also limits the size of a tuple. You can set
417 it bigger if you need bigger tuples (although TOAST should reduce the need
418 to have large tuples, since fields can be spread across multiple tuples).
419 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
420 currently 2^15 (32768). This is determined by the 15-bit widths of the
421 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
422 Changing BLCKSZ requires an initdb.''')
424 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
425 cdata.set('RELSEG_SIZE', get_option('segsize') * 131072)
426 cdata.set('DEF_PGPORT', get_option('pgport'))
427 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
428 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
429 if get_option('system_tzdata') != ''
430 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
435 ###############################################################
437 ###############################################################
439 # These are set by the equivalent --xxxdir configure options. We
440 # append "postgresql" to some of them, if the string does not already
441 # contain "pgsql" or "postgres", in order to avoid directory clutter.
445 dir_prefix = get_option('prefix')
447 dir_bin = get_option('bindir')
449 dir_data = get_option('datadir')
450 if not (dir_data.contains('pgsql') or dir_data.contains('postgres'))
451 dir_data = dir_data / pkg
454 dir_sysconf = get_option('sysconfdir')
455 if not (dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
456 dir_sysconf = dir_sysconf / pkg
459 dir_lib = get_option('libdir')
461 dir_lib_pkg = dir_lib
462 if not (dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
463 dir_lib_pkg = dir_lib_pkg / pkg
466 dir_pgxs = dir_lib_pkg / 'pgxs'
468 dir_include = get_option('includedir')
470 dir_include_pkg = dir_include
471 dir_include_pkg_rel = ''
472 if not (dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
473 dir_include_pkg = dir_include_pkg / pkg
474 dir_include_pkg_rel = pkg
477 dir_man = get_option('mandir')
479 # FIXME: These used to be separately configurable - worth adding?
480 dir_doc = get_option('datadir') / 'doc' / 'postgresql'
481 dir_doc_html = dir_doc
483 dir_locale = get_option('localedir')
487 dir_bitcode = dir_lib_pkg / 'bitcode'
488 dir_include_internal = dir_include_pkg / 'internal'
489 dir_include_server = dir_include_pkg / 'server'
490 dir_include_extension = dir_include_server / 'extension'
491 dir_data_extension = dir_data / 'extension'
495 ###############################################################
496 # Search paths, preparation for compiler tests
498 # NB: Arguments added later are not automatically used for subsequent
499 # configuration-time checks (so they are more isolated). If they should be
500 # used, they need to be added to test_c_args as well.
501 ###############################################################
503 postgres_inc = [include_directories(postgres_inc_d)]
504 test_lib_d = postgres_lib_d
505 test_c_args = cppflags + cflags
509 ###############################################################
511 ###############################################################
513 bsd_authopt = get_option('bsd_auth')
514 bsd_auth = not_found_dep
515 if cc.check_header('bsd_auth.h', required: bsd_authopt,
516 args: test_c_args, include_directories: postgres_inc)
517 cdata.set('USE_BSD_AUTH', 1)
518 bsd_auth = declare_dependency()
523 ###############################################################
526 # For now don't search for DNSServiceRegister in a library - only Apple's
527 # Bonjour implementation, which is always linked, works.
528 ###############################################################
530 bonjouropt = get_option('bonjour')
531 bonjour = dependency('', required : false)
532 if cc.check_header('dns_sd.h', required: bonjouropt,
533 args: test_c_args, include_directories: postgres_inc) and \
534 cc.has_function('DNSServiceRegister',
535 args: test_c_args, include_directories: postgres_inc)
536 cdata.set('USE_BONJOUR', 1)
537 bonjour = declare_dependency()
542 ###############################################################
544 ###############################################################
546 gssapiopt = get_option('gssapi')
549 if not gssapiopt.disabled()
550 gssapi = dependency('krb5-gssapi', required: gssapiopt)
551 have_gssapi = gssapi.found()
554 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
555 args: test_c_args, include_directories: postgres_inc)
556 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
557 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
558 cdata.set('HAVE_GSSAPI_H', 1)
564 elif cc.has_function('gss_init_sec_context', dependencies: gssapi,
565 args: test_c_args, include_directories: postgres_inc)
566 cdata.set('ENABLE_GSS', 1)
568 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
569 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
570 elif gssapiopt.enabled()
571 error('''could not find function 'gss_init_sec_context' required for GSSAPI''')
577 gssapi = not_found_dep
582 ###############################################################
584 ###############################################################
586 ldapopt = get_option('ldap')
587 if ldapopt.disabled()
589 ldap_r = not_found_dep
590 elif host_system == 'windows'
591 ldap = cc.find_library('wldap32', required: ldapopt)
594 # macos framework dependency is buggy for ldap (one can argue whether it's
595 # Apple's or meson's fault), leading to an endless recursion with ldap.h
596 # including itself. See https://github.com/mesonbuild/meson/issues/10002
597 # Luckily we only need pkg-config support, so the workaround isn't
599 ldap = dependency('ldap', method: 'pkg-config', required: false)
602 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
605 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
606 has_headers: 'ldap.h', header_include_directories: postgres_inc)
608 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
609 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
610 # library from a separate OpenLDAP installation). The most reliable
611 # way to check that is to check for a function introduced in 2.5.
613 # don't have ldap, we shouldn't check for ldap_r
614 elif cc.has_function('ldap_verify_credentials',
615 dependencies: ldap, args: test_c_args)
616 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
619 # Use ldap_r for FE if available, else assume ldap is thread-safe.
620 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
621 has_headers: 'ldap.h', header_include_directories: postgres_inc)
622 if not ldap_r.found()
625 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
626 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
629 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
630 # process. Check for OpenLDAP versions known not to tolerate doing so;
631 # assume non-OpenLDAP implementations are safe. The dblink test suite
632 # exercises the hazardous interaction directly.
633 compat_test_code = '''
635 #if !defined(LDAP_VENDOR_VERSION) || \
636 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
637 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
641 if not cc.compiles(compat_test_code,
642 name: 'LDAP implementation compatible',
643 dependencies: ldap, args: test_c_args)
645 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
646 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
647 *** also uses LDAP will crash on exit.''')
652 # XXX: this shouldn't be tested in the windows case, but should be tested in
653 # the dependency() success case
654 if ldap.found() and cc.has_function('ldap_initialize',
655 dependencies: ldap, args: test_c_args)
656 cdata.set('HAVE_LDAP_INITIALIZE', 1)
661 assert(ldap_r.found())
662 cdata.set('USE_LDAP', 1)
664 assert(not ldap_r.found())
669 ###############################################################
671 ###############################################################
673 llvmopt = get_option('llvm')
674 if not llvmopt.disabled()
675 add_languages('cpp', required: true, native: false)
676 llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
680 cdata.set('USE_LLVM', 1)
682 cpp = meson.get_compiler('cpp')
684 llvm_binpath = llvm.get_variable(configtool: 'bindir')
686 ccache = find_program('ccache', native: true, required: false)
687 clang = find_program(llvm_binpath / 'clang', required: true)
695 ###############################################################
697 ###############################################################
699 icuopt = get_option('icu')
700 if not icuopt.disabled()
701 icu = dependency('icu-uc', required: icuopt.enabled())
702 icu_i18n = dependency('icu-i18n', required: icuopt.enabled())
705 cdata.set('USE_ICU', 1)
710 icu_i18n = not_found_dep
715 ###############################################################
717 ###############################################################
719 libxmlopt = get_option('libxml')
720 if not libxmlopt.disabled()
721 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
724 cdata.set('USE_LIBXML', 1)
727 libxml = not_found_dep
732 ###############################################################
734 ###############################################################
736 libxsltopt = get_option('libxslt')
737 if not libxsltopt.disabled()
738 libxslt = dependency('libxslt', required: libxsltopt)
741 cdata.set('USE_LIBXSLT', 1)
744 libxslt = not_found_dep
749 ###############################################################
751 ###############################################################
753 lz4opt = get_option('lz4')
754 if not lz4opt.disabled()
755 lz4 = dependency('liblz4', required: lz4opt)
758 cdata.set('USE_LZ4', 1)
759 cdata.set('HAVE_LIBLZ4', 1)
768 ###############################################################
769 # Library: Tcl (for pltcl)
771 # NB: tclConfig.sh is used in autoconf build for getting
772 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
773 # variables. For now we have not seen a need to copy
774 # that behaviour to the meson build.
775 ###############################################################
777 tclopt = get_option('pltcl')
778 tcl_version = get_option('tcl_version')
779 tcl_dep = not_found_dep
780 if not tclopt.disabled()
783 tcl_dep = dependency(tcl_version, required: false)
785 if not tcl_dep.found()
786 tcl_dep = cc.find_library(tcl_version,
791 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
792 tcl_dep = not_found_dep
798 ###############################################################
800 ###############################################################
802 pamopt = get_option('pam')
803 if not pamopt.disabled()
804 pam = dependency('pam', required: false)
807 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
811 pam_header_found = false
813 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
814 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
815 args: test_c_args, include_directories: postgres_inc)
816 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
817 pam_header_found = true
818 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
819 args: test_c_args, include_directories: postgres_inc)
820 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
821 pam_header_found = true
825 cdata.set('USE_PAM', 1)
836 ###############################################################
837 # Library: Perl (for plperl)
838 ###############################################################
840 perlopt = get_option('plperl')
841 perl_dep = not_found_dep
842 if not perlopt.disabled()
845 # First verify that perl has the necessary dependencies installed
846 perl_mods = run_command(
848 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
851 if perl_mods.returncode() != 0
852 perl_may_work = false
853 perl_msg = 'perl installation does not have the required modules'
856 # Then inquire perl about its configuration
858 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
859 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
860 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
861 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
862 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
864 perl_inc_dir = '@0@/CORE'.format(archlibexp)
866 if useshrplib != 'true'
867 perl_may_work = false
868 perl_msg = 'need a shared perl'
873 # On most platforms, archlibexp is also where the Perl include files live ...
874 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
875 # ... but on newer macOS versions, we must use -iwithsysroot to look
877 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
878 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
879 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
882 # check compiler finds header
883 if not cc.has_header('perl.h', required: false,
884 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
885 perl_may_work = false
886 perl_msg = 'missing perl.h'
891 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
893 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
894 foreach flag : perl_ccflags_r.split(' ')
895 if flag.startswith('-D') and \
896 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
901 if host_system == 'windows'
902 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
905 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
906 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
908 # We are after Embed's ldopts, but without the subset mentioned in
909 # Config's ccdlflags and ldflags. (Those are the choices of those who
910 # built the Perl installation, which are not necessarily appropriate
911 # for building PostgreSQL.)
912 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
913 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
914 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
917 foreach ldopt : ldopts.split(' ')
918 if ldopt == '' or ldopt in undesired
922 perl_ldopts += ldopt.strip('"')
925 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
926 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
928 perl_dep_int = declare_dependency(
929 compile_args: perl_ccflags,
930 link_args: perl_ldopts,
931 version: perlversion,
934 # While we're at it, check that we can link to libperl.
935 # On most platforms, if perl.h is there then libperl.so will be too, but
936 # at this writing Debian packages them separately.
940 #define __inline__ inline
948 if not cc.links(perl_link_test, name: 'libperl',
949 args: test_c_args + perl_ccflags + perl_ldopts,
950 include_directories: postgres_inc)
951 perl_may_work = false
952 perl_msg = 'missing libperl'
955 endif # perl_may_work
958 perl_dep = perl_dep_int
961 error('dependency plperl failed: @0@'.format(perl_msg))
963 message('disabling optional dependency plperl: @0@'.format(perl_msg))
970 ###############################################################
971 # Library: Python (for plpython)
972 ###############################################################
974 pyopt = get_option('plpython')
975 if not pyopt.disabled()
976 pm = import('python')
977 python3_inst = pm.find_installation(required: pyopt.enabled())
978 python3_dep = python3_inst.dependency(embed: true, required: pyopt.enabled())
979 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt.enabled())
980 python3_dep = not_found_dep
983 python3_dep = not_found_dep
988 ###############################################################
990 ###############################################################
992 if not get_option('readline').disabled()
993 libedit_preferred = get_option('libedit_preferred')
994 # Set the order of readline dependencies
995 check_readline_deps = libedit_preferred ? \
996 ['libedit', 'readline'] : ['readline', 'libedit']
998 foreach readline_dep : check_readline_deps
999 readline = dependency(readline_dep, required: false)
1000 if not readline.found()
1001 readline = cc.find_library(readline_dep,
1002 required: get_option('readline').enabled(),
1011 cdata.set('HAVE_LIBREADLINE', 1)
1014 'header_prefix': 'editline/',
1015 'flag_prefix': 'EDITLINE_',
1018 'header_prefix': 'readline/',
1019 'flag_prefix': 'READLINE_',
1022 'header_prefix': '',
1026 # Set the order of prefixes
1027 prefixes = libedit_preferred ? \
1028 [editline_prefix, default_prefix, readline_prefix] : \
1029 [readline_prefix, default_prefix, editline_prefix]
1031 at_least_one_header_found = false
1032 foreach header : ['history', 'readline']
1034 foreach prefix : prefixes
1035 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1036 # Check history.h and readline.h
1037 if not is_found and cc.has_header(header_file,
1038 args: test_c_args, include_directories: postgres_inc,
1039 dependencies: [readline], required: false)
1040 if header == 'readline'
1041 readline_h = header_file
1043 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1045 at_least_one_header_found = true
1050 if not at_least_one_header_found
1051 error('''readline header not found
1052 If you have @0@ already installed, see see meson-log/meson-log.txt for details on the
1053 failure. It is possible the compiler isn't looking in the proper directory.
1054 Use -Dreadline=false to disable readline support.'''.format(readline_dep))
1059 'history_truncate_file',
1060 'rl_completion_matches',
1061 'rl_filename_completion_function',
1062 'rl_reset_screen_size',
1066 foreach func : check_funcs
1067 found = cc.has_function(func, dependencies: [readline],
1068 args: test_c_args, include_directories: postgres_inc)
1069 cdata.set('HAVE_'+func.to_upper(), found ? 1 : false)
1073 'rl_completion_suppress_quote',
1074 'rl_filename_quote_characters',
1075 'rl_filename_quoting_function',
1078 foreach var : check_vars
1079 cdata.set('HAVE_'+var.to_upper(),
1080 cc.has_header_symbol(readline_h, var,
1081 args: test_c_args, include_directories: postgres_inc,
1082 prefix: '#include <stdio.h>',
1083 dependencies: [readline]) ? 1 : false)
1086 # If found via cc.find_library() ensure headers are found when using the
1087 # dependency. On meson < 0.57 one cannot do compiler checks using the
1088 # dependency returned by declare_dependency(), so we can't do this above.
1089 if readline.type_name() == 'library'
1090 readline = declare_dependency(dependencies: readline,
1091 include_directories: postgres_inc)
1094 # On windows with mingw readline requires auto-import to successfully
1095 # link, as the headers don't use declspec(dllimport)
1096 if host_system == 'windows' and cc.get_id() != 'msvc'
1097 readline = declare_dependency(dependencies: readline,
1098 link_args: '-Wl,--enable-auto-import')
1102 # XXX: Figure out whether to implement mingw warning equivalent
1104 readline = not_found_dep
1109 ###############################################################
1111 ###############################################################
1113 selinux = not_found_dep
1114 selinuxopt = get_option('selinux')
1115 if meson.version().version_compare('>=0.59')
1116 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1118 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1119 cdata.set('HAVE_LIBSELINUX',
1120 selinux.found() ? 1 : false)
1124 ###############################################################
1126 ###############################################################
1128 systemd = not_found_dep
1129 systemdopt = get_option('systemd')
1130 if meson.version().version_compare('>=0.59')
1131 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1133 systemd = dependency('libsystemd', required: systemdopt)
1134 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1138 ###############################################################
1140 ###############################################################
1142 if get_option('ssl') == 'openssl'
1144 # Try to find openssl via pkg-config et al, if that doesn't work
1145 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1146 # the library names that we know about.
1148 # via pkg-config et al
1149 ssl = dependency('openssl', required: false)
1151 # via library + headers
1153 ssl_lib = cc.find_library('ssl',
1155 header_include_directories: postgres_inc,
1156 has_headers: ['openssl/ssl.h', 'openssl/err.h'])
1157 crypto_lib = cc.find_library('crypto',
1159 header_include_directories: postgres_inc)
1160 ssl_int = [ssl_lib, crypto_lib]
1162 ssl = declare_dependency(dependencies: ssl_int,
1163 include_directories: postgres_inc)
1165 cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: true)
1166 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: true)
1172 ['CRYPTO_new_ex_data', {'required': true}],
1173 ['SSL_new', {'required': true}],
1175 # Function introduced in OpenSSL 1.0.2.
1176 ['X509_get_signature_nid'],
1178 # Functions introduced in OpenSSL 1.1.0. We used to check for
1179 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1180 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1181 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1183 ['OPENSSL_init_ssl'],
1186 ['ASN1_STRING_get0_data'],
1190 # OpenSSL versions before 1.1.0 required setting callback functions, for
1191 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1192 # function was removed.
1196 foreach c : check_funcs
1198 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1199 required = c.get(1, {}).get('required', false)
1200 if required and not val
1201 error('openssl function @0@ is required'.format(func))
1203 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1207 cdata.set('USE_OPENSSL', 1,
1208 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1209 cdata.set('OPENSSL_API_COMPAT', '0x10001000L',
1210 description: '''Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.''')
1217 ###############################################################
1219 ###############################################################
1221 uuidopt = get_option('uuid')
1222 if uuidopt != 'none'
1223 uuidname = uuidopt.to_upper()
1224 if uuidopt == 'e2fs'
1225 uuid = dependency('uuid', required: true)
1226 uuidfunc = 'uuid_generate'
1227 uuidheader = 'uuid/uuid.h'
1228 elif uuidopt == 'bsd'
1229 # libc should have uuid function
1230 uuid = declare_dependency()
1231 uuidfunc = 'uuid_to_string'
1232 uuidheader = 'uuid.h'
1233 elif uuidopt == 'ossp'
1234 uuid = dependency('ossp-uuid', required: true)
1235 uuidfunc = 'uuid_export'
1236 uuidheader = 'ossp/uuid.h'
1241 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1242 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1244 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1246 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1247 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1249 uuid = not_found_dep
1254 ###############################################################
1256 ###############################################################
1258 zlibopt = get_option('zlib')
1259 zlib = not_found_dep
1260 if not zlibopt.disabled()
1261 zlib_t = dependency('zlib', required: zlibopt)
1263 if zlib_t.type_name() == 'internal'
1264 # if fallback was used, we don't need to test if headers are present (they
1265 # aren't built yet, so we can't test)
1267 elif not zlib_t.found()
1268 warning('did not find zlib')
1269 elif not cc.has_header('zlib.h',
1270 args: test_c_args, include_directories: postgres_inc,
1271 dependencies: [zlib_t], required: zlibopt.enabled())
1272 warning('zlib header not found')
1273 elif not cc.has_type('z_streamp',
1274 dependencies: [zlib_t], prefix: '#include <zlib.h>',
1275 args: test_c_args, include_directories: postgres_inc)
1276 if zlibopt.enabled()
1277 error('zlib version is too old')
1279 warning('zlib version is too old')
1286 cdata.set('HAVE_LIBZ', 1)
1292 ###############################################################
1293 # Library: tap test dependencies
1294 ###############################################################
1296 # Check whether tap tests are enabled or not
1297 tap_tests_enabled = false
1298 tapopt = get_option('tap_tests')
1299 if not tapopt.disabled()
1300 # Checking for perl modules for tap tests
1301 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1302 if perl_ipc_run_check.returncode() != 0
1303 message(perl_ipc_run_check.stderr().strip())
1305 error('Additional Perl modules are required to run TAP tests.')
1307 warning('Additional Perl modules are required to run TAP tests.')
1310 tap_tests_enabled = true
1316 ###############################################################
1318 ###############################################################
1320 zstdopt = get_option('zstd')
1321 if not zstdopt.disabled()
1322 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1325 cdata.set('USE_ZSTD', 1)
1326 cdata.set('HAVE_LIBZSTD', 1)
1330 zstd = not_found_dep
1335 ###############################################################
1337 ###############################################################
1339 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1340 # unnecessarily, because we optionally rely on newer features.
1342 #include <stdbool.h>
1343 #include <complex.h>
1345 #include <inttypes.h>
1347 struct named_init_test {
1352 extern void structfunc(struct named_init_test);
1354 int main(int argc, char **argv)
1356 struct named_init_test nit = {
1361 for (int loop_var = 0; loop_var < 3; loop_var++)
1366 structfunc((struct named_init_test){1, 0});
1372 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1373 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1374 args: test_c_args + ['-std=c99'])
1375 test_c_args += '-std=c99'
1376 cflags += '-std=c99'
1378 error('C compiler does not support C99')
1382 sizeof_long = cc.sizeof('long', args: test_c_args)
1383 cdata.set('SIZEOF_LONG', sizeof_long)
1385 cdata.set('HAVE_LONG_INT_64', 1)
1386 cdata.set('PG_INT64_TYPE', 'long int')
1387 cdata.set_quoted('INT64_MODIFIER', 'l')
1388 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1389 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1390 cdata.set('PG_INT64_TYPE', 'long long int')
1391 cdata.set_quoted('INT64_MODIFIER', 'll')
1393 error('do not know how to get a 64bit int')
1396 if host_machine.endian() == 'big'
1397 cdata.set('WORDS_BIGENDIAN', 1)
1400 alignof_types = ['short', 'int', 'long', 'double']
1402 foreach t : alignof_types
1403 align = cc.alignment(t, args: test_c_args)
1407 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1409 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1411 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1412 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1415 # Check if __int128 is a working 128 bit integer type, and if so
1416 # define PG_INT128_TYPE to that typename.
1418 # This currently only detects a GCC/clang extension, but support for other
1419 # environments may be added in the future.
1421 # For the moment we only test for support for 128bit math; support for
1422 # 128bit literals and snprintf is not required.
1425 * We don't actually run this test, just link it to verify that any support
1426 * functions needed for __int128 are present.
1428 * These are globals to discourage the compiler from folding all the
1429 * arithmetic tests down to compile-time constants. We do not have
1430 * convenient support for 128bit literals at this point...
1432 __int128 a = 48828125;
1433 __int128 b = 97656250;
1438 a = (a << 12) + 1; /* 200000000001 */
1439 b = (b << 12) + 5; /* 400000000005 */
1440 /* try the most relevant arithmetic ops */
1443 /* must use the results, else compiler may optimize arithmetic away */
1449 buggy_int128 = false
1451 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1452 # If not cross-compiling, we can test for bugs and disable use of __int128
1453 # with buggy compilers. If cross-compiling, hope for the best.
1454 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1455 if not meson.is_cross_build()
1457 /* This must match the corresponding code in c.h: */
1458 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1459 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1461 typedef __int128 int128a
1462 #if defined(pg_attribute_aligned)
1463 pg_attribute_aligned(8)
1468 void pass_by_val(void *buffer, int128a par) { holder = par; }
1472 long int i64 = 97656225L << 12;
1474 pass_by_val(main, (int128a) i64);
1478 name: '__int128 alignment bug',
1480 assert(r.compiled())
1481 if r.returncode() != 0
1483 message('__int128 support present but buggy and thus disabled')
1488 cdata.set('PG_INT128_TYPE', '__int128')
1489 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.
1490 alignment('__int128', args: test_c_args))
1495 # Check if the C compiler knows computed gotos (gcc extension, also
1496 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1498 # Checking whether computed gotos are supported syntax-wise ought to
1499 # be enough, as the syntax is otherwise illegal.
1501 static inline int foo(void)
1503 void *labeladdrs[] = {&&my_label};
1504 goto *labeladdrs[0];
1509 cdata.set('HAVE_COMPUTED_GOTO', 1)
1513 # Check if the C compiler understands _Static_assert(),
1514 # and define HAVE__STATIC_ASSERT if so.
1516 # We actually check the syntax ({ _Static_assert(...) }), because we need
1517 # gcc-style compound expressions to be able to wrap the thing into macros.
1519 int main(int arg, char **argv)
1521 ({ _Static_assert(1, "foo"); });
1525 cdata.set('HAVE__STATIC_ASSERT', 1)
1529 # We use <stdbool.h> if we have it and it declares type bool as having
1530 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1531 if cc.has_type('_Bool', args: test_c_args) \
1532 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1533 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1534 cdata.set('HAVE__BOOL', 1)
1535 cdata.set('PG_USE_STDBOOL', 1)
1539 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1540 # warning for each use of %m.
1541 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1543 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1544 static void call_log(void)
1546 emit_log(0, "error: %s: %m", "foo");
1549 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1550 foreach a : printf_attributes
1551 if cc.compiles(testsrc.format(a),
1552 args: test_c_args + attrib_error_args, name: 'format ' + a)
1553 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1559 if cc.has_function_attribute('visibility:default') and \
1560 cc.has_function_attribute('visibility:hidden')
1561 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1563 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1564 # inlineshidden to C code as well... Any either way, we want to put these
1565 # flags into exported files (pgxs, .pc files).
1566 cflags_mod += '-fvisibility=hidden'
1567 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1568 ldflags_mod += '-fvisibility=hidden'
1572 # Check if various builtins exist. Some builtins are tested separately,
1573 # because we want to test something more complicated than the generic case.
1586 foreach builtin : builtins
1587 fname = '__builtin_@0@'.format(builtin)
1588 if cc.has_function(fname, args: test_c_args)
1589 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1594 # Check if the C compiler understands __builtin_types_compatible_p,
1595 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1597 # We check usage with __typeof__, though it's unlikely any compiler would
1598 # have the former and not the latter.
1601 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1603 name: '__builtin_types_compatible_p',
1605 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1609 # Check if the C compiler understands __builtin_$op_overflow(),
1610 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1612 # Check for the most complicated case, 64 bit multiplication, as a
1613 # proxy for all of the operations. To detect the case where the compiler
1614 # knows the function but library support is missing, we must link not just
1615 # compile, and store the results in global variables so the compiler doesn't
1616 # optimize away the call.
1624 return __builtin_mul_overflow(a, b, &result);
1626 name: '__builtin_mul_overflow',
1627 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1629 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1633 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1634 # here. To prevent problems due to two detection methods working, stop
1635 # checking after one.
1638 int main(int arg, char **argv)
1640 unsigned int exx[4] = {0, 0, 0, 0};
1641 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1643 ''', name: '__get_cpuid',
1645 cdata.set('HAVE__GET_CPUID', 1)
1648 int main(int arg, char **argv)
1650 unsigned int exx[4] = {0, 0, 0, 0};
1653 ''', name: '__cpuid',
1655 cdata.set('HAVE__CPUID', 1)
1659 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1660 # versions of clang do not understand -fexcess-precision=standard, the use of
1661 # x87 floating point operations leads to problems like isinf possibly returning
1662 # false for a value that is infinite when converted from the 80bit register to
1663 # the 8byte memory representation.
1665 # Only perform the test if the compiler doesn't understand
1666 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1668 if '-fexcess-precision=standard' not in cflags
1669 if not cc.compiles('''
1670 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1673 name: '', args: test_c_args)
1674 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1680 ###############################################################
1682 ###############################################################
1684 common_functional_flags = [
1685 # Disable strict-aliasing rules; needed for gcc 3.3+
1686 '-fno-strict-aliasing',
1687 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1689 '-fexcess-precision=standard',
1692 cflags += cc.get_supported_arguments(common_functional_flags)
1694 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1697 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1698 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1700 common_warning_flags = [
1701 '-Wmissing-prototypes',
1703 # Really don't want VLAs to be used in our dialect of C
1705 # On macOS, complain about usage of symbols newer than the deployment target
1706 '-Werror=unguarded-availability-new',
1708 '-Wmissing-format-attribute',
1709 '-Wimplicit-fallthrough=3',
1710 '-Wcast-function-type',
1711 # This was included in -Wall/-Wformat in older GCC versions
1712 '-Wformat-security',
1715 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1717 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1720 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1721 # the result for them
1722 if cc.has_argument('-Wdeclaration-after-statement')
1723 cflags_warn += '-Wdeclaration-after-statement'
1724 using_declaration_after_statement_warning = true
1726 using_declaration_after_statement_warning = false
1730 # The following tests want to suppress various unhelpful warnings by adding
1731 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1732 # switches, so we have to test for the positive form and if that works,
1733 # add the negative form.
1735 negative_warning_flags = [
1736 # Suppress clang's unhelpful unused-command-line-argument warnings.
1737 'unused-command-line-argument',
1739 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1740 # of warnings when building plperl because of usages in the Perl headers.
1741 'compound-token-split-by-macro',
1743 # Similarly disable useless truncation warnings from gcc 8+
1744 'format-truncation',
1745 'stringop-truncation',
1747 # To make warning_level=2 / -Wextra work, we'd need at least the following
1749 # 'missing-field-initializers',
1751 # 'unused-parameter',
1754 foreach w : negative_warning_flags
1755 if cc.has_argument('-W' + w)
1756 cflags_warn += '-Wno-' + w
1758 if llvm.found() and cpp.has_argument('-W' + w)
1759 cxxflags_warn += '-Wno-' + w
1765 if cc.get_id() == 'msvc'
1767 '/wd4018', # signed/unsigned mismatch
1768 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1769 '/wd4273', # inconsistent DLL linkage
1770 '/wd4101', # unreferenced local variable
1771 '/wd4102', # unreferenced label
1772 '/wd4090', # different 'modifier' qualifiers
1773 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1781 '/D_CRT_SECURE_NO_DEPRECATE',
1782 '/D_CRT_NONSTDC_NO_DEPRECATE',
1785 # We never need export libraries. As link.exe reports their creation, they
1786 # are unnecessarily noisy. Similarly, we don't need import library for
1787 # modules, we only import them dynamically, and they're also noisy.
1789 ldflags_mod += '/NOIMPLIB'
1794 ###############################################################
1796 ###############################################################
1798 if not get_option('spinlocks')
1799 warning('Not using spinlocks will cause poor performance')
1801 cdata.set('HAVE_SPINLOCKS', 1)
1804 if not get_option('atomics')
1805 warning('Not using atomics will cause poor performance')
1807 # XXX: perhaps we should require some atomics support in this case these
1809 cdata.set('HAVE_ATOMICS', 1)
1812 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
1813 'desc': '__sync_lock_test_and_set(char)',
1816 __sync_lock_test_and_set(&lock, 1);
1817 __sync_lock_release(&lock);'''},
1819 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
1820 'desc': '__sync_lock_test_and_set(int32)',
1823 __sync_lock_test_and_set(&lock, 1);
1824 __sync_lock_release(&lock);'''},
1826 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
1827 'desc': '__sync_val_compare_and_swap(int32)',
1830 __sync_val_compare_and_swap(&val, 0, 37);'''},
1832 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
1833 'desc': '__sync_val_compare_and_swap(int64)',
1836 __sync_val_compare_and_swap(&val, 0, 37);'''},
1838 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
1839 'desc': ' __atomic_compare_exchange_n(int32)',
1843 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1845 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
1846 'desc': ' __atomic_compare_exchange_n(int64)',
1850 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1853 foreach check : atomic_checks
1858 }'''.format(check['test'])
1860 cdata.set(check['name'],
1862 name: check['desc'],
1863 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
1871 ###############################################################
1872 # Select CRC-32C implementation.
1874 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
1875 # use the special CRC instructions for calculating CRC-32C. If we're not
1876 # targeting such a processor, but we can nevertheless produce code that uses
1877 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
1878 # implementations and select which one to use at runtime, depending on whether
1879 # SSE 4.2 is supported by the processor we're running on.
1881 # Similarly, if we are targeting an ARM processor that has the CRC
1882 # instructions that are part of the ARMv8 CRC Extension, use them. And if
1883 # we're not targeting such a processor, but can nevertheless produce code that
1884 # uses the CRC instructions, compile both, and select at runtime.
1885 ###############################################################
1887 have_optimized_crc = false
1889 if host_cpu == 'x86' or host_cpu == 'x86_64'
1891 if cc.get_id() == 'msvc'
1892 cdata.set('USE_SSE42_CRC32C', false)
1893 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
1894 have_optimized_crc = true
1898 #include <nmmintrin.h>
1902 unsigned int crc = 0;
1903 crc = _mm_crc32_u8(crc, 0);
1904 crc = _mm_crc32_u32(crc, 0);
1905 /* return computed value, to prevent the above being optimized away */
1910 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
1912 # Use Intel SSE 4.2 unconditionally.
1913 cdata.set('USE_SSE42_CRC32C', 1)
1914 have_optimized_crc = true
1915 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
1916 args: test_c_args + ['-msse4.2'])
1917 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
1918 # the runtime check.
1919 cflags_crc += '-msse4.2'
1920 cdata.set('USE_SSE42_CRC32C', false)
1921 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
1922 have_optimized_crc = true
1927 elif host_cpu == 'arm' or host_cpu == 'aarch64'
1930 #include <arm_acle.h>
1934 unsigned int crc = 0;
1935 crc = __crc32cb(crc, 0);
1936 crc = __crc32ch(crc, 0);
1937 crc = __crc32cw(crc, 0);
1938 crc = __crc32cd(crc, 0);
1940 /* return computed value, to prevent the above being optimized away */
1945 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
1947 # Use ARM CRC Extension unconditionally
1948 cdata.set('USE_ARMV8_CRC32C', 1)
1949 have_optimized_crc = true
1950 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
1951 args: test_c_args + ['-march=armv8-a+crc'])
1952 # Use ARM CRC Extension, with runtime check
1953 cflags_crc += '-march=armv8-a+crc'
1954 cdata.set('USE_ARMV8_CRC32C', false)
1955 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
1956 have_optimized_crc = true
1960 if not have_optimized_crc
1961 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
1963 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
1968 ###############################################################
1969 # Other CPU specific stuff
1970 ###############################################################
1972 if host_cpu == 'x86_64'
1977 long long x = 1; long long r;
1978 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
1980 name: '@0@: popcntq instruction'.format(host_cpu),
1982 cdata.set('HAVE_X86_64_POPCNTQ', 1)
1985 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
1986 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
1987 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
1990 addi(int ra, int si)
1993 if (__builtin_constant_p(si))
1994 __asm__ __volatile__(
1995 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
1998 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
2001 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
2008 ###############################################################
2009 # Library / OS tests
2010 ###############################################################
2012 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2013 # unnecessary checks over and over, particularly on windows.
2027 'sys/personality.h',
2036 foreach header : header_checks
2037 varname = 'HAVE_' + header.underscorify().to_upper()
2039 # Emulate autoconf behaviour of not-found->undef, found->1
2040 found = cc.has_header(header,
2041 include_directories: postgres_inc, args: test_c_args)
2042 cdata.set(varname, found ? 1 : false,
2043 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2048 ['F_FULLFSYNC', 'fcntl.h'],
2049 ['fdatasync', 'unistd.h'],
2050 ['posix_fadvise', 'fcntl.h'],
2051 ['strlcat', 'string.h'],
2052 ['strlcpy', 'string.h'],
2053 ['strnlen', 'string.h'],
2056 # Need to check for function declarations for these functions, because
2057 # checking for library symbols wouldn't handle deployment target
2058 # restrictions on macOS
2060 ['preadv', 'sys/uio.h'],
2061 ['pwritev', 'sys/uio.h'],
2064 foreach c : decl_checks
2068 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2070 found = cc.has_header_symbol(header, func,
2071 args: test_c_args, include_directories: postgres_inc,
2073 cdata.set10(varname, found, description:
2074 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2075 don't.'''.format(func))
2079 if cc.has_type('struct cmsgcred',
2080 args: test_c_args + ['@0@'.format(cdata.get('HAVE_SYS_UCRED_H')) == 'false' ? '' : '-DHAVE_SYS_UCRED_H'],
2081 include_directories: postgres_inc,
2083 #include <sys/socket.h>
2084 #include <sys/param.h>
2085 #ifdef HAVE_SYS_UCRED_H
2086 #include <sys/ucred.h>
2088 cdata.set('HAVE_STRUCT_CMSGCRED', 1)
2090 cdata.set('HAVE_STRUCT_CMSGCRED', false)
2093 if cc.has_type('struct option',
2094 args: test_c_args, include_directories: postgres_inc,
2095 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2096 cdata.set('HAVE_STRUCT_OPTION', 1)
2100 foreach c : ['opterr', 'optreset']
2101 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2110 '''.format(c), name: c, args: test_c_args)
2111 cdata.set(varname, 1)
2113 cdata.set(varname, false)
2117 if cc.has_type('socklen_t',
2118 args: test_c_args, include_directories: postgres_inc,
2120 #include <sys/socket.h>''')
2121 cdata.set('HAVE_SOCKLEN_T', 1)
2124 if cc.has_member('struct sockaddr', 'sa_len',
2125 args: test_c_args, include_directories: postgres_inc,
2127 #include <sys/types.h>
2128 #include <sys/socket.h>''')
2129 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2132 if cc.has_member('struct tm', 'tm_zone',
2133 args: test_c_args, include_directories: postgres_inc,
2135 #include <sys/types.h>
2138 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2143 extern int foo(void);
2146 return timezone / 60;
2149 name: 'global variable `timezone\' exists',
2150 args: test_c_args, include_directories: postgres_inc)
2151 cdata.set('HAVE_INT_TIMEZONE', 1)
2153 cdata.set('HAVE_INT_TIMEZONE', false)
2156 if cc.has_type('union semun',
2158 include_directories: postgres_inc,
2160 #include <sys/types.h>
2161 #include <sys/ipc.h>
2162 #include <sys/sem.h>
2164 cdata.set('HAVE_UNION_SEMUN', 1)
2172 switch (strerror_r(1, buf, sizeof(buf)))
2173 { case 0: break; default: break; }
2176 args: test_c_args, include_directories: postgres_inc)
2177 cdata.set('STRERROR_R_INT', 1)
2179 cdata.set('STRERROR_R_INT', false)
2182 # Check for the locale_t type and find the right header file. macOS
2183 # needs xlocale.h; standard is locale.h, but glibc also has an
2184 # xlocale.h file that we should not use.
2185 if cc.has_type('locale_t', prefix: '#include <locale.h>')
2186 cdata.set('HAVE_LOCALE_T', 1)
2187 elif cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2188 cdata.set('HAVE_LOCALE_T', 1)
2189 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2192 # Check if the C compiler understands typeof or a variant. Define
2193 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2194 foreach kw : ['typeof', '__typeof__', 'decltype']
2205 args: test_c_args, include_directories: postgres_inc)
2207 cdata.set('HAVE_TYPEOF', 1)
2209 cdata.set('typeof', kw)
2217 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2218 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2219 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2220 wcstombs_l_test = '''
2232 if (not cc.compiles(wcstombs_l_test.format(''),
2233 name: 'wcstombs_l') and
2234 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2235 name: 'wcstombs_l in xlocale.h'))
2236 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2240 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2241 # understands, because it conflicts with __declspec(restrict). Therefore we
2242 # define pg_restrict to the appropriate definition, which presumably won't
2245 # We assume C99 support, so we don't need to make this conditional.
2247 # XXX: Historically we allowed platforms to disable restrict in template
2248 # files, but that was only added for AIX when building with XLC, which we
2249 # don't support yet.
2250 cdata.set('pg_restrict', '__restrict')
2254 #include <machine/vmparam.h>
2255 #include <sys/exec.h>
2259 PS_STRINGS->ps_nargvstr = 1;
2260 PS_STRINGS->ps_argvstr = "foo";
2263 name: 'PS_STRINGS', args: test_c_args)
2264 cdata.set('HAVE_PS_STRINGS', 1)
2266 cdata.set('HAVE_PS_STRINGS', false)
2270 # Most libraries are included only if they demonstrably provide a function we
2271 # need, but libm is an exception: always include it, because there are too
2272 # many compilers that play cute optimization games that will break probes for
2273 # standard functions such as pow().
2274 os_deps += cc.find_library('m', required: false)
2276 rt_dep = cc.find_library('rt', required: false)
2278 dl_dep = cc.find_library('dl', required: false)
2280 util_dep = cc.find_library('util', required: false)
2281 posix4_dep = cc.find_library('posix4', required: false)
2283 getopt_dep = cc.find_library('getopt', required: false)
2284 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2285 # Check if we want to replace getopt/getopt_long even if provided by the system
2286 # - Mingw has adopted a GNU-centric interpretation of optind/optreset,
2287 # so always use our version on Windows
2288 # - On OpenBSD and Solaris, getopt() doesn't do what we want for long options
2289 # (i.e., allow '-' as a flag character), so use our version on those platforms
2290 # - We want to use system's getopt_long() only if the system provides struct
2292 always_replace_getopt = host_system in ['windows', 'openbsd', 'solaris']
2293 always_replace_getopt_long = host_system == 'windows' or not cdata.has('HAVE_STRUCT_OPTION')
2296 execinfo_dep = cc.find_library('execinfo', required: false)
2298 if host_system == 'cygwin'
2299 cygipc_dep = cc.find_library('cygipc', required: false)
2301 cygipc_dep = not_found_dep
2304 if host_system == 'sunos'
2305 socket_dep = cc.find_library('socket', required: false)
2307 socket_dep = not_found_dep
2310 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2311 # unnecessary checks over and over, particularly on windows.
2313 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2314 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2315 ['clock_gettime', {'dependencies': [rt_dep, posix4_dep], 'define': false}],
2317 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2318 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2319 # required. Just checking for dlsym() ought to suffice.
2320 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2322 ['fdatasync', {'dependencies': [rt_dep, posix4_dep], 'define': false}], # Solaris
2324 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
2325 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],
2335 ['posix_fallocate'],
2338 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2339 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2340 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2341 ['setproctitle', {'dependencies': [util_dep]}],
2342 ['setproctitle_fast'],
2343 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2344 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2345 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2346 ['socket', {'dependencies': [socket_dep], 'define': false}],
2348 ['strerror_r', {'dependencies': [thread_dep]}],
2353 ['sync_file_range'],
2359 func_check_results = {}
2360 foreach c : func_checks
2362 kwargs = c.get(1, {})
2363 deps = kwargs.get('dependencies', [])
2365 if kwargs.get('skip', false)
2369 found = cc.has_function(func, args: test_c_args)
2376 found = cc.has_function(func, args: test_c_args,
2377 dependencies: [dep])
2385 func_check_results += {func: found}
2387 if kwargs.get('define', true)
2388 # Emulate autoconf behaviour of not-found->undef, found->1
2389 cdata.set('HAVE_' + func.underscorify().to_upper(),
2391 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2396 if cc.has_function('syslog', args: test_c_args) and \
2397 cc.check_header('syslog.h', args: test_c_args)
2398 cdata.set('HAVE_SYSLOG', 1)
2402 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2404 if sema_kind == 'unnamed_posix' and \
2405 not func_check_results.get('sem_init', false)
2409 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2410 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2412 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2413 cdata.set_quoted('DLSUFFIX', dlsuffix)
2417 ###############################################################
2419 ###############################################################
2421 # XXX: About to rely on thread safety in the autoconf build, so not worth
2422 # implementing a fallback.
2423 cdata.set('ENABLE_THREAD_SAFETY', 1)
2427 ###############################################################
2429 ###############################################################
2431 nlsopt = get_option('nls')
2432 libintl = not_found_dep
2434 if not nlsopt.disabled()
2435 # otherwise there'd be lots of
2436 # "Gettext not found, all translation (po) targets will be ignored."
2437 # warnings if not found.
2438 msgfmt = find_program('msgfmt', required: nlsopt.enabled(), native: true)
2440 # meson 0.59 has this wrapped in dependency('int')
2441 if (msgfmt.found() and
2442 cc.check_header('libintl.h', required: nlsopt,
2443 args: test_c_args, include_directories: postgres_inc))
2446 if cc.has_function('ngettext')
2447 libintl = declare_dependency()
2449 libintl = cc.find_library('intl',
2450 has_headers: ['libintl.h'], required: nlsopt,
2451 header_include_directories: postgres_inc,
2457 i18n = import('i18n')
2458 cdata.set('ENABLE_NLS', 1)
2464 ###############################################################
2466 ###############################################################
2468 # Set up compiler / linker arguments to be used everywhere, individual targets
2469 # can add further args directly, or indirectly via dependencies
2470 add_project_arguments(cflags, language: ['c'])
2471 add_project_arguments(cppflags, language: ['c'])
2472 add_project_arguments(cflags_warn, language: ['c'])
2473 add_project_arguments(cxxflags, language: ['cpp'])
2474 add_project_arguments(cppflags, language: ['cpp'])
2475 add_project_arguments(cxxflags_warn, language: ['cpp'])
2476 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2479 # Collect a number of lists of things while recursing through the source
2480 # tree. Later steps then can use those.
2482 # list of targets for various alias targets
2483 backend_targets = []
2486 contrib_targets = []
2487 testprep_targets = []
2490 # Define the tests to distribute them to the correct test styles later
2495 # Default options for targets
2497 # First identify rpaths
2498 bin_install_rpaths = []
2499 lib_install_rpaths = []
2500 mod_install_rpaths = []
2503 # Don't add rpaths on darwin for now - as long as only absolute references to
2504 # libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
2505 # their final destination.
2506 if host_system != 'darwin'
2507 # Add absolute path to libdir to rpath. This ensures installed binaries /
2508 # libraries find our libraries (mainly libpq).
2509 bin_install_rpaths += dir_prefix / dir_lib
2510 lib_install_rpaths += dir_prefix / dir_lib
2511 mod_install_rpaths += dir_prefix / dir_lib
2513 # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
2515 # Not needed on darwin even if we use relative rpaths for our own libraries,
2516 # as the install_name of libraries in extra_lib_dirs will point to their
2518 bin_install_rpaths += postgres_lib_d
2519 lib_install_rpaths += postgres_lib_d
2520 mod_install_rpaths += postgres_lib_d
2524 # Define arguments for default targets
2526 default_target_args = {
2527 'implicit_include_directories': false,
2531 default_lib_args = default_target_args + {
2533 'install_rpath': ':'.join(lib_install_rpaths),
2536 internal_lib_args = default_lib_args + {
2537 'build_by_default': false,
2541 default_mod_args = default_lib_args + {
2543 'install_dir': dir_lib_pkg,
2544 'install_rpath': ':'.join(mod_install_rpaths),
2547 default_bin_args = default_target_args + {
2548 'install_dir': dir_bin,
2549 'install_rpath': ':'.join(bin_install_rpaths),
2554 # Helper for exporting a limited number of symbols
2555 gen_export_kwargs = {
2556 'input': 'exports.txt',
2557 'output': '@BASENAME@.'+export_file_suffix,
2558 'command': [perl, files('src/tools/gen_export.pl'),
2559 '--format', export_file_format,
2560 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2561 'build_by_default': false,
2567 # headers that the whole build tree depends on
2568 generated_headers = []
2569 # headers that the backend build depends on
2570 generated_backend_headers = []
2571 # configure_files() output, needs a way of converting to file names
2572 configure_files = []
2574 # generated files that might conflict with a partial in-tree autoconf build
2575 generated_sources = []
2576 # same, for paths that differ between autoconf / meson builds
2577 # elements are [dir, [files]]
2578 generated_sources_ac = {}
2581 # First visit src/include - all targets creating headers are defined
2582 # within. That makes it easy to add the necessary dependencies for the
2583 # subsequent build steps.
2585 subdir('src/include')
2589 # Then through src/port and src/common, as most other things depend on them
2591 frontend_port_code = declare_dependency(
2592 compile_args: ['-DFRONTEND'],
2593 include_directories: [postgres_inc],
2594 dependencies: os_deps,
2597 backend_port_code = declare_dependency(
2598 compile_args: ['-DBUILDING_DLL'],
2599 include_directories: [postgres_inc],
2600 sources: [errcodes], # errcodes.h is needed due to use of ereport
2601 dependencies: os_deps,
2606 frontend_common_code = declare_dependency(
2607 compile_args: ['-DFRONTEND'],
2608 include_directories: [postgres_inc],
2609 sources: generated_headers,
2610 dependencies: [os_deps, zlib, zstd],
2613 backend_common_code = declare_dependency(
2614 compile_args: ['-DBUILDING_DLL'],
2615 include_directories: [postgres_inc],
2616 sources: generated_headers,
2617 dependencies: [os_deps, zlib, zstd],
2620 subdir('src/common')
2622 frontend_shlib_code = declare_dependency(
2623 compile_args: ['-DFRONTEND'],
2624 include_directories: [postgres_inc],
2625 link_args: ldflags_sl,
2626 link_with: [pgport_shlib, common_shlib],
2627 sources: generated_headers,
2628 dependencies: [os_deps, libintl],
2632 frontend_shlib_code,
2641 subdir('src/interfaces/libpq')
2642 # fe_utils depends on libpq
2643 subdir('src/fe_utils')
2645 frontend_code = declare_dependency(
2646 include_directories: [postgres_inc],
2647 link_with: [fe_utils, common_static, pgport_static],
2648 sources: generated_headers,
2649 dependencies: [os_deps, libintl],
2652 backend_both_deps += [
2669 backend_mod_deps = backend_both_deps + os_deps
2671 backend_code = declare_dependency(
2672 compile_args: ['-DBUILDING_DLL'],
2673 include_directories: [postgres_inc],
2674 link_args: ldflags_be,
2676 sources: generated_headers + generated_backend_headers,
2677 dependencies: os_deps + backend_both_deps + backend_deps,
2680 # src/backend/meson.build defines backend_mod_code used for extension
2684 # Then through the main sources. That way contrib can have dependencies on
2685 # main sources. Note that this explicitly doesn't enter src/test, right now a
2686 # few regression tests depend on contrib files.
2693 subdir('src/interfaces/libpq/test')
2694 subdir('src/interfaces/ecpg/test')
2696 subdir('doc/src/sgml')
2698 generated_sources_ac += {'': ['GNUmakefile']}
2701 # If there are any files in the source directory that we also generate in the
2702 # build directory, they might get preferred over the newly generated files,
2703 # e.g. because of a #include "file", which always will search in the current
2705 message('checking for file conflicts between source and build directory')
2706 conflicting_files = []
2707 potentially_conflicting_files_t = []
2708 potentially_conflicting_files_t += generated_headers
2709 potentially_conflicting_files_t += generated_backend_headers
2710 potentially_conflicting_files_t += generated_backend_sources
2711 potentially_conflicting_files_t += generated_sources
2713 potentially_conflicting_files = []
2715 # convert all sources of potentially conflicting files into uniform shape
2716 foreach t : potentially_conflicting_files_t
2717 potentially_conflicting_files += t.full_path()
2719 foreach t : configure_files
2721 potentially_conflicting_files += meson.current_build_dir() / t
2723 foreach sub, fnames : generated_sources_ac
2724 sub = meson.build_root() / sub
2725 foreach fname : fnames
2726 potentially_conflicting_files += sub / fname
2730 # find and report conflicting files
2731 foreach build_path : potentially_conflicting_files
2732 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
2733 # str.replace is in 0.56
2734 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
2735 if fs.exists(src_path) or fs.is_symlink(src_path)
2736 conflicting_files += src_path
2739 # XXX: Perhaps we should generate a file that would clean these up? The list
2741 if conflicting_files.length() > 0
2742 errmsg_cleanup = '''
2743 Conflicting files in source directory:
2746 The conflicting files need to be removed, either by removing the files listed
2747 above, or by running configure and then make maintainer-clean.
2749 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
2750 error(errmsg_nonclean_base.format(errmsg_cleanup))
2755 ###############################################################
2757 ###############################################################
2759 # DESTDIR for the installation we'll run tests in
2760 test_install_destdir = meson.build_root() / 'tmp_install/'
2762 # DESTDIR + prefix appropriately munged
2763 if build_system != 'windows'
2764 # On unixoid systems this is trivial, we just prepend the destdir
2765 assert(dir_prefix.startswith('/')) # enforced by meson
2766 test_install_location = '@0@@1@'.format(test_install_destdir, dir_prefix)
2768 # drives, drive-relative paths, etc make this complicated on windows, call
2769 # meson's logic for it
2771 meson_bin, meson_args, 'runpython', '-c',
2772 'import sys; from mesonbuild.scripts import destdir_join; print(destdir_join(sys.argv[4], sys.argv[5]))',
2773 test_install_destdir, dir_prefix]
2774 test_install_location = run_command(command, check: true).stdout().strip()
2777 meson_install_args = meson_args + ['install'] + {
2778 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
2783 meson_bin, args: meson_install_args ,
2784 env: {'DESTDIR':test_install_destdir},
2790 test_result_dir = meson.build_root() / 'testrun'
2793 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
2794 # inevitable conflicts from running tests in parallel, hackishly assign
2795 # different ports for different tests.
2799 test_env = environment()
2801 temp_install_bindir = test_install_location / get_option('bindir')
2802 test_env.set('PG_REGRESS', pg_regress.full_path())
2803 test_env.set('REGRESS_SHLIB', regress_module.full_path())
2805 # Test suites that are not safe by default but can be run if selected
2806 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
2807 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
2808 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
2810 # Add the temporary installation to the library search path on platforms where
2811 # that works (everything but windows, basically). On windows everything
2812 # library-like gets installed into bindir, solving that issue.
2813 if library_path_var != ''
2814 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
2819 ###############################################################
2821 ###############################################################
2823 testwrap = files('src/tools/testwrap')
2825 foreach test_dir : tests
2828 '--basedir', meson.build_root(),
2829 '--srcdir', test_dir['sd'],
2830 '--testgroup', test_dir['name'],
2833 foreach kind, v : test_dir
2834 if kind in ['sd', 'bd', 'name']
2840 if kind in ['regress', 'isolation', 'ecpg']
2841 if kind == 'regress'
2843 elif kind == 'isolation'
2844 runner = pg_isolation_regress
2846 runner = pg_regress_ecpg
2849 test_output = test_result_dir / test_dir['name'] / kind
2853 '--inputdir', t.get('inputdir', test_dir['sd']),
2854 '--expecteddir', t.get('expecteddir', test_dir['sd']),
2855 '--outputdir', test_output,
2856 '--temp-instance', test_output / 'tmp_check',
2858 '--dlpath', test_dir['bd'],
2859 '--max-concurrent-tests=20',
2860 '--port', testport.to_string(),
2861 ] + t.get('regress_args', [])
2863 if t.has_key('schedule')
2864 test_command += ['--schedule', t['schedule'],]
2867 if kind == 'isolation'
2868 test_command += t.get('specs', [])
2870 test_command += t.get('sql', [])
2874 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
2877 'suite': [test_dir['name']],
2880 'depends': test_deps + t.get('deps', []),
2882 } + t.get('test_kwargs', {})
2884 test(test_dir['name'] / kind,
2886 args: testwrap_base + [
2890 kwargs: test_kwargs,
2895 if not tap_tests_enabled
2901 '-I', meson.source_root() / 'src/test/perl',
2902 '-I', test_dir['sd'],
2905 # Add temporary install, the build directory for non-installed binaries and
2906 # also test/ for non-installed test binaries built separately.
2908 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
2910 foreach name, value : t.get('env', {})
2911 env.set(name, value)
2916 'suite': [test_dir['name']],
2918 'depends': test_deps + t.get('deps', []),
2920 } + t.get('test_kwargs', {})
2922 foreach onetap : t['tests']
2923 # Make tap test names prettier, remove t/ and .pl
2925 if onetap_p.startswith('t/')
2926 onetap_p = onetap.split('t/')[1]
2928 if onetap_p.endswith('.pl')
2929 onetap_p = fs.stem(onetap_p)
2932 test(test_dir['name'] / onetap_p,
2934 kwargs: test_kwargs,
2935 args: testwrap_base + [
2936 '--testname', onetap_p,
2938 test_dir['sd'] / onetap,
2943 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
2946 endforeach # kinds of tests
2948 endforeach # directories with tests
2952 ###############################################################
2954 ###############################################################
2956 alias_target('backend', backend_targets)
2957 alias_target('bin', bin_targets + [libpq_st])
2958 alias_target('pl', pl_targets)
2959 alias_target('contrib', contrib_targets)
2960 alias_target('testprep', testprep_targets)
2964 ###############################################################
2965 # The End, The End, My Friend
2966 ###############################################################
2968 if meson.version().version_compare('>=0.57')
2972 'data block size': cdata.get('BLCKSZ'),
2973 'WAL block size': cdata.get('XLOG_BLCKSZ') / 1024,
2974 'segment size': cdata.get('RELSEG_SIZE') / 131072,
2976 section: 'Data layout',
2981 'host system': '@0@ @1@'.format(host_system, host_cpu),
2982 'build system': '@0@ @1@'.format(build_machine.system(),
2983 build_machine.cpu_family()),
2990 'linker': '@0@'.format(cc.get_linker_id()),
2991 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
2993 section: 'Compiler',
2998 'CPP FLAGS': ' '.join(cppflags),
2999 'C FLAGS, functional': ' '.join(cflags),
3000 'C FLAGS, warnings': ' '.join(cflags_warn),
3001 'C FLAGS, modules': ' '.join(cflags_mod),
3002 'C FLAGS, user specified': ' '.join(get_option('c_args')),
3003 'LD FLAGS': ' '.join(ldflags + get_option('c_link_args')),
3005 section: 'Compiler Flags',
3011 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
3013 section: 'Compiler',
3018 'C++ FLAGS, functional': ' '.join(cxxflags),
3019 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
3020 'C++ FLAGS, user specified': ' '.join(get_option('cpp_args')),
3022 section: 'Compiler Flags',
3028 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
3031 section: 'Programs',
3037 'bsd_auth': bsd_auth,
3048 'plpython': python3_dep,
3050 'readline': readline,
3058 section: 'External libraries',