如何在 macOS High Sierra 10.13.6 上使用 Homerew 安装 llvm@13?出现 "Built target lldELF" 错误

How to install llvm@13 with Homerew on macOS High Sierra 10.13.6? Got "Built target lldELF" error

虽然 Homebrew 不再支持 High Sierra,但我需要安装 llvm@13 公式作为其他公式的依赖项。所以我尝试这样安装它:

$ brew install llvm
...
==> Downloading https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/llvm-project-13.0.0.src.tar.xz
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/8fd68fc8f968137c5080826db6e58682326235960fd8469363eb27d0799978ca--llvm-project-13.0.0.src.tar.xz
...
==> Installing llvm
==> cmake -G Unix Makefiles .. -DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;lld;lldb;mlir;polly -DLLVM_ENABLE_RUNTIMES=compiler-rt;libcxx;libcxxabi;libunwind;openmp -DLLVM_POLLY_L
==> cmake --build .
...
[ 79%] Built target lldELF
make: *** [all] Error 2

长时间编译出现错误。我也在 ~/Library/Logs/Homebrew/llvm/02.cmake:

中发现了这个错误
/tmp/llvm-20211109-12151-m0zvtm/llvm-project-13.0.0.src/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm:246:52: error: use of undeclared identifier 'CPU_SUBTYPE_ARM64E'
    if (cputype == CPU_TYPE_ARM64 && cpusubtype == CPU_SUBTYPE_ARM64E) {
                                                   ^
1 error generated.
make[2]: *** [tools/lldb/source/Host/macosx/objcxx/CMakeFiles/lldbHostMacOSXObjCXX.dir/HostInfoMacOSX.mm.o] Error 1
make[1]: *** [tools/lldb/source/Host/macosx/objcxx/CMakeFiles/lldbHostMacOSXObjCXX.dir/all] Error 2

我该如何修复该编译错误?

在启用调试模式的情况下安装 llvm:

$ brew install --debug llvm

安装过程遇到问题中提到的相同错误,但提供了一些选项来解决该问题。选择选项 5:

 - raise
 - ignore
 - backtrace
 - irb
 - shell
Choose an action: 5

它提供了 shell 访问 llvm 公式的当前构建目录的权限。查找当前文件夹:

$ pwd
/private/tmp/llvm-20211109-12151-m0zvtm/llvm-project-13.0.0.src

将位置更改为构建目录:

cd llvm/build

编辑 HostInfoMacOSX.mm 并删除条件的第二部分:

vi ../../lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm

您需要更改第 246 行:

    if (cputype == CPU_TYPE_ARM64 && cpusubtype == CPU_SUBTYPE_ARM64E) {

至:

    if (cputype == CPU_TYPE_ARM64) {

然后重新运行最后一条命令:

$ cmake --build .

完成需要一些时间:

...
[100%] Linking CXX executable ../../../../bin/lldb-vscode
cd /tmp/llvm-20211109-12151-m0zvtm/llvm-project-13.0.0.src/llvm/build/tools/lldb/tools/lldb-vscode && /usr/local/Cellar/cmake/3.21.4/bin/cmake -E cmake_link_script CMakeFiles/lldb-v
scode.dir/link.txt --verbose=1
/usr/local/Homebrew/Library/Homebrew/shims/mac/super/clang++  -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wn
o-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-c
lass-memaccess -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wno-deprecated-declarations -Wno-unkn
own-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -O3 -DNDEBUG -Wl,-search_paths_first -Wl,-headerpad_max_install_names  -stdlib=libc++ -Wl,-sectcreate,__
TEXT,__info_plist,/tmp/llvm-20211109-12151-m0zvtm/llvm-project-13.0.0.src/llvm/build/tools/lldb/tools/lldb-vscode/lldb-vscode-Info.plist  -Wl,-dead_strip CMakeFiles/lldb-vscode.dir/
lldb-vscode.cpp.o CMakeFiles/lldb-vscode.dir/BreakpointBase.cpp.o CMakeFiles/lldb-vscode.dir/ExceptionBreakpoint.cpp.o CMakeFiles/lldb-vscode.dir/FifoFiles.cpp.o CMakeFiles/lldb-vsc
ode.dir/FunctionBreakpoint.cpp.o CMakeFiles/lldb-vscode.dir/IOStream.cpp.o CMakeFiles/lldb-vscode.dir/JSONUtils.cpp.o CMakeFiles/lldb-vscode.dir/LLDBUtils.cpp.o CMakeFiles/lldb-vsco
de.dir/OutputRedirector.cpp.o CMakeFiles/lldb-vscode.dir/ProgressEvent.cpp.o CMakeFiles/lldb-vscode.dir/RunInTerminal.cpp.o CMakeFiles/lldb-vscode.dir/SourceBreakpoint.cpp.o CMakeFi
les/lldb-vscode.dir/VSCode.cpp.o -o ../../../../bin/lldb-vscode  -Wl,-rpath,@loader_path/../lib ../../../../lib/liblldb.13.0.0.dylib -lpthread ../../../../lib/libclang-cpp.dylib ../
../../../lib/libLLVM.dylib
[100%] Built target lldb-vscode
/usr/local/Cellar/cmake/3.21.4/bin/cmake -E cmake_progress_start /tmp/llvm-20211109-12151-m0zvtm/llvm-project-13.0.0.src/llvm/build/CMakeFiles 0

然后运行安装命令:

$ cmake --build . --target install

结果的尾部应该是:

...
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/lib/cmake/llvm/./CheckAtomic.cmake
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/lib/cmake/llvm/./FindSphinx.cmake
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/lib/cmake/llvm/./FindGRPC.cmake
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/lib/cmake/llvm/./TableGen.cmake

执行最后一条命令:

$ cmake --build . --target install-xcode-toolchain

结果的尾部应该是:

...
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/Toolchains/LLVM13.0.0.xctoolchain//usr/lib/cmake/llvm/./CheckAtomic.cmake
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/Toolchains/LLVM13.0.0.xctoolchain//usr/lib/cmake/llvm/./FindSphinx.cmake
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/Toolchains/LLVM13.0.0.xctoolchain//usr/lib/cmake/llvm/./FindGRPC.cmake
-- Installing: /usr/local/Cellar/llvm/13.0.0_1/Toolchains/LLVM13.0.0.xctoolchain//usr/lib/cmake/llvm/./TableGen.cmake
Built target install-xcode-toolchain
/usr/local/Cellar/cmake/3.21.4/bin/cmake -E cmake_progress_start /tmp/llvm-20211109-12151-m0zvtm/llvm-project-13.0.0.src/llvm/build/CMakeFiles 0

然后按control+d到return调试菜单。由于最后两个命令是 运行 手动执行的,因此您需要通过选择选项 2:

来忽略其余错误
 - raise
 - ignore
 - backtrace
 - irb
 - shell
Choose an action: 2
==> cmake --build . --target install
...
cmake
--build
.
--target
install

Error: could not load cache
BuildError: Failed executing: cmake --build . --target install
1. raise
2. ignore
3. backtrace
4. irb
5. shell
Choose an action: 2
==> cmake --build . --target install-xcode-toolchain
...

cmake
--build
.
--target
install-xcode-toolchain

Error: could not load cache

BuildError: Failed executing: cmake --build . --target install-xcode-toolchain
1. raise
2. ignore
3. backtrace
4. irb
5. shell
Choose an action: 2

会继续安装到其余的:

==> Fixing /usr/local/Cellar/llvm/13.0.0_1/bin/FileCheck permissions from 755 to 555
==> Fixing /usr/local/Cellar/llvm/13.0.0_1/bin/analyze-build permissions from 755 to 555
...
==> Changing dylib ID of /usr/local/Cellar/llvm/13.0.0_1/lib/libunwind.1.0.dylib
  from @rpath/libunwind.1.dylib
    to /usr/local/opt/llvm/lib/libunwind.1.dylib
/usr/local/Homebrew/Library/Homebrew/brew.rb (Formulary::FromPathLoader): loading /usr/local/opt/llvm/.brew/llvm.rb
==> Caveats
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"

llvm is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have llvm first in your PATH, run:
  echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.zshrc

For compilers to find llvm you may need to set:
  export LDFLAGS="-L/usr/local/opt/llvm/lib"
  export CPPFLAGS="-I/usr/local/opt/llvm/include"

==> Summary
  /usr/local/Cellar/llvm/13.0.0_1: 10,907 files, 1.8GB, built in 1418 minutes 39 seconds

可以这样验证,默认llvm@10预装:

$ /usr/bin/clang --version
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

以及 llvm@13 的新 Homebrew 版本:

$ /usr/local/opt/llvm/bin/clang --version
Homebrew clang version 13.0.0
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin

@HamidRohani 为那些仍在修改 High Sierra (10.13) 的人提供了一个很好的解决方案。让最新版本的 LLVM 在我的旧 MAC 上与较旧的 XCode(在我的例子中是 clang 版本 10.0.1)编译是一个很大的帮助。我名义上的贡献...

或者,您可以在 HostInfoMacOSX.mm 中的第 41 行之后定义符号:

// Kludge: Symbol definition extracted from a modern machine.h
#ifndef CPU_SUBTYPE_ARM64E
#    define CPU_SUBTYPE_ARM64E        ((cpu_subtype_t) 2)
#endif

现在,无需修改第 246 行。该定义将解析任何(可能的)后续引用。让我汇总在 brew 的 debug-shell:

中执行的上述步骤
cmake . -DLLVM_CREATE_XCODE_TOOLCHAIN=On
cmake --build .
cmake --build . --target install
cmake --build . --target install-xcode-toolchain

关于 LLVM-related 变量,将 LLVM_CREATE_XCODE_TOOLCHAIN 设置为 On 指示 CMake 生成名为 'install-xcode-toolchain' 的目标。 1 The target is a work-around to System Integrity Protection (SIP); "Xcode toolchains are a mostly-undocumented feature that allows multiple copies of low level tools to be installed to different locations, and users can easily switch between them." 2

Brew 的注意事项 Brew 给出了一些使用新编译器的必要注意事项:“因为 macOS 已经提供了这个软件,同时安装另一个版本可能会导致各种麻烦。”要使用你的新编译器,“你需要在你的 PATH 中首先有 llvm,并且为了让编译器找到你可能需要设置的 llvm”LDFLAGS 和 CDFLAGS。但是由于这些 gems-of-wisdom 出现在 million-lines 输出的末尾附近,让我在这里 re-iterate:

export PATH="/usr/local/opt/llvm/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/llvm/lib"
export CPPFLAGS="-I/usr/local/opt/llvm/include"

设置 PATH 很简单。然而,我不需要设置 LDFLAGS 或 CPPFLAGS。此外,这个额外的警告并不令人高兴,“要使用捆绑的 libc++,请添加以下 LDFLAGS”:

export LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"

无论如何,继续......为了证明一切都很好,一个包含 的 C++ foo 程序;不在 High Sierra 的图书馆:

#include <iostream>

// C++17: Modern C++ compiler has std filesystem                                                                                            
#include <filesystem>
namespace fs = std::filesystem;
typedef std::filesystem::path my_path;

using namespace std;
int main ()
{
  fs::path path{"/tmp"};
  path /= "foo.txt";

  ofstream ofs(path);
  ofs << "Hello World." << endl;
  ofs.close();

  return 0;
}

很明显,一个无意义的程序,但是要编译:

unset CPPFLAGS
unset LDFLAGS
clang++ -std=c++17  -L/usr/local/opt/llvm/lib  foo.cpp -o foo

再次表明我不需要 CPPFLAGS 和 LDFLAGS。因此,可执行文件链接到正确的 libc++ 库:

MacIntel:c++fs mjo$ otool -L foo
foo:
    /usr/local/opt/llvm/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)

尽情享受吧。