LoginSignup
2
2

MacOSで `undefined symbols` のリンクエラーが発生する(binutilsが悪さする)

Posted at

はじめに

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上にarranlibがある)

エラー発生のしくみ

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にはありませんでした。

解決の方法

  1. binutilsをアンインストールする
$ brew uninstall binutils
// Pathを削除する
#export PATH="/usr/local/opt/binutils/bin:$PATH"
  1. 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は不要なので削除のまま運用していこうと思う。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2