-# Copyright (c) 2022-2023, PostgreSQL Global Development Group
+# Copyright (c) 2022-2024, PostgreSQL Global Development Group
# Entry point for building PostgreSQL with meson
#
project('postgresql',
['c'],
- version: '17devel',
+ version: '17beta1',
license: 'PostgreSQL',
# We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for
# Basic platform specific configuration
###############################################################
-# meson's system names don't quite map to our "traditional" names. In some
-# places we need the "traditional" name, e.g., for mapping
-# src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
-# that purpose.
-portname = host_system
-
exesuffix = '' # overridden below where necessary
dlsuffix = '.so' # overridden below where necessary
library_path_var = 'LD_LIBRARY_PATH'
if host_system == 'dragonfly'
# apparently the most similar
host_system = 'netbsd'
+elif host_system == 'android'
+ # while android isn't quite a normal linux, it seems close enough
+ # for our purposes so far
+ host_system = 'linux'
endif
-if host_system == 'aix'
- library_path_var = 'LIBPATH'
-
- export_file_format = 'aix'
- export_fmt = '-Wl,-bE:@0@'
- mod_link_args_fmt = ['-Wl,-bI:@0@']
- mod_link_with_dir = 'libdir'
- mod_link_with_name = '@0@.imp'
-
- # M:SRE sets a flag indicating that an object is a shared library. Seems to
- # work in some circumstances without, but required in others.
- ldflags_sl += '-Wl,-bM:SRE'
- ldflags_be += '-Wl,-brtllib'
-
- # Native memset() is faster, tested on:
- # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
- # - AIX 5.3 ML3, gcc 4.0.1
- memset_loop_limit = 0
+# meson's system names don't quite map to our "traditional" names. In some
+# places we need the "traditional" name, e.g., for mapping
+# src/include/port/$os.h to src/include/pg_config_os.h. Define portname for
+# that purpose.
+portname = host_system
-elif host_system == 'cygwin'
+if host_system == 'cygwin'
sema_kind = 'unnamed_posix'
cppflags += '-D_GNU_SOURCE'
dlsuffix = '.dll'
cflags += ['-isysroot', pg_sysroot]
ldflags += ['-isysroot', pg_sysroot]
endif
+
# meson defaults to -Wl,-undefined,dynamic_lookup for modules, which we
# don't want because a) it's different from what we do for autoconf, b) it
- # causes warnings starting in macOS Ventura
- ldflags_mod += ['-Wl,-undefined,error']
+ # causes warnings in macOS Ventura. But using -Wl,-undefined,error causes a
+ # warning starting in Sonoma. So only add -Wl,-undefined,error if it does
+ # not cause a warning.
+ if cc.has_multi_link_arguments('-Wl,-undefined,error', '-Werror')
+ ldflags_mod += '-Wl,-undefined,error'
+ endif
+
+ # Starting in Sonoma, the linker warns about the same library being
+ # linked twice. Which can easily happen when multiple dependencies
+ # depend on the same library. Quiesce the ill considered warning.
+ ldflags += cc.get_supported_link_arguments('-Wl,-no_warn_duplicate_libraries')
elif host_system == 'freebsd'
sema_kind = 'unnamed_posix'
python = find_program(get_option('PYTHON'), required: true, native: true)
flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35')
bison = find_program(get_option('BISON'), native: true, version: '>= 2.3')
-sed = find_program(get_option('SED'), 'sed', native: true)
+sed = find_program(get_option('SED'), 'sed', native: true, required: false)
prove = find_program(get_option('PROVE'), native: true, required: false)
-tar = find_program(get_option('TAR'), native: true)
-gzip = find_program(get_option('GZIP'), native: true)
+tar = find_program(get_option('TAR'), native: true, required: false)
+gzip = find_program(get_option('GZIP'), native: true, required: false)
program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
openssl = find_program(get_option('OPENSSL'), native: true, required: false)
program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
###############################################################
cdata.set('USE_ASSERT_CHECKING', get_option('cassert') ? 1 : false)
+cdata.set('USE_INJECTION_POINTS', get_option('injection_points') ? 1 : false)
blocksize = get_option('blocksize').to_int() * 1024
if xmllint_bin.found() and xsltproc_bin.found()
docs_dep = declare_dependency()
elif docs_opt.enabled()
- error('missing required tools for docs in HTML / man page format')
+ error('missing required tools (xmllint and xsltproc needed) for docs in HTML / man page format')
endif
endif
llvmopt = get_option('llvm')
llvm = not_found_dep
if add_languages('cpp', required: llvmopt, native: false)
- llvm = dependency('llvm', version: '>=3.9', method: 'config-tool', required: llvmopt)
+ llvm = dependency('llvm', version: '>=10', method: 'config-tool', required: llvmopt)
if llvm.found()
if not at_least_one_header_found
error('''readline header not found
-If you have @0@ already installed, see meson-log/meson-log.txt for details on the
+If you have @0@ already installed, see meson-logs/meson-log.txt for details on the
failure. It is possible the compiler isn't looking in the proper directory.
Use -Dreadline=disabled to disable readline support.'''.format(readline_dep))
endif
error('unknown uuid build option value: @0@'.format(uuidopt))
endif
- if not cc.has_header_symbol(uuidheader, uuidfunc, args: test_c_args, dependencies: uuid)
+ if not cc.has_header_symbol(uuidheader, uuidfunc,
+ args: test_c_args,
+ include_directories: postgres_inc,
+ dependencies: uuid)
error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc))
endif
cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1)
cdata.set('SIZEOF_LONG', sizeof_long)
if sizeof_long == 8
cdata.set('HAVE_LONG_INT_64', 1)
- cdata.set('PG_INT64_TYPE', 'long int')
+ pg_int64_type = 'long int'
cdata.set_quoted('INT64_MODIFIER', 'l')
elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
cdata.set('HAVE_LONG_LONG_INT_64', 1)
- cdata.set('PG_INT64_TYPE', 'long long int')
+ pg_int64_type = 'long long int'
cdata.set_quoted('INT64_MODIFIER', 'll')
else
error('do not know how to get a 64bit int')
endif
+cdata.set('PG_INT64_TYPE', pg_int64_type)
if host_machine.endian() == 'big'
cdata.set('WORDS_BIGENDIAN', 1)
endif
+# Determine memory alignment requirements for the basic C data types.
+
alignof_types = ['short', 'int', 'long', 'double']
-maxalign = 0
foreach t : alignof_types
align = cc.alignment(t, args: test_c_args)
- if maxalign < align
- maxalign = align
- endif
cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
endforeach
-cdata.set('MAXIMUM_ALIGNOF', maxalign)
+
+# Compute maximum alignment of any basic type.
+#
+# We require 'double' to have the strictest alignment among the basic types,
+# because otherwise the C ABI might impose 8-byte alignment on some of the
+# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could
+# cause a mismatch between the tuple layout and the C struct layout of a
+# catalog tuple. We used to carefully order catalog columns such that any
+# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
+# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
+# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
+#
+# We assume without checking that int64's alignment is at least as strong
+# as long, char, short, or int. Note that we intentionally do not consider
+# any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
+# would be too much of a penalty for disk and memory space.
+alignof_double = cdata.get('ALIGNOF_DOUBLE')
+if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
+ error('alignment of int64 is greater than the alignment of double')
+endif
+cdata.set('MAXIMUM_ALIGNOF', alignof_double)
cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
if not meson.is_cross_build()
r = cc.run('''
/* This must match the corresponding code in c.h: */
- #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
+ #if defined(__GNUC__) || defined(__SUNPRO_C)
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
#elif defined(_MSC_VER)
#define pg_attribute_aligned(a) __declspec(align(a))
endif
+# Check for __get_cpuid_count() and __cpuidex() in a similar fashion.
+if cc.links('''
+ #include <cpuid.h>
+ int main(int arg, char **argv)
+ {
+ unsigned int exx[4] = {0, 0, 0, 0};
+ __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
+ }
+ ''', name: '__get_cpuid_count',
+ args: test_c_args)
+ cdata.set('HAVE__GET_CPUID_COUNT', 1)
+elif cc.links('''
+ #include <intrin.h>
+ int main(int arg, char **argv)
+ {
+ unsigned int exx[4] = {0, 0, 0, 0};
+ __cpuidex(exx, 7, 0);
+ }
+ ''', name: '__cpuidex',
+ args: test_c_args)
+ cdata.set('HAVE__CPUIDEX', 1)
+endif
+
+
# Defend against clang being used on x86-32 without SSE2 enabled. As current
# versions of clang do not understand -fexcess-precision=standard, the use of
# x87 floating point operations leads to problems like isinf possibly returning
endforeach
-# From Project.pm
if cc.get_id() == 'msvc'
cflags_warn += [
'/wd4018', # signed/unsigned mismatch
endif
+###############################################################
+# Check for the availability of XSAVE intrinsics.
+###############################################################
+
+cflags_xsave = []
+if host_cpu == 'x86' or host_cpu == 'x86_64'
+
+ prog = '''
+#include <immintrin.h>
+
+int main(void)
+{
+ return _xgetbv(0) & 0xe0;
+}
+'''
+
+ if cc.links(prog, name: 'XSAVE intrinsics without -mxsave',
+ args: test_c_args)
+ cdata.set('HAVE_XSAVE_INTRINSICS', 1)
+ elif cc.links(prog, name: 'XSAVE intrinsics with -mxsave',
+ args: test_c_args + ['-mxsave'])
+ cdata.set('HAVE_XSAVE_INTRINSICS', 1)
+ cflags_xsave += '-mxsave'
+ endif
+
+endif
+
+
+###############################################################
+# Check for the availability of AVX-512 popcount intrinsics.
+###############################################################
+
+cflags_popcnt = []
+if host_cpu == 'x86_64'
+
+ prog = '''
+#include <immintrin.h>
+
+int main(void)
+{
+ const char buf[sizeof(__m512i)];
+ INT64 popcnt = 0;
+ __m512i accum = _mm512_setzero_si512();
+ const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
+ const __m512i cnt = _mm512_popcnt_epi64(val);
+ accum = _mm512_add_epi64(accum, cnt);
+ popcnt = _mm512_reduce_add_epi64(accum);
+ /* return computed value, to prevent the above being optimized away */
+ return popcnt == 0;
+}
+'''
+
+ if cc.links(prog, name: 'AVX-512 popcount without -mavx512vpopcntdq -mavx512bw',
+ args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+ cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
+ elif cc.links(prog, name: 'AVX-512 popcount with -mavx512vpopcntdq -mavx512bw',
+ args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))] + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
+ cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
+ cflags_popcnt += ['-mavx512vpopcntdq'] + ['-mavx512bw']
+ endif
+
+endif
+
###############################################################
# Select CRC-32C implementation.
['pwritev', 'sys/uio.h'],
]
+# Check presence of some optional LLVM functions.
+if llvm.found()
+ decl_checks += [
+ ['LLVMCreateGDBRegistrationListener', 'llvm-c/ExecutionEngine.h'],
+ ['LLVMCreatePerfJITEventListener', 'llvm-c/ExecutionEngine.h'],
+ ]
+endif
+
foreach c : decl_checks
func = c.get(0)
header = c.get(1)
# conflict.
#
# We assume C99 support, so we don't need to make this conditional.
-#
-# XXX: Historically we allowed platforms to disable restrict in template
-# files, but that was only added for AIX when building with XLC, which we
-# don't support yet.
cdata.set('pg_restrict', '__restrict')
['backtrace_symbols', {'dependencies': [execinfo_dep]}],
['clock_gettime', {'dependencies': [rt_dep], 'define': false}],
['copyfile'],
+ ['copy_file_range'],
# gcc/clang's sanitizer helper library provides dlopen but not dlsym, thus
# when enabling asan the dlopen check doesn't notice that -ldl is actually
# required. Just checking for dlsym() ought to suffice.
['posix_fadvise'],
['posix_fallocate'],
['ppoll'],
- ['pstat'],
['pthread_barrier_wait', {'dependencies': [thread_dep]}],
['pthread_is_threaded_np', {'dependencies': [thread_dep]}],
['sem_init', {'dependencies': [rt_dep, thread_dep], 'skip': sema_kind != 'unnamed_posix', 'define': false}],
''',
test_initdb_template,
temp_install_bindir / 'initdb',
- '--auth', 'trust', '--no-sync', '--no-instructions', '--no-locale',
+ '--auth', 'trust', '--no-sync', '--no-instructions', '--lc-messages=C',
'--no-clean'
],
priority: setup_tests_priority - 1,
+###############################################################
+# Distribution archive
+###############################################################
+
+# Meson has its own distribution building command (meson dist), but we
+# are not using that at this point. The main problem is that, the way
+# they have implemented it, it is not deterministic. Also, we want it
+# to be equivalent to the "make" version for the time being. But the
+# target name "dist" in meson is reserved for that reason, so we call
+# the custom target "pgdist".
+
+git = find_program('git', required: false, native: true, disabler: true)
+bzip2 = find_program('bzip2', required: false, native: true)
+
+distdir = meson.project_name() + '-' + meson.project_version()
+
+pg_git_revision = get_option('PG_GIT_REVISION')
+
+# Note: core.autocrlf=false is needed to avoid line-ending conversion
+# in case the environment has a different setting. Without this, a
+# tarball created on Windows might be different than on, and unusable
+# on, Unix machines.
+
+tar_gz = custom_target('tar.gz',
+ build_always_stale: true,
+ command: [git, '-C', '@SOURCE_ROOT@',
+ '-c', 'core.autocrlf=false',
+ 'archive',
+ '--format', 'tar.gz',
+ '-9',
+ '--prefix', distdir + '/',
+ '-o', join_paths(meson.build_root(), '@OUTPUT@'),
+ pg_git_revision],
+ output: distdir + '.tar.gz',
+)
+
+if bzip2.found()
+ tar_bz2 = custom_target('tar.bz2',
+ build_always_stale: true,
+ command: [git, '-C', '@SOURCE_ROOT@',
+ '-c', 'core.autocrlf=false',
+ '-c', 'tar.tar.bz2.command="@0@" -c'.format(bzip2.path()),
+ 'archive',
+ '--format', 'tar.bz2',
+ '--prefix', distdir + '/',
+ '-o', join_paths(meson.build_root(), '@OUTPUT@'),
+ pg_git_revision],
+ output: distdir + '.tar.bz2',
+ )
+else
+ tar_bz2 = custom_target('tar.bz2',
+ command: [perl, '-e', 'exit 1'],
+ output: distdir + '.tar.bz2',
+ )
+endif
+
+alias_target('pgdist', [tar_gz, tar_bz2])
+
+# Make the standard "dist" command fail, to prevent accidental use.
+# But not if we are in a subproject, in case the parent project wants to
+# create a dist using the standard Meson command.
+if not meson.is_subproject()
+ # We can only pass the identifier perl here when we depend on >= 0.55
+ if meson.version().version_compare('>=0.55')
+ meson.add_dist_script(perl, '-e', 'exit 1')
+ endif
+endif
+
+
+
###############################################################
# The End, The End, My Friend
###############################################################