How to deal with gcc's <cstdlib> with multiarch glibc headers?
Hi,
I was offered some CPU cycles to research the impact of #798955 (moving
glibc's headers to /usr/include/<triplet>). I'll post another mail with
a summary, but there is already one quite obvious issue affecting
multiple packages. The implications are not quite clear to me, so maybe
someone else can chime in?
/usr/include/c++/8/cstdlib contains the following code:
| // Need to ensure this finds the C library's <stdlib.h> not a libstdc++
| // wrapper that might already be installed later in the include search path.
| #define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
| #include_next <stdlib.h>
| #undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
After fixing #798955, glibc's stdlib.h will live in
/usr/include/<triplet>. One can figure out the default include search
path with "gcc -E -Wp,-v - </dev/null". Notably, /usr/include/<triplet>
comes before /usr/include. Adding -x c++ gives the search path for C++.
Notably /usr/include/c++/8 comes before both others.
Now most of the time, that works, but some packages (such as
chromium-browser, fcitx-qt5, fw4spl, or gemma) insist on adding some
-isystem /usr/include/<triplet>. That changes order and one can get:
| /usr/include/c++/8/cstdlib:75:15: fatal error: stdlib.h: No such file or directory
| #include_next <stdlib.h>
| ^~~~~~~~~~
| compilation terminated.
You can trigger the very same error on a standard sid system using
-isystem /usr/include:
| echo '#include <cstdlib>' | g++ -isystem /usr/include -x c++ -E - >/dev/null
After messing with system include order, that's a little expected, but I
wonder whether it should work anyway.
Now gcc also ships /usr/include/c++/8/stdlib.h which starts with:
| #if !defined __cplusplus || defined _GLIBCXX_INCLUDE_NEXT_C_HEADERS
| # include_next <stdlib.h>
| #else
So it seems that if we replaced the #include_next in cstdlib with a
plain #include, it should always work, regardless of the search order:
If glibc's header comes first, all is fine. Otherwise, the
_GLIBCXX_INCLUDE_NEXT_C_HEADERS macro will instruct gcc's stdlib.h to
#include_next glibc's stdlib.h, so it should also be fine. What I don't
understand is: why does cstdlib use #include_next at all? What problem
is solved by not using plain #include?
Then the question arises whether adding /usr/include/<triplet> via
-isystem is something that should work. Should we fix chromium-browser
et al here?
Thanks in advance
Helmut
Reply to: