発生した問題
RaspberryPi Zero W のベアメタル環境で Circle を使って C++ アプリの開発をしていたのですが、自作のZ80エミュレータをビルドしてみたところ、以下のようなエラーになりました。
% make
cp ../src/* .
make -f Build.mak
make: *** [all] Error 2
どのようなエラーが原因なのか分からないですね...
原因が分からない原因
Build.mak の内容は次のようになっています。
CIRCLEHOME = ./circle
OBJS = main.o
LIBS = $(CIRCLEHOME)/lib/libcircle.a
include $(CIRCLEHOME)/Rules.mk
-include $(DEPS)
Circle が提供する Rules.mk へ渡すオプション情報だけ定義したシンプルな Makefile です。
Rules.mk の内容をざっくり確認したところ、
- コードの依存関係チェック
- コンパイル
という流れでビルド処理をしていたので、試しに依存関係チェックを省略できる CHECK_DEPS = 0
という環境変数を定義してみました。
CIRCLEHOME = ./circle
# コレを追加
CHECK_DEPS = 0
OBJS = main.o
LIBS = $(CIRCLEHOME)/lib/libcircle.a
include $(CIRCLEHOME)/Rules.mk
-include $(DEPS)
すると、エラーが以下のように変わり、無事原因が分かるようになります。
% make
cp ../src/* .
make -f Build.mak
CPP kernel.o
In file included from kernel.cpp:29:
z80.hpp:29:10: fatal error: functional: No such file or directory
29 | #include <functional>
| ^~~~~~~~~~~~
compilation terminated.
make[1]: *** [kernel.o] Error 1
make: *** [all] Error 2
要するに、functional(std::function
)がCircleではまだ使えないようですね。
対策(参考)
前章までが本記事の本題で、以下は具体的にこの問題をどう対処したかを参考までに記します。
functional 以外にも map, vector, 例外あたりがベアメタル環境では使えない(参考)ので、それらを排除できるコンパイルオプションを追加する力技で対処することにしました。
以下Pull Requestの最新commitの状態で、
Build.mak に以下を付与すれば無事コンパイルが通りました。
CPPFLAGS = -DZ80_DISABLE_DEBUG -DZ80_DISABLE_BREAKPOINT -DZ80_DISABLE_NESTCHECK -DZ80_NO_FUNCTIONAL -DZ80_NO_EXCEPTION
幸い、主要な機能ではSTLを使っていなかったので助かりました。
あまり美しい対処ではないですが仕方ないかなと。
美しく組みたければベアメタルでなんか組まずにLinuxを入れてしまうのがベスト
2023.12.12追記
Circle での C++ STL (map や vector) の利用ですが こちらのドキュメント に使い方が書かれていました。Config.mk に STDLIB_SUPPORT=3
を定義すれば C++ STL (map や vector) が使えるようです。
STDLIB_SUPPORT=3
2023.12.13追記
STDLIB_SUPPORT=3
を定義してみましたが map や vector は使えないようでした。
一部C++標準ヘッダーは使えるが freestanding mode の範囲内に限られ、map や vector はそれに含まれないようです。
#include <map>
をすると以下のようなエラーになりました。
/Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/aarch64-none-elf/include/c++/13.2.1/bits/requires_hosted.h:34:4: error: #error "This header is not available in freestanding mode."
34 | # error "This header is not available in freestanding mode."
| ^~~~~
freestanding mode:
https://stackoverflow.com/questions/23258415/whats-freestanding-mode-for-libstdc
ということで、やはりベアメタルであれば STL は基本使えないということで、当初記事に書いた通り「STL を使いたい場合は Linux を使う」のがベターかもしれません。
どうしても STL を使いたい場合は EASTL とかかな(未検証)
https://github.com/electronicarts/EASTL