升级到 Catalina 10.15后无法在 Mac 上编译 C 程序

有一个以前的问题 升级到 Mojave 后无法在 Mac 上编译 C 程序,和答案已经涵盖了什么出错的大多数变化。

现在,从2019-10-07周一开始,您可以升级到 macOS Catalina 10.15。在升级过程中,/usr/include目录又一次被更新打乱了,尽管 XCode 11.0是在升级(从 Mojave 10.14.6)到 Catalina 之前安装的。因此,预期存在 /usr/include目录的编译器不再工作。

关于 Mojave 问题的主要建议步骤ーー使用以下命令:

open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg

因为目录 /Library/Developer/CommandLineTools/Packages/不存在(所以还没有要打开的 .pkg文件) ,所以不能在门外工作。

是否有一个好的(正式的)方法来创建和填充目录 /usr/include

66482 次浏览

TL;DR

It appears that Apple considers /usr/include as something that has gone the way of the dodo — it is extinct — or maybe it's like Monty Python's Parrot.

Using the Apple-provided GCC (actually, that's Clang by any other name, as the version information shows) or Clang avoids problems. Both /usr/bin/gcc and /usr/bin/clang will find the system libraries four directory levels below:

/Applications/Xcode.app/Contents/Developer/Platforms/…

If you build your own GCC or other compiler, you will (probably) need to configure it to find the system libraries under the Xcode application directory.

Explorations

Immediately after the upgrade, I ran XCode 11.0. It wanted to install some extra components, so I let it do so. However, that did not reinstate /usr/include or the directory under /Library.

One of the other bits of advice in the previous question was to run:

xcode-select --install

When doing so, it claimed that it downloaded the command line utilities, and it ensured that /usr/bin/gcc and /usr/bin/clang etc were present. That's a useful step (though I didn't definitively check whether they were present before).

$ /usr/bin/gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$

Using /usr/bin/gcc, it is now possible to compile programs:

$ make CC=/usr/bin/gcc al
co  RCS/al.c,v al.c
RCS/al.c,v  -->  al.c
revision 1.7
done
/usr/bin/gcc -I/Users/jleffler/inc -g -O3 -std=c11 -pedantic -Wall -Wextra -Werror -Wshadow -Wmissing-prototypes -Wpointer-arith  -Wold-style-definition -Wcast-qual -Wstrict-prototypes -DHAVE_MEMMEM -DHAVE_STRNDUP -DHAVE_STRNLEN  -DHAVE_GETDELIM   -o al al.c -L/Users/jleffler/lib/64  -ljl
$

However, /usr/include is still missing. There is a directory under /Library now:

$ ls /Library/Developer
CommandLineTools  PrivateFrameworks
$ ls /Library/Developer/CommandLineTools
Library SDKs    usr
$ ls /Library/Developer/CommandLineTools/SDKs
MacOSX.sdk      MacOSX10.14.sdk MacOSX10.15.sdk
$ ls /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/
Entitlements.plist SDKSettings.json   System
Library            SDKSettings.plist  usr
$

Neither the System nor the Library directory contain anything very promising.

When all else fails, read the manual

Next step — find and read the release notes:

There's no information in there that relates to this. So, the probability is (AFAICS, after only an hour or two's effort) that Apple no longer support /usr/include — though it does still have a fully-loaded /usr/lib (no /lib though).

Time to check another compilation with GCC option -v added (in the makefile I used, setting UFLAGS adds the option to C compiler command line):

$ make UFLAGS=-v CC=/usr/bin/gcc ww
co  RCS/ww.c,v ww.c
RCS/ww.c,v  -->  ww.c
revision 4.9
done
/usr/bin/gcc -I/Users/jleffler/inc -g -O3 -std=c11 -pedantic -Wall -Wextra -Werror -Wshadow -Wmissing-prototypes -Wpointer-arith  -Wold-style-definition -Wcast-qual -Wstrict-prototypes -DHAVE_MEMMEM -DHAVE_STRNDUP -DHAVE_STRNLEN  -DHAVE_GETDELIM -v  -o ww ww.c -L/Users/jleffler/lib/64  -ljl
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ww.c -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-sdk-version=10.15 -target-cpu penryn -dwarf-column-info -debug-info-kind=standalone -dwarf-version=4 -debugger-tuning=lldb -ggnu-pubnames -target-linker-version 512.4 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -I /Users/jleffler/inc -D HAVE_MEMMEM -D HAVE_STRNDUP -D HAVE_STRNLEN -D HAVE_GETDELIM -I/usr/local/include -O3 -Wall -Wextra -Werror -Wshadow -Wmissing-prototypes -Wpointer-arith -Wold-style-definition -Wcast-qual -Wstrict-prototypes -Wno-framework-include-private-from-public -Wno-atimport-in-framework-header -Wno-extra-semi-stmt -Wno-quoted-include-in-framework-header -pedantic -std=c11 -fdebug-compilation-dir /Users/jleffler/src/cmd -ferror-limit 19 -fmessage-length 110 -stack-protector 1 -fstack-check -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=macosx-10.15.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -vectorize-loops -vectorize-slp -o /var/folders/77/zx9nk6dn7_dg4xd4stvt42v00000gn/T/ww-4cb85b.o -x c ww.c
clang -cc1 version 11.0.0 (clang-1100.0.33.8) default target x86_64-apple-darwin19.0.0
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/Users/jleffler/inc
/usr/local/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.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/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -lto_library /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib -dynamic -arch x86_64 -macosx_version_min 10.15.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -o ww -L/Users/jleffler/lib/64 /var/folders/77/zx9nk6dn7_dg4xd4stvt42v00000gn/T/ww-4cb85b.o -ljl -L/usr/local/lib -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/lib/darwin/libclang_rt.osx.a
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil" -o ww.dSYM ww
$

The key information in that blizzard of data is:

-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk

That's effectively the 'root' directory for the compilation, so there should be sub-directories under that for usr and usr/include:

$ ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
Entitlements.plist SDKSettings.json   System
Library            SDKSettings.plist  usr
$ ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr
bin     include lib     libexec share
$ ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
AppleTextureEncoder.h  dns_util.h             memory.h               simd
AssertMacros.h         dtrace.h               menu.h                 slapi-plugin.h
Availability.h         editline               miscfs                 spawn.h
AvailabilityInternal.h err.h                  module.modulemap       sqlite3.h
AvailabilityMacros.h   errno.h                monetary.h             sqlite3ext.h
AvailabilityVersions.h eti.h                  monitor.h              stab.h
…lots more lines…
dirent.h               mach-o                 security               xcselect.h
disktab.h              mach_debug             semaphore.h            xlocale
dispatch               machine                servers                xlocale.h
dlfcn.h                malloc                 setjmp.h               xpc
dns.h                  math.h                 sgtty.h                zconf.h
dns_sd.h               membership.h           signal.h               zlib.h
$

This shows that the mile-long and totally unmemorable directory name does contain the standard C and POSIX headers, plus Apple-specific extras.

The previous /usr/local/ directory appears to be intact; the warning about usr/local/include not existing under the -isysrootdir is harmless (and not visible without the -v option).

For me adding the following path to CPATH solved the issue:

export CPATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include

Before you proceed, make sure to install xcode command line tools.

xcode-select --install

Actually, you can do it! Actually all the C headers are found here in this folder:

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/

We just need to create symlink for all the headers file into this folder:

/usr/local/include/

It worked for me! the following command line will take care of all the problems:

sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/* /usr/local/include/

You will get some warning. Some of the headers already exists, like this:

ln: /usr/local/include//tcl.h: File exists
ln: /usr/local/include//tclDecls.h: File exists
ln: /usr/local/include//tclPlatDecls.h: File exists
ln: /usr/local/include//tclTomMath.h: File exists
ln: /usr/local/include//tclTomMathDecls.h: File exists
ln: /usr/local/include//tk.h: File exists
ln: /usr/local/include//tkDecls.h: File exists
ln: /usr/local/include//tkPlatDecls.h: File exists

totally ok to ignore. that's all.

Set the following implicit Make variables to point to where the headers are now located for Xcode Command Line Tools (Xcode CLI):

export CFLAGS+=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CCFLAGS+=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CXXFLAGS+=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CPPFLAGS+=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk

The -isysroot option updates the location of the root files away from the system root directory /.

So, this ensures that the common /usr/* files are found in their new place.

That is, the files at /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk are now found. These files are:

Entitlements.plist
Library
SDKSettings.json
SDKSettings.plist
System
usr

apue.h dependency was still missing in my /usr/local/include after following Komol Nath Roy answer in this question.

I downloaded the dependency manually from git and placed it in /usr/local/include

I am a newbie with C++ compiler for R in OSX and I got the same issue that C++ could not find the header after OS was updated (missing math.h although it was there). I followed instructions from https://thecoatlessprofessor.com/programming/cpp/r-compiler-tools-for-rcpp-on-macos/ but nothing changed.

Finally, it worked for me after I reinstalled the Xcode CLI

xcode-select --install

and then change the flags to Var as @Coatless suggested:

export CFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CCFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CXXFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CPPFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk

In my case I seemed to have llvm and gcc also installed using homebrew. When I removed those, and thus relied fully on the macOS clang, it could find the headers and the compiling worked again.

The solution was simpler than I thought. Install clang/llvm.

brew install llvm

Then we need to create symlinks ourselves.

for f in /usr/local/Cellar/llvm/9.0.0_1/bin/clang*; do ln -s ${f} /usr/local/bin/"${f##*/}"; done

And

ln -s /usr/local/Cellar/llvm/9.0.0_1/include/c++ /usr/local/include/c++

Depending upon your llvm version, modify the above commands.

Now, you can compile C++ programs without passing any custom flags.

clang++ hello.cpp

I tried 1) manually linking 2) brew install llvm, but they did not work.

Finally, this worked for me: https://gitmemory.com/issue/pytorch/pytorch/31190/565153503

By setting the following env vars:

export CC=clang
export CXX=clang++
export MACOSX_DEPLOYMENT_TARGET=10.9

For me, it works well as follow:

1. xcode-select --install


2. sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/* /usr/local/include/


3. export SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk

On MacOS Catalina 10.15.4, with Xcode Version 11.5 (11E608c) I also needed to update the library path in my .zshrc (the MacOSX.sdk paths are new):

export CPATH='/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include:/opt/local/include'
export LIBRARY_PATH='/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib:/opt/local/lib'

Short Answer

/Library/Developer/CommandLineTools/usr/bin/clang++ -o main main.cpp -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk

The Result

Explanation

In current macOS version, the c/c++ headers are searched inside /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/, instead of /usr/include. So you need to 'reset' the root directory using -isysroot option.

Hope this makes sense 🙂.

In my case, i did a millions things but i reckon following steps helped fix ruby installation.

  1. xcode-select --install
  2. Set these flags
export CFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CCFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CXXFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
export CPPFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
  1. sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/* /usr/local/include/

  2. export SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk

  3. rbenv install 2.6.3 -v

If you have both the command line tools and XCode installed, make sure the SDK installed by the command line tools is actually being used:

#Check the current sdk

$ xcrun --show-sdk-path

#Change sdk

$ sudo xcode-select -s /Library/Developer/CommandLineTools #Using CommandLineTools SDK

$ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer #Using XCode.app SDK

kudos to https://stackoverflow.com/a/61526989/596599 for this answer.

For me the error was: xcrun[20873:1179298] Failed to open macho file at /Library/Developer/CommandLineTools/usr/bin/clang++ for reading: Too many levels of symbolic links

So I opened my terminal and went to the following folder (as mentioned by the error message): /Library/Developer/CommandLineTools/usr/bin/

Then I deleted the shortcut file named clang++

sudo rm clang++

Next, I made a copy of executable file named clang and renamed the copied file to clang++

sudo cp clang clang++

And finally it works.

If using an external LLVM installation, add these to your ~/.bash_profile

LLVM_PATH="/usr/local/opt/llvm/" # or any other path
LLVM_VERSION="11.0.0"
export PATH="$LLVM_PATH:$PATH"
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
export LD_LIBRARY_PATH="$LLVM_PATH/lib/:$LD_LIBRARY_PATH"
export DYLD_LIBRARY_PATH="$LLVM_PATH/lib/:$DYLD_LIBRARY_PATH"
export CPATH="$LLVM_PATH/lib/clang/$LLVM_VERSION/include/"
export LDFLAGS="-L$LLVM_PATH/lib"
export CPPFLAGS="-I$LLVM_PATH/include"
export CC="$LLVM_PATH/bin/clang"
export CXX="$LLVM_PATH/bin/clang++"

(adjust the clang version and the external llvm installation path.)

Then run source ~/.bash_profile