SNSへはこちら

各種マイコン用gccのバージョン・ビルド法等まとめ

現在最新バージョンで gcc 9.1.0 がリリースされていますが、マイコンに関してはサポート状況がアーキテクチャによって異なるようです。

本記事では僕が現在(2019/7/15) PC に入っているマイコン用ツールチェインのバージョンやビルド方法について多少触れたいと思います。
「別に組込みで最新のコンパイラ使えなくてもいいじゃない」と思われるでしょう。
しかし、僕は新しいものがどうしても使いたいのです。だって C++2a したくないですか??
ということで、なるべく C++ が使えて、かつなるべく最新バージョンのツールチェインを使いたいという気持ちでこの記事を書いています。

ホスト環境

例によって Mac ですが、以下のような構成でビルドをします。gcc 等は Xcode に付いている clang ではなく、GNU 生粋の gcc です。

  • OS: macOS Mojave
  • CC: GCC 9.1.0
  • CXX: G++ 9.1.0

各環境のバージョン等

以下、特記無き場合は以下のツールチェインを用いています。

  • binutils-2.32
  • newlib-3.1.0

また、なるべく C++ の環境も欲しいので、極力ビルドするようにしています。本記事は基本的にすんなりビルドできたアーキテクチャでは説明はしません。苦労した点の記載となります。
各種 configure コマンドは、以下のようで共通しています。

# binutils
$ ../configure --target=(対象アーキテクチャ) --prefix=/usr/local/cross/(対象アーキテクチャ名) --disable-werror --disable-nls --disable-bootstrap

# gcc(1回目)
$ ../configure --target=(対象アーキテクチャ) --prefix=/usr/local/cross/(対象アーキテクチャ名) --disable-werror --disable-nls --disable-bootstrap --disable-libssp --enable-languages=c,c++ --with-newlib

# newlib
$ ../configure --target=(対象アーキテクチャ) --prefix=/usr/local/cross/(対象アーキテクチャ名) --disable-werror --disable-bootstrap --disable-newlib-supplied-syscalls --enable-newlib-reent-small --disable-newlib-fvwrite-in-streamio --disable-newlib-fseek-optimization --disable-newlib-wide-orient --enable-newlib-nano-malloc --disable-newlib-unbuf-stream-opt --enable-lite-exit --enable-newlib-global-atexit --enable-newlib-nano-formatted-io --enable-target-optspace  --disable-nls

# gcc(2回目)
$../configure --target=(対象アーキテクチャ) --prefix=/usr/local/cross/(対象アーキテクチャ名) --disable-werror --disable-nls --disable-bootstrap --disable-libssp --enable-languages=c,c++ --with-newlib --disable-libstdcxx-pch

また、ひょっとしたら newlib のビルド中に __attribute__((alias("hoge"))) 関連で怒られるかもしれないので、その時は該当ソースコード開いて直接 __attribute__((weak, alias("hoge"))) と変更してください。

AVR

newlib ではなく、AVR ように最適化された独自の実装である AVR-libc を用いています。newlib に変えて、AVR-libcのビルドを行います。

$ ../configure --prefix=/usr/local/cross/avr --build=`../config.guess` --host=avr

これだと現状 g++ のビルドは出来ますが、libstdc++ のビルドはエラーで行えません(AVR-libc では公式に非サポートとされている)。ですが、8bit マイコンなのでそこまで必要ではないでしょうね。

近い内に newlib での実装をビルドして libstdc++ を使えるようにしたいと思います。
(そういえば僕は AVR アセンブリばっかやってて、 C コンパイラ使ったこと殆ど無いんだった)

H8300

H8 マイコンのアーキテクチャです。こちらは2つのビルド状況を確認しています。

最新バージョン(Cのみ)

最新の gcc-9.1.0 を用いていますが、こちらは libstdc++ のビルドがうまくいかない ため、C言語のみの対応です。
ビット数を管理するソースファイルにて、std::size_t の配列があるのですが、H8 アーキテクチャ上では std::size_t のビット長が短いため、配列の要素が格納できないらしいです。
また、C++17 のメモリ管理機構において、コンパイル時の static_assert に失敗します。これはもうどうしようもない。

8.3.0 (C & C++)

こちらのバージョンは現在最新の gcc 9.1.0 の1つ前のバージョンです。実はこれも libstdc++ のビルドで失敗します。
ですが、多少 Makefile に手を加えることでビルドを完了することが出来ます

具体的には、basic_string.hinternal compiler error: unrecognizable insn として怒られます。ヘッダが整っていないとか、環境がだめだとかじゃなくて、C++ 用ライブラリをビルドするための xgcc で内部エラー(バグ?)が起きてしまっているのです。悲しい。

どのように回避するかと言うとそれは簡単で、エラーが起きたらh8300-elf/Makefileの526行目にあるCXXFLAGS_FOR_TARGET-g -O0変えるだけです。最適化を切ることでこのエラーはなぜか起きなくなります。

最新バージョンではないですが、-std=c++17 が使えるのでまあいいでしょう。新しいからと言って C言語のためだけに 9.1.0 にする理由はありませんね。だって C は(おおむね)もう十分に枯れている言語ですから。

MSP430

TI の低消費電力マイコンに使われるアーキテクチャです。こちらは gcc 9.1.0 で問題なく C も C++ も利用できます

M32C

このサブセットである、R8C を搭載したマイコンのために使っています。ルネサス的にはもう古いとみなしているようです。
gcc-6.4.0 で gcc が使えますが、ビルドに少々癖があります

newlib ビルド時に、またしても internal compiler error で怒られるので、m32c_elf/MakefileCFLAGS_FOR_TARGET += -g -Os とすればいいでしょう。

さらに、2回目の gcc ビルドで libstdc++-v3 を作るときにも internal compiler error になってしまいます。これについてはダメっぽいです。g++ はビルドできるのですが、libstdc++ができません。

RL78

RX の下位スペックを担うアーキテクチャです。gcc 9.1.0 で問題なく C も C++ も利用できます

SH

古いマイコンである、SuperH です。皆さん知らないかもしれませんが、このマイコンは 32bit なんですよ。gcc 9.1.0 で問題なく C も C++ も利用できます

ちなみに、32bit である証拠ですが...次のソースファイルをコンパイルします。

// b.c
int f(void) {
    return sizeof(void *);
}
$ sh-elf-gcc -Os -c b.c
$ sh-elf-objdump -d b.o

中身はこんな感じになっています。確かに、4Bytes == 32bits ですね。


b.o: file format elf32-sh Disassembly of section .text: 00000000 <_f>: 0: 00 0b rts 2: e0 04 mov #4,r0

RX

ルネサス主力のマイコンシリーズのうちの1つで、様々なモデルやアーキテクチャのバージョンが出ていて、今もなお版図を広げています。
gcc 9.1.0 で問題なく C も C++ も利用できますが、 gcc 公式のソースからビルドすると printf 系の関数を使うと %f の処理でマイコンが止まってしまうという問題があります。

また、ビルド時に Fatal error: Infinite loop encountered whilst attempting to compute the addresses of symbols in section P と言われてエラーになることがあります。その時は rx-elf/libstdc++-v3/MakefileCXXFLAGS, CXXFLAGS_FOR_TARGET, CXXFLAGS_FOR_BUILD-mrelax を追加してください。
こちらを参考にしました。

実際のところ、printf%f をうまく処理させるためには GNU Tools から ななんと古代の gcc-4.9.4 をビルドするしか無いんですね〜〜
一応 C++ も使えますが、C++14 は一部のみの対応です。ですのでコンパイルオプションは -std=c++14 がサポートされておらず、-std=c++1y とする必要があります。古代ですね

ARM

arm-none-eabi として使います。現在も続々と用いられているアーキテクチャのため、こちらも gcc 9.1.0 で問題なく C も C++ も利用できます

MIPS

最近はあまり使われていませんかね。こちらも 32bit のアーキテクチャです。メジャーどころだと PIC32MX シリーズで用いられています。
gcc 9.1.0 で問題なく C も C++ も利用できます

FT32

実は FTDI はマイコンも製造しているんですね。それ用のツールチェインです(ぶっちゃけよく分かっていない)。
gcc 9.1.0 で問題なく C も C++ も利用できます

Xtensa

ESP32で利用されているコアです。ESP32 用のコンフィギュレーションで考えます(xtensa-esp32-elf)。

binutils と gcc のビルドはうまくいきます。一方で newlib でこのアーキテクチャはサポートされていないようで、configure 時に「そんなもの知らん」って怒られます。
ではどうするか?ですが、製造元の espressif が用意している newlib のアレンジ版を使うことになります(コメントありがとうございます!)。こちらが以下。

Version of newlib used in ESP32 ROM and ESP-IDF. Contribute to espressif/newlib-esp32 development by creating an account on GitHub.

ビルド方法は本家のものと同一。ESP32 のメーカーページではすでにバイナリが配布されていますが、アレンジしたい!という方はこちらから是非どうぞ。

コメント

  1. 名無し より:

    はじめまして。ESP32ではnewlib-esp32(ttps://github.com/espressif/newlib-esp32)を使用するとビルドに成功しました。

    参考にnewlib-esp32を使って作ったgccの-vを示します。
    Using built-in specs.
    COLLECT_GCC=/usr/local/cross/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcc
    COLLECT_LTO_WRAPPER=/usr/local/cross/xtensa-esp32-elf/libexec/gcc/xtensa-esp32-elf/10.2.0/lto-wrapper
    Target: xtensa-esp32-elf
    Configured with: /home/username/xtensa-esp32-elf/gcc-10.2.0/configure --target=xtensa-esp32-elf --prefix=/usr/local/cross/xtensa-esp32-elf --disable-bootstrap --disable-libssp --disable-nls --enable-languages=c,c++ --enable-threads=posix --with-newlib --with-pkgversion='GCC:v10.2.0, newlib-esp32:esp_based_on_3_0_0-1590f7f, date:20200905'
    Thread model: posix
    Supported LTO compression algorithms: zlib
    gcc version 10.2.0 (GCC:v10.2.0, newlib-esp32:esp_based_on_3_0_0-1590f7f, date:20200905)

    • shima-529 より:

      詳細に情報ありがとうございます。そうでした。メーカー独自のアレンジ版で出来たんですね。
      記事本文に追記させていただきます。

      ちなみに現状、本家のnewlib-3.3.0でもxtensaはビルドできないようです。こちらもご参考まで。

      • 名無し より:

        返信が遅れてしまいすみません。
        こちらの環境でv3.1~3.3まで念の為一通り試しましたが、いずれも同様のエラーでした。

        さて話は変わりますが、今現在8bit AVR用に本家newlibをビルドしようとしているのですが、avr-arの処理中にstdio/lib.aやstrlib/lib.aが見つからず(1>/dev/nullした限りでは一部のソースがコンパイルエラーしてlib.aが生成できず404になったと思われます)ビルドに失敗するようです。こちらの環境だけかはわかりませんが、参考までにしていただければと思います