概要
デフォルトでインストールされている clang++ と違うバージョンのものを使う必要があり、 https://releases.llvm.org/ から tar.xz アーカイブでダウンロードして使っていたところ、ビルドの際にエラーが出ていた。
対処法などをメモしておく。
環境
https://github.com/llvm/llvm-project/releases/tag/llvmorg-16.0.0
から
をダウンロードして、/usr/local/
以下にインストールした状態
$ sw_vers ProductName: macOS ProductVersion: 13.3.1 ProductVersionExtra: (a) BuildVersion: 22E772610a $ clang++ --version clang version 16.0.0 Target: arm64-apple-darwin22.4.0 Thread model: posix InstalledDir: /usr/local/bin
デフォルトの clang++ (/usr/bin/clang++)
だと問題は生じない
問題
// main.cc int main() {}
例えば、上のような空の main 関数だけのファイルを
$ clang++ main.cc
でコンパイルするだけでも、以下のリンクエラーが発生
ld: library not found for -lSystem clang-16: error: linker command failed with exit code 1 (use -v to see invocation)
さらに、標準ヘッダをなにか使うようなものをコンパイルしてみると...
// hello.cc #include <iostream> int main() { std::cout << "Hello, clang!" << std::endl; }
以下のように大量にエラーが出てくる。
In file included from hello.cc:1: In file included from /usr/local/bin/../include/c++/v1/iostream:43: In file included from /usr/local/bin/../include/c++/v1/ios:220: In file included from /usr/local/bin/../include/c++/v1/__ios/fpos.h:14: In file included from /usr/local/bin/../include/c++/v1/iosfwd:100: In file included from /usr/local/bin/../include/c++/v1/__mbstate_t.h:29: /usr/local/bin/../include/c++/v1/wchar.h:143:77: error: use of undeclared identifier 'wcschr' wchar_t* __libcpp_wcschr(const wchar_t* __s, wchar_t __c) {return (wchar_t*)wcschr(__s, __c);} ^ /usr/local/bin/../include/c++/v1/wchar.h:150:87: error: use of undeclared identifier 'wcspbrk' wchar_t* __libcpp_wcspbrk(const wchar_t* __s1, const wchar_t* __s2) {return (wchar_t*)wcspbrk(__s1, __s2);} /* ... */ ^ /usr/local/bin/../include/c++/v1/stdlib.h:150:34: error: unknown type name 'ldiv_t' inline _LIBCPP_INLINE_VISIBILITY ldiv_t div(long __x, long __y) _NOEXCEPT { ^ /usr/local/bin/../include/c++/v1/stdlib.h:151:12: error: no member named 'ldiv' in the global namespace return ::ldiv(__x, __y); ~~^ /usr/local/bin/../include/c++/v1/stdlib.h:154:34: error: unknown type name 'lldiv_t' inline _LIBCPP_INLINE_VISIBILITY lldiv_t div(long long __x, ^ /usr/local/bin/../include/c++/v1/stdlib.h:156:12: error: no member named 'lldiv' in the global namespace return ::lldiv(__x, __y); ~~^ fatal error: too many errors emitted, stopping now [-ferror-limit=] 20 errors generated.
stdlib.h
や wchar.h
等のC由来のヘッダファイルがうまく読み込まれていない?
対処法
リンクエラーについて、もう一回内容を見てみる。
ld: library not found for -lSystem clang-16: error: linker command failed with exit code 1 (use -v to see invocation)
libSystem
というライブラリが見つからないと言っているらしい。
探してみると...
$ fd 'libSystem' / /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib/libSystem.tbd /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib/libSystem.B_asan.tbd /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib/libSystem.B.tbd /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib/libSystem_asan.tbd /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/CoreTelephony.framework/Support/libSystemDetermination.tbd # more files...
どうやら /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk
以下などにあるらしい。
実際、
clang++ -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib main.cc
などで明示的にライブラリの search path に入れてやることでコンパイルが通るようになった。
(/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/
はバージョン番号付きの .sdk
ディレクトリへのシンボリックリンクになっている。)
ヘッダファイルの方に関するエラーも
$ clang++ \ -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1 \ -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include \ -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib \ hello.cc
のように明示的に include path を追加してやるとコンパイルが通った。
環境変数
コマンドラインでパスを明示してやることで一応の解決はするのだが、オプションが長すぎてやってられない。 これらのパスを常に探してくれるように指定するためには環境変数を使ってやればよい。
ライブラリのほうは LIBRARY_PATH
、ヘッダのほうは CPATH
を使えば良いようである。
設定の一例を以下に載せておく。
export SDK_ROOT="/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" export CPATH="${SDK_ROOT}/usr/include:${CPATH}" export CPATH="${SDK_ROOT}/usr/include/c++/v1:${CPATH}" export LIBRARY_PATH="${SDK_ROOT}/usr/lib:${LIBRARY_PATH}"
蛇足
環境変数について、man clang
の ENVIRONMENT セクションにドキュメントされている。
ただし、この中に LIBRARY_PATH
の記述は見当たらない。
man gcc
のほうには記述があるので、clang 側が暗黙に gcc への互換性を保つような実装をしているということだろうか?
ライブラリの search path について、LDFLAGS
や LD_LIBRARY_PATH
等を使えば良いと書いてある記述も見かけたが、自分の環境ではうまく動かなかった。
また、一応以上のやり方で解決に至ったものの、MacOS まわりの開発環境に疎いのもあって結局 MacOSX.sdk
が何者なのかとかはよくわからない。
詳しい方がいたらぜひ教えていただけたら幸いである。