conflicting builtins in clang with musl (stddef.h)

Hello there,

I'm building a Linux distribution based on musl and LLVM as default
toolchain (including lld/libc++/libc++abi/libunwind rather than GNU).
For most of the time this works pretty well.

However I'm having troubles with few packages, webkit for instance
fails because of max_align_t being redeclared in musl's stddef.h

I see that stddef.h is provided by both musl and in the private clang
include directories.

    /include/stddef.h
    /lib/clang/8.0.0/include/stddef.h

Usually, compiling a sample program works:

$ cat test.cpp
#include <stddef.h>
#include <limits>
#include <type_traits>

int main() {
}

$ clang++ -std=c++17 -v test.cpp
Vanilla Linux clang version 8.0.0 (tags/RELEASE_800/final) (based on
LLVM 8.0.0)
Target: x86_64-unknown-linux-musl
Thread model: posix
InstalledDir: /bin
"/bin/clang-8" -cc1 -triple x86_64-unknown-linux-musl -emit-obj
-mrelax-all -disable-free -disable-llvm-verifier -discard-value-names
-main-file-name test.cpp -mrelocation-model pic -pic-level 2 -pic-is-
pie -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose
-mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-
64 -dwarf-column-info -debugger-tuning=gdb -v -resource-dir
/lib/clang/8.0.0 -internal-isystem /bin/../include/c++/v1 -internal-
isystem /usr/local/include -internal-isystem /lib/clang/8.0.0/include
-internal-externc-isystem /include -internal-externc-isystem
/usr/include -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /tmp
-ferror-limit 19 -fmessage-length 274 -fobjc-runtime=gcc -fcxx-
exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics
-o /tmp/test-0249b1.o -x c++ test.cpp -faddrsig
clang -cc1 version 8.0.0 based upon LLVM 8.0.0 default target x86_64-
linux-musl
ignoring nonexistent directory "/usr/local/include"
ignoring duplicate directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/bin/../include/c++/v1
/lib/clang/8.0.0/include
/include
End of search list.
"/bin/ld.lld" -pie --eh-frame-hdr -m elf_x86_64 -dynamic-linker
/lib/ld-musl-x86_64.so.1 -o a.out /bin/../lib/Scrt1.o
/bin/../lib/crti.o /lib/clang/8.0.0/lib/linux/crtbeginS.o -L/bin/../lib
-L/lib -L/usr/lib /tmp/test-0249b1.o -lc++ -lm
/lib/clang/8.0.0/lib/linux/libclang_rt.builtins-x86_64.a -lc
/lib/clang/8.0.0/lib/linux/libclang_rt.builtins-x86_64.a
/lib/clang/8.0.0/lib/linux/crtendS.o /bin/../lib/crtn.o

However, webkit's CMake for some reasons adds -isystem /include which
breaks the build with the error I mentioned above. I can reproduce it
with this example of code too:

$ clang++ -isystem /include -std=c++17 test.cpp
In file included from test.cpp:2:
In file included from /bin/../include/c++/v1/limits:106:
In file included from /bin/../include/c++/v1/type_traits:406:
In file included from /bin/../include/c++/v1/cstddef:45:
In file included from /lib/clang/8.0.0/include/stddef.h:118:
/lib/clang/8.0.0/include/__stddef_max_align_t.h:40:3: error: typedef
redefinition with different types ('struct max_align_t' vs 'struct
max_align_t')
} max_align_t;
  ^
/include/bits/alltypes.h:49:54: note: previous definition is here
typedef struct { long long __ll; long double __ld; } max_align_t;
                                                     ^
1 error generated.

I've asked to the musl's maintainer and said that clang should not
provide std* files that are already present in musl. He also said that
the include order should be inversed to use '/include' first. I've
checked FreeBSD which also use clang and they effectively removed
stddef.h and all headers that are already provided by their own libc.

So I've tried to remove them temporarily but now, it's the opposite.
webkit fails to find stddef.h even though it's provided by musl in
/include/stddef.h.

# clang++ -std=c++17 -isystem /include test.cpp
In file included from test.cpp:2:
In file included from /bin/../include/c++/v1/limits:106:
In file included from /bin/../include/c++/v1/type_traits:406:
/bin/../include/c++/v1/cstddef:45:15: fatal error: 'stddef.h' file not
found
#include_next <stddef.h>
              ^~~~~~~~~~
1 error generated.

I'm scratching my hair trying to understand what is wrong and what
should I do here.

Also, I can't understand why CMake adds all these -isystem include
directories. But this is a webkit issue I guess.

Any ideas/recommandations are welcome.

Kind regards,

Hello there,

I'm building a Linux distribution based on musl and LLVM as default
toolchain (including lld/libc++/libc++abi/libunwind rather than GNU).
For most of the time this works pretty well.

However I'm having troubles with few packages, webkit for instance
fails because of max_align_t being redeclared in musl's stddef.h

I see that stddef.h is provided by both musl and in the private clang
include directories.

    /include/stddef.h
    /lib/clang/8.0.0/include/stddef.h

Usually, compiling a sample program works:

$ cat test.cpp
#include <stddef.h>
#include <limits>
#include <type_traits>

int main() {
}

$ clang++ -std=c++17 -v test.cpp
Vanilla Linux clang version 8.0.0 (tags/RELEASE_800/final) (based on
LLVM 8.0.0)
Target: x86_64-unknown-linux-musl
Thread model: posix
InstalledDir: /bin
"/bin/clang-8" -cc1 -triple x86_64-unknown-linux-musl -emit-obj
-mrelax-all -disable-free -disable-llvm-verifier -discard-value-names
-main-file-name test.cpp -mrelocation-model pic -pic-level 2 -pic-is-
pie -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose
-mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-
64 -dwarf-column-info -debugger-tuning=gdb -v -resource-dir
/lib/clang/8.0.0 -internal-isystem /bin/../include/c++/v1 -internal-
isystem /usr/local/include -internal-isystem /lib/clang/8.0.0/include
-internal-externc-isystem /include -internal-externc-isystem
/usr/include -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /tmp
-ferror-limit 19 -fmessage-length 274 -fobjc-runtime=gcc -fcxx-
exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics
-o /tmp/test-0249b1.o -x c++ test.cpp -faddrsig
clang -cc1 version 8.0.0 based upon LLVM 8.0.0 default target x86_64-
linux-musl
ignoring nonexistent directory "/usr/local/include"
ignoring duplicate directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/bin/../include/c++/v1
/lib/clang/8.0.0/include
/include
End of search list.
"/bin/ld.lld" -pie --eh-frame-hdr -m elf_x86_64 -dynamic-linker
/lib/ld-musl-x86_64.so.1 -o a.out /bin/../lib/Scrt1.o
/bin/../lib/crti.o /lib/clang/8.0.0/lib/linux/crtbeginS.o -L/bin/../lib
-L/lib -L/usr/lib /tmp/test-0249b1.o -lc++ -lm
/lib/clang/8.0.0/lib/linux/libclang_rt.builtins-x86_64.a -lc
/lib/clang/8.0.0/lib/linux/libclang_rt.builtins-x86_64.a
/lib/clang/8.0.0/lib/linux/crtendS.o /bin/../lib/crtn.o

However, webkit's CMake for some reasons adds -isystem /include which
breaks the build with the error I mentioned above. I can reproduce it
with this example of code too:

$ clang++ -isystem /include -std=c++17 test.cpp
In file included from test.cpp:2:
In file included from /bin/../include/c++/v1/limits:106:
In file included from /bin/../include/c++/v1/type_traits:406:
In file included from /bin/../include/c++/v1/cstddef:45:
In file included from /lib/clang/8.0.0/include/stddef.h:118:
/lib/clang/8.0.0/include/__stddef_max_align_t.h:40:3: error: typedef
redefinition with different types ('struct max_align_t' vs 'struct
max_align_t')
} max_align_t;
  ^
/include/bits/alltypes.h:49:54: note: previous definition is here
typedef struct { long long __ll; long double __ld; } max_align_t;
                                                     ^
1 error generated.

I've asked to the musl's maintainer and said that clang should not
provide std* files that are already present in musl. He also said that
the include order should be inversed to use '/include' first. I've
checked FreeBSD which also use clang and they effectively removed
stddef.h and all headers that are already provided by their own libc.

So I've tried to remove them temporarily but now, it's the opposite.
webkit fails to find stddef.h even though it's provided by musl in
/include/stddef.h.

# clang++ -std=c++17 -isystem /include test.cpp
In file included from test.cpp:2:
In file included from /bin/../include/c++/v1/limits:106:
In file included from /bin/../include/c++/v1/type_traits:406:
/bin/../include/c++/v1/cstddef:45:15: fatal error: 'stddef.h' file not
found
#include_next <stddef.h>
              ^~~~~~~~~~
1 error generated.

I'm scratching my hair trying to understand what is wrong and what
should I do here.

Also, I can't understand why CMake adds all these -isystem include
directories. But this is a webkit issue I guess.

Any ideas/recommandations are welcome.

you might want to look at the patches we have for webkit

https://git.openembedded.org/openembedded-core/tree/meta/recipes-sato/webkit/webkitgtk

especially
https://git.openembedded.org/openembedded-core/tree/meta/recipes-sato/webkit/webkitgtk/0001-Fix-build-with-musl.patch
https://git.openembedded.org/openembedded-core/tree/meta/recipes-sato/webkit/webkitgtk/0001-WebKitMacros-Append-to-I-and-not-to-isystem.patch

the second patch will help solve your current problem, but there will
be more down the line :slight_smile:

We have a layer for Yocto/OE which builds a linux distribution in a
cross environment using clang + clang-runtime + musl as you are using.
It might be useful for you
in what you are doing. See

https://github.com/kraj/meta-clang

if you want latest 9.0-rc stuff then its in kraj/master branch

...

I've asked to the musl's maintainer and said that clang should not
provide std* files that are already present in musl. He also said that
the include order should be inversed to use '/include' first. I've
checked FreeBSD which also use clang and they effectively removed
stddef.h and all headers that are already provided by their own libc.

Indeed, but that situation is not ideal. E.g. if some builds their own
clang, they still get all the conflicting headers, which are put first
in the default include path.

It would be better for the future to make clang's internal headers
compatible with both FreeBSD's and musl's standard headers. For
example, by first including the system header using #include_next, and
then taking care not to attempt to override any types or macros defined
by the system header, such as max_align_t.

So I've tried to remove them temporarily but now, it's the opposite.
webkit fails to find stddef.h even though it's provided by musl in
/include/stddef.h.

# clang++ -std=c++17 -isystem /include test.cpp
In file included from test.cpp:2:
In file included from /bin/../include/c++/v1/limits:106:
In file included from /bin/../include/c++/v1/type_traits:406:
/bin/../include/c++/v1/cstddef:45:15: fatal error: 'stddef.h' file not
found
#include_next <stddef.h>
             ^~~~~~~~~~
1 error generated.

This is because you have placed /include before any other include paths,
and none of those other include paths will likely contain a stddef.h
file.

For example, on FreeBSD the default include path order for a C++
compilation is as follows:

#include <...> search starts here:
/usr/include/c++/v1
/usr/lib/clang/8.0.1/include
/usr/include

The C++ header /usr/include/c++/v1/cstddef will search for the *next*
<stddef.h>, which will be found in /usr/include (as we do not put it in
/usr/lib/clang/8.0.1/include).

However, if you use -isystem /usr/include, similar to what you have
done, the include path order becomes:

#include <...> search starts here:
/usr/include
/usr/include/c++/v1
/usr/lib/clang/8.0.1/include

Now, any header under /usr/include/c++/v1 will only be able to search
the paths coming *after* it, and will therefore not find <stddef.h>.

-Dimitry

you might want to look at the patches we have for webkit

https://git.openembedded.org/openembedded-core/tree/meta/recipes-sato/webkit/webkitgtk

especially
https://git.openembedded.org/openembedded-core/tree/meta/recipes-sato/webkit/webkitgtk/0001-Fix-build-with-musl.patch
https://git.openembedded.org/openembedded-core/tree/meta/recipes-sato/webkit/webkitgtk/0001-WebKitMacros-Append-to-I-and-not-to-isystem.patch

Thanks, the second patch helped but there were still some -isystem here and there. I've updated the patch to change all I've found in the tree.

http://hg.malikania.fr/vanilla/file/tip/www/webkitgtk/patch-isystem.patch

the second patch will help solve your current problem, but there will
be more down the line :slight_smile:

We have a layer for Yocto/OE which builds a linux distribution in a
cross environment using clang + clang-runtime + musl as you are using.
It might be useful for you
in what you are doing. See

https://github.com/kraj/meta-clang

Thanks! Very interesting.

Regards,