From: Aidar Imamov Subject: [PATCH v4] meson: expose OpenSSL and ICU compiler flags to PGXS-built extensions Some external dependencies have headers that are included by public server headers (e.g. libpq-be.h includes openssl/ssl.h). Extensions built with PGXS that include such headers need the dependency's compiler flags on the search path. The autoconf build picks these up from CPPFLAGS passed to configure (for OpenSSL) and from pkg-config's ICU_CFLAGS (for ICU); the meson build provided neither, so on systems where the dependency lives in a non-default prefix (e.g. Homebrew on macOS) such extensions failed to compile. meson doesn't expose the compiler flags of a dependency, so get them from the tool that found it. For pkg-config, run pkg-config --cflags with the same pkg_config_path, sys_root and pkg_config_libdir settings meson uses, asking for icu-uc and icu-i18n together as configure does, and fail if that doesn't work. For CMake, use the include directories meson recorded in PACKAGE_INCLUDE_DIRS, and warn if there are none. As with autoconf, OpenSSL goes into CPPFLAGS and ICU into ICU_CFLAGS, which Makefile.global adds to CPPFLAGS. pg_config --cppflags includes both. Dependencies found in other ways are not covered. In particular, extra_include_dirs of cc.find_library() never reaches PGXS, which is a more general gap than the one fixed here. --- meson.build | 88 +++++++++++++++++++++++++++++++++++++++ src/common/meson.build | 2 +- src/include/meson.build | 6 ++- src/makefiles/meson.build | 4 +- 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/meson.build b/meson.build index d05634fef0d..e4a8342e0cb 100644 --- a/meson.build +++ b/meson.build @@ -3346,6 +3346,94 @@ endif +############################################################### +# Dependency compiler flags for PGXS and pg_config +############################################################### + +# Extensions built with PGXS need the include paths of dependencies whose +# headers are included by public server headers (e.g. libpq-be.h includes +# ). As in the autoconf build, OpenSSL goes into CPPFLAGS and +# ICU into ICU_CFLAGS. +# +# Meson doesn't expose a dependency's compiler flags, so ask the tool that +# found it: pkg-config or CMake. Dependencies found in other ways get no flags +# here. Method 'system' is only used if the headers are on the default search +# path, and extra_include_dirs of cc.find_library() isn't passed on to PGXS at +# all, which is a separate gap. + +# Run pkg-config with the same settings Meson uses, so that we get the flags +# from the same .pc files. +pkg_config = find_program('pkg-config', required: false) +pkg_config_env = environment() +pkg_config_path = get_option('pkg_config_path') +if pkg_config_path.length() > 0 + pkg_config_env.set('PKG_CONFIG_PATH', pkg_config_path) +endif +pkg_config_sysroot = meson.get_external_property('sys_root', '') +if pkg_config_sysroot != '' + pkg_config_env.set('PKG_CONFIG_SYSROOT_DIR', pkg_config_sysroot) +endif +pkg_config_libdir = [] + meson.get_external_property('pkg_config_libdir', []) +if pkg_config_libdir.length() > 0 + pkg_config_env.set('PKG_CONFIG_LIBDIR', pkg_config_libdir) +endif + +# Dependencies to get compiler flags for: the dependency objects, and the +# pkg-config modules to query (together, like configure's PKG_CHECK_MODULES). +pgxs_flag_deps = { + 'openssl': {'deps': [ssl], 'pc_modules': ['openssl']}, + 'icu': {'deps': [icu, icu_i18n], 'pc_modules': ['icu-uc', 'icu-i18n']}, +} + +pgxs_dep_cflags = {} +foreach dep_name, dep_info : pgxs_flag_deps + dep_objs = dep_info['deps'] + dep_flags = [] + + if not dep_objs[0].found() + # nothing to do + elif dep_objs[0].type_name() == 'pkgconfig' + pc_modules = dep_info['pc_modules'] + if not pkg_config.found() + error('pkg-config is needed to get the compiler flags of @0@'.format( + dep_name)) + endif + pc_cflags = run_command(pkg_config, '--cflags', pc_modules, + env: pkg_config_env, check: false) + if pc_cflags.returncode() != 0 + error('pkg-config --cflags @0@ failed:\n@1@'.format( + ' '.join(pc_modules), pc_cflags.stderr())) + endif + # Use the output as is, like configure, keeping pkg-config's quoting + if pc_cflags.stdout().strip() != '' + dep_flags += pc_cflags.stdout().strip() + endif + elif dep_objs[0].type_name() == 'cmake' + # Meson sets PACKAGE_INCLUDE_DIRS from the package's _INCLUDE_DIRS, + # _INCLUDES or _INCLUDE_DIR, for Find modules and package + # config files alike. Those variables can't be read directly: FindOpenSSL, + # for one, sets OPENSSL_INCLUDE_DIR only through find_path(), which Meson's + # CMake trace doesn't see. + foreach dep : dep_objs + incdirs = dep.get_variable(cmake: 'PACKAGE_INCLUDE_DIRS', + default_value: '') + foreach incdir_raw : incdirs.split(';') + incdir = incdir_raw.strip() + if incdir != '' and '-I' + incdir not in dep_flags + dep_flags += '-I' + incdir + endif + endforeach + endforeach + if dep_flags.length() == 0 + warning('could not find include directories of @0@ via CMake, PGXS builds may not find its headers'.format(dep_name)) + endif + endif + + pgxs_dep_cflags += {dep_name: dep_flags} +endforeach + + + ############################################################### # Build ############################################################### diff --git a/src/common/meson.build b/src/common/meson.build index fc89a173346..594380266b7 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -78,7 +78,7 @@ ryu_cflags += cflags_no_decl_after_statement config_info_sources = files('config_info.c',) config_info_cflags = [ '-DVAL_CC="@0@"'.format(var_cc), - '-DVAL_CPPFLAGS="@0@"'.format(var_cppflags), + '-DVAL_CPPFLAGS="@0@"'.format(var_cppflags_pg_config), '-DVAL_CFLAGS="@0@"'.format(var_cflags), '-DVAL_CFLAGS_SL="@0@"'.format(var_cflags_sl), '-DVAL_LDFLAGS="@0@"'.format(var_ldflags), diff --git a/src/include/meson.build b/src/include/meson.build index 7d734d92dab..37915393744 100644 --- a/src/include/meson.build +++ b/src/include/meson.build @@ -47,7 +47,11 @@ else var_cxx = 'g++' var_cxxflags = '' endif -var_cppflags = ' '.join(cppflags) +var_cppflags = ' '.join(cppflags + pgxs_dep_cflags['openssl']) +# pg_config --cppflags also includes ICU_CFLAGS, as with autoconf, where +# Makefile.global adds $(ICU_CFLAGS) to CPPFLAGS +var_cppflags_pg_config = ' '.join( + cppflags + pgxs_dep_cflags['openssl'] + pgxs_dep_cflags['icu']) 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 diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build index d0430b3519e..1822cb0e128 100644 --- a/src/makefiles/meson.build +++ b/src/makefiles/meson.build @@ -80,6 +80,8 @@ pgxs_kv = { 'perl_includespec': perl_includespec, 'python_includespec': python_includespec, + 'ICU_CFLAGS': ' '.join(pgxs_dep_cflags['icu']), + # these seem to be standard these days 'MKDIR_P': 'mkdir -p', 'LN_S': 'ln -s', @@ -158,8 +160,6 @@ pgxs_bins = { } pgxs_empty = [ - 'ICU_CFLAGS', # needs to be added, included by public server headers - # hard to see why we'd need these ones? 'ZIC', 'TCLSH', -- 2.47.1