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
24 ###############################################################
26 ###############################################################
29 pkgconfig = import('pkgconfig')
31 host_system = host_machine.system()
32 host_cpu = host_machine.cpu_family()
34 cc = meson.get_compiler('c')
36 not_found_dep = dependency('', required: false)
37 thread_dep = dependency('threads')
41 ###############################################################
43 ###############################################################
45 # It's very easy to get into confusing states when the source directory
46 # contains an in-place build. E.g. the wrong pg_config.h will be used. So just
47 # refuse to build in that case.
49 # There's a more elaborate check later, that checks for conflicts around all
50 # generated files. But we can only do that much further down the line, so this
51 # quick check seems worth it. Adhering to this advice should clean up the
52 # conflict, but won't protect against somebody doing make distclean or just
53 # removing pg_config.h
54 errmsg_nonclean_base = '''
56 Non-clean source code directory detected.
58 To build with meson the source tree may not have an in-place, ./configure
59 style, build configured. You can have both meson and ./configure style builds
60 for the same source tree by building out-of-source / VPATH with
61 configure. Alternatively use a separate check out for meson based builds.
65 if fs.exists(meson.current_source_dir() / 'src' / 'include' / 'pg_config.h')
66 errmsg_cleanup = 'To clean up, run make maintainer-clean in the source tree.'
67 error(errmsg_nonclean_base.format(errmsg_cleanup))
72 ###############################################################
73 # Variables to be determined
74 ###############################################################
76 postgres_inc_d = ['src/include']
77 postgres_inc_d += get_option('extra_include_dirs')
79 postgres_lib_d = get_option('extra_lib_dirs')
98 backend_both_deps = []
104 # source of data for pg_config.h etc
105 cdata = configuration_data()
109 ###############################################################
110 # Version and other metadata
111 ###############################################################
113 pg_version = meson.project_version()
115 if pg_version.endswith('devel')
116 pg_version_arr = [pg_version.split('devel')[0], '0']
117 elif pg_version.contains('beta')
118 pg_version_arr = [pg_version.split('beta')[0], '0']
119 elif pg_version.contains('rc')
120 pg_version_arr = [pg_version.split('rc')[0], '0']
122 pg_version_arr = pg_version.split('.')
125 pg_version_major = pg_version_arr[0].to_int()
126 pg_version_minor = pg_version_arr[1].to_int()
127 pg_version_num = (pg_version_major * 10000) + pg_version_minor
129 pg_url = 'https://www.postgresql.org/'
131 cdata.set_quoted('PACKAGE_NAME', 'PostgreSQL')
132 cdata.set_quoted('PACKAGE_BUGREPORT', 'pgsql-bugs@lists.postgresql.org')
133 cdata.set_quoted('PACKAGE_URL', pg_url)
134 cdata.set_quoted('PACKAGE_VERSION', pg_version)
135 cdata.set_quoted('PACKAGE_STRING', 'PostgreSQL @0@'.format(pg_version))
136 cdata.set_quoted('PACKAGE_TARNAME', 'postgresql')
138 pg_version += get_option('extra_version')
139 cdata.set_quoted('PG_VERSION', pg_version)
140 cdata.set_quoted('PG_VERSION_STR', 'PostgreSQL @0@ on @1@, compiled by @2@-@3@'.format(
141 pg_version, build_machine.cpu_family(), cc.get_id(), cc.version()))
142 cdata.set_quoted('PG_MAJORVERSION', pg_version_major.to_string())
143 cdata.set('PG_MAJORVERSION_NUM', pg_version_major)
144 cdata.set('PG_MINORVERSION_NUM', pg_version_minor)
145 cdata.set('PG_VERSION_NUM', pg_version_num)
146 cdata.set_quoted('CONFIGURE_ARGS', '')
150 ###############################################################
151 # Basic platform specific configuration
152 ###############################################################
154 # meson's system names don't quite map to our "traditional" names. In some
155 # places we need the "traditional" name, e.g., for mapping
156 # src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
158 portname = host_system
160 exesuffix = '' # overridden below where necessary
161 dlsuffix = '.so' # overridden below where necessary
162 library_path_var = 'LD_LIBRARY_PATH'
164 # Format of file to control exports from libraries, and how to pass them to
165 # the compiler. For export_fmt @0@ is the path to the file export file.
166 export_file_format = 'gnu'
167 export_file_suffix = 'list'
168 export_fmt = '-Wl,--version-script=@0@'
170 # Flags to add when linking a postgres extension, @0@ is path to
171 # the relevant object on the platform.
172 mod_link_args_fmt = []
174 memset_loop_limit = 1024
176 # Choice of shared memory and semaphore implementation
180 # We implement support for some operating systems by pretending they're
181 # another. Map here, before determining system properties below
182 if host_system == 'dragonfly'
183 # apparently the most similar
184 host_system = 'netbsd'
187 if host_system == 'aix'
188 library_path_var = 'LIBPATH'
190 export_file_format = 'aix'
191 export_fmt = '-Wl,-bE:@0@'
192 mod_link_args_fmt = ['-Wl,-bI:@0@']
193 mod_link_with_dir = 'libdir'
194 mod_link_with_name = '@0@.imp'
196 # M:SRE sets a flag indicating that an object is a shared library. Seems to
197 # work in some circumstances without, but required in others.
198 ldflags_sl += '-Wl,-bM:SRE'
199 ldflags_be += '-Wl,-brtllib'
201 # Native memset() is faster, tested on:
202 # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
203 # - AIX 5.3 ML3, gcc 4.0.1
204 memset_loop_limit = 0
206 elif host_system == 'cygwin'
207 cppflags += '-D_GNU_SOURCE'
209 elif host_system == 'darwin'
211 library_path_var = 'DYLD_LIBRARY_PATH'
213 export_file_format = 'darwin'
214 export_fmt = '-exported_symbols_list=@0@'
216 mod_link_args_fmt = ['-bundle_loader', '@0@']
217 mod_link_with_dir = 'bindir'
218 mod_link_with_name = '@0@'
220 sysroot_args = [files('src/tools/darwin_sysroot'), get_option('darwin_sysroot')]
221 pg_sysroot = run_command(sysroot_args, check:true).stdout().strip()
222 message('darwin sysroot: @0@'.format(pg_sysroot))
223 cflags += ['-isysroot', pg_sysroot]
224 ldflags += ['-isysroot', pg_sysroot]
226 elif host_system == 'freebsd'
227 sema_kind = 'unnamed_posix'
229 elif host_system == 'linux'
230 sema_kind = 'unnamed_posix'
231 cppflags += '-D_GNU_SOURCE'
233 elif host_system == 'netbsd'
234 # We must resolve all dynamic linking in the core server at program start.
235 # Otherwise the postmaster can self-deadlock due to signals interrupting
236 # resolution of calls, since NetBSD's linker takes a lock while doing that
237 # and some postmaster signal handlers do things that will also acquire that
238 # lock. As long as we need "-z now", might as well specify "-z relro" too.
239 # While there's not a hard reason to adopt these settings for our other
240 # executables, there's also little reason not to, so just add them to
242 ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
244 elif host_system == 'openbsd'
247 elif host_system == 'sunos'
249 export_fmt = '-Wl,-M@0@'
250 cppflags += '-D_POSIX_PTHREAD_SEMANTICS'
252 elif host_system == 'windows'
256 library_path_var = ''
258 export_file_format = 'win'
259 export_file_suffix = 'def'
260 if cc.get_id() == 'msvc'
261 export_fmt = '/DEF:@0@'
262 mod_link_with_name = '@0@.exe.lib'
265 mod_link_with_name = 'lib@0@.exe.a'
267 mod_link_args_fmt = ['@0@']
268 mod_link_with_dir = 'libdir'
273 cdata.set('WIN32_STACK_RLIMIT', 4194304)
274 if cc.get_id() == 'msvc'
275 ldflags += '/INCREMENTAL:NO'
276 ldflags += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
277 # ldflags += '/nxcompat' # generated by msbuild, should have it for ninja?
279 ldflags += '-Wl,--stack,@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
282 os_deps += cc.find_library('ws2_32', required: true)
283 secur32_dep = cc.find_library('secur32', required: true)
284 backend_deps += secur32_dep
285 libpq_deps += secur32_dep
287 postgres_inc_d += 'src/include/port/win32'
288 if cc.get_id() == 'msvc'
289 postgres_inc_d += 'src/include/port/win32_msvc'
292 windows = import('windows')
295 # XXX: Should we add an option to override the host_system as an escape
297 error('unknown host system: @0@'.format(host_system))
302 ###############################################################
304 ###############################################################
307 perl = find_program(get_option('PERL'), required: true, native: true)
308 python = find_program(get_option('PYTHON'), required: true, native: true)
309 flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.31')
310 bison = find_program(get_option('BISON'), native: true, version: '>= 1.875')
311 sed = find_program(get_option('SED'), 'sed', native: true)
312 prove = find_program(get_option('PROVE'), native: true)
313 tar = find_program(get_option('TAR'), native: true)
314 gzip = find_program(get_option('GZIP'), native: true)
315 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
316 touch = find_program('touch', native: true)
317 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
318 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
319 missing = find_program('config/missing', native: true)
322 install_sh = find_program('config/install-sh', native: true)
326 bison_version_c = run_command(bison, '--version', check: true)
327 # bison version string helpfully is something like
328 # >>bison (GNU bison) 3.8.1<<
329 bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
330 if bison_version.version_compare('>=3.0')
331 bison_flags += ['-Wno-deprecated']
334 bison_cmd = [bison, bison_flags, '-o', '@OUTPUT0@', '-d', '@INPUT@']
336 'output': ['@BASENAME@.c', '@BASENAME@.h'],
337 'command': bison_cmd,
341 flex_wrapper = files('src/tools/pgflex')
342 flex_cmd = [python, flex_wrapper,
343 '--builddir', '@BUILD_ROOT@',
344 '--srcdir', '@SOURCE_ROOT@',
345 '--privatedir', '@PRIVATE_DIR@',
346 '--flex', flex, '--perl', perl,
347 '-i', '@INPUT@', '-o', '@OUTPUT0@',
350 wget = find_program('wget', required: false, native: true)
351 wget_flags = ['-O', '@OUTPUT0@', '--no-use-server-timestamps']
355 ###############################################################
356 # Path to meson (for tests etc)
357 ###############################################################
359 # NB: this should really be part of meson, see
360 # https://github.com/mesonbuild/meson/issues/8511
361 meson_binpath_r = run_command(python, 'src/tools/find_meson', check: true)
363 if meson_binpath_r.returncode() != 0 or meson_binpath_r.stdout() == ''
364 error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
365 meson_binpath_r.returncode(),
366 meson_binpath_r.stdout(),
367 meson_binpath_r.stderr()))
370 meson_binpath_s = meson_binpath_r.stdout().split('\n')
371 meson_binpath_len = meson_binpath_s.length()
373 if meson_binpath_len < 1
374 error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
381 foreach e : meson_binpath_s
392 if meson_impl not in ['muon', 'meson']
393 error('unknown meson implementation "@0@"'.format(meson_impl))
396 meson_bin = find_program(meson_binpath, native: true)
400 ###############################################################
402 ###############################################################
404 cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
406 cdata.set('BLCKSZ', get_option('blocksize').to_int() * 1024, description:
407 '''Size of a disk block --- this also limits the size of a tuple. You can set
408 it bigger if you need bigger tuples (although TOAST should reduce the need
409 to have large tuples, since fields can be spread across multiple tuples).
410 BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
411 currently 2^15 (32768). This is determined by the 15-bit widths of the
412 lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
413 Changing BLCKSZ requires an initdb.''')
415 cdata.set('XLOG_BLCKSZ', get_option('wal_blocksize').to_int() * 1024)
416 cdata.set('RELSEG_SIZE', get_option('segsize') * 131072)
417 cdata.set('DEF_PGPORT', get_option('pgport'))
418 cdata.set_quoted('DEF_PGPORT_STR', get_option('pgport').to_string())
419 cdata.set_quoted('PG_KRB_SRVNAM', get_option('krb_srvnam'))
420 if get_option('system_tzdata') != ''
421 cdata.set_quoted('SYSTEMTZDIR', get_option('system_tzdata'))
426 ###############################################################
428 ###############################################################
430 # These are set by the equivalent --xxxdir configure options. We
431 # append "postgresql" to some of them, if the string does not already
432 # contain "pgsql" or "postgres", in order to avoid directory clutter.
436 dir_prefix = get_option('prefix')
438 dir_bin = get_option('bindir')
440 dir_data = get_option('datadir')
441 if not (dir_data.contains('pgsql') or dir_data.contains('postgres'))
442 dir_data = dir_data / pkg
445 dir_sysconf = get_option('sysconfdir')
446 if not (dir_sysconf.contains('pgsql') or dir_sysconf.contains('postgres'))
447 dir_sysconf = dir_sysconf / pkg
450 dir_lib = get_option('libdir')
452 dir_lib_pkg = dir_lib
453 if not (dir_lib_pkg.contains('pgsql') or dir_lib_pkg.contains('postgres'))
454 dir_lib_pkg = dir_lib_pkg / pkg
457 dir_pgxs = dir_lib_pkg / 'pgxs'
459 dir_include = get_option('includedir')
461 dir_include_pkg = dir_include
462 dir_include_pkg_rel = ''
463 if not (dir_include_pkg.contains('pgsql') or dir_include_pkg.contains('postgres'))
464 dir_include_pkg = dir_include_pkg / pkg
465 dir_include_pkg_rel = pkg
468 dir_man = get_option('mandir')
470 # FIXME: These used to be separately configurable - worth adding?
471 dir_doc = get_option('datadir') / 'doc' / 'postgresql'
472 dir_doc_html = dir_doc
474 dir_locale = get_option('localedir')
478 dir_bitcode = dir_lib_pkg / 'bitcode'
479 dir_include_internal = dir_include_pkg / 'internal'
480 dir_include_server = dir_include_pkg / 'server'
481 dir_include_extension = dir_include_server / 'extension'
482 dir_data_extension = dir_data / 'extension'
486 ###############################################################
487 # Search paths, preparation for compiler tests
489 # NB: Arguments added later are not automatically used for subsequent
490 # configuration-time checks (so they are more isolated). If they should be
491 # used, they need to be added to test_c_args as well.
492 ###############################################################
494 postgres_inc = [include_directories(postgres_inc_d)]
495 test_lib_d = postgres_lib_d
496 test_c_args = cppflags + cflags
500 ###############################################################
502 ###############################################################
504 bsd_authopt = get_option('bsd_auth')
505 bsd_auth = not_found_dep
506 if cc.check_header('bsd_auth.h', required: bsd_authopt,
507 args: test_c_args, include_directories: postgres_inc)
508 cdata.set('USE_BSD_AUTH', 1)
509 bsd_auth = declare_dependency()
514 ###############################################################
517 # For now don't search for DNSServiceRegister in a library - only Apple's
518 # Bonjour implementation, which is always linked, works.
519 ###############################################################
521 bonjouropt = get_option('bonjour')
522 bonjour = dependency('', required : false)
523 if cc.check_header('dns_sd.h', required: bonjouropt,
524 args: test_c_args, include_directories: postgres_inc) and \
525 cc.has_function('DNSServiceRegister',
526 args: test_c_args, include_directories: postgres_inc)
527 cdata.set('USE_BONJOUR', 1)
528 bonjour = declare_dependency()
533 ###############################################################
535 ###############################################################
537 gssapiopt = get_option('gssapi')
540 if not gssapiopt.disabled()
541 gssapi = dependency('krb5-gssapi', required: gssapiopt)
542 have_gssapi = gssapi.found()
545 elif cc.check_header('gssapi/gssapi.h', dependencies: gssapi, required: false,
546 args: test_c_args, include_directories: postgres_inc)
547 cdata.set('HAVE_GSSAPI_GSSAPI_H', 1)
548 elif cc.check_header('gssapi.h', args: test_c_args, dependencies: gssapi, required: gssapiopt)
549 cdata.set('HAVE_GSSAPI_H', 1)
555 elif cc.has_function('gss_init_sec_context', dependencies: gssapi,
556 args: test_c_args, include_directories: postgres_inc)
557 cdata.set('ENABLE_GSS', 1)
559 krb_srvtab = 'FILE:/@0@/krb5.keytab)'.format(get_option('sysconfdir'))
560 cdata.set_quoted('PG_KRB_SRVTAB', krb_srvtab)
561 elif gssapiopt.enabled()
562 error('''could not find function 'gss_init_sec_context' required for GSSAPI''')
568 gssapi = not_found_dep
573 ###############################################################
575 ###############################################################
577 ldapopt = get_option('ldap')
578 if host_system == 'windows'
579 ldap = cc.find_library('wldap32', required: ldapopt)
582 # macos framework dependency is buggy for ldap (one can argue whether it's
583 # Apple's or meson's fault), leading to an endless recursion with ldap.h
584 # including itself. See https://github.com/mesonbuild/meson/issues/10002
585 # Luckily we only need pkg-config support, so the workaround isn't
587 ldap = dependency('ldap', method: 'pkg-config', required: false)
590 # Before 2.5 openldap didn't have a pkg-config file, and it might not be
593 ldap = cc.find_library('ldap', required: ldapopt, dirs: test_lib_d,
594 has_headers: 'ldap.h', header_include_directories: postgres_inc)
596 # The separate ldap_r library only exists in OpenLDAP < 2.5, and if we
597 # have 2.5 or later, we shouldn't even probe for ldap_r (we might find a
598 # library from a separate OpenLDAP installation). The most reliable
599 # way to check that is to check for a function introduced in 2.5.
601 # don't have ldap, we shouldn't check for ldap_r
602 elif cc.has_function('ldap_verify_credentials',
603 dependencies: ldap, args: test_c_args)
604 ldap_r = ldap # ldap >= 2.5, no need for ldap_r
607 # Use ldap_r for FE if available, else assume ldap is thread-safe.
608 ldap_r = cc.find_library('ldap_r', required: false, dirs: test_lib_d,
609 has_headers: 'ldap.h', header_include_directories: postgres_inc)
610 if not ldap_r.found()
613 # On some platforms ldap_r fails to link without PTHREAD_LIBS.
614 ldap_r = declare_dependency(dependencies: [ldap_r, thread_dep])
617 # PostgreSQL sometimes loads libldap_r and plain libldap into the same
618 # process. Check for OpenLDAP versions known not to tolerate doing so;
619 # assume non-OpenLDAP implementations are safe. The dblink test suite
620 # exercises the hazardous interaction directly.
621 compat_test_code = '''
623 #if !defined(LDAP_VENDOR_VERSION) || \
624 (defined(LDAP_API_FEATURE_X_OPENLDAP) && \
625 LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
629 if not cc.compiles(compat_test_code,
630 name: 'LDAP implementation compatible',
631 dependencies: ldap, args: test_c_args)
633 *** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
634 *** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
635 *** also uses LDAP will crash on exit.''')
640 # XXX: this shouldn't be tested in the windows case, but should be tested in
641 # the dependency() success case
642 if ldap.found() and cc.has_function('ldap_initialize',
643 dependencies: ldap, args: test_c_args)
644 cdata.set('HAVE_LDAP_INITIALIZE', 1)
649 assert(ldap_r.found())
650 cdata.set('USE_LDAP', 1)
652 assert(not ldap_r.found())
657 ###############################################################
659 ###############################################################
661 llvmopt = get_option('llvm')
662 if not llvmopt.disabled()
663 add_languages('cpp', required: true, native: false)
664 llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
668 cdata.set('USE_LLVM', 1)
670 cpp = meson.get_compiler('cpp')
672 llvm_binpath = llvm.get_variable(configtool: 'bindir')
674 ccache = find_program('ccache', native: true, required: false)
675 clang = find_program(llvm_binpath / 'clang', required: true)
683 ###############################################################
685 ###############################################################
687 icuopt = get_option('icu')
688 if not icuopt.disabled()
689 icu = dependency('icu-uc', required: icuopt.enabled())
690 icu_i18n = dependency('icu-i18n', required: icuopt.enabled())
693 cdata.set('USE_ICU', 1)
698 icu_i18n = not_found_dep
703 ###############################################################
705 ###############################################################
707 libxmlopt = get_option('libxml')
708 if not libxmlopt.disabled()
709 libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
712 cdata.set('USE_LIBXML', 1)
715 libxml = not_found_dep
720 ###############################################################
722 ###############################################################
724 libxsltopt = get_option('libxslt')
725 if not libxsltopt.disabled()
726 libxslt = dependency('libxslt', required: libxsltopt)
729 cdata.set('USE_LIBXSLT', 1)
732 libxslt = not_found_dep
737 ###############################################################
739 ###############################################################
741 lz4opt = get_option('lz4')
742 if not lz4opt.disabled()
743 lz4 = dependency('liblz4', required: lz4opt)
746 cdata.set('USE_LZ4', 1)
747 cdata.set('HAVE_LIBLZ4', 1)
756 ###############################################################
757 # Library: Tcl (for pltcl)
759 # NB: tclConfig.sh is used in autoconf build for getting
760 # TCL_SHARED_BUILD, TCL_INCLUDE_SPEC, TCL_LIBS and TCL_LIB_SPEC
761 # variables. For now we have not seen a need to copy
762 # that behaviour to the meson build.
763 ###############################################################
765 tclopt = get_option('pltcl')
766 tcl_version = get_option('tcl_version')
767 tcl_dep = not_found_dep
768 if not tclopt.disabled()
771 tcl_dep = dependency(tcl_version, required: false)
773 if not tcl_dep.found()
774 tcl_dep = cc.find_library(tcl_version,
779 if not cc.has_header('tcl.h', dependencies: tcl_dep, required: tclopt)
780 tcl_dep = not_found_dep
786 ###############################################################
788 ###############################################################
790 pamopt = get_option('pam')
791 if not pamopt.disabled()
792 pam = dependency('pam', required: false)
795 pam = cc.find_library('pam', required: pamopt, dirs: test_lib_d)
799 pam_header_found = false
801 # header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.
802 if cc.check_header('security/pam_appl.h', dependencies: pam, required: false,
803 args: test_c_args, include_directories: postgres_inc)
804 cdata.set('HAVE_SECURITY_PAM_APPL_H', 1)
805 pam_header_found = true
806 elif cc.check_header('pam/pam_appl.h', dependencies: pam, required: pamopt,
807 args: test_c_args, include_directories: postgres_inc)
808 cdata.set('HAVE_PAM_PAM_APPL_H', 1)
809 pam_header_found = true
813 cdata.set('USE_PAM', 1)
824 ###############################################################
825 # Library: Perl (for plperl)
826 ###############################################################
828 perlopt = get_option('plperl')
829 perl_dep = not_found_dep
830 if not perlopt.disabled()
833 # First verify that perl has the necessary dependencies installed
834 perl_mods = run_command(
836 '-MConfig', '-MOpcode', '-MExtUtils::Embed', '-MExtUtils::ParseXS',
839 if perl_mods.returncode() != 0
840 perl_may_work = false
841 perl_msg = 'perl installation does not have the required modules'
844 # Then inquire perl about its configuration
846 perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
847 perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
848 archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
849 privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
850 useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
852 perl_inc_dir = '@0@/CORE'.format(archlibexp)
854 if useshrplib != 'true'
855 perl_may_work = false
856 perl_msg = 'need a shared perl'
861 # On most platforms, archlibexp is also where the Perl include files live ...
862 perl_ccflags = ['-I@0@'.format(perl_inc_dir)]
863 # ... but on newer macOS versions, we must use -iwithsysroot to look
865 if not fs.is_file('@0@/perl.h'.format(perl_inc_dir)) and \
866 fs.is_file('@0@@1@/perl.h'.format(pg_sysroot, perl_inc_dir))
867 perl_ccflags = ['-iwithsysroot', perl_inc_dir]
870 # check compiler finds header
871 if not cc.has_header('perl.h', required: false,
872 args: test_c_args + perl_ccflags, include_directories: postgres_inc)
873 perl_may_work = false
874 perl_msg = 'missing perl.h'
879 perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
881 # See comments for PGAC_CHECK_PERL_EMBED_CCFLAGS in perl.m4
882 foreach flag : perl_ccflags_r.split(' ')
883 if flag.startswith('-D') and \
884 (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
889 if host_system == 'windows'
890 perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
893 message('CCFLAGS recommended by perl: @0@'.format(perl_ccflags_r))
894 message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
896 # We are after Embed's ldopts, but without the subset mentioned in
897 # Config's ccdlflags and ldflags. (Those are the choices of those who
898 # built the Perl installation, which are not necessarily appropriate
899 # for building PostgreSQL.)
900 ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
901 undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split()
902 undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split()
905 foreach ldopt : ldopts.split(' ')
906 if ldopt == '' or ldopt in undesired
910 perl_ldopts += ldopt.strip('"')
913 message('LDFLAGS recommended by perl: "@0@"'.format(ldopts))
914 message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts)))
916 perl_dep_int = declare_dependency(
917 compile_args: perl_ccflags,
918 link_args: perl_ldopts,
919 version: perlversion,
922 # While we're at it, check that we can link to libperl.
923 # On most platforms, if perl.h is there then libperl.so will be too, but
924 # at this writing Debian packages them separately.
928 #define __inline__ inline
936 if not cc.links(perl_link_test, name: 'libperl',
937 args: test_c_args + perl_ccflags + perl_ldopts,
938 include_directories: postgres_inc)
939 perl_may_work = false
940 perl_msg = 'missing libperl'
943 endif # perl_may_work
946 perl_dep = perl_dep_int
949 error('dependency plperl failed: @0@'.format(perl_msg))
951 message('disabling optional dependency plperl: @0@'.format(perl_msg))
958 ###############################################################
959 # Library: Python (for plpython)
960 ###############################################################
962 pyopt = get_option('plpython')
963 if not pyopt.disabled()
964 pm = import('python')
965 python3_inst = pm.find_installation(required: pyopt.enabled())
966 python3_dep = python3_inst.dependency(embed: true, required: pyopt.enabled())
967 if not cc.check_header('Python.h', dependencies: python3_dep, required: pyopt.enabled())
968 python3_dep = not_found_dep
971 python3_dep = not_found_dep
976 ###############################################################
978 ###############################################################
980 if not get_option('readline').disabled()
981 libedit_preferred = get_option('libedit_preferred')
982 # Set the order of readline dependencies
983 check_readline_deps = libedit_preferred ? \
984 ['libedit', 'readline'] : ['readline', 'libedit']
986 foreach readline_dep : check_readline_deps
987 readline = dependency(readline_dep, required: false)
988 if not readline.found()
989 readline = cc.find_library(readline_dep,
990 required: get_option('readline').enabled(),
999 cdata.set('HAVE_LIBREADLINE', 1)
1002 'header_prefix': 'editline/',
1003 'flag_prefix': 'EDITLINE_',
1006 'header_prefix': 'readline/',
1007 'flag_prefix': 'READLINE_',
1010 'header_prefix': '',
1014 # Set the order of prefixes
1015 prefixes = libedit_preferred ? \
1016 [editline_prefix, default_prefix, readline_prefix] : \
1017 [readline_prefix, default_prefix, editline_prefix]
1019 at_least_one_header_found = false
1020 foreach header : ['history', 'readline']
1022 foreach prefix : prefixes
1023 header_file = '@0@@1@.h'.format(prefix['header_prefix'], header)
1024 # Check history.h and readline.h
1025 if not is_found and cc.has_header(header_file,
1026 args: test_c_args, include_directories: postgres_inc,
1027 dependencies: [readline], required: false)
1028 if header == 'readline'
1029 readline_h = header_file
1031 cdata.set('HAVE_@0@@1@_H'.format(prefix['flag_prefix'], header).to_upper(), 1)
1033 at_least_one_header_found = true
1038 if not at_least_one_header_found
1039 error('''readline header not found
1040 If you have @0@ already installed, see see meson-log/meson-log.txt for details on the
1041 failure. It is possible the compiler isn't looking in the proper directory.
1042 Use -Dreadline=false to disable readline support.'''.format(readline_dep))
1047 'history_truncate_file',
1048 'rl_completion_matches',
1049 'rl_filename_completion_function',
1050 'rl_reset_screen_size',
1054 foreach func : check_funcs
1055 found = cc.has_function(func, dependencies: [readline],
1056 args: test_c_args, include_directories: postgres_inc)
1057 cdata.set('HAVE_'+func.to_upper(), found ? 1 : false)
1061 'rl_completion_suppress_quote',
1062 'rl_filename_quote_characters',
1063 'rl_filename_quoting_function',
1066 foreach var : check_vars
1067 cdata.set('HAVE_'+var.to_upper(),
1068 cc.has_header_symbol(readline_h, var,
1069 args: test_c_args, include_directories: postgres_inc,
1070 prefix: '#include <stdio.h>',
1071 dependencies: [readline]) ? 1 : false)
1074 # If found via cc.find_library() ensure headers are found when using the
1075 # dependency. On meson < 0.57 one cannot do compiler checks using the
1076 # dependency returned by declare_dependency(), so we can't do this above.
1077 if readline.type_name() == 'library'
1078 readline = declare_dependency(dependencies: readline,
1079 include_directories: postgres_inc)
1083 # XXX: Figure out whether to implement mingw warning equivalent
1085 readline = not_found_dep
1090 ###############################################################
1092 ###############################################################
1094 selinux = not_found_dep
1095 selinuxopt = get_option('selinux')
1096 if meson.version().version_compare('>=0.59')
1097 selinuxopt = selinuxopt.disable_auto_if(host_system != 'linux')
1099 selinux = dependency('libselinux', required: selinuxopt, version: '>= 2.1.10')
1100 cdata.set('HAVE_LIBSELINUX',
1101 selinux.found() ? 1 : false)
1105 ###############################################################
1107 ###############################################################
1109 systemd = not_found_dep
1110 systemdopt = get_option('systemd')
1111 if meson.version().version_compare('>=0.59')
1112 systemdopt = systemdopt.disable_auto_if(host_system != 'linux')
1114 systemd = dependency('libsystemd', required: systemdopt)
1115 cdata.set('USE_SYSTEMD', systemd.found() ? 1 : false)
1119 ###############################################################
1121 ###############################################################
1123 if get_option('ssl') == 'openssl'
1125 # Try to find openssl via pkg-config et al, if that doesn't work
1126 # (e.g. because it's provided as part of the OS, like on FreeBSD), look for
1127 # the library names that we know about.
1129 # via pkg-config et al
1130 ssl = dependency('openssl', required: false)
1132 # via library + headers
1134 ssl_lib = cc.find_library('ssl',
1136 header_include_directories: postgres_inc,
1137 has_headers: ['openssl/ssl.h', 'openssl/err.h'])
1138 crypto_lib = cc.find_library('crypto',
1140 header_include_directories: postgres_inc)
1141 ssl_int = [ssl_lib, crypto_lib]
1143 ssl = declare_dependency(dependencies: ssl_int,
1144 include_directories: postgres_inc)
1146 cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: true)
1147 cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: true)
1153 ['CRYPTO_new_ex_data', {'required': true}],
1154 ['SSL_new', {'required': true}],
1156 # Function introduced in OpenSSL 1.0.2.
1157 ['X509_get_signature_nid'],
1159 # Functions introduced in OpenSSL 1.1.0. We used to check for
1160 # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
1161 # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1162 # doesn't have these OpenSSL 1.1.0 functions. So check for individual
1164 ['OPENSSL_init_ssl'],
1167 ['ASN1_STRING_get0_data'],
1171 # OpenSSL versions before 1.1.0 required setting callback functions, for
1172 # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
1173 # function was removed.
1177 foreach c : check_funcs
1179 val = cc.has_function(func, args: test_c_args, dependencies: ssl_int)
1180 required = c.get(1, {}).get('required', false)
1181 if required and not val
1182 error('openssl function @0@ is required'.format(func))
1184 cdata.set('HAVE_' + func.to_upper(), val ? 1 : false)
1188 cdata.set('USE_OPENSSL', 1,
1189 description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
1190 cdata.set('OPENSSL_API_COMPAT', '0x10001000L',
1191 description: '''Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.''')
1198 ###############################################################
1200 ###############################################################
1202 uuidopt = get_option('uuid')
1203 if uuidopt != 'none'
1204 uuidname = uuidopt.to_upper()
1205 if uuidopt == 'e2fs'
1206 uuid = dependency('uuid', required: true)
1207 uuidfunc = 'uuid_generate'
1208 uuidheader = 'uuid/uuid.h'
1209 elif uuidopt == 'bsd'
1210 # libc should have uuid function
1211 uuid = declare_dependency()
1212 uuidfunc = 'uuid_to_string'
1213 uuidheader = 'uuid.h'
1214 elif uuidopt == 'ossp'
1215 uuid = dependency('ossp-uuid', required: true)
1216 uuidfunc = 'uuid_export'
1217 uuidheader = 'ossp/uuid.h'
1222 if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
1223 error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
1225 cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
1227 cdata.set('HAVE_UUID_@0@'.format(uuidname), 1,
1228 description: 'Define to 1 if you have @0@ UUID support.'.format(uuidname))
1230 uuid = not_found_dep
1235 ###############################################################
1237 ###############################################################
1239 zlibopt = get_option('zlib')
1240 zlib = not_found_dep
1241 if not zlibopt.disabled()
1242 zlib_t = dependency('zlib', required: zlibopt)
1244 if zlib_t.type_name() == 'internal'
1245 # if fallback was used, we don't need to test if headers are present (they
1246 # aren't built yet, so we can't test)
1248 elif not zlib_t.found()
1249 warning('did not find zlib')
1250 elif not cc.has_header('zlib.h',
1251 args: test_c_args, include_directories: postgres_inc,
1252 dependencies: [zlib_t], required: zlibopt.enabled())
1253 warning('zlib header not found')
1254 elif not cc.has_type('z_streamp',
1255 dependencies: [zlib_t], prefix: '#include <zlib.h>',
1256 args: test_c_args, include_directories: postgres_inc)
1257 if zlibopt.enabled()
1258 error('zlib version is too old')
1260 warning('zlib version is too old')
1267 cdata.set('HAVE_LIBZ', 1)
1273 ###############################################################
1274 # Library: tap test dependencies
1275 ###############################################################
1277 # Check whether tap tests are enabled or not
1278 tap_tests_enabled = false
1279 tapopt = get_option('tap_tests')
1280 if not tapopt.disabled()
1281 # Checking for perl modules for tap tests
1282 perl_ipc_run_check = run_command(perl, 'config/check_modules.pl', check: false)
1283 if perl_ipc_run_check.returncode() != 0
1284 message(perl_ipc_run_check.stderr().strip())
1286 error('Additional Perl modules are required to run TAP tests.')
1288 warning('Additional Perl modules are required to run TAP tests.')
1291 tap_tests_enabled = true
1297 ###############################################################
1299 ###############################################################
1301 zstdopt = get_option('zstd')
1302 if not zstdopt.disabled()
1303 zstd = dependency('libzstd', required: zstdopt, version: '>=1.4.0')
1306 cdata.set('USE_ZSTD', 1)
1307 cdata.set('HAVE_LIBZSTD', 1)
1311 zstd = not_found_dep
1316 ###############################################################
1318 ###############################################################
1320 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
1321 # unnecessarily, because we optionally rely on newer features.
1323 #include <stdbool.h>
1324 #include <complex.h>
1326 #include <inttypes.h>
1328 struct named_init_test {
1333 extern void structfunc(struct named_init_test);
1335 int main(int argc, char **argv)
1337 struct named_init_test nit = {
1342 for (int loop_var = 0; loop_var < 3; loop_var++)
1347 structfunc((struct named_init_test){1, 0});
1353 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
1354 if cc.compiles(c99_test, name: 'c99 with -std=c99',
1355 args: test_c_args + ['-std=c99'])
1356 test_c_args += '-std=c99'
1357 cflags += '-std=c99'
1359 error('C compiler does not support C99')
1363 sizeof_long = cc.sizeof('long', args: test_c_args)
1364 cdata.set('SIZEOF_LONG', sizeof_long)
1366 cdata.set('HAVE_LONG_INT_64', 1)
1367 cdata.set('PG_INT64_TYPE', 'long int')
1368 cdata.set_quoted('INT64_MODIFIER', 'l')
1369 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
1370 cdata.set('HAVE_LONG_LONG_INT_64', 1)
1371 cdata.set('PG_INT64_TYPE', 'long long int')
1372 cdata.set_quoted('INT64_MODIFIER', 'll')
1374 error('do not know how to get a 64bit int')
1377 if host_machine.endian() == 'big'
1378 cdata.set('WORDS_BIGENDIAN', 1)
1381 alignof_types = ['short', 'int', 'long', 'double']
1383 foreach t : alignof_types
1384 align = cc.alignment(t, args: test_c_args)
1388 cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
1390 cdata.set('MAXIMUM_ALIGNOF', maxalign)
1392 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
1393 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
1396 # Check if __int128 is a working 128 bit integer type, and if so
1397 # define PG_INT128_TYPE to that typename.
1399 # This currently only detects a GCC/clang extension, but support for other
1400 # environments may be added in the future.
1402 # For the moment we only test for support for 128bit math; support for
1403 # 128bit literals and snprintf is not required.
1406 * We don't actually run this test, just link it to verify that any support
1407 * functions needed for __int128 are present.
1409 * These are globals to discourage the compiler from folding all the
1410 * arithmetic tests down to compile-time constants. We do not have
1411 * convenient support for 128bit literals at this point...
1413 __int128 a = 48828125;
1414 __int128 b = 97656250;
1419 a = (a << 12) + 1; /* 200000000001 */
1420 b = (b << 12) + 5; /* 400000000005 */
1421 /* try the most relevant arithmetic ops */
1424 /* must use the results, else compiler may optimize arithmetic away */
1430 buggy_int128 = false
1432 # Use of non-default alignment with __int128 tickles bugs in some compilers.
1433 # If not cross-compiling, we can test for bugs and disable use of __int128
1434 # with buggy compilers. If cross-compiling, hope for the best.
1435 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
1436 if not meson.is_cross_build()
1438 /* This must match the corresponding code in c.h: */
1439 #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
1440 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
1442 typedef __int128 int128a
1443 #if defined(pg_attribute_aligned)
1444 pg_attribute_aligned(8)
1449 void pass_by_val(void *buffer, int128a par) { holder = par; }
1453 long int i64 = 97656225L << 12;
1455 pass_by_val(main, (int128a) i64);
1459 name: '__int128 alignment bug',
1461 assert(r.compiled())
1462 if r.returncode() != 0
1464 message('__int128 support present but buggy and thus disabled')
1469 cdata.set('PG_INT128_TYPE', '__int128')
1470 cdata.set('ALIGNOF_PG_INT128_TYPE', cc.
1471 alignment('__int128', args: test_c_args))
1476 # Check if the C compiler knows computed gotos (gcc extension, also
1477 # available in at least clang). If so, define HAVE_COMPUTED_GOTO.
1479 # Checking whether computed gotos are supported syntax-wise ought to
1480 # be enough, as the syntax is otherwise illegal.
1482 static inline int foo(void)
1484 void *labeladdrs[] = {&&my_label};
1485 goto *labeladdrs[0];
1490 cdata.set('HAVE_COMPUTED_GOTO', 1)
1494 # Check if the C compiler understands _Static_assert(),
1495 # and define HAVE__STATIC_ASSERT if so.
1497 # We actually check the syntax ({ _Static_assert(...) }), because we need
1498 # gcc-style compound expressions to be able to wrap the thing into macros.
1500 int main(int arg, char **argv)
1502 ({ _Static_assert(1, "foo"); });
1506 cdata.set('HAVE__STATIC_ASSERT', 1)
1510 # We use <stdbool.h> if we have it and it declares type bool as having
1511 # size 1. Otherwise, c.h will fall back to declaring bool as unsigned char.
1512 if cc.has_type('_Bool', args: test_c_args) \
1513 and cc.has_type('bool', prefix: '#include <stdbool.h>', args: test_c_args) \
1514 and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
1515 cdata.set('HAVE__BOOL', 1)
1516 cdata.set('PG_USE_STDBOOL', 1)
1520 # Need to check a call with %m because netbsd supports gnu_printf but emits a
1521 # warning for each use of %m.
1522 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
1524 extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));
1525 static void call_log(void)
1527 emit_log(0, "error: %s: %m", "foo");
1530 attrib_error_args = cc.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
1531 foreach a : printf_attributes
1532 if cc.compiles(testsrc.format(a),
1533 args: test_c_args + attrib_error_args, name: 'format ' + a)
1534 cdata.set('PG_PRINTF_ATTRIBUTE', a)
1540 if cc.has_function_attribute('visibility:default') and \
1541 cc.has_function_attribute('visibility:hidden')
1542 cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
1544 # Only newer versions of meson know not to apply gnu_symbol_visibility =
1545 # inlineshidden to C code as well... Any either way, we want to put these
1546 # flags into exported files (pgxs, .pc files).
1547 cflags_mod += '-fvisibility=hidden'
1548 cxxflags_mod += ['-fvisibility=hidden', '-fvisibility-inlines-hidden']
1549 ldflags_mod += '-fvisibility=hidden'
1553 # Check if various builtins exist. Some builtins are tested separately,
1554 # because we want to test something more complicated than the generic case.
1567 foreach builtin : builtins
1568 fname = '__builtin_@0@'.format(builtin)
1569 if cc.has_function(fname, args: test_c_args)
1570 cdata.set('HAVE@0@'.format(fname.to_upper()), 1)
1575 # Check if the C compiler understands __builtin_types_compatible_p,
1576 # and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
1578 # We check usage with __typeof__, though it's unlikely any compiler would
1579 # have the former and not the latter.
1582 static int y[__builtin_types_compatible_p(__typeof__(x), int)];
1584 name: '__builtin_types_compatible_p',
1586 cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
1590 # Check if the C compiler understands __builtin_$op_overflow(),
1591 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
1593 # Check for the most complicated case, 64 bit multiplication, as a
1594 # proxy for all of the operations. To detect the case where the compiler
1595 # knows the function but library support is missing, we must link not just
1596 # compile, and store the results in global variables so the compiler doesn't
1597 # optimize away the call.
1605 return __builtin_mul_overflow(a, b, &result);
1607 name: '__builtin_mul_overflow',
1608 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
1610 cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
1614 # XXX: The configure.ac check for __cpuid() is broken, we don't copy that
1615 # here. To prevent problems due to two detection methods working, stop
1616 # checking after one.
1619 int main(int arg, char **argv)
1621 unsigned int exx[4] = {0, 0, 0, 0};
1622 __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
1624 ''', name: '__get_cpuid',
1626 cdata.set('HAVE__GET_CPUID', 1)
1629 int main(int arg, char **argv)
1631 unsigned int exx[4] = {0, 0, 0, 0};
1634 ''', name: '__cpuid',
1636 cdata.set('HAVE__CPUID', 1)
1640 # Defend against clang being used on x86-32 without SSE2 enabled. As current
1641 # versions of clang do not understand -fexcess-precision=standard, the use of
1642 # x87 floating point operations leads to problems like isinf possibly returning
1643 # false for a value that is infinite when converted from the 80bit register to
1644 # the 8byte memory representation.
1646 # Only perform the test if the compiler doesn't understand
1647 # -fexcess-precision=standard, that way a potentially fixed compiler will work
1649 if '-fexcess-precision=standard' not in cflags
1650 if not cc.compiles('''
1651 #if defined(__clang__) && defined(__i386__) && !defined(__SSE2_MATH__)
1654 name: '', args: test_c_args)
1655 error('Compiling PostgreSQL with clang, on 32bit x86, requires SSE2 support. Use -msse2 or use gcc.')
1661 ###############################################################
1663 ###############################################################
1665 common_functional_flags = [
1666 # Disable strict-aliasing rules; needed for gcc 3.3+
1667 '-fno-strict-aliasing',
1668 # Disable optimizations that assume no overflow; needed for gcc 4.3+
1670 '-fexcess-precision=standard',
1673 cflags += cc.get_supported_arguments(common_functional_flags)
1675 cxxflags += cpp.get_supported_arguments(common_functional_flags)
1678 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
1679 unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
1681 common_warning_flags = [
1682 '-Wmissing-prototypes',
1684 # Really don't want VLAs to be used in our dialect of C
1686 # On macOS, complain about usage of symbols newer than the deployment target
1687 '-Werror=unguarded-availability-new',
1689 '-Wmissing-format-attribute',
1690 '-Wimplicit-fallthrough=3',
1691 '-Wcast-function-type',
1692 # This was included in -Wall/-Wformat in older GCC versions
1693 '-Wformat-security',
1696 cflags_warn += cc.get_supported_arguments(common_warning_flags)
1698 cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
1701 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
1702 # the result for them
1703 if cc.has_argument('-Wdeclaration-after-statement')
1704 cflags_warn += '-Wdeclaration-after-statement'
1705 using_declaration_after_statement_warning = true
1707 using_declaration_after_statement_warning = false
1711 # The following tests want to suppress various unhelpful warnings by adding
1712 # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo
1713 # switches, so we have to test for the positive form and if that works,
1714 # add the negative form.
1716 negative_warning_flags = [
1717 # Suppress clang's unhelpful unused-command-line-argument warnings.
1718 'unused-command-line-argument',
1720 # Remove clang 12+'s compound-token-split-by-macro, as this causes a lot
1721 # of warnings when building plperl because of usages in the Perl headers.
1722 'compound-token-split-by-macro',
1724 # Similarly disable useless truncation warnings from gcc 8+
1725 'format-truncation',
1726 'stringop-truncation',
1728 # To make warning_level=2 / -Wextra work, we'd need at least the following
1730 # 'missing-field-initializers',
1732 # 'unused-parameter',
1735 foreach w : negative_warning_flags
1736 if cc.has_argument('-W' + w)
1737 cflags_warn += '-Wno-' + w
1739 if llvm.found() and cpp.has_argument('-W' + w)
1740 cxxflags_warn += '-Wno-' + w
1746 if cc.get_id() == 'msvc'
1748 '/wd4018', # signed/unsigned mismatch
1749 '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
1750 '/wd4273', # inconsistent DLL linkage
1751 '/wd4101', # unreferenced local variable
1752 '/wd4102', # unreferenced label
1753 '/wd4090', # different 'modifier' qualifiers
1754 '/wd4267', # conversion from 'size_t' to 'type', possible loss of data
1762 '/D_CRT_SECURE_NO_DEPRECATE',
1763 '/D_CRT_NONSTDC_NO_DEPRECATE',
1766 # We never need export libraries. As link.exe reports their creation, they
1767 # are unnecessarily noisy. Similarly, we don't need import library for
1768 # modules, we only import them dynamically, and they're also noisy.
1770 ldflags_mod += '/NOIMPLIB'
1775 ###############################################################
1777 ###############################################################
1779 if not get_option('spinlocks')
1780 warning('Not using spinlocks will cause poor performance')
1782 cdata.set('HAVE_SPINLOCKS', 1)
1785 if not get_option('atomics')
1786 warning('Not using atomics will cause poor performance')
1788 # XXX: perhaps we should require some atomics support in this case these
1790 cdata.set('HAVE_ATOMICS', 1)
1793 {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
1794 'desc': '__sync_lock_test_and_set(char)',
1797 __sync_lock_test_and_set(&lock, 1);
1798 __sync_lock_release(&lock);'''},
1800 {'name': 'HAVE_GCC__SYNC_INT32_TAS',
1801 'desc': '__sync_lock_test_and_set(int32)',
1804 __sync_lock_test_and_set(&lock, 1);
1805 __sync_lock_release(&lock);'''},
1807 {'name': 'HAVE_GCC__SYNC_INT32_CAS',
1808 'desc': '__sync_val_compare_and_swap(int32)',
1811 __sync_val_compare_and_swap(&val, 0, 37);'''},
1813 {'name': 'HAVE_GCC__SYNC_INT64_CAS',
1814 'desc': '__sync_val_compare_and_swap(int64)',
1817 __sync_val_compare_and_swap(&val, 0, 37);'''},
1819 {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
1820 'desc': ' __atomic_compare_exchange_n(int32)',
1824 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1826 {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
1827 'desc': ' __atomic_compare_exchange_n(int64)',
1831 __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
1834 foreach check : atomic_checks
1839 }'''.format(check['test'])
1841 cdata.set(check['name'],
1843 name: check['desc'],
1844 args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
1852 ###############################################################
1853 # Select CRC-32C implementation.
1855 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
1856 # use the special CRC instructions for calculating CRC-32C. If we're not
1857 # targeting such a processor, but we can nevertheless produce code that uses
1858 # the SSE intrinsics, perhaps with some extra CFLAGS, compile both
1859 # implementations and select which one to use at runtime, depending on whether
1860 # SSE 4.2 is supported by the processor we're running on.
1862 # Similarly, if we are targeting an ARM processor that has the CRC
1863 # instructions that are part of the ARMv8 CRC Extension, use them. And if
1864 # we're not targeting such a processor, but can nevertheless produce code that
1865 # uses the CRC instructions, compile both, and select at runtime.
1866 ###############################################################
1868 have_optimized_crc = false
1870 if host_cpu == 'x86' or host_cpu == 'x86_64'
1872 if cc.get_id() == 'msvc'
1873 cdata.set('USE_SSE42_CRC32C', false)
1874 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
1875 have_optimized_crc = true
1879 #include <nmmintrin.h>
1883 unsigned int crc = 0;
1884 crc = _mm_crc32_u8(crc, 0);
1885 crc = _mm_crc32_u32(crc, 0);
1886 /* return computed value, to prevent the above being optimized away */
1891 if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2',
1893 # Use Intel SSE 4.2 unconditionally.
1894 cdata.set('USE_SSE42_CRC32C', 1)
1895 have_optimized_crc = true
1896 elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2',
1897 args: test_c_args + ['-msse4.2'])
1898 # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for
1899 # the runtime check.
1900 cflags_crc += '-msse4.2'
1901 cdata.set('USE_SSE42_CRC32C', false)
1902 cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
1903 have_optimized_crc = true
1908 elif host_cpu == 'arm' or host_cpu == 'aarch64'
1911 #include <arm_acle.h>
1915 unsigned int crc = 0;
1916 crc = __crc32cb(crc, 0);
1917 crc = __crc32ch(crc, 0);
1918 crc = __crc32cw(crc, 0);
1919 crc = __crc32cd(crc, 0);
1921 /* return computed value, to prevent the above being optimized away */
1926 if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd without -march=armv8-a+crc',
1928 # Use ARM CRC Extension unconditionally
1929 cdata.set('USE_ARMV8_CRC32C', 1)
1930 have_optimized_crc = true
1931 elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc',
1932 args: test_c_args + ['-march=armv8-a+crc'])
1933 # Use ARM CRC Extension, with runtime check
1934 cflags_crc += '-march=armv8-a+crc'
1935 cdata.set('USE_ARMV8_CRC32C', false)
1936 cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1)
1937 have_optimized_crc = true
1941 if not have_optimized_crc
1942 # fall back to slicing-by-8 algorithm, which doesn't require any special CPU
1944 cdata.set('USE_SLICING_BY_8_CRC32C', 1)
1949 ###############################################################
1950 # Other CPU specific stuff
1951 ###############################################################
1953 if host_cpu == 'x86_64'
1958 long long x = 1; long long r;
1959 __asm__ __volatile__ (" popcntq %1,%0\n" : "=q"(r) : "rm"(x));
1961 name: '@0@: popcntq instruction'.format(host_cpu),
1963 cdata.set('HAVE_X86_64_POPCNTQ', 1)
1966 elif host_cpu == 'ppc' or host_cpu == 'ppc64'
1967 # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
1968 if cdata.has('HAVE__BUILTIN_CONSTANT_P')
1971 addi(int ra, int si)
1974 if (__builtin_constant_p(si))
1975 __asm__ __volatile__(
1976 " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
1979 int test_adds(int x) { return addi(3, x) + addi(x, 5); }
1982 cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
1989 ###############################################################
1990 # Library / OS tests
1991 ###############################################################
1993 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
1994 # unnecessary checks over and over, particularly on windows.
2008 'sys/personality.h',
2017 foreach header : header_checks
2018 varname = 'HAVE_' + header.underscorify().to_upper()
2020 # Emulate autoconf behaviour of not-found->undef, found->1
2021 found = cc.has_header(header,
2022 include_directories: postgres_inc, args: test_c_args)
2023 cdata.set(varname, found ? 1 : false,
2024 description: 'Define to 1 if you have the <@0@> header file.'.format(header))
2029 ['F_FULLFSYNC', 'fcntl.h'],
2030 ['fdatasync', 'unistd.h'],
2031 ['posix_fadvise', 'fcntl.h'],
2032 ['strlcat', 'string.h'],
2033 ['strlcpy', 'string.h'],
2034 ['strnlen', 'string.h'],
2037 # Need to check for function declarations for these functions, because
2038 # checking for library symbols wouldn't handle deployment target
2039 # restrictions on macOS
2041 ['preadv', 'sys/uio.h'],
2042 ['pwritev', 'sys/uio.h'],
2045 foreach c : decl_checks
2049 varname = 'HAVE_DECL_' + func.underscorify().to_upper()
2051 found = cc.has_header_symbol(header, func,
2052 args: test_c_args, include_directories: postgres_inc,
2054 cdata.set10(varname, found, description:
2055 '''Define to 1 if you have the declaration of `@0@', and to 0 if you
2056 don't.'''.format(func))
2060 if cc.has_type('struct cmsgcred',
2061 args: test_c_args + ['@0@'.format(cdata.get('HAVE_SYS_UCRED_H')) == 'false' ? '' : '-DHAVE_SYS_UCRED_H'],
2062 include_directories: postgres_inc,
2064 #include <sys/socket.h>
2065 #include <sys/param.h>
2066 #ifdef HAVE_SYS_UCRED_H
2067 #include <sys/ucred.h>
2069 cdata.set('HAVE_STRUCT_CMSGCRED', 1)
2071 cdata.set('HAVE_STRUCT_CMSGCRED', false)
2074 if cc.has_type('struct option',
2075 args: test_c_args, include_directories: postgres_inc,
2076 prefix: '@0@'.format(cdata.get('HAVE_GETOPT_H')) == '1' ? '#include <getopt.h>' : '')
2077 cdata.set('HAVE_STRUCT_OPTION', 1)
2081 foreach c : ['opterr', 'optreset']
2082 varname = 'HAVE_INT_' + c.underscorify().to_upper()
2091 '''.format(c), name: c, args: test_c_args)
2092 cdata.set(varname, 1)
2094 cdata.set(varname, false)
2098 if cc.has_type('socklen_t',
2099 args: test_c_args, include_directories: postgres_inc,
2101 #include <sys/socket.h>''')
2102 cdata.set('HAVE_SOCKLEN_T', 1)
2105 if cc.has_member('struct sockaddr', 'sa_len',
2106 args: test_c_args, include_directories: postgres_inc,
2108 #include <sys/types.h>
2109 #include <sys/socket.h>''')
2110 cdata.set('HAVE_STRUCT_SOCKADDR_SA_LEN', 1)
2113 if cc.has_member('struct tm', 'tm_zone',
2114 args: test_c_args, include_directories: postgres_inc,
2116 #include <sys/types.h>
2119 cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
2124 extern int foo(void);
2127 return timezone / 60;
2130 name: 'global variable `timezone\' exists',
2131 args: test_c_args, include_directories: postgres_inc)
2132 cdata.set('HAVE_INT_TIMEZONE', 1)
2134 cdata.set('HAVE_INT_TIMEZONE', false)
2137 if cc.has_type('union semun',
2139 include_directories: postgres_inc,
2141 #include <sys/types.h>
2142 #include <sys/ipc.h>
2143 #include <sys/sem.h>
2145 cdata.set('HAVE_UNION_SEMUN', 1)
2153 switch (strerror_r(1, buf, sizeof(buf)))
2154 { case 0: break; default: break; }
2157 args: test_c_args, include_directories: postgres_inc)
2158 cdata.set('STRERROR_R_INT', 1)
2160 cdata.set('STRERROR_R_INT', false)
2163 # Check for the locale_t type and find the right header file. macOS
2164 # needs xlocale.h; standard is locale.h, but glibc also has an
2165 # xlocale.h file that we should not use.
2166 if cc.has_type('locale_t', prefix: '#include <locale.h>')
2167 cdata.set('HAVE_LOCALE_T', 1)
2168 elif cc.has_type('locale_t', prefix: '#include <xlocale.h>')
2169 cdata.set('HAVE_LOCALE_T', 1)
2170 cdata.set('LOCALE_T_IN_XLOCALE', 1)
2173 # Check if the C compiler understands typeof or a variant. Define
2174 # HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
2175 foreach kw : ['typeof', '__typeof__', 'decltype']
2186 args: test_c_args, include_directories: postgres_inc)
2188 cdata.set('HAVE_TYPEOF', 1)
2190 cdata.set('typeof', kw)
2198 # Try to find a declaration for wcstombs_l(). It might be in stdlib.h
2199 # (following the POSIX requirement for wcstombs()), or in locale.h, or in
2200 # xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE.
2201 wcstombs_l_test = '''
2213 if (not cc.compiles(wcstombs_l_test.format(''),
2214 name: 'wcstombs_l') and
2215 cc.compiles(wcstombs_l_test.format('#include <xlocale.h>'),
2216 name: 'wcstombs_l in xlocale.h'))
2217 cdata.set('WCSTOMBS_L_IN_XLOCALE', 1)
2221 # MSVC doesn't cope well with defining restrict to __restrict, the spelling it
2222 # understands, because it conflicts with __declspec(restrict). Therefore we
2223 # define pg_restrict to the appropriate definition, which presumably won't
2226 # We assume C99 support, so we don't need to make this conditional.
2228 # XXX: Historically we allowed platforms to disable restrict in template
2229 # files, but that was only added for AIX when building with XLC, which we
2230 # don't support yet.
2231 cdata.set('pg_restrict', '__restrict')
2235 #include <machine/vmparam.h>
2236 #include <sys/exec.h>
2240 PS_STRINGS->ps_nargvstr = 1;
2241 PS_STRINGS->ps_argvstr = "foo";
2244 name: 'PS_STRINGS', args: test_c_args)
2245 cdata.set('HAVE_PS_STRINGS', 1)
2247 cdata.set('HAVE_PS_STRINGS', false)
2251 # Most libraries are included only if they demonstrably provide a function we
2252 # need, but libm is an exception: always include it, because there are too
2253 # many compilers that play cute optimization games that will break probes for
2254 # standard functions such as pow().
2255 os_deps += cc.find_library('m', required: false)
2257 rt_dep = cc.find_library('rt', required: false)
2259 dl_dep = cc.find_library('dl', required: false)
2261 util_dep = cc.find_library('util', required: false)
2262 posix4_dep = cc.find_library('posix4', required: false)
2264 getopt_dep = cc.find_library('getopt', required: false)
2265 gnugetopt_dep = cc.find_library('gnugetopt', required: false)
2268 execinfo_dep = cc.find_library('execinfo', required: false)
2270 if host_system == 'cygwin'
2271 cygipc_dep = cc.find_library('cygipc', required: false)
2273 cygipc_dep = not_found_dep
2276 if host_system == 'sunos'
2277 socket_dep = cc.find_library('socket', required: false)
2279 socket_dep = not_found_dep
2282 # XXX: Might be worth conditioning some checks on the OS, to avoid doing
2283 # unnecessary checks over and over, particularly on windows.
2285 ['_configthreadlocale', {'skip': host_system != 'windows'}],
2286 ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2287 ['clock_gettime', {'dependencies': [rt_dep, posix4_dep], 'define': false}],
2289 # gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
2290 # when enabling asan the dlopen check doesn't notice that -ldl is actually
2291 # required. Just checking for dlsym() ought to suffice.
2292 ['dlsym', {'dependencies': [dl_dep], 'define': false}],
2294 ['fdatasync', {'dependencies': [rt_dep, posix4_dep], 'define': false}], # Solaris
2296 ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep]}],
2297 ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep]}],
2307 ['posix_fallocate'],
2310 ['pthread_barrier_wait', {'dependencies': [thread_dep]}],
2311 ['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
2312 ['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
2313 ['setproctitle', {'dependencies': [util_dep]}],
2314 ['setproctitle_fast'],
2315 ['shm_open', {'dependencies': [rt_dep], 'define': false}],
2316 ['shm_unlink', {'dependencies': [rt_dep], 'define': false}],
2317 ['shmget', {'dependencies': [cygipc_dep], 'define': false}],
2318 ['socket', {'dependencies': [socket_dep], 'define': false}],
2320 ['strerror_r', {'dependencies': [thread_dep]}],
2325 ['sync_file_range'],
2331 func_check_results = {}
2332 foreach c : func_checks
2334 kwargs = c.get(1, {})
2335 deps = kwargs.get('dependencies', [])
2337 if kwargs.get('skip', false)
2341 found = cc.has_function(func, args: test_c_args)
2348 found = cc.has_function(func, args: test_c_args,
2349 dependencies: [dep])
2357 func_check_results += {func: found}
2359 if kwargs.get('define', true)
2360 # Emulate autoconf behaviour of not-found->undef, found->1
2361 cdata.set('HAVE_' + func.underscorify().to_upper(),
2363 description: 'Define to 1 if you have the `@0@\' function.'.format(func))
2368 if cc.has_function('syslog', args: test_c_args) and \
2369 cc.check_header('syslog.h', args: test_c_args)
2370 cdata.set('HAVE_SYSLOG', 1)
2374 # if prerequisites for unnamed posix semas aren't fulfilled, fall back to sysv
2376 if sema_kind == 'unnamed_posix' and \
2377 not func_check_results.get('sem_init', false)
2381 cdata.set('USE_@0@_SHARED_MEMORY'.format(shmem_kind.to_upper()), 1)
2382 cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
2384 cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
2385 cdata.set_quoted('DLSUFFIX', dlsuffix)
2389 ###############################################################
2391 ###############################################################
2393 # XXX: About to rely on thread safety in the autoconf build, so not worth
2394 # implementing a fallback.
2395 cdata.set('ENABLE_THREAD_SAFETY', 1)
2399 ###############################################################
2401 ###############################################################
2403 nlsopt = get_option('nls')
2404 libintl = not_found_dep
2406 if not nlsopt.disabled()
2407 # otherwise there'd be lots of
2408 # "Gettext not found, all translation (po) targets will be ignored."
2409 # warnings if not found.
2410 msgfmt = find_program('msgfmt', required: nlsopt.enabled(), native: true)
2412 # meson 0.59 has this wrapped in dependency('int')
2413 if (msgfmt.found() and
2414 cc.check_header('libintl.h', required: nlsopt,
2415 args: test_c_args, include_directories: postgres_inc))
2418 if cc.has_function('ngettext')
2419 libintl = declare_dependency()
2421 libintl = cc.find_library('intl',
2422 has_headers: ['libintl.h'], required: nlsopt,
2423 header_include_directories: postgres_inc,
2429 i18n = import('i18n')
2430 cdata.set('ENABLE_NLS', 1)
2436 ###############################################################
2438 ###############################################################
2440 # Set up compiler / linker arguments to be used everywhere, individual targets
2441 # can add further args directly, or indirectly via dependencies
2442 add_project_arguments(cflags, language: ['c'])
2443 add_project_arguments(cppflags, language: ['c'])
2444 add_project_arguments(cflags_warn, language: ['c'])
2445 add_project_arguments(cxxflags, language: ['cpp'])
2446 add_project_arguments(cppflags, language: ['cpp'])
2447 add_project_arguments(cxxflags_warn, language: ['cpp'])
2448 add_project_link_arguments(ldflags, language: ['c', 'cpp'])
2451 # Collect a number of lists of things while recursing through the source
2452 # tree. Later steps then can use those.
2454 # list of targets for various alias targets
2455 backend_targets = []
2458 contrib_targets = []
2459 testprep_targets = []
2462 # Define the tests to distribute them to the correct test styles later
2467 # Default options for targets
2469 # First identify rpaths
2470 bin_install_rpaths = []
2471 lib_install_rpaths = []
2472 mod_install_rpaths = []
2474 # Add extra_lib_dirs to rpath. Not needed on darwin, as the install_name of
2475 # libraries in extra_lib_dirs will be used anyway.
2476 if host_system != 'darwin'
2477 bin_install_rpaths += postgres_lib_d
2478 lib_install_rpaths += postgres_lib_d
2479 mod_install_rpaths += postgres_lib_d
2483 # Define arguments for default targets
2485 default_target_args = {
2486 'implicit_include_directories': false,
2490 default_lib_args = default_target_args + {
2492 'install_rpath': ':'.join(lib_install_rpaths),
2495 internal_lib_args = default_lib_args + {
2496 'build_by_default': false,
2500 default_mod_args = default_lib_args + {
2502 'install_dir': dir_lib_pkg,
2503 'install_rpath': ':'.join(mod_install_rpaths),
2506 default_bin_args = default_target_args + {
2507 'install_dir': dir_bin,
2508 'install_rpath': ':'.join(bin_install_rpaths),
2513 # Helper for exporting a limited number of symbols
2514 gen_export_kwargs = {
2515 'input': 'exports.txt',
2516 'output': '@BASENAME@.'+export_file_suffix,
2517 'command': [perl, files('src/tools/gen_export.pl'),
2518 '--format', export_file_format,
2519 '--input', '@INPUT0@', '--output', '@OUTPUT0@'],
2520 'build_by_default': false,
2526 # headers that the whole build tree depends on
2527 generated_headers = []
2528 # headers that the backend build depends on
2529 generated_backend_headers = []
2530 # configure_files() output, needs a way of converting to file names
2531 configure_files = []
2533 # generated files that might conflict with a partial in-tree autoconf build
2534 generated_sources = []
2535 # same, for paths that differ between autoconf / meson builds
2536 # elements are [dir, [files]]
2537 generated_sources_ac = {}
2540 # First visit src/include - all targets creating headers are defined
2541 # within. That makes it easy to add the necessary dependencies for the
2542 # subsequent build steps.
2544 subdir('src/include')
2548 # Then through src/port and src/common, as most other things depend on them
2550 frontend_port_code = declare_dependency(
2551 compile_args: ['-DFRONTEND'],
2552 include_directories: [postgres_inc],
2553 dependencies: os_deps,
2556 backend_port_code = declare_dependency(
2557 compile_args: ['-DBUILDING_DLL'],
2558 include_directories: [postgres_inc],
2559 sources: [errcodes], # errcodes.h is needed due to use of ereport
2560 dependencies: os_deps,
2565 frontend_common_code = declare_dependency(
2566 compile_args: ['-DFRONTEND'],
2567 include_directories: [postgres_inc],
2568 sources: generated_headers,
2569 dependencies: [os_deps, zlib, zstd],
2572 backend_common_code = declare_dependency(
2573 compile_args: ['-DBUILDING_DLL'],
2574 include_directories: [postgres_inc],
2575 sources: generated_headers,
2576 dependencies: [os_deps, zlib, zstd],
2579 subdir('src/common')
2581 frontend_shlib_code = declare_dependency(
2582 compile_args: ['-DFRONTEND'],
2583 include_directories: [postgres_inc],
2584 link_args: ldflags_sl,
2585 link_with: [pgport_shlib, common_shlib],
2586 sources: generated_headers,
2587 dependencies: [os_deps, libintl],
2591 frontend_shlib_code,
2600 subdir('src/interfaces/libpq')
2601 # fe_utils depends on libpq
2602 subdir('src/fe_utils')
2604 frontend_code = declare_dependency(
2605 include_directories: [postgres_inc],
2606 link_with: [fe_utils, common_static, pgport_static],
2607 sources: generated_headers,
2608 dependencies: [os_deps, libintl],
2611 backend_both_deps += [
2628 backend_mod_deps = backend_both_deps + os_deps
2630 backend_code = declare_dependency(
2631 compile_args: ['-DBUILDING_DLL'],
2632 include_directories: [postgres_inc],
2633 link_args: ldflags_be,
2635 sources: generated_headers + generated_backend_headers,
2636 dependencies: os_deps + backend_both_deps + backend_deps,
2639 # src/backend/meson.build defines backend_mod_code used for extension
2643 # Then through the main sources. That way contrib can have dependencies on
2644 # main sources. Note that this explicitly doesn't enter src/test, right now a
2645 # few regression tests depend on contrib files.
2652 subdir('src/interfaces/libpq/test')
2653 subdir('src/interfaces/ecpg/test')
2655 subdir('doc/src/sgml')
2657 generated_sources_ac += {'': ['GNUmakefile']}
2660 # If there are any files in the source directory that we also generate in the
2661 # build directory, they might get preferred over the newly generated files,
2662 # e.g. because of a #include "file", which always will search in the current
2664 message('checking for file conflicts between source and build directory')
2665 conflicting_files = []
2666 potentially_conflicting_files_t = []
2667 potentially_conflicting_files_t += generated_headers
2668 potentially_conflicting_files_t += generated_backend_headers
2669 potentially_conflicting_files_t += generated_backend_sources
2670 potentially_conflicting_files_t += generated_sources
2672 potentially_conflicting_files = []
2674 # convert all sources of potentially conflicting files into uniform shape
2675 foreach t : potentially_conflicting_files_t
2676 potentially_conflicting_files += t.full_path()
2678 foreach t : configure_files
2680 potentially_conflicting_files += meson.current_build_dir() / t
2682 foreach sub, fnames : generated_sources_ac
2683 sub = meson.build_root() / sub
2684 foreach fname : fnames
2685 potentially_conflicting_files += sub / fname
2689 # find and report conflicting files
2690 foreach build_path : potentially_conflicting_files
2691 build_path = host_system == 'windows' ? fs.as_posix(build_path) : build_path
2692 # str.replace is in 0.56
2693 src_path = meson.current_source_dir() / build_path.split(meson.current_build_dir() / '')[1]
2694 if fs.exists(src_path) or fs.is_symlink(src_path)
2695 conflicting_files += src_path
2698 # XXX: Perhaps we should generate a file that would clean these up? The list
2700 if conflicting_files.length() > 0
2701 errmsg_cleanup = '''
2702 Conflicting files in source directory:
2705 The conflicting files need to be removed, either by removing the files listed
2706 above, or by running configure and then make maintainer-clean.
2708 errmsg_cleanup = errmsg_cleanup.format(' '.join(conflicting_files))
2709 error(errmsg_nonclean_base.format(errmsg_cleanup))
2714 ###############################################################
2716 ###############################################################
2718 # The determination of where a DESTDIR install points to is ugly, it's somewhat hard
2719 # to combine two absolute paths portably...
2721 prefix = get_option('prefix')
2723 test_prefix = prefix
2725 if fs.is_absolute(get_option('prefix'))
2726 if host_system == 'windows'
2727 if prefix.split(':\\').length() == 1
2731 test_prefix = prefix.split(':\\')[1]
2734 assert(prefix.startswith('/'))
2735 test_prefix = './@0@'.format(prefix)
2739 # DESTDIR for the installation used to run tests in
2740 test_install_destdir = meson.build_root() / 'tmp_install/'
2741 # DESTDIR + prefix appropriately munged
2742 test_install_location = test_install_destdir / test_prefix
2745 meson_install_args = meson_args + ['install'] + {
2746 'meson': ['--quiet', '--only-changed', '--no-rebuild'],
2751 meson_bin, args: meson_install_args ,
2752 env: {'DESTDIR':test_install_destdir},
2758 test_result_dir = meson.build_root() / 'testrun'
2761 # XXX: pg_regress doesn't assign unique ports on windows. To avoid the
2762 # inevitable conflicts from running tests in parallel, hackishly assign
2763 # different ports for different tests.
2767 test_env = environment()
2769 temp_install_bindir = test_install_location / get_option('bindir')
2770 test_env.set('PG_REGRESS', pg_regress.full_path())
2771 test_env.set('REGRESS_SHLIB', regress_module.full_path())
2773 # Test suites that are not safe by default but can be run if selected
2774 # by the user via the whitespace-separated list in variable PG_TEST_EXTRA.
2775 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
2776 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
2778 # Add the temporary installation to the library search path on platforms where
2779 # that works (everything but windows, basically). On windows everything
2780 # library-like gets installed into bindir, solving that issue.
2781 if library_path_var != ''
2782 test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
2787 ###############################################################
2789 ###############################################################
2791 testwrap = files('src/tools/testwrap')
2793 foreach test_dir : tests
2796 '--basedir', meson.build_root(),
2797 '--srcdir', test_dir['sd'],
2798 '--testgroup', test_dir['name'],
2801 foreach kind, v : test_dir
2802 if kind in ['sd', 'bd', 'name']
2808 if kind in ['regress', 'isolation', 'ecpg']
2809 if kind == 'regress'
2811 elif kind == 'isolation'
2812 runner = pg_isolation_regress
2814 runner = pg_regress_ecpg
2817 test_output = test_result_dir / test_dir['name'] / kind
2821 '--inputdir', t.get('inputdir', test_dir['sd']),
2822 '--expecteddir', t.get('expecteddir', test_dir['sd']),
2823 '--outputdir', test_output,
2824 '--temp-instance', test_output / 'tmp_check',
2826 '--dlpath', test_dir['bd'],
2827 '--max-concurrent-tests=20',
2828 '--port', testport.to_string(),
2829 ] + t.get('regress_args', [])
2831 if t.has_key('schedule')
2832 test_command += ['--schedule', t['schedule'],]
2835 if kind == 'isolation'
2836 test_command += t.get('specs', [])
2838 test_command += t.get('sql', [])
2842 env.prepend('PATH', temp_install_bindir, test_dir['bd'])
2845 'suite': [test_dir['name']],
2848 'depends': test_deps + t.get('deps', []),
2850 } + t.get('test_kwargs', {})
2852 test(test_dir['name'] / kind,
2854 args: testwrap_base + [
2858 kwargs: test_kwargs,
2863 if not tap_tests_enabled
2869 '-I', meson.source_root() / 'src/test/perl',
2870 '-I', test_dir['sd'],
2873 # Add temporary install, the build directory for non-installed binaries and
2874 # also test/ for non-installed test binaries built separately.
2876 env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test')
2878 foreach name, value : t.get('env', {})
2879 env.set(name, value)
2884 'suite': [test_dir['name']],
2886 'depends': test_deps + t.get('deps', []),
2888 } + t.get('test_kwargs', {})
2890 foreach onetap : t['tests']
2891 # Make tap test names prettier, remove t/ and .pl
2893 if onetap_p.startswith('t/')
2894 onetap_p = onetap.split('t/')[1]
2896 if onetap_p.endswith('.pl')
2897 onetap_p = fs.stem(onetap_p)
2900 test(test_dir['name'] / onetap_p,
2902 kwargs: test_kwargs,
2903 args: testwrap_base + [
2904 '--testname', onetap_p,
2906 test_dir['sd'] / onetap,
2911 error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
2914 endforeach # kinds of tests
2916 endforeach # directories with tests
2920 ###############################################################
2922 ###############################################################
2924 alias_target('backend', backend_targets)
2925 alias_target('bin', bin_targets + [libpq_st])
2926 alias_target('pl', pl_targets)
2927 alias_target('contrib', contrib_targets)
2928 alias_target('testprep', testprep_targets)
2932 ###############################################################
2933 # The End, The End, My Friend
2934 ###############################################################
2936 if meson.version().version_compare('>=0.57')
2940 'data block size': cdata.get('BLCKSZ'),
2941 'WAL block size': cdata.get('XLOG_BLCKSZ') / 1024,
2942 'segment size': cdata.get('RELSEG_SIZE') / 131072,
2944 section: 'Data layout',
2949 'host system': '@0@ @1@'.format(host_system, host_cpu),
2950 'build system': '@0@ @1@'.format(build_machine.system(),
2951 build_machine.cpu_family()),
2958 'linker': '@0@'.format(cc.get_linker_id()),
2959 'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
2961 section: 'Compiler',
2966 'CPP FLAGS': ' '.join(cppflags),
2967 'C FLAGS, functional': ' '.join(cflags),
2968 'C FLAGS, warnings': ' '.join(cflags_warn),
2970 section: 'Compiler Flags',
2976 'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
2978 section: 'Compiler',
2983 'C++ FLAGS, functional': ' '.join(cxxflags),
2984 'C++ FLAGS, warnings': ' '.join(cxxflags_warn),
2986 section: 'Compiler Flags',
2992 'bison': '@0@ @1@'.format(bison.full_path(), bison_version),
2995 section: 'Programs',
3001 'bsd_auth': bsd_auth,
3012 'plpython': python3_dep,
3014 'readline': readline,
3022 section: 'External libraries',