Decouple C++ support in Meson's PGXS from LLVM enablement

Started by Tristan Partin9 months ago18 messages
#1Tristan Partin
tristan@partin.io
1 attachment(s)

Howdy folks,

While playing around with pg_duckdb[0]https://github.com/duckdb/pg_duckdb, a Postgres extension written in
C++ which uses PGXS, I came across a strange build error:

std=c++17 -Wno-sign-compare...
/bin/sh: line 1: -Wno-sign-compare: command not found

I was very confused by the error, but reading the command line, it made
sense. After talking to Jelte off-list, he told me to try a Postgres
installation that had been built with autotools. Today, I finally had
a chance to try that tip, and building pg_duckdb succeeded.

I spent some time exploring the Meson build a bit, and I realized that
C++ support in PGXS is tied to LLVM enablement. Checking the autotools
build in the configure.ac script indicates that that is not the case for
it.

On master, C++ support looks like:

llvmopt = get_option('llvm')
llvm = not_found_dep
if add_languages('cpp', required: llvmopt, native: false)
llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
if llvm.found()

cdata.set('USE_LLVM', 1)

cpp = meson.get_compiler('cpp')

By default, the `llvm` option is disabled, which Meson takes to mean,
"do not check for C++ support". Thusly, add_languages() returns false.
In addition, every check for adding to cxxflags, et. al. is gated on
llvm.found(), which is always false for the `not_found_dep`. All this
considered, the Makefile.global of a Postgres build roughly looked like:

CXX =
CXXFLAGS =
...

This then accounts for the original pg_duckdb command line looking the
way that it did.

Attached is a patch which decouples C++ support in PGXS from LLVM for
a Meson-compiled Postgres.

[0]: https://github.com/duckdb/pg_duckdb

--
Tristan Partin
Neon (https://neon.tech)

Attachments:

0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enablem.patchtext/x-patch; charset=utf-8; name=0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enablem.patchDownload
From aba365ed36a82f41e8bd6a7f61b90c91f1556d08 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH] Decouple C++ support in Meson's PGXS from LLVM enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 27 +++++++++++++++++----------
 src/include/meson.build   |  2 +-
 src/makefiles/meson.build |  9 ++++++---
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/meson.build b/meson.build
index a1516e54529..f63769f8b67 100644
--- a/meson.build
+++ b/meson.build
@@ -40,6 +40,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -798,15 +802,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp and not llvmopt.disabled()
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -815,8 +817,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -2053,7 +2060,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2077,7 +2084,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2131,7 +2138,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2192,7 +2199,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3920,7 +3927,7 @@ if meson.version().version_compare('>=0.57')
     section: 'Compiler Flags',
   )
 
-  if llvm.found()
+  if have_cpp
     summary(
       {
         'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index 2e4b7aa529e..c2aef484fcc 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,7 +36,7 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
   var_cxxflags = ''
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 55da678ec27..bee83a66e81 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -121,16 +120,20 @@ pgxs_kv = {
   'LIBS': var_libs,
 }
 
+if have_cpp
+  pgxs_kv += {
+    'CXX': ' '.join(cpp.cmd_array()),
+  }
+endif
+
 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
-- 
Tristan Partin
https://tristan.partin.io

In reply to: Tristan Partin (#1)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Thu, 17 Apr 2025 at 03:57, Tristan Partin <tristan@partin.io> wrote:

I spent some time exploring the Meson build a bit, and I realized that
C++ support in PGXS is tied to LLVM enablement. Checking the autotools
build in the configure.ac script indicates that that is not the case for
it.

Thank you for looking into this. I didn't try the patch, but just
reading it it all looks sensible (although my meson knowledge is quite
limited). I assume you tried to build pg_duckdb with a Meson based PG
build containing this patch and pg_duckdb built correctly?

#3Tristan Partin
tristan@partin.io
In reply to: Jelte Fennema-Nio (#2)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Thu Apr 17, 2025 at 2:15 AM CDT, Jelte Fennema-Nio wrote:

On Thu, 17 Apr 2025 at 03:57, Tristan Partin <tristan@partin.io> wrote:

I spent some time exploring the Meson build a bit, and I realized that
C++ support in PGXS is tied to LLVM enablement. Checking the autotools
build in the configure.ac script indicates that that is not the case for
it.

Thank you for looking into this. I didn't try the patch, but just
reading it it all looks sensible (although my meson knowledge is quite
limited). I assume you tried to build pg_duckdb with a Meson based PG
build containing this patch and pg_duckdb built correctly?

I took some time to backpatch to 17 on my machine so that I could build
pg_duckdb, and indeed with the backpatch applied, pg_duckdb compiles
successfully.

I do however hit linker errors later, but that is unrelated to the
current patch discussion. I'll discuss them with you in a different
forum.

--
Tristan Partin
https://tristan.partin.io

#4Tristan Partin
tristan@partin.io
In reply to: Tristan Partin (#1)
1 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Wed Apr 16, 2025 at 8:57 PM CDT, Tristan Partin wrote:

Howdy folks,

While playing around with pg_duckdb[0], a Postgres extension written in
C++ which uses PGXS, I came across a strange build error:

std=c++17 -Wno-sign-compare...
/bin/sh: line 1: -Wno-sign-compare: command not found

I was very confused by the error, but reading the command line, it made
sense. After talking to Jelte off-list, he told me to try a Postgres
installation that had been built with autotools. Today, I finally had
a chance to try that tip, and building pg_duckdb succeeded.

I spent some time exploring the Meson build a bit, and I realized that
C++ support in PGXS is tied to LLVM enablement. Checking the autotools
build in the configure.ac script indicates that that is not the case for
it.

On master, C++ support looks like:

llvmopt = get_option('llvm')
llvm = not_found_dep
if add_languages('cpp', required: llvmopt, native: false)
llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
if llvm.found()

cdata.set('USE_LLVM', 1)

cpp = meson.get_compiler('cpp')

By default, the `llvm` option is disabled, which Meson takes to mean,
"do not check for C++ support". Thusly, add_languages() returns false.
In addition, every check for adding to cxxflags, et. al. is gated on
llvm.found(), which is always false for the `not_found_dep`. All this
considered, the Makefile.global of a Postgres build roughly looked like:

CXX =
CXXFLAGS =
...

This then accounts for the original pg_duckdb command line looking the
way that it did.

Attached is a patch which decouples C++ support in PGXS from LLVM for
a Meson-compiled Postgres.

[0]: https://github.com/duckdb/pg_duckdb

With PGConf NYC around the corner, I thought I would rebase the original
patch. Please find v2 attached, which applies on top of
b0fb2c6aa5a485e28210e13ae5536c1231b1261f[0]https://github.com/tristan957/postgres/commit/b0fb2c6aa5a485e28210e13ae5536c1231b1261f :D.

GitHub branch: https://github.com/tristan957/postgres/tree/meson-cpp

[0]: https://github.com/tristan957/postgres/commit/b0fb2c6aa5a485e28210e13ae5536c1231b1261f

--
Tristan Partin
https://tristan.partin.io

Attachments:

v2-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v2-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From 6fb5b831cc3d9795214dfc89fbfcb57c61447481 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v2] Decouple C++ support in Meson's PGXS from LLVM enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 27 +++++++++++++++++----------
 src/include/meson.build   |  2 +-
 src/makefiles/meson.build |  9 ++++++---
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/meson.build b/meson.build
index 395416a606..c596af31f5 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -827,15 +831,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp and not llvmopt.disabled()
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -844,8 +846,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -2061,7 +2068,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2085,7 +2092,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2139,7 +2146,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2200,7 +2207,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3929,7 +3936,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cpp
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index 7cb3075da2..9be2f25e4a 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,7 +36,7 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
   var_cxxflags = ''
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 0def244c90..ff62200e5f 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -119,16 +118,20 @@ pgxs_kv = {
   'LIBS': var_libs,
 }
 
+if have_cpp
+  pgxs_kv += {
+    'CXX': ' '.join(cpp.cmd_array()),
+  }
+endif
+
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif
-- 
Tristan Partin
https://tristan.partin.io

#5Josef Šimánek
josef.simanek@gmail.com
In reply to: Tristan Partin (#1)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

ne 2. 11. 2025 v 17:21 odesílatel Tristan Partin <tristan@partin.io> napsal:

Howdy folks,

While playing around with pg_duckdb[0], a Postgres extension written in
C++ which uses PGXS, I came across a strange build error:

std=c++17 -Wno-sign-compare...
/bin/sh: line 1: -Wno-sign-compare: command not found

I was very confused by the error, but reading the command line, it made
sense. After talking to Jelte off-list, he told me to try a Postgres
installation that had been built with autotools. Today, I finally had
a chance to try that tip, and building pg_duckdb succeeded.

I spent some time exploring the Meson build a bit, and I realized that
C++ support in PGXS is tied to LLVM enablement. Checking the autotools
build in the configure.ac script indicates that that is not the case for
it.

On master, C++ support looks like:

llvmopt = get_option('llvm')
llvm = not_found_dep
if add_languages('cpp', required: llvmopt, native: false)
llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
if llvm.found()

cdata.set('USE_LLVM', 1)

cpp = meson.get_compiler('cpp')

By default, the `llvm` option is disabled, which Meson takes to mean,
"do not check for C++ support". Thusly, add_languages() returns false.
In addition, every check for adding to cxxflags, et. al. is gated on
llvm.found(), which is always false for the `not_found_dep`. All this
considered, the Makefile.global of a Postgres build roughly looked like:

CXX =
CXXFLAGS =
...

Did local build and review. I can confirm it detects CXX properly with
llvm disabled. Tested with

meson setup "$BUILD_DIR" \
--prefix="$INSTALL_DIR" \
--buildtype=debug \
-Dcassert=true \
-Dllvm=disabled

pre-patch (resulting into empty CXX) and post-patch (properly assigned
"ccache c++" to CXX).

Show quoted text

This then accounts for the original pg_duckdb command line looking the
way that it did.

Attached is a patch which decouples C++ support in PGXS from LLVM for
a Meson-compiled Postgres.

[0]: https://github.com/duckdb/pg_duckdb

--
Tristan Partin
Neon (https://neon.tech)

#6BharatDB
bharatdbpg@gmail.com
In reply to: Josef Šimánek (#5)
1 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

Hi Tristan, Andres, Jelte, and pgsql-hackers,

Thank you for the excellent work on decoupling C++ support in Meson from
LLVM

SUMMARY: v2 PATCH TESTED AND WORKS PERFECTLY

- Built PostgreSQL 19devel (current master) with Meson

- Config: -Dllvm=disabled -Dcpp_support=auto

- Before patch: CXX = (empty) → extension fails with shell error

- After patch: CXX = ccache c++ → extension builds successfully

- Tested with minimal C++ extension → cpp_test.so created

REPRODUCTION & FIX STEPS

1. git remote add tristan https://github.com/tristan957/postgres.git

git fetch tristan

git checkout -b meson-cpp tristan/meson-cpp

2. meson setup build-fixed .. -Dllvm=disabled -Dcpp_support=auto

meson compile && meson install

3. Built test C++ extension:

cd ~/cpp_test_ext && make clean && make

VERIFIED OUTPUT
$ grep -E "^(CXX|CXXFLAGS) =" build-fixed/src/Makefile.global

CXX = ccache c++

CXXFLAGS = -fno-strict-aliasing -fwrapv -Wall -g -O0 ...

$ ls -l ~/cpp_test_ext/*.so

-rwxr-xr-x 1 boss boss 21568 Nov 4 12:18
/home/boss/cpp_test_ext/cpp_test.so

Patch applies cleanly and works perfectly on 19devel.

While testing the C++ PGXS patch, I noticed a usability gap:

If no C++ compiler is installed (e.g., `g++` missing), Meson silently

proceeds with C++ disabled — users only discover the issue when extensions

like pg_duckdb fail with confusing build errors.

This patch adds a clear, single warning during configuration:

WARNING: No C++ compiler found on your system.

Extensions using C++ (e.g. pg_duckdb) will FAIL to build.

Install g++ or clang++ to enable C++ support.

- Only shown when `add_languages('cpp')` returns `false`

- No warning when C++ is available

- Tested on PostgreSQL 19devel (with and without `g++`)

Attached: `0001-meson-warn-when-no-C-compiler-is-found.patch`

Happy to revise if there are better ways to surface this — open to
suggestions!

Thanks again for the great work on Meson C++ support.

Best regards,

Lakshmi

Attachments:

0001-meson-warn-when-no-C-compiler-is-found.patchtext/x-patch; charset=US-ASCII; name=0001-meson-warn-when-no-C-compiler-is-found.patchDownload
From a220d781b3a53565c799ea48b92460467c089f6c Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH] meson: warn when no C++ compiler is found

---
 meson.build               | 34 +++++++++++++++++++++++-----------
 src/include/meson.build   |  2 +-
 src/makefiles/meson.build |  9 ++++++---
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 395416a606..a0afb0d5a8 100644
--- a/meson.build
+++ b/meson.build
@@ -41,13 +41,22 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
+# === USER WARNING: No C++ compiler found ===
+if not have_cpp
+  warning('No C++ compiler found on your system.\n' +
+          '         Extensions using C++ (e.g. pg_duckdb) will FAIL to build.\n' +
+          '         Install g++ or clang++ to enable C++ support.')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
 auto_features = get_option('auto_features')
 
 
-
 ###############################################################
 # Safety first
 ###############################################################
@@ -827,15 +836,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp and not llvmopt.disabled()
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -844,8 +851,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -2061,7 +2073,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2085,7 +2097,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2139,7 +2151,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2200,7 +2212,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3929,7 +3941,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cpp
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index 7cb3075da2..9be2f25e4a 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,7 +36,7 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
   var_cxxflags = ''
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 0def244c90..ff62200e5f 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -119,16 +118,20 @@ pgxs_kv = {
   'LIBS': var_libs,
 }
 
+if have_cpp
+  pgxs_kv += {
+    'CXX': ' '.join(cpp.cmd_array()),
+  }
+endif
+
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif
-- 
2.39.5

#7Peter Eisentraut
peter@eisentraut.org
In reply to: Tristan Partin (#4)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On 28.09.25 23:16, Tristan Partin wrote:

Attached is a patch which decouples C++ support in PGXS from LLVM for
a Meson-compiled Postgres.

[0]: https://github.com/duckdb/pg_duckdb

With PGConf NYC around the corner, I thought I would rebase the original
patch. Please find v2 attached, which applies on top of
b0fb2c6aa5a485e28210e13ae5536c1231b1261f[0] :D.

This patch makes sense to me. But I wonder what the behavior should be
if no C++ compiler is found. Because then you're back to the state
you're started from, with the confusing make error. If you imagine a
packager building postgresql in a minimal environment, and without llvm
for some reason, then they would ship PGXS in that state without noticing.

The AC_PROG_CXX macro sets CXX to g++ if no C++ compiler is found. Then
a PGXS user would at least get an error message about g++ not found and
they can fix it by installing it. Maybe we should do that under Meson too.

An alternative would be to add some kind of build option or feature to
enable C++ support explicitly.

In reply to: Peter Eisentraut (#7)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Fri, 7 Nov 2025 at 16:39, Peter Eisentraut <peter@eisentraut.org> wrote:

The AC_PROG_CXX macro sets CXX to g++ if no C++ compiler is found. Then
a PGXS user would at least get an error message about g++ not found and
they can fix it by installing it. Maybe we should do that under Meson too.

I think that sounds reasonable.

(although I think using c++ instead of g++ would make more sense
though, but that seems like a separate thread as it would also apply
to that autoconf code)

#9Tristan Partin
tristan@partin.io
In reply to: Peter Eisentraut (#7)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Fri Nov 7, 2025 at 9:39 AM CST, Peter Eisentraut wrote:

On 28.09.25 23:16, Tristan Partin wrote:

Attached is a patch which decouples C++ support in PGXS from LLVM for
a Meson-compiled Postgres.

[0]: https://github.com/duckdb/pg_duckdb

With PGConf NYC around the corner, I thought I would rebase the original
patch. Please find v2 attached, which applies on top of
b0fb2c6aa5a485e28210e13ae5536c1231b1261f[0] :D.

This patch makes sense to me. But I wonder what the behavior should be
if no C++ compiler is found. Because then you're back to the state
you're started from, with the confusing make error. If you imagine a
packager building postgresql in a minimal environment, and without llvm
for some reason, then they would ship PGXS in that state without noticing.

The AC_PROG_CXX macro sets CXX to g++ if no C++ compiler is found. Then
a PGXS user would at least get an error message about g++ not found and
they can fix it by installing it. Maybe we should do that under Meson too.

An alternative would be to add some kind of build option or feature to
enable C++ support explicitly.

Great idea. I need to re-spin the patch anyway after a discussion with
Jelte at NYC. I'll be sure to add this as well.

--
Tristan Partin
Databricks (https://databricks.com)

#10Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Tristan Partin (#9)
1 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Fri Nov 7, 2025 at 5:29 PM CET, Tristan Partin wrote:

Great idea. I need to re-spin the patch anyway after a discussion with
Jelte at NYC. I'll be sure to add this as well.

I took the liberty of updating the patch to include the g++ fallback and
simplify the check a little bit (I seem to remember that that was what
we discussed in NYC).

Attachments:

v3-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v3-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From cf327e6f5ae0b0ac22abb4e5699bc231eafb5f36 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v3] Decouple C++ support in Meson's PGXS from LLVM enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 29 ++++++++++++++++++-----------
 src/include/meson.build   |  2 +-
 src/makefiles/meson.build | 17 ++++++++++++++---
 3 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 467f7f005a6..4c158fd3ca8 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -836,15 +840,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -853,8 +855,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -1916,7 +1923,7 @@ endforeach
 
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
-if llvm.found()
+if have_cpp
   attrib_error_args = cpp.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
     if cpp.compiles(testsrc.format(a),
@@ -2083,7 +2090,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2107,7 +2114,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2161,7 +2168,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2229,7 +2236,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3950,7 +3957,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cpp
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index d9c7b709330..e10edfefcf9 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,7 +36,7 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
   var_cxxflags = ''
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 124df2c8582..84fe8198a5a 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -119,16 +118,28 @@ pgxs_kv = {
   'LIBS': var_libs,
 }
 
+if have_cpp
+  pgxs_kv += {
+    'CXX': ' '.join(cpp.cmd_array()),
+  }
+else
+  # Default to 'g++' so PGXS users get a clear "g++ not found" error
+  # when building C++ extensions. Otherwise they'd get a confusing error
+  # because no binary is specified in the build commands and the first flag
+  # would be interpreted as the program.
+  pgxs_kv += {
+    'CXX': 'g++',
+  }
+endif
+
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif

base-commit: 094b61ce3ebbb1258675cb9b4eca9198628e2177
-- 
2.52.0

#11Tristan Partin
tristan@partin.io
In reply to: Jelte Fennema-Nio (#10)
1 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Fri Jan 2, 2026 at 10:06 AM CST, Jelte Fennema-Nio wrote:

On Fri Nov 7, 2025 at 5:29 PM CET, Tristan Partin wrote:

Great idea. I need to re-spin the patch anyway after a discussion with
Jelte at NYC. I'll be sure to add this as well.

I took the liberty of updating the patch to include the g++ fallback and
simplify the check a little bit (I seem to remember that that was what
we discussed in NYC).

Never saw this email, but here is a little bit cleaner patch. Sorry for
taking a long time to follow up!

--
Tristan Partin
Databricks (https://databricks.com)

Attachments:

v4-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v4-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From 6e719dbb4f867308a43870b465ff64ef4980b317 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v4] Decouple C++ support in Meson's PGXS from LLVM enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 27 +++++++++++++++++----------
 src/include/meson.build   |  8 +++++++-
 src/makefiles/meson.build |  4 +---
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/meson.build b/meson.build
index 467f7f005a6..9a5a2acb1bb 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -836,15 +840,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp and not llvmopt.disabled()
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -853,8 +855,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -2083,7 +2090,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2107,7 +2114,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2161,7 +2168,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2229,7 +2236,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3950,7 +3957,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cpp
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index d9c7b709330..32f276bd31e 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,9 +36,15 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
+  var_cxx = ' '.join(cpp.cmd_array())
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
+  # Default to 'g++' so PGXS users get a clear "g++ not found" error when
+  # building C++ extensions. Otherwise they'd get a confusing error because no
+  # binary is specified in the build commands and the first flag would be
+  # interpreted as the program.
+  var_cxx = 'c++'
   var_cxxflags = ''
 endif
 var_cppflags = ' '.join(cppflags)
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 124df2c8582..6f5072081da 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -86,6 +85,7 @@ pgxs_kv = {
 
   'CC': var_cc,
   'CPP': var_cpp,
+  'CXX': var_cxx,
   'GCC': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
 
   'CPPFLAGS': var_cppflags,
@@ -122,13 +122,11 @@ pgxs_kv = {
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif
-- 
Tristan Partin
https://tristan.partin.io

#12Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Tristan Partin (#11)
1 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Sat Jan 3, 2026 at 5:49 AM CET, Tristan Partin wrote:

On Fri Jan 2, 2026 at 10:06 AM CST, Jelte Fennema-Nio wrote:

On Fri Nov 7, 2025 at 5:29 PM CET, Tristan Partin wrote:

Great idea. I need to re-spin the patch anyway after a discussion with
Jelte at NYC. I'll be sure to add this as well.

I took the liberty of updating the patch to include the g++ fallback and
simplify the check a little bit (I seem to remember that that was what
we discussed in NYC).

Never saw this email, but here is a little bit cleaner patch. Sorry for
taking a long time to follow up!

I like a lot better how you default to g++. Here's a version of yours
with a few small "improvements" from my last version:
1. Removal of the unnecessary "and not llvmopt.disabled()" check
2. Replacement of a an additional recenlty added llvm.found() check with have_cpp
3. Default to g++ instead of c++. I know I said I liked the c++ better,
and I still do, but it seems better to align with autoconf for now
and then change both of these later if we want to.

Attachments:

v5-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v5-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From 2e6de2426265873c720e963bba639e26ea38b99c Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v5] Decouple C++ support in Meson's PGXS from LLVM enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 29 ++++++++++++++++++-----------
 src/include/meson.build   |  8 +++++++-
 src/makefiles/meson.build |  4 +---
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 467f7f005a6..4c158fd3ca8 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -836,15 +840,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -853,8 +855,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -1916,7 +1923,7 @@ endforeach
 
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
-if llvm.found()
+if have_cpp
   attrib_error_args = cpp.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
     if cpp.compiles(testsrc.format(a),
@@ -2083,7 +2090,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2107,7 +2114,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2161,7 +2168,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2229,7 +2236,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3950,7 +3957,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cpp
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index d9c7b709330..32f276bd31e 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,9 +36,15 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
+  var_cxx = ' '.join(cpp.cmd_array())
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
+  # Default to 'g++' so PGXS users get a clear "g++ not found" error when
+  # building C++ extensions. Otherwise they'd get a confusing error because no
+  # binary is specified in the build commands and the first flag would be
+  # interpreted as the program.
+  var_cxx = 'c++'
   var_cxxflags = ''
 endif
 var_cppflags = ' '.join(cppflags)
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 124df2c8582..6f5072081da 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -86,6 +85,7 @@ pgxs_kv = {
 
   'CC': var_cc,
   'CPP': var_cpp,
+  'CXX': var_cxx,
   'GCC': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
 
   'CPPFLAGS': var_cppflags,
@@ -122,13 +122,11 @@ pgxs_kv = {
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif

base-commit: 094b61ce3ebbb1258675cb9b4eca9198628e2177
-- 
2.52.0

#13Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Jelte Fennema-Nio (#12)
1 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Sat Jan 3, 2026 at 10:42 AM CET, Jelte Fennema-Nio wrote:

3. Default to g++ instead of c++. I know I said I liked the c++ better,
and I still do, but it seems better to align with autoconf for now
and then change both of these later if we want to.

Apparently I had sent an outdated patch... And didn't actually include
that. Fixed now.

Attachments:

v6-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v6-0001-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From 09fcc76ebeeca0016a9d7ac69e1b9e0f8dcfe4ed Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v6] Decouple C++ support in Meson's PGXS from LLVM enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 29 ++++++++++++++++++-----------
 src/include/meson.build   |  8 +++++++-
 src/makefiles/meson.build |  4 +---
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 467f7f005a6..4c158fd3ca8 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cpp = add_languages('cpp', required: false, native: false)
+if have_cpp
+  cpp = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -836,15 +840,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cpp
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -853,8 +855,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -1916,7 +1923,7 @@ endforeach
 
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
-if llvm.found()
+if have_cpp
   attrib_error_args = cpp.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
     if cpp.compiles(testsrc.format(a),
@@ -2083,7 +2090,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cpp
   cxxflags += cpp.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2107,7 +2114,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cpp
   cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2161,7 +2168,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if have_cpp and cpp.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2229,7 +2236,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cpp
   cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3950,7 +3957,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cpp
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index d9c7b709330..92c733bf493 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,9 +36,15 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cpp
+  var_cxx = ' '.join(cpp.cmd_array())
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
+  # Default to 'g++' so PGXS users get a clear "g++ not found" error when
+  # building C++ extensions. Otherwise they'd get a confusing error because no
+  # binary is specified in the build commands and the first flag would be
+  # interpreted as the program.
+  var_cxx = 'g++'
   var_cxxflags = ''
 endif
 var_cppflags = ' '.join(cppflags)
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 124df2c8582..6f5072081da 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -86,6 +85,7 @@ pgxs_kv = {
 
   'CC': var_cc,
   'CPP': var_cpp,
+  'CXX': var_cxx,
   'GCC': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
 
   'CPPFLAGS': var_cppflags,
@@ -122,13 +122,11 @@ pgxs_kv = {
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif

base-commit: 094b61ce3ebbb1258675cb9b4eca9198628e2177
-- 
2.52.0

#14Peter Eisentraut
peter@eisentraut.org
In reply to: Jelte Fennema-Nio (#13)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On 04.01.26 00:07, Jelte Fennema-Nio wrote:

On Sat Jan 3, 2026 at 10:42 AM CET, Jelte Fennema-Nio wrote:

3. Default to g++ instead of c++. I know I said I liked the c++ better,
   and I still do, but it seems better to align with autoconf for now
   and then change both of these later if we want to.

Apparently I had sent an outdated patch... And didn't actually include
that. Fixed now.

This looks good to me.

There is an unfortunate cpp/cxx naming conflict. For example, this
seems very confusing:

var_cpp = ' '.join(cc.cmd_array() + ['-E'])
...
if have_cpp
var_cxx = ' '.join(cpp.cmd_array())

Here, we use "cpp" to mean two different things in the space of a few lines.

Perhaps we should prefer to use the less ambiguous name "cxx"
throughout. So change

     +have_cpp = add_languages('cpp', required: false, native: false)
     +if have_cpp
     +  cpp = meson.get_compiler('cpp')
     +endif

to

     +have_cxx = add_languages('cpp', required: false, native: false)
     +if have_cxx
     +  cxx = meson.get_compiler('cpp')
     +endif

Then the potentially confusing use of "cpp" is contained in these two lines.

#15Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Peter Eisentraut (#14)
2 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Mon Jan 5, 2026 at 9:38 AM CET, Peter Eisentraut wrote:

Perhaps we should prefer to use the less ambiguous name "cxx"
throughout.

Done

Attachments:

v7-0001-meson-rename-cpp-variable-to-cxx.patchtext/x-patch; charset=utf-8; name=v7-0001-meson-rename-cpp-variable-to-cxx.patchDownload
From d82337f6101e600bcd99b8a2714631d11c61711c Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Mon, 5 Jan 2026 09:49:43 +0100
Subject: [PATCH v7 1/2] meson: rename cpp variable to cxx

Since CPP is also used to mean C PreProcessor in our meson.build files
it's confusing to use it to also mean C PlusPlus. This uses the
non-ambiguous cxx wherever possible.
---
 meson.build | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/meson.build b/meson.build
index c3834a9dc8f..80dd51a0d4a 100644
--- a/meson.build
+++ b/meson.build
@@ -843,7 +843,7 @@ if add_languages('cpp', required: llvmopt, native: false)
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
+    cxx = meson.get_compiler('cpp')
 
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
@@ -1917,10 +1917,10 @@ endforeach
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
 if llvm.found()
-  attrib_error_args = cpp.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
+  attrib_error_args = cxx.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
-    if cpp.compiles(testsrc.format(a),
-        args: attrib_error_args, name: 'cppformat ' + a)
+    if cxx.compiles(testsrc.format(a),
+        args: attrib_error_args, name: 'cxxformat ' + a)
       cdata.set('PG_CXX_PRINTF_ATTRIBUTE', a)
       break
     endif
@@ -2084,7 +2084,7 @@ common_functional_flags = [
 
 cflags += cc.get_supported_arguments(common_functional_flags)
 if llvm.found()
-  cxxflags += cpp.get_supported_arguments(common_functional_flags)
+  cxxflags += cxx.get_supported_arguments(common_functional_flags)
 endif
 
 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
@@ -2108,7 +2108,7 @@ common_warning_flags = [
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
 if llvm.found()
-  cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
+  cxxflags_warn += cxx.get_supported_arguments(common_warning_flags)
 endif
 
 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
@@ -2161,7 +2161,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if llvm.found() and cxx.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2230,7 +2230,7 @@ endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
 if llvm.found()
-  cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
+  cxxflags_builtin = cxx.get_supported_arguments(common_builtin_flags)
 endif
 
 
@@ -3951,7 +3951,7 @@ summary(
 if llvm.found()
   summary(
     {
-      'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
+      'C++ compiler': '@0@ @1@'.format(cxx.get_id(), cxx.version()),
     },
     section: 'Compiler',
   )

base-commit: 4c144e0452daa2508a008bb4cde520613bbd386d
-- 
2.52.0

v7-0002-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v7-0002-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From cce830ffdf911776f04179a2165a91a0a9f96da5 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v7 2/2] Decouple C++ support in Meson's PGXS from LLVM
 enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 29 ++++++++++++++++++-----------
 src/include/meson.build   |  8 +++++++-
 src/makefiles/meson.build |  4 +---
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 80dd51a0d4a..c1ea236103f 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cxx = add_languages('cpp', required: false, native: false)
+if have_cxx
+  cxx = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -836,15 +840,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cxx
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cxx = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -853,8 +855,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -1916,7 +1923,7 @@ endforeach
 
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
-if llvm.found()
+if have_cxx
   attrib_error_args = cxx.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
     if cxx.compiles(testsrc.format(a),
@@ -2083,7 +2090,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cxx
   cxxflags += cxx.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2107,7 +2114,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cxx
   cxxflags_warn += cxx.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2161,7 +2168,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cxx.has_argument('-W' + w)
+  if have_cxx and cxx.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2229,7 +2236,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cxx
   cxxflags_builtin = cxx.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3948,7 +3955,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cxx
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cxx.get_id(), cxx.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index d9c7b709330..c8ac3e60291 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,9 +36,15 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cxx
+  var_cxx = ' '.join(cxx.cmd_array())
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
+  # Default to 'g++' so PGXS users get a clear "g++ not found" error when
+  # building C++ extensions. Otherwise they'd get a confusing error because no
+  # binary is specified in the build commands and the first flag would be
+  # interpreted as the program.
+  var_cxx = 'g++'
   var_cxxflags = ''
 endif
 var_cppflags = ' '.join(cppflags)
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 124df2c8582..6f5072081da 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -86,6 +85,7 @@ pgxs_kv = {
 
   'CC': var_cc,
   'CPP': var_cpp,
+  'CXX': var_cxx,
   'GCC': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
 
   'CPPFLAGS': var_cppflags,
@@ -122,13 +122,11 @@ pgxs_kv = {
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif
-- 
2.52.0

#16Andres Freund
andres@anarazel.de
In reply to: Jelte Fennema-Nio (#15)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

Hi,

On 2026-01-05 09:56:28 +0100, Jelte Fennema-Nio wrote:

On Mon Jan 5, 2026 at 9:38 AM CET, Peter Eisentraut wrote:

Perhaps we should prefer to use the less ambiguous name "cxx"
throughout.

Done

I've not analyzed why yet, but unfortunately this currently fails in CI:
https://cirrus-ci.com/task/5825100705955840
[18:05:47.624] /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libselinux.so: error adding symbols: file in wrong format

The failure seems somewhat unrelated, odd.

Greetings,

Andres Freund

#17Jelte Fennema-Nio
postgres@jeltef.nl
In reply to: Andres Freund (#16)
3 attachment(s)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On Mon Jan 5, 2026 at 10:55 PM CET, Andres Freund wrote:

I've not analyzed why yet, but unfortunately this currently fails in CI:
https://cirrus-ci.com/task/5825100705955840
[18:05:47.624] /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libselinux.so: error adding symbols: file in wrong format

The failure seems somewhat unrelated, odd.

Fixed now (in a separate commit, but feel free to squash them). I had
run into this already on my copyObject patchset, didn't notice that it
also happened here.

Attachments:

v8-0001-meson-rename-cpp-variable-to-cxx.patchtext/x-patch; charset=utf-8; name=v8-0001-meson-rename-cpp-variable-to-cxx.patchDownload
From 25efebb6a48bb37a767018f9cf942a6276cbe528 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Mon, 5 Jan 2026 09:49:43 +0100
Subject: [PATCH v8 1/3] meson: rename cpp variable to cxx

Since CPP is also used to mean C PreProcessor in our meson.build files
it's confusing to use it to also mean C PlusPlus. This uses the
non-ambiguous cxx wherever possible.
---
 meson.build | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/meson.build b/meson.build
index c3834a9dc8f..80dd51a0d4a 100644
--- a/meson.build
+++ b/meson.build
@@ -843,7 +843,7 @@ if add_languages('cpp', required: llvmopt, native: false)
 
     cdata.set('USE_LLVM', 1)
 
-    cpp = meson.get_compiler('cpp')
+    cxx = meson.get_compiler('cpp')
 
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
@@ -1917,10 +1917,10 @@ endforeach
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
 if llvm.found()
-  attrib_error_args = cpp.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
+  attrib_error_args = cxx.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
-    if cpp.compiles(testsrc.format(a),
-        args: attrib_error_args, name: 'cppformat ' + a)
+    if cxx.compiles(testsrc.format(a),
+        args: attrib_error_args, name: 'cxxformat ' + a)
       cdata.set('PG_CXX_PRINTF_ATTRIBUTE', a)
       break
     endif
@@ -2084,7 +2084,7 @@ common_functional_flags = [
 
 cflags += cc.get_supported_arguments(common_functional_flags)
 if llvm.found()
-  cxxflags += cpp.get_supported_arguments(common_functional_flags)
+  cxxflags += cxx.get_supported_arguments(common_functional_flags)
 endif
 
 vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
@@ -2108,7 +2108,7 @@ common_warning_flags = [
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
 if llvm.found()
-  cxxflags_warn += cpp.get_supported_arguments(common_warning_flags)
+  cxxflags_warn += cxx.get_supported_arguments(common_warning_flags)
 endif
 
 # A few places with imported code get a pass on -Wdeclaration-after-statement, remember
@@ -2161,7 +2161,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cpp.has_argument('-W' + w)
+  if llvm.found() and cxx.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2230,7 +2230,7 @@ endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
 if llvm.found()
-  cxxflags_builtin = cpp.get_supported_arguments(common_builtin_flags)
+  cxxflags_builtin = cxx.get_supported_arguments(common_builtin_flags)
 endif
 
 
@@ -3951,7 +3951,7 @@ summary(
 if llvm.found()
   summary(
     {
-      'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version()),
+      'C++ compiler': '@0@ @1@'.format(cxx.get_id(), cxx.version()),
     },
     section: 'Compiler',
   )

base-commit: 7dc95cc3b94f2f558606e5ec307466a4e3dbc832
-- 
2.52.0

v8-0002-CI-Configure-g-with-32bit-for-32bit-build.patchtext/x-patch; charset=utf-8; name=v8-0002-CI-Configure-g-with-32bit-for-32bit-build.patchDownload
From 887e048bebf01792674fb466941798c7ef01ff16 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Mon, 5 Jan 2026 23:13:12 +0100
Subject: [PATCH v8 2/3] CI: Configure g++ with 32bit for 32bit build

In future commits we'll start to make improvements to C++
infrastructure. This requires that for our 32bit builds we also build
C++ code for the 32bit architecture.
---
 .cirrus.tasks.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index 745bd198b42..2bbbc3de2c9 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -570,6 +570,7 @@ task:
         su postgres <<-EOF
           set -e
           export CC='ccache gcc -m32'
+          export CXX='ccache g++ -m32'
           meson setup \
             ${MESON_COMMON_PG_CONFIG_ARGS} \
             --buildtype=debug \
-- 
2.52.0

v8-0003-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchtext/x-patch; charset=utf-8; name=v8-0003-Decouple-C-support-in-Meson-s-PGXS-from-LLVM-enab.patchDownload
From a9fcdfbdfb32d8ef0be7b344ba375928fd1f6954 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Wed, 16 Apr 2025 20:25:21 -0500
Subject: [PATCH v8 3/3] Decouple C++ support in Meson's PGXS from LLVM
 enablement

This is important for Postgres extensions that are written in C++, such
as pg_duckdb, which uses PGXS as the build system currently. In the
autotools build, C++ is not coupled to LLVM. If the autotools build is
configured without --with-llvm, the C++ compiler and the various flags
get persisted into the Makefile.global.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 meson.build               | 29 ++++++++++++++++++-----------
 src/include/meson.build   |  8 +++++++-
 src/makefiles/meson.build |  4 +---
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 80dd51a0d4a..c1ea236103f 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ build_system = build_machine.system()
 host_cpu = host_machine.cpu_family()
 
 cc = meson.get_compiler('c')
+have_cxx = add_languages('cpp', required: false, native: false)
+if have_cxx
+  cxx = meson.get_compiler('cpp')
+endif
 
 not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
@@ -836,15 +840,13 @@ endif
 
 llvmopt = get_option('llvm')
 llvm = not_found_dep
-if add_languages('cpp', required: llvmopt, native: false)
+if have_cxx
   llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt)
 
   if llvm.found()
 
     cdata.set('USE_LLVM', 1)
 
-    cxx = meson.get_compiler('cpp')
-
     llvm_binpath = llvm.get_variable(configtool: 'bindir')
 
     ccache = find_program('ccache', native: true, required: false)
@@ -853,8 +855,13 @@ if add_languages('cpp', required: llvmopt, native: false)
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
   endif
-elif llvmopt.auto()
-  message('llvm requires a C++ compiler')
+else
+  msg = 'llvm requires a C++ compiler'
+  if llvmopt.auto()
+    message(msg)
+  elif llvmopt.enabled()
+    error(msg)
+  endif
 endif
 
 
@@ -1916,7 +1923,7 @@ endforeach
 
 # We need to repeat the test for C++ because gcc and clang prefer different
 # format archetypes.
-if llvm.found()
+if have_cxx
   attrib_error_args = cxx.get_supported_arguments('-Werror=format', '-Werror=ignored-attributes')
   foreach a : printf_attributes
     if cxx.compiles(testsrc.format(a),
@@ -2083,7 +2090,7 @@ common_functional_flags = [
 ]
 
 cflags += cc.get_supported_arguments(common_functional_flags)
-if llvm.found()
+if have_cxx
   cxxflags += cxx.get_supported_arguments(common_functional_flags)
 endif
 
@@ -2107,7 +2114,7 @@ common_warning_flags = [
 ]
 
 cflags_warn += cc.get_supported_arguments(common_warning_flags)
-if llvm.found()
+if have_cxx
   cxxflags_warn += cxx.get_supported_arguments(common_warning_flags)
 endif
 
@@ -2161,7 +2168,7 @@ foreach w : negative_warning_flags
   if cc.has_argument('-W' + w)
     cflags_warn += '-Wno-' + w
   endif
-  if llvm.found() and cxx.has_argument('-W' + w)
+  if have_cxx and cxx.has_argument('-W' + w)
     cxxflags_warn += '-Wno-' + w
   endif
 endforeach
@@ -2229,7 +2236,7 @@ elif optimization == 's'
 endif
 
 cflags_builtin = cc.get_supported_arguments(common_builtin_flags)
-if llvm.found()
+if have_cxx
   cxxflags_builtin = cxx.get_supported_arguments(common_builtin_flags)
 endif
 
@@ -3948,7 +3955,7 @@ summary(
   section: 'Compiler Flags',
 )
 
-if llvm.found()
+if have_cxx
   summary(
     {
       'C++ compiler': '@0@ @1@'.format(cxx.get_id(), cxx.version()),
diff --git a/src/include/meson.build b/src/include/meson.build
index d9c7b709330..c8ac3e60291 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -36,9 +36,15 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
 var_cflags = ' '.join(cflags + cflags_builtin + cflags_warn + get_option('c_args'))
-if llvm.found()
+if have_cxx
+  var_cxx = ' '.join(cxx.cmd_array())
   var_cxxflags = ' '.join(cxxflags + cxxflags_builtin + cxxflags_warn + get_option('cpp_args'))
 else
+  # Default to 'g++' so PGXS users get a clear "g++ not found" error when
+  # building C++ extensions. Otherwise they'd get a confusing error because no
+  # binary is specified in the build commands and the first flag would be
+  # interpreted as the program.
+  var_cxx = 'g++'
   var_cxxflags = ''
 endif
 var_cppflags = ' '.join(cppflags)
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 124df2c8582..6f5072081da 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -31,7 +31,6 @@ if not working_strip
   strip_shared_cmd = [':']
 endif
 
-
 pgxs_kv = {
   'PACKAGE_URL': pg_url,
   'PACKAGE_VERSION': pg_version,
@@ -86,6 +85,7 @@ pgxs_kv = {
 
   'CC': var_cc,
   'CPP': var_cpp,
+  'CXX': var_cxx,
   'GCC': cc.get_argument_syntax() == 'gcc' ? 'yes' : 'no',
 
   'CPPFLAGS': var_cppflags,
@@ -122,13 +122,11 @@ pgxs_kv = {
 if llvm.found()
   pgxs_kv += {
     'CLANG': clang.full_path(),
-    'CXX': ' '.join(cpp.cmd_array()),
     'LLVM_BINPATH': llvm_binpath,
   }
 else
   pgxs_kv += {
     'CLANG': '',
-    'CXX': '',
     'LLVM_BINPATH': '',
   }
 endif
-- 
2.52.0

#18Peter Eisentraut
peter@eisentraut.org
In reply to: Jelte Fennema-Nio (#17)
Re: Decouple C++ support in Meson's PGXS from LLVM enablement

On 05.01.26 23:18, Jelte Fennema-Nio wrote:

On Mon Jan 5, 2026 at 10:55 PM CET, Andres Freund wrote:

I've not analyzed why yet, but unfortunately this currently fails in CI:
https://cirrus-ci.com/task/5825100705955840
[18:05:47.624] /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libselinux.so:
error adding symbols: file in wrong format

The failure seems somewhat unrelated, odd.

Fixed now (in a separate commit, but feel free to squash them). I had
run into this already on my copyObject patchset, didn't notice that it
also happened here.

committed