はじめに
MacOS上でasdfを使用してerlang
をインストール時に以下のエラーが発生した。
LD /Users/xxxx/.asdf/plugins/erlang/kerl-home/builds/asdf_26.0/otp_src_26.0/lib/erl_interface/bin/x86_64-apple-darwin22.4.0/erl_call
ld: warning: ignoring file /Users/xxxxxx/.asdf/plugins/erlang/kerl-home/builds/asdf_26.0/otp_src_26.0/lib/erl_interface/obj/x86_64-apple-darwin22.4.0/libei.a, building for macOS-x86_64 but attempting to link with file built for macOS-x86_64
Undefined symbols for architecture x86_64:
"___erl_errno_place", referenced from:
_main in erl_call-456a49.o
"_ei_connect", referenced from:
_main in erl_call-456a49.o
このエラーを調査して、表題のとおりbinutils
が影響している事がわかったのでここに記述します。
なお、この問題は、erlang
に限らずMacOS特有の話で、いろんなappのインストール、build(make)のリンク時に発生します。
参考資料(原因がわかった後に見つけた記事)
macでライブラリをビルドしてインストールするときはbinutilsに気をつける
こんな場合に発生します
- MacOS上、Gnu binutils のバイナリツールがインストールされている。
$ which -a ar
/usr/local/opt/binutils/bin/ar
/usr/bin/ar
- make時に複数のobjをarchiveにし、そのライブラリー(*.a)とリンクする場合(Makefile上に
ar
、ranlib
がある)
エラー発生のしくみ
Makeする時に使用するコマンドには
- compiler : gcc, g++ -- MacOS上にあり
- archive : ar, ranlib -- MacOSとbinuntilsとの両方にあり
- linker : ld -- MacOS上にあり(binutilsにはなかった)
binutils のar、ranlibのコマンドでarchiveを作り、 MacOS のlinker(ld)でリンクしたので、archiveファイルを読めずにundefined symbol
のエラーが発生した。
MacOSのarで作るarchiveが標準のarchive(binutilsで作った)と違っているため。
linker(ld)をbinutilsのものを使用すれば、良いのかも、と思ったんですが、linker(ld)がbinutilsにはありませんでした。
解決の方法
-
binutils
をアンインストールする
$ brew uninstall binutils
// Pathを削除する
#export PATH="/usr/local/opt/binutils/bin:$PATH"
-
binutils
を使いたい場合は、一時的にpathを無効にするか、ar,ranlibをMacOSのもの指定とする
そもそも、binutils
は一体必要なのか
binutils
には以下のものがあります。
/usr/local/opt/binutils/bin
にあって/usr/bin
にないもののリストです。
X: なし、◯: あり
name | /usr/bin |
---|---|
addr2line* | X |
ar* | ◯ |
c++filt* | ◯ |
coffdump* | X |
dlltool* | X |
dllwrap* | X |
elfedit* | ◯ |
nm* | ◯ |
objcopy* | X |
objdump* | ◯ |
ranlib* | ◯ |
readelf* | X |
size* | ◯ |
srconv* | X |
strings* | ◯ |
strip* | ◯ |
sysdump* | X |
windmc* | X |
windres* | X |
binutils
にあり、/usr/bin(MacOS)
にないものがあるが、必要なものは準備されている。
従って、MacOSは独自のものを開発しているので、「MacOSで開発する場合はこのGnu binutils
は使うべきでない」と考える。
ただ、buildroot(組込みlinux)
などのクロスコンパイルで使用される事があるのでの注意または処置が必要となると思われる。
最後に
私の場合、たぶん、ESP32(SoC)のクロスコンパイラをインストールした時に手順に従いインストールしたと思う。
で、想像するに、少し前はMacOSでもGnuのgcc
を使用していて、このbinutils
が必要であったが、clang(表面上gccと名前は同じ)をMacOSでの標準となり、この際、MacOS専用のフォーマットに変えたためにその歪みが現れたのでは、と。
想像の範囲から出てないが、今のところ、binutils
は不要なので削除のまま運用していこうと思う。