Homebrew 2.0.0でLinuxbrewが統合され、Homebrew-fileもLinuxに対応させたので Linuxでの環境作りにもHomebrewを使い始めましたが、 エラーが出てしまっていてなんとなく無理やり対処していた部分がありました。 ライブラリ関連のエラーですが、 悪さをしていたのはglibcパッケージでした。
起こっていた問題
適当に必要なパッケージをインストール後、LD_LIBRARY_PATH
に
$HOME/.linuxbrew/libを加えると
$ ls
ls: 0s": ELF: x: Error 1325453653
といた様に、基本的なコマンド(ls
、grep
、cat
など)
がエラーを起こしてまともに作業できない状態になってしまいました。
また、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 error
がgo
関連で出るようになってしまったので
再度調べてみました。
原因
原因はglibc
パッケージがインストールされていることでした。
このパッケージはgcc
の依存パッケージとしてインストールされていました。
gcc
自体はbrew deps --tree --installed
とかで確認すると
どれにも依存されてないように見えたのですが、
どうやらインストール先を/home/linuxbrew/.linuxbrewではなく、$HOME/.linuxbrewにしているため、
いくつかのパッケージがbottleからではなくソースからコンパイルしてインストールされるようになっていて、
これをインストールする際にgcc
がインストールされるようです。
今回のupgrade
に関してもアップグレードされたのはtmux
でtmux
はgcc
に依存していませんが
ソースからびるどされるため、この際にgcc
をインストール、そしてその依存先のglibc
もインストールしていました。
上でいろいろやったら使えるようになったと書いてますが、
gcc
やglibc
に関して問題があるのはなんとなくわかっていて
これらをアンインストールしたら使えるようになっていた、という状態だったようで、
再度アップグレードに際してglibc
がインストールされ問題が再発するようになってしまったようです。
もうちょっと詳しく見てみると、
$HOME/.linuxbrew/lib/ld.so
のリンクがが問題のもとになっています。
このld.so
はglibc
をインストールすると、その中の
$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
ちなみに現在、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にはまだオプションありのものが残っているようです。
ともかく、gcc
がglibc
なしでインストールできるようなので
そうすればよいのですが、これらは
$HOME/.linuxbrewにインストールしようとすると
最初に
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
をした段階でインストールされてしまいます。
(初期インストールでgit
などビルドを必要とするパッケージがあるため。)
なのでこの後にgo
などをインストールすると問題が起こります。
そこで、まず初期インストールを行ったらgcc
、glibc
を削除して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
を意図的にインストールしたい場合を除き
この対処法で大概の問題は解決出来るはずです。