Hello again hackers,
I've been toying with LLVM-related code recently while I finished up
a new extension [1] that also uses the LLVM. That led me to this
finding.
configure finds clang only through PATH, independently of the LLVM
installation chosen with LLVM_CONFIG. On Debian 13, which ships LLVM 19
by default with 21 in trixie-backports, this goes wrong in both
directions:
* LLVM_CONFIG=llvm-config-21, unversioned clang on PATH is clang-19:
configure succeeds, bitcode comes from clang-19, llvmjit.so links
LLVM 21. That combination happens to work.
* LLVM_CONFIG=llvm-config-19, clang on PATH is clang-21: configure
succeeds, and every JIT compilation then ends the backend:
error: Unknown attribute kind (102) (Producer: 'LLVM21.1.8' Reader:
'LLVM 19.1.7')
(That's LLVM's default diagnostic handler calling exit(1) while
reading llvmjit_types.bc, so it shows up as a backend exiting with
status 1 rather than a crash.)
* LLVM_CONFIG=llvm-config-21 and no unversioned clang on PATH:
configure fails, although /usr/lib/llvm-21/bin/clang is right there.
The meson build has always used the clang from llvm-config --bindir,
falling back to PATH. The attached patch makes configure do the same,
in the order Andres suggested in [1]: an explicit CLANG wins, then the
clang in llvm-config --bindir, then PATH. An explicit CLANG is still
the way to use a faster clang when building against an assertion-enabled
LLVM, which was Andres's concern about always using the bundled one.
Tested on Debian 13 with all three cases above, plus an explicit
CLANG="ccache clang-19", which is kept as given.
Since this changes which compiler configure picks, I haven't marked it
for backpatching; it applies to 17 through 19 if a committer thinks it
should go back.
This has come up before ([2], Heikki in 2018, and in [3]), and Jelte hit
the same mismatch more recently while testing typeof_unqual.
best.
-greg
[1] https://codeberg.org/gregburd/pg_pure
[2] https://postgr.es/m/2eda6b0f-cf08-b847-c33a-cb0e746d21ef%40iki.fi
[3] https://postgr.es/m/C5C97974-FB47-45AF-9DD3-30969302866A%40anarazel.de
From a097ae1bd4998eeb036a5c2a444c5c02b0bcf6be Mon Sep 17 00:00:00 2001
From: Greg Burd <[email protected]>
Date: Tue, 27 Oct 2026 21:04:46 -0400
Subject: [PATCH v2 2/2] jit: Prefer clang from llvm-config --bindir in
configure.
configure looked for clang only in PATH, independently of the LLVM
installation selected with LLVM_CONFIG. With more than one LLVM
version installed, as on Debian and Ubuntu where a newer one is
available alongside the default, that silently picks a clang that
doesn't match the LLVM library llvmjit.so links against. If that
clang is newer, every JIT compilation fails, because LLVM can't read
the bitcode in llvmjit_types.bc:
error: Unknown attribute kind (102) (Producer: 'LLVM21.1.8' Reader: 'LLVM
19.1.7')
and the backend exits. If no unversioned clang is in PATH at all,
configure fails even though the LLVM installation provides one.
Look for clang in llvm-config --bindir first, falling back to PATH as
before. An explicitly set CLANG still wins, which remains the way to
use a faster clang when building against an assertion-enabled LLVM.
This is the search order Andres Freund suggested, and what the meson
build has always done.
Author: Greg Burd <[email protected]>
Suggested-by: Andres Freund <[email protected]>
Discussion: https://postgr.es/m/2eda6b0f-cf08-b847-c33a-cb0e746d21ef%40iki.fi
Discussion:
https://postgr.es/m/C5C97974-FB47-45AF-9DD3-30969302866A%40anarazel.de
---
config/llvm.m4 | 10 ++++++----
configure | 10 ++++++----
doc/src/sgml/installation.sgml | 6 +++++-
3 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/config/llvm.m4 b/config/llvm.m4
index 5d4f14cb900..fd5e6c5b7fc 100644
--- a/config/llvm.m4
+++ b/config/llvm.m4
@@ -30,9 +30,13 @@ AC_DEFUN([PGAC_LLVM_SUPPORT],
fi
AC_MSG_NOTICE([using llvm $pgac_llvm_version])
- # need clang to create some bitcode files
+ # need clang to create some bitcode files. Prefer the one belonging to the
+ # LLVM installation found above, like meson does, as LLVM can't read
+ # bitcode produced by a newer clang, and an older one isn't guaranteed to
+ # work either.
AC_ARG_VAR(CLANG, [path to clang compiler to generate bitcode])
- PGAC_PATH_PROGS(CLANG, clang)
+ LLVM_BINPATH=`$LLVM_CONFIG --bindir`
+ PGAC_PATH_PROGS(CLANG, clang, [], [$LLVM_BINPATH$PATH_SEPARATOR$PATH])
if test -z "$CLANG"; then
AC_MSG_ERROR([clang not found, but required when compiling --with-llvm,
specify with CLANG=])
fi
@@ -91,8 +95,6 @@ AC_DEFUN([PGAC_LLVM_SUPPORT],
esac
done
- LLVM_BINPATH=`$LLVM_CONFIG --bindir`
-
dnl LLVM_CONFIG, CLANG are already output via AC_ARG_VAR
AC_SUBST(LLVM_LIBS)
AC_SUBST(LLVM_CPPFLAGS)
diff --git a/configure b/configure
index 6b05d4c84ab..4234d027959 100755
--- a/configure
+++ b/configure
@@ -5037,8 +5037,12 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: using llvm $pgac_llvm_version" >&5
$as_echo "$as_me: using llvm $pgac_llvm_version" >&6;}
- # need clang to create some bitcode files
+ # need clang to create some bitcode files. Prefer the one belonging to the
+ # LLVM installation found above, like meson does, as LLVM can't read
+ # bitcode produced by a newer clang, and an older one isn't guaranteed to
+ # work either.
+ LLVM_BINPATH=`$LLVM_CONFIG --bindir`
if test -z "$CLANG"; then
for ac_prog in clang
do
@@ -5055,7 +5059,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
+for as_dir in $LLVM_BINPATH$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -5151,8 +5155,6 @@ fi
esac
done
- LLVM_BINPATH=`$LLVM_CONFIG --bindir`
-
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index e4159522e18..1c69d4c8f3d 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -972,7 +972,11 @@ build-postgresql:
<command>clang</command> compiler (specified, if necessary, using the
<envar>CLANG</envar> environment variable), and a working C++
compiler (specified, if necessary, using the <envar>CXX</envar>
- environment variable).
+ environment variable). If <envar>CLANG</envar> is not set, the
+ <command>clang</command> in the directory reported by
+ <literal>llvm-config --bindir</literal> is used if it exists,
+ otherwise <command>clang</command> is searched for in your
+ <envar>PATH</envar>.
</para>
</listitem>
</varlistentry>
--
2.54.0