meson: Add basic PGXS compatibility
authorAndres Freund <[email protected]>
Wed, 7 Dec 2022 02:56:46 +0000 (18:56 -0800)
committerAndres Freund <[email protected]>
Wed, 7 Dec 2022 02:56:46 +0000 (18:56 -0800)
Generate a Makefile.global that's complete enough for PGXS to work for some
extensions. It is likely that this compatibility layer will not suffice for
every extension and not all platforms - we can expand it over time.

This allows extensions to use a single buildsystem across all the supported
postgres versions. Once all supported PG versions support meson, we can remove
the compatibility layer.

Reviewed-by: Peter Eisentraut <[email protected]>
Discussion: https://postgr.es/m/20221005200710[email protected]

meson.build
meson_options.txt
src/common/meson.build
src/include/meson.build
src/makefiles/meson.build [new file with mode: 0644]
src/meson.build

index 172c144135225db8c188d754be16a8f0f620db32..39fc3ddab260cc8284f25a7bd0e6d4c7d4b1221c 100644 (file)
@@ -337,9 +337,6 @@ program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
 missing = find_program('config/missing', native: true)
 
-# used by PGXS
-install_sh = find_program('config/install-sh', native: true)
-
 bison_flags = []
 if bison.found()
   bison_version_c = run_command(bison, '--version', check: true)
@@ -1741,11 +1738,10 @@ endif
 
 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
 # the result for them
+cflags_no_decl_after_statement = []
 if cc.has_argument('-Wdeclaration-after-statement')
   cflags_warn += '-Wdeclaration-after-statement'
-  using_declaration_after_statement_warning = true
-else
-  using_declaration_after_statement_warning = false
+  cflags_no_decl_after_statement += '-Wno-declaration-after-statement'
 endif
 
 
index c7ea57994dc78ae80f7c80128c7047b33bef3cb8..2c871969f52ca62508a90df7bb50abc72144c93c 100644 (file)
@@ -172,6 +172,9 @@ option('PYTHON', type : 'array', value: ['python3', 'python'],
 option('SED', type : 'string', value: 'gsed',
   description: 'path to sed binary')
 
+option('STRIP', type : 'string', value: 'strip',
+  description: 'path to strip binary, used for PGXS emulation')
+
 option('TAR', type : 'string', value: 'tar',
   description: 'path to tar binary')
 
index 1c9b8a3a018276b3012a18efd072a803ff489467..f69d75e9c6ed1939aeb25c658403ad93810454ad 100644 (file)
@@ -64,9 +64,7 @@ ryu_sources = files(
 )
 ryu_cflags = []
 
-if using_declaration_after_statement_warning
-  ryu_cflags += ['-Wno-declaration-after-statement']
-endif
+ryu_cflags += cflags_no_decl_after_statement
 
 config_info_sources = files('config_info.c',)
 config_info_cflags = [
index 35c06c4856a5928c998c78ce0504ee7e1e92b2af..0b15919bb87fc1c8bc37f492a21eea8b47522037 100644 (file)
@@ -49,8 +49,14 @@ else
   var_cxxflags = ''
 endif
 var_cppflags = ' '.join(cppflags)
-var_cflags_sl = '-fPIC' #FIXME
-var_ldflags = ' '.join(ldflags + get_option('c_link_args'))
+var_cflags_sl = ' '.join(cc.get_supported_arguments('-fPIC'))
+# explicitly add -Wl,--as-needed, normally added by meson, but we want it for
+# PGXS compatibility
+var_ldflags = ' '.join(
+  ldflags
+  + cc.get_supported_link_arguments('-Wl,--as-needed')
+  + get_option('c_link_args')
+)
 var_ldflags_sl = ''.join(ldflags_sl)
 var_ldflags_ex = '' # FIXME
 # FIXME - some extensions might directly use symbols from one of libs. If
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
new file mode 100644 (file)
index 0000000..3bcb0dc
--- /dev/null
@@ -0,0 +1,260 @@
+### Compute pgxs_data, used in src/meson.build to generate Makefile.global
+### etc, that's complete enough for PGXS to work.
+
+
+# Emulation of PGAC_CHECK_STRIP
+strip_bin = find_program(get_option('STRIP'), required: false, native: true)
+strip_cmd = strip_bin.found() ? [strip_bin.path()] : [':']
+
+working_strip = false
+if strip_bin.found()
+  strip_version = run_command(strip_bin, '-V', check: false)
+
+  if strip_version.returncode() == 0 and (
+      strip_version.stdout().contains('GNU strip') or
+      strip_version.stderr().contains('GNU strip'))
+    working_strip = true
+    strip_static_cmd = strip_cmd + ['-x']
+    strip_shared_cmd = strip_cmd + ['--strip-unneeded']
+  elif host_system == 'darwin'
+    working_strip = true
+    strip_static_cmd = strip_cmd + ['-x']
+    strip_shared_cmd = strip_cmd + ['-x']
+  endif
+endif
+
+if not working_strip
+  strip_cmd = [':']
+  strip_static_cmd = [':']
+  strip_shared_cmd = [':']
+endif
+
+
+pgxs_kv = {
+  'PACKAGE_URL': pg_url,
+  'PACKAGE_VERSION': pg_version,
+  'PG_MAJORVERSION': pg_version_major,
+  'PG_VERSION_NUM': pg_version_num,
+  'configure_input': 'meson',
+
+  'vpath_build': 'yes',
+  'autodepend': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
+
+  'host_cpu': host_cpu,
+  'host': '@0@-@1@'.format(host_cpu, host_system),
+  'host_os': host_system,
+  'build_os': build_machine.system(),
+  'PORTNAME': portname,
+  'PG_SYSROOT': pg_sysroot,
+
+  'abs_top_builddir': meson.build_root(),
+  'abs_top_srcdir': meson.source_root(),
+
+  'enable_thread_safety': 'yes',
+  'enable_rpath': 'yes',
+  'enable_nls': libintl.found() ? 'yes' : 'no',
+  'enable_tap_tests': tap_tests_enabled ? 'yes' : 'no',
+  'enable_debug': get_option('debug') ? 'yes' : 'no',
+  'enable_coverage': 'no',
+  'enable_dtrace': dtrace.found() ? 'yes' : 'no',
+
+  'DLSUFFIX': dlsuffix,
+  'EXEEXT': exesuffix,
+
+  'SUN_STUDIO_CC': 'no', # not supported so far
+
+  # want the chosen option, rather than the library
+  'with_ssl' : get_option('ssl'),
+  'with_uuid': uuidopt,
+
+  'default_port': get_option('pgport'),
+  'with_system_tzdata': get_option('system_tzdata'),
+
+  'with_krb_srvnam': get_option('krb_srvnam'),
+  'krb_srvtab': krb_srvtab,
+
+  'STRIP': ' '.join(strip_cmd),
+  'STRIP_STATIC_LIB': ' '.join(strip_static_cmd),
+  'STRIP_SHARED_LIB': ' '.join(strip_shared_cmd),
+
+  # these seem to be standard these days
+  'MKDIR_P': 'mkdir -p',
+  'LN_S': 'ln -s',
+  # Just always use the install_sh fallback that autoconf uses. Unlikely to
+  # matter performance-wise for extensions. If it turns out to do, we can
+  'install_bin': '$(SHELL) $(top_srcdir)/config/install-sh -c',
+
+  'CC': var_cc,
+  'CPP': var_cpp,
+  'GCC': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
+
+  'CPPFLAGS': var_cppflags,
+  'CFLAGS': var_cflags,
+  'CXXFLAGS': var_cxxflags,
+  'CFLAGS_SL': var_cflags_sl,
+  'CFLAGS_SL_MODULE': ' '.join(cflags_mod),
+  'CXXFLAGS_SL_MODULE': ' '.join(cxxflags_mod),
+  'PERMIT_DECLARATION_AFTER_STATEMENT':
+    ' '.join(cflags_no_decl_after_statement),
+
+  'CFLAGS_CRC': ' '.join(cflags_crc),
+  'CFLAGS_UNROLL_LOOPS': ' '.join(unroll_loops_cflags),
+  'CFLAGS_VECTORIZE': ' '.join(vectorize_cflags),
+
+  'LDFLAGS': var_ldflags,
+  'LDFLAGS_EX': var_ldflags_ex,
+  'LDFLAGS_EX_BE':
+    ' '.join(cc.get_supported_link_arguments('-Wl,--export-dynamic')),
+  'LDFLAGS_SL': var_ldflags_sl,
+
+  # TODO: requires bitcode generation to be implemented for meson
+  'BITCODE_CFLAGS': '',
+  'BITCODE_CXXFLAGS': '',
+
+  'BISONFLAGS': ' '.join(bison_flags),
+  'FLEXFLAGS': ' '.join(flex_flags),
+
+  'LIBS': var_libs,
+}
+
+if llvm.found()
+  pgxs_kv += {
+    'CLANG': clang.path(),
+    'CXX': ' '.join(cpp.cmd_array()),
+    'LLVM_BINPATH': llvm_binpath,
+  }
+else
+  pgxs_kv += {
+    'CLANG': '',
+    'CXX': '',
+    'LLVM_BINPATH': '',
+  }
+endif
+
+pgxs_bins = {
+  'AR':
+    find_program(['ar'], native: true, required: false),
+  'AWK':
+    find_program(['gawk', 'mawk', 'nawk', 'awk'], native: true, required: false),
+  'BISON': bison,
+  'FLEX': flex,
+  'GZIP': gzip,
+  'LZ4': program_lz4,
+  'OPENSSL': openssl,
+  'PERL': perl,
+  'PROVE': prove,
+  'PYTHON': python,
+  'TAR': tar,
+  'ZSTD': program_zstd,
+  'DTRACE': dtrace,
+}
+
+pgxs_empty = [
+  'ICU_CFLAGS', # needs to be added, included by public server headers
+
+  # hard to see why we'd need either?
+  'ZIC',
+  'TCLSH',
+
+  # docs don't seem to be supported by pgxs
+  'XMLLINT',
+  'XSLTPROC',
+  'DBTOEPUB',
+  'FOP',
+
+  # supporting coverage for pgxs-in-meson build doesn't seem worth it
+  'GENHTML',
+  'LCOV',
+  'GCOV',
+  'MSGFMT_FLAGS',
+
+  # translation doesn't appear to be supported by pgxs
+  'MSGFMT',
+  'XGETTEXT',
+  'MSGMERGE',
+  'WANTED_LANGUAGES',
+
+  # Not needed because we don't build the server / PLs with the generated makefile
+  'LIBOBJS', 'PG_CRC32C_OBJS', 'TAS',
+  'DTRACEFLAGS', # only server has dtrace probes
+
+  'perl_archlibexp', 'perl_embed_ccflags', 'perl_embed_ldflags', 'perl_includespec', 'perl_privlibexp',
+  'python_additional_libs', 'python_includespec', 'python_libdir', 'python_libspec', 'python_majorversion', 'python_version',
+
+  # possible that some of these are referenced explicitly in pgxs makefiles?
+  # For now not worth it.
+  'TCL_INCLUDE_SPEC', 'TCL_LIBS', 'TCL_LIB_SPEC', 'TCL_SHARED_BUILD',
+
+  'LLVM_CFLAGS', 'LLVM_CPPFLAGS', 'LLVM_CXXFLAGS', 'LLVM_LIBS',
+
+  'LDAP_LIBS_BE', 'LDAP_LIBS_FE',
+
+  'UUID_LIBS',
+
+  'PTHREAD_CFLAGS', 'PTHREAD_LIBS',
+
+  'ICU_LIBS',
+]
+
+if host_system == 'windows' and cc.get_argument_syntax() != 'msvc'
+  pgxs_bins += {'WINDRES': windres}
+else
+  pgxs_empty += 'WINDRES'
+endif
+
+pgxs_dirs = {
+  'prefix': get_option('prefix'),
+
+  'bindir': '${exec_prefix}' / get_option('bindir'),
+  'datarootdir': '${prefix}' / get_option('datadir'),
+  'datadir': '${datarootdir}',
+  'docdir': '${prefix}' / dir_doc,
+  'exec_prefix': '${prefix}',
+  'htmldir': '${docdir}',
+  'includedir': '${prefix}' / get_option('includedir'),
+  'libdir': '${exec_prefix}' / get_option('libdir'),
+  'localedir': '${prefix}' / get_option('localedir'),
+  'mandir': '${prefix}' / get_option('mandir'),
+  'sysconfdir': '${prefix}' / get_option('sysconfdir'),
+}
+
+pgxs_deps = {
+  'bonjour': bonjour,
+  'bsd_auth': bsd_auth,
+  'gssapi': gssapi,
+  'icu': icu,
+  'ldap': ldap,
+  'libxml': libxml,
+  'libxslt': libxslt,
+  'llvm': llvm,
+  'lz4': lz4,
+  'nls': libintl,
+  'pam': pam,
+  'perl': perl_dep,
+  'python': python3_dep,
+  'readline': readline,
+  'selinux': selinux,
+  'systemd': systemd,
+  'tcl': tcl_dep,
+  'zlib': zlib,
+  'zstd': zstd,
+}
+
+
+pgxs_cdata = configuration_data(pgxs_kv)
+
+foreach b, p : pgxs_bins
+  pgxs_cdata.set(b, p.found() ? p.path() : '')
+endforeach
+
+foreach pe : pgxs_empty
+  pgxs_cdata.set(pe, '')
+endforeach
+
+foreach d, p : pgxs_dirs
+  pgxs_cdata.set(d, p)
+endforeach
+
+foreach d, v : pgxs_deps
+  pgxs_cdata.set('with_@0@'.format(d), v.found() ? 'yes' : 'no')
+endforeach
index b515af15bfaaae92047ef707b3d3fc8e3d6b230b..654c0edfc3c19af71f6b14c6cc50e68e248851f6 100644 (file)
@@ -10,3 +10,40 @@ subdir('bin')
 subdir('pl')
 
 subdir('interfaces')
+
+
+### Generate a Makefile.global that's complete enough for PGXS to work.
+#
+# This is somewhat ugly, but allows extensions to use a single buildsystem
+# across all the supported postgres versions. Once all supported PG versions
+# support meson, we can remove all of this.
+#
+# XXX: Should we make this optional?
+
+# pgxs_cdata is built in makefiles/meson.build, but some of the generated
+# files are output into src/
+subdir('makefiles')
+
+makefile_global = configure_file(
+  input: 'Makefile.global.in',
+  output: 'Makefile.global',
+  configuration: pgxs_cdata,
+  install: true,
+  install_dir: dir_pgxs / 'src',
+)
+configure_files += makefile_global
+
+makefile_port = configure_file(
+  input: 'makefiles' / 'Makefile.@0@'.format(portname),
+  output: 'Makefile.port',
+  copy: true,
+  install_dir: dir_pgxs / 'src')
+configure_files += makefile_port
+
+install_data(
+  'Makefile.shlib', 'nls-global.mk',
+  install_dir: dir_pgxs / 'src')
+
+install_data(
+  'makefiles/pgxs.mk',
+  install_dir: dir_pgxs / 'src' / 'makefiles')