Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Fail to build LLVM due to cmath on macOS 10.13 #51542

Closed Quuxplusone closed 3 years ago

Quuxplusone commented 3 years ago
Bugzilla Link PR52575
Status RESOLVED INVALID
Importance P normal
Reported by Chris Long (chris@chrislong.dev)
Reported on 2021-11-21 20:35:21 -0800
Last modified on 2021-11-22 02:29:28 -0800
Version 12.0
Hardware Macintosh MacOS X
CC dimitry@andric.com, htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
Fixed by commit(s)
Attachments 02.log (63983 bytes, text/plain)
Blocks
Blocked by
See also
Created attachment 25464
Full build log

I originally reported this at https://github.com/rust-lang/rust/issues/88068
and was told this is an upstream issue in LLVM; from browsing the Rust source,
it appears the regression appeared between LLVM 11 and 12.

When trying to build Rust using Homebrew on macOS 10.13, I'm receiving several
errors similar to:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/cmath:325:9:
error: no member named 'isunordered' in the global namespace
using ::isunordered;
      ~~^

I've attached the whole build log. Per
https://stackoverflow.com/a/68113682/165713, a mitigation seems to be to add a
CMake directive like "set(CMAKE_OSX_SYSROOT
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk)".
A Rust engineer also suggested possible fixes at
https://stackoverflow.com/a/58670035.

Apologies for not having more detail; I'm new to Rust and even newer to LLVM,
but I'll definitely help here however I can!
Quuxplusone commented 3 years ago

Attached 02.log (63983 bytes, text/plain): Full build log

Quuxplusone commented 3 years ago
This error occurs because you are compiling a C++ program, and are using "-
isystem
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include",
which puts this directory at the front of your include search dirs, *before*
the libc++ include directory.

This will not work correctly, and you should probably just stop adding -
isystem. But if that is not possible for other reasons, you should also add the
libc++ include directory *before* the regular include directory, i.e. do
something like:

-isystem ${SDKDIR}/usr/include/c++/v1 -isystem ${SDKDIR}/usr/include

(Assuming here that
SDKDIR="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk")

How this happens is as follows. By default, if you compile a C++ program, clang
sets up the include search dirs similar to:

#include <...> search starts here:
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)

Any header such as <cmath> or <math.h> will therefore be found *first* in the
libc++ include directory, ${SDKDIR}/usr/include/c++/v1. Whenever libc++ wants
to use the C version of <math.h>, it will include it using
#include_next<math.h>, which attempts to find math.h from the *next* path in
the search directory list.

So normally, including <cmath> goes like:
* #include <cmath>       -> finds ${SDKDIR}/usr/include/c++/v1/cmath
* #include <math.h>      -> finds ${SDKDIR}/usr/include/c++/v1/math.h (this is
a wrapper header)
* #include_next <math.h> -> finds ${SDKDIR}/usr/include/math.h

Now if you add -isystem ${SDKDIR}/usr/include to your compilation, the include
search dirs will look like:

#include <...> search starts here:
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)

I.e., ${SDKDIR}/usr/include is now before ${SDKDIR}/usr/include/c++/v1, and
then including <cmath> goes like:
* #include <cmath>       -> still finds ${SDKDIR}/usr/include/c++/v1/cmath, as
before
* #include <math.h>      -> finds ${SDKDIR}/usr/include/math.h, the plain C one
and *not* the wrapper header
* there won't be any #include_next <math.h> now since the plain C version does
not do that
* back in <cmath>, several "using" directives will now fail since the libc++
math.h wrapper was not included first

So the conclusion of this story is: if you really must set your own system
include paths using -isystem, that is fine, but you *must* also set the C++
include paths correctly, and in the right order, not only the plain C include
paths.
Quuxplusone commented 3 years ago

Thank you for the detailed info Dimitry; that all makes total sense! I'll check the Rust build system to see if I can find out where these flags are being set and try to submit a patch downstream :)

Quuxplusone commented 3 years ago
(In reply to Chris Long from comment #2)
> Thank you for the detailed info Dimitry; that all makes total sense! I'll
> check the Rust build system to see if I can find out where these flags are
> being set and try to submit a patch downstream :)

Note that in FreeBSD we've also encountered this issue with a number of ports,
which were setting their own -isystem flags incorrectly. E.g. this is not
limited to macOS. :)