最新のgcc 9.x系をソースからビルド

皆様いかがお過ごしでしょうか。SBCいじりをしていると思わぬ壁にぶち当たることが多いです。特にこれが面倒だったなぁなんて思ったのがgccのコンパイル。あとパスを通すとか。

私自身が今使っているOrange Pi3なのですが、これがひどいもので、gccが7系がデフォルトです。ちなみにOSはArmbian Bionic(Ubuntu Server相当)です。

今から長々と書くので経緯から読みたい人、私がエラー解決にあたってやったことなどを書くので、目次から必要な部分だけ読んでください。長いですが、経緯も読んでいくとどんな対策をして結果がどうだったとかもあるので、環境によってはその中で試す方法のほうが早い場合もあるので、読んでいただいて損はないかと思いますのでよろしければ。

目次

経緯

最初にも書いた通り、gccが7系がOraqngePi3だとデフォルトです。まずエラーの内容など、色々把握するうえで必要になるのでとりあえず調べてみましょう。

sudo apt-get -y install gcc
gcc -v
.....
7.3.2

古いですねぇ…。古いだけなら困らないのですが、実害があったりして、最新のプログラムがコンパイルできなったりします。そもそも私がgcc9系をコンパイルしようと思ったのが、とあるほかのツールのビルドにおいて、以下のようなエラーを得たからです。長いので一部だけ抜粋したものを掲載します。

fatal error: filesystem: No such file or directory
....
std::filesystem::__cxx11::directory_iterator not dinined

こんな感じのがだらだらと出てコンパイルできなかったんですね。ちなみにこのエラーが出たのが、この記事のAviSynthPlusのビルド中に出ました。私自身がその記事の手順通りにやってるのでセットアップ終盤でこのエラーが出て相当解決に時間をかけたのでしんどかったのをよく覚えています。

ちなみに、Raspberry Piではこの現象が起こらなったので、参考までにRaspberry Piのgccのバージョンはこんな感じでした。


$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/8/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian 8.3.0-6+rpi1' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=arm-linux-gnueabihf- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --disable-libquadmath-support --enable-plugin --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-werror --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 8.3.0 (Raspbian 8.3.0-6+rpi1)

gccのバージョン違うってことはおそらくバージョンまわりは怪しいよなと少し目星はつけていました。

エラーの解決までに試したこと

そもそもなぜこのエラーが出るのか。理由を調べると大体以下のような感です。

  • filesystemの完全なサポートがgcc 8系の一部バージョンから可能であったとのことで、簡単に言うならgccのバージョンせい。
  • filesystemが最近実装されたというのもあり、プログラム上での表記がgccのバージョンによって違うみたいのでそういった理由。 
  • 主にgcc8系では、オプションの付け忘れ。"-std=c++17"を付ける必要がある。

ちなみにgcc 8系での実装されたとのことで、少なくともgcc 7系ではそもそも非対応だった。それ以外にも調べていると、C++のソースコードに含まれる

#include <filesystem>

これを、以下のように変更してみるというのも海外の掲示板には書かれていた。

#include <experimental/filesystem>

どうもこれ自体はgcc 6系から実装されているようですが、filesystemの一部しか実装されていないようなので、とりあえず書き換えてみたものの、最初に紹介したエラーが出てコンパイルできませんでした(英語の記事の一部なので誤訳していたらすみません。とりあえず私には無意味な方法でした)。

じゃあgcc8系を少なくともインストールする必要があるのかとなり、もしかしてレポジトリ探せばあるのではということで、さっそくOrange Pi探してみます。

sudo apt search gcc

ここをさがしていたら、発見しました色々出てきますが、その中からさがしましょう。今回はgcc-8で探しましたが、見つからなければ、上のコマンドのようにgccでさがしてみましょう。より新しいgcc-9があるかもしれません。

$ sudo apt search gcc-8
...
gcc-8/bionic-security,bionic-updates,now 8.4.0-1ubuntu1~18.04 arm64
...

これで解決できそう!ていうかほとんどの場合これで解決すると思います。Orange Piってサポートがひどすぎると有名とはいえ、aptにあるということは、ソースからコンパイルする必要はないはず。なので私の場合はgcc-8でいい(はずだった、詳しくは後述)のでいれてみます。

sudo apt-get install gcc-8

よし、これでコンパイルできるぞ!と思ったら今度はさらに意味の分からないエラー、というかこんなエラー初めて見たよっていうのが出ました。正直検索してもでてこないし、記録として残さなかったですが意味はある程度覚えています。英語のエラーがsomething wrong かbrokenかなんかで出たと思うのですが、おおむね以下のような意味の文がでました。

gcc-8:gcc-8が破損しているためコンパイルができません。

!?!??!?!!wwwwww

さっきはある程度コンパイルが進んでエラーがでたのに今度は最初からこのエラー。むしろ状況が悪化して笑いました。gccが壊れてるなんてエラー初めて見たんですけど…。ちなみにパスが通っていないと別のエラーが出るっていうのが後でわかったので、少なくともこれはパスが通っていないとかでもなかったはずです。

先ほども書きましたが、ほとんどこんなエラーが出ないはずですし、当時調べたんですがこんなエラーにあたって困っている人はいませんでした。後でも書くのですが、gccってビルドするとき、1回目は元からあるgccを使ってビルドを行い、次にビルドで出来上がった新しいgccでもう1回新しいgcc自身をビルドできるかっていうテストを何回かするんですね。なのでgccが壊れているなんてそうあり得ないはずなんですが、壊れていたそうですね。サポート悪すぎて捨てたくなってきます…。

一応念のため、gcc 7系の状態で、以下のオプションを再度指定して、私のやりたかったAviSynthPlusのビルドをやってみます。Raspberry Piでなんもいじらなくてよかったので解決する可能性はほぼありません。

cmake -DCMAKE_CXX_FLAGS=-latomic,-std=c++17 ../ -G Ninja

一応こんな風にしたんですが、当然のごとくできないので、あきらめて、gccをコンパイルというのが今回の非常に長い経緯試したことです。もうgccをビルドせざるを得ない状況に追い込まれました。

gccのビルドとインストール

gccのビルドを行います。私のインストールしたバージョンは、gcc 9.2.0なのですが、基本的に新しいもので問題ないので、記事執筆時点では最新の9.4.0をおすすめしておきます。なんなら更新点をみているとOrange Pi3の動作モードのaarch64に対してピンポイントで変更が行われているのでイチオシです。数字を読み替えてもらえば同じ手順でできるかと思います。

必要パッケージのインストール

以下のコマンドを実行します。

sudo apt-get install -y autogen flex bison build-essential make libreadline-dev libgmp-dev libmpfr-dev libmpc-dev libppl-dev libcloog-ppl-dev

gccのソースコードの保存

以下のコマンドを実行します。上記の通りですが、私の場合は9.2.0だったというだけで、同じaarch64なら執筆現在で最新の9.4.0がおすすめです。数字を読み替えるだけで大丈夫かと思いますが、試していないので、やってみた方いれば結果をコメントで教えていただければ助かります。

wget http://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/releases/gcc-9.2.0/gcc-9.2.0.tar.gz
tar zxf gcc-9.2.0.tar.gz

gccのビルド

以下のコマンドを実行します。必要に応じて読み替えてください。

cd gcc-9.4.0
./configure --disable-multilib --enable-libstdcxx-filesystem-ts=yes

ここで気を付けてもらいたいのが、configureもまあまあ時間がかかります。ここでないライブラリなどは教えてくれるので、なければそのパッケージを入れてください。私が最初に書いた分で十分だとは思うのですがね。

次がいよいよビルドするのですが恐ろしく時間がかかります。Orange Pi3で5時間ちょっとかかりました。寝る前に実行するのがおすすめです。ちなみにmakeしているときにssh接続してるターミナルを閉じると作業が中断されてしまうので、screenなどを用いてプロセスが動くようにしておくかそのターミナルを接続しっぱなしにしてください。

一応時間を短縮する方法があるのですが、コンパイラなのもありますし、時間があるのであれば後述のオプションは使用しないことをお勧めします。

非推奨の時短オプション

上ですでに実行している./configureの部分に以下のオプションを追加することによって時間を短くすることができます。

--disable-bootstrap

これが何をしているかというと、gccのビルドの際、1回目は元からあるコンパイラを使ってビルドを行い、次にビルドで出来上がった新しいgccでもう1回新しいgcc自身をビルドできるかっていうテストを何回かするんですね。それを無効化するので時短できます。ただし非推奨ですし、5時間から短くなると言っても、終わるのはそれでも1時間半位かかると思うので、気長に待ったほうがいいと思います。

では以下のコマンドを実行してmakeを行います。"-j4"の部分は処理に使うコア数をしていしてください。Orange Pi3 は4コアなので全部使うので -j4としています。

make -j4

5時間ぐらいすると終わりました。ではインストールしていきます。

さてここで古いのと混同を防ぐために古いgccを消してしまします。そしてインストールもします。

sudo apt purge gcc
sudo make install

この段階でgcc -vってやっても表示されずミスった?おかしなことした?とか思うかもしれませんが落ち着いてください。再起動すれば反映してくれます。

sudo reboot

しかしこのままではうまいこと動いてくれませんので、「パスを通す」を言われるような作業をします。ここで他サイトを見て躓いたのですが、以下のコマンドだと一時的にしかパスは通りません。再起動するとパスが通っていないので、実行時にエラーが出てしまいます。

export PATH=/usr/local/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64

上のコマンドで一時的にパスが通るので、動作確認はできますが、せっかっく最新のをビルドしたのですから今後はそっちを使うはずです。なので永続的にパスを通せる設定をしましょう。

今回はすべてのユーザで使うこと、あとはターミナル開いていないときに何かあったら困るので、/etc/environmentに追記してパスを永続的に通します。

sudo nano /etc/environment

おそらくgcc -vは通るということはgccのありか自体はわかっているので、ライブラリのパスを通せば大丈夫です。

以下を追記します。

LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64

LD_LIBRARY_PATHが書いてあって違う場所が書かれていたら、:を付けてパスを追記してください。PATHの部分にはデフォルトのインストール場所(ほとんどの場合、/usr/local/binだと思います)が含まれていなければ、同様の方法で追記してください。参考までに追記した後をのせておきます。

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/$
ARCH=arm64
LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
LC_ALL="C"

実はいつか紹介しますが、LC_ALL="C"にずっと苦しめられていたことに後で気づくという展開が待っています。これは関係ないので、置いておきます。

これでパスも通したのでgccのビルドとインストールが終わりですお疲れさまでした。

感想

時間かかりすぎだなぁが一番思いました。ほかのサイトではあたかもexportでパスを通すのは終わりみたいな書き方しているので、コンパイルはできたのに、しかも最初は動いてたのに再起動したら、usr/local/lib : libavisynth.so not foundとか言われて、すごく焦った。なんせgccのビルドは初めてだったもので。頑張って調べるとパスが永続的にとおっていないこと、通し方が2種類あるとのことまでたどり着いでこの記事を最終的に自分のメモとして、誰かの役に立ったらということで公開したけれど、需要あるのかな。

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です