rcmdnk's blog

20190208_homebrew_200_200

Homebrew 2.0.0でLinuxbrewが統合され、Homebrew-fileもLinuxに対応させたので Linuxでの環境作りにもHomebrewを使い始めましたが、 エラーが出てしまっていてなんとなく無理やり対処していた部分がありました。 ライブラリ関連のエラーですが、 悪さをしていたのはglibcパッケージでした。

起こっていた問題

適当に必要なパッケージをインストール後、LD_LIBRARY_PATH$HOME/.linuxbrew/libを加えると

$ ls
ls: 0s": ELF: x: Error 1325453653

といた様に、基本的なコマンド(lsgrepcatなど) がエラーを起こしてまともに作業できない状態になってしまいました。

また、goをインストールしたところ、

$ go
go: relocation error: /usr/lib64/libc.so.6: symbol _dl_starting_up, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 with link time reference

と言ったエラーが起こりました。

ここで

$ export LD_LIBRARY_PATH=$HOME/.linuxbrew/lib:$LD_LIBRARY_PATH

とするとgoは使えるようになるのですが上のエラーが出るのでどうしようもなくなった、という問題。

その後、いろいろパッケージのインストールやアンインストールや Homebrewの再インストールなどをしてなんとなく使えるような状態に出来てしまったのですが、 brew upgradeしたところまたrelocation errorgo関連で出るようになってしまったので 再度調べてみました。

原因

原因はglibcパッケージがインストールされていることでした。 このパッケージはgccの依存パッケージとしてインストールされていました。 gcc自体はbrew deps --tree --installedとかで確認すると どれにも依存されてないように見えたのですが、 どうやらインストール先を/home/linuxbrew/.linuxbrewではなく、$HOME/.linuxbrewにしているため、 いくつかのパッケージがbottleからではなくソースからコンパイルしてインストールされるようになっていて、 これをインストールする際にgccがインストールされるようです。

今回のupgradeに関してもアップグレードされたのはtmuxtmuxgccに依存していませんが ソースからびるどされるため、この際にgccをインストール、そしてその依存先のglibcもインストールしていました。

上でいろいろやったら使えるようになったと書いてますが、 gccglibcに関して問題があるのはなんとなくわかっていて これらをアンインストールしたら使えるようになっていた、という状態だったようで、 再度アップグレードに際してglibcがインストールされ問題が再発するようになってしまったようです。

もうちょっと詳しく見てみると、

$HOME/.linuxbrew/lib/ld.so

のリンクがが問題のもとになっています。 このld.soglibcをインストールすると、その中の $HOME/.linuxbrew/Cellar/glibc/2.23/lib/ld-linux-x86-64.so.2へのリンクになります。

一方、glibcが入っていない状態でld.soを必要するパッケージ(tmuxなどソースからコンパイルするもの)をインストールしたり、 gcc--without-glibcでインストールすると /usr/lib64/ld-linux-x86-64.so.2など、システムのldライブラリに対するリンクとして生成されます。

これ以上詳しくは省きますが そもそもglibcを複数システムに入れるといろいろ面倒な問題が起こってしまうようで、 この辺の違いが起因で 上のエラーが起こったりします。

linux - Multiple glibc libraries on a single host - Stack Overflow

CentOS6 で Zabbix 3.0 を動かす (力業編) - Qiita

ちなみに現在、Homebrewでインストールされるglibcは2.23 でテストした環境(CentOS 7.5)では2.17がインストールされていました。

glibcに依存しているgccなどのFormulaでは

depends_on "glibc" => (Formula["glibc"].installed? || OS::Linux::Glibc.system_version < Formula["glibc"].version) ? :recommended : :optional

のような書き方になっていて、システムのglibcがFormulaの定義より新しければ:optionalとなって--with-glibcと 明示しなければglibcはインストールしないようになっています。

逆にシステムのglibcが古い場合は:recommendedになって--without-glibcとしない限りインストールするようになっています。

glibcに依存しているパッケージ

現在のLinux用のFormulaのcore(Homebrew/linuxbrew-core) の中でglibcに依存しているものは

  • clang-format
  • gcc
  • gcc@5
  • gcc@6
  • gcc@7
  • gcc@8
  • llvm
  • llvm@4
  • llvm@5
  • llvm@7
  • libgweather

だけで、libgweatherだけが

depends_on "glibc"

と単純なglibc依存をしていて後はすべて上のようなオプションで設定できる仕様になっていました。 (多分libgweatherもそう出来るけど忘れられているだけだと思いますが。)

なのでこれらのパッケージを使うときは以下の解決法などを行うときもちょっと注意が必要です。 特にlibgweatherはこのままではどうしようもないので 別に自分でFormulaを用意するかCoreのものを変更してもらうしか無いです。 (再々libgweatherに依存しているパッケージはCore内にはありません。)

ちなみにLinuxでは Homebrew/homebrew-core の代わりに Homebrew/linuxbrew-core が使われるのですが、 brew tapしてみるとhomebrew/coreが見えて、実際 $HOME/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core にlinuxbrew-coreがインストールされている状態でした。 coreはHomebrewが直接Tapするものなので中で名前を合わせるような変換を入れているようです。 (Tapする際にレポジトリ名にhomebrew-という接頭詞がないとTap出来ない仕様ですが、linuxbrew-coreは中で直接特別扱いしているようです。)

解決法

gcc自体は/usr/bin/gccとしてシステム自体にインストールされている環境だったので gccすらインストールする必要がない状態なのですが、 これに関してはHomebrewの中身に入っていて簡単にオプションで外れるかどうかはわかりませんでした。 (オプションとしてありそうだとは思うのですが調べきれてません。)

一方、gcc自体のオプションを見てみると上にも書いたようにオプションで設定できるようになっていてinfoを見てみると

$ brew info gcc
gcc: stable 5.5.0 (bottled)
GNU compiler collection
https://gcc.gnu.org/
/home/user/.linuxbrew/Cellar/gcc/5.5.0_4 (2 files, 8.1KB)
  Built from source
From: https://github.com/Homebrew/linuxbrew-core/blob/master/Formula/gcc.rb
==> Dependencies
Required: zlib (installed), gmp (installed), libmpc (installed), mpfr (installed), [email protected] (installed)
Recommended: glibc (installed)
==> Options
--without-glibc
        Build without glibc support

と最後の--without-glibcを使うとglibcなしでインストール出来ます。

ちなみにMac版だと

$ brew info gcc
gcc: stable 8.3.0 (bottled), HEAD
GNU compiler collection
https://gcc.gnu.org/
/usr/local/Cellar/gcc/8.3.0_2 (1,414 files, 288.5MB) *
  Poured from bottle on 2019-XX-XX at XX:XX:XX
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/gcc.rb
==> Dependencies
Required: gmp ✔, isl ✔, libmpc ✔, mpfr ✔
==> Options
--HEAD
        Install HEAD version
==> Analytics
install: 111,890 (30 days), 290,273 (90 days), 818,489 (365 days)
install_on_request: 52,849 (30 days), 137,514 (90 days), 395,719 (365 days)
build_error: 0 (30 days)

となっていてそもそもいろいろ状態が違います。 そもそもHomebrewではMac用のhomebrew-coreい入っているパッケージのFormualからはオプションが 2.0.0になるにあたりすべて削除されましたが、 linuxbrew-coreにはまだオプションありのものが残っているようです。

ともかく、gccglibcなしでインストールできるようなので そうすればよいのですが、これらは $HOME/.linuxbrewにインストールしようとすると 最初に

$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

をした段階でインストールされてしまいます。 (初期インストールでgitなどビルドを必要とするパッケージがあるため。)

なのでこの後にgoなどをインストールすると問題が起こります。

そこで、まず初期インストールを行ったらgccglibcを削除してgcc--without-glibcで入れ直します。

$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
$ brew uninstall gcc glibc
$ brew cleanup
$ brew install gcc --without-glibc

途中でbrew cleanupをしているのは glibcをアンインストールした段階で$HOME/.linuxbrew/lib/ld.so がリンク切れのシンボリックリンクとして残ってしまい、これが原因でbrewコマンドなどで、

/home/user/.linuxbrew/Homebrew/Library/Homebrew/brew.sh: /home/user/.linuxbrew/opt/curl/bin/curl: /home/user/.linuxbrew/lib/ld.so: bad ELF interpreter: No such file or directory

といったようなWarningが出てしまうためです。(これは無視して無理やりgccの再インストールをしても出来ないことはないのですが。)

これでgccの再インストールが出来たら、

$ brew info gcc
gcc: stable 5.5.0 (bottled)
GNU compiler collection
https://gcc.gnu.org/
/home/user/.linuxbrew/Cellar/gcc/5.5.0_4 (1,335 files, 143.4MB) *
  Built from source on 2019-XX-XX at XX:XX:XX with: --without-glibc
From: https://github.com/Homebrew/linuxbrew-core/blob/master/Formula/gcc.rb
==> Dependencies
Required: zlib (installed), gmp (installed), libmpc (installed), mpfr (installed), [email protected] (installed)
Recommended: glibc (uninstalled)
==> Options
--without-glibc
        Build without glibc support

のようにwith: --without-glibcでビルドされた、となっているはずです。 また、brew lsしてもglibcが無いことを確認してください。

これでglibcなしでgccがインストールできたので goとかtmuxとか好きなパッケージをインストールしていきます。

この状態だとrelocation errorは起こりません。

また、

export LD_LIBRARY_PATH=$HOME/.linuxbrew/lib:$LD_LIBRARY_PATH

の設定をしても

$ ls
ls: 0s": ELF: x: Error 1325453653

のようなエラーは起きなくなるのでライブラリを常時使うこともできます。

もしすでにいろいろパッケージをインストールしてしまっていて、それらが問題を起こすようであれば 殆どの場合はbrew reinstall <package>をすれば解決できるはずです。 (gitなどは最初にglibcを入れた後にコンパイルしていますがglibcを削除した後でも問題なく動きました。)

まとめ

問題が起こるのは

  • /home/linuxbrew/.linuxbrewではなく$HOME/.linuxbrewを使う
  • システムのglibcがFormulaの指定より古い

の場合にglibcがインストールされてしまう場合です。

glibcをインストールしても上手いことやる方法もあるかもしれませんが、 glibcを意図的にインストールしたい場合を除き この対処法で大概の問題は解決出来るはずです。

Sponsored Links
Sponsored Links

« メールの内容がGmailでnonameという添付ファイルになってしまう問題 smenu: コマンドライン用選択ツール »

}