There are two ways to use the pre-built binaries of clang+llvm on a glibc
system, such as Ubuntu:
a) Use CC=clang, CXX=clang++. This makes use of the clang++ runtime
libraries. But AFAIU these are ABI-incompatible with the system's
libstdc++ and thus with all other preinstalled libraries that use
C++.
b) Use CXX="clang++ -I/usr/include/c++/11
-I/usr/include/x86_64-linux-gnu/c++/11 -L/usr/lib/gcc/x86_64-linux-gnu/11"
with -I and -L options that ensure taht the system's libstdc++ gets
used. So that it becomes ABI-compatible with preinstalled libraries.
The approach b) encounters a build a error in a testdir of all of gnulib,
however:
/home/bruno/inst-clang/18.1.4/bin/clang++ -I/usr/include/c++/11
-I/usr/include/x86_64-linux-gnu/c++/11 -L/usr/lib/gcc/x86_64-linux-gnu/11
-Wl,-rpath,/home/bruno/inst-clang/18.1.4/lib -DHAVE_CONFIG_H -DEXEEXT=\"\"
-DEXEEXT=\"\" -I. -I../../gltests -I.. -DGNULIB_STRICT_CHECKING=1
-DIN_GNULIB_TESTS=1 -I. -I../../gltests -I.. -I../../gltests/.. -I../gllib
-I../../gltests/../gllib -I/media/develdata/devel/inst-x86_64-64/include -Wall
-Wno-error -g -O2 -MT test-nullptr-c++.o -MD -MP -MF $depbase.Tpo -c -o
test-nullptr-c++.o ../../gltests/test-nullptr-c++.cc &&\
mv -f $depbase.Tpo $depbase.Po
clang++: warning: -Wl,-rpath,/home/bruno/inst-clang/18.1.4/lib: 'linker' input
unused [-Wunused-command-line-argument]
clang++: warning: argument unused during compilation:
'-L/usr/lib/gcc/x86_64-linux-gnu/11' [-Wunused-command-line-argument]
../../gltests/test-nullptr-c++.cc:38:3: error: use of undeclared identifier
'_gl_pre_abort'
38 | ASSERT (first[0] == 't');
| ^
../../gltests/macros.h:85:15: note: expanded from macro 'ASSERT'
85 | _gl_pre_abort ();
\
| ^
../../gltests/test-nullptr-c++.cc:42:3: error: use of undeclared identifier
'_gl_pre_abort'
42 | ASSERT (arg == NULL);
| ^
../../gltests/macros.h:85:15: note: expanded from macro 'ASSERT'
85 | _gl_pre_abort ();
\
| ^
../../gltests/test-nullptr-c++.cc:45:3: error: use of undeclared identifier
'_gl_pre_abort'
45 | ASSERT (arg[0] == 'f');
| ^
../../gltests/macros.h:85:15: note: expanded from macro 'ASSERT'
85 | _gl_pre_abort ();
\
| ^
../../gltests/test-nullptr-c++.cc:48:3: error: use of undeclared identifier
'_gl_pre_abort'
48 | ASSERT (arg == NULL);
| ^
../../gltests/macros.h:85:15: note: expanded from macro 'ASSERT'
85 | _gl_pre_abort ();
\
| ^
4 errors generated.
make[4]: *** [Makefile:27303: test-nullptr-c++.o] Error 1
Where does this error come from?
* When a #include <stdlib.h> is encountered, gllib/stdlib.h is no
longer the first file in the "next" chain. But rather that chain
consists of
1. /usr/include/c++/11/stdlib.h
2. gllib/stdlib.h
3. /usr/include/stdlib.h
* At the first #include <stdlib.h>, __need_system_stdlib_h happens
to be set (by gllib/pthread.h), and so the bulk of gllib/stdlib.h
is bypassed.
* Further #include <stdlib.h> don't even reach gllib/stdlib.h, since
the file in position 1 (/usr/include/c++/11/stdlib.h), which does
not obey the __need_system_stdlib_h convention, expands to nothing.
* Thus, the declaration of _gl_pre_abort in gllib/stdlib.h is never seen.
This patch fixes it.
2024-07-13 Bruno Haible <[email protected]>
stdlib: Support use of clang++ on Ubuntu.
* lib/stdlib.in.h: Ignore __need_system_stdlib_h when GCC's
c++/11/stdlib.h is being included or has been included.
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index cfc69d0a50..47a8856dc7 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -20,9 +20,18 @@
#endif
@PRAGMA_COLUMNS@
-#if defined __need_system_stdlib_h || defined __need_malloc_and_calloc
+#if (defined __need_system_stdlib_h && !defined _GLIBCXX_STDLIB_H) || defined
__need_malloc_and_calloc
/* Special invocation conventions inside some gnulib header files,
- and inside some glibc header files, respectively. */
+ and inside some glibc header files, respectively.
+ Do not recognize this special invocation convention when GCC's
+ c++/11/stdlib.h is being included or has been included. This is needed
+ to support the use of clang+llvm binaries on Ubuntu 22.04 with
+ CXX="$clangdir/bin/clang++ -I/usr/include/c++/11 \
+ -I/usr/include/x86_64-linux-gnu/c++/11
+ -L/usr/lib/gcc/x86_64-linux-gnu/11
+ -Wl,-rpath,$clangdir/lib"
+ because in this case /usr/include/c++/11/stdlib.h (which does not support
+ the convention) is seen before the gnulib-generated stdlib.h. */
#@INCLUDE_NEXT@ @NEXT_STDLIB_H@