Arduino IDEは如何にしてコンパイルを行っているのか?

Arduino IDEで開発を行っています。ソースが長くなってきたので複数ファイルに分割したのですが2個目の.inoファイル先頭にライブラリーのincludeを行ったところ、その.h内で大量のコンパイルエラーが出たのです。

いろいろ調べたら、なんてことはなく1個目の.inoのブロックが閉じてなかった("}"が足りなかった)ってオチでした。

Arduino IDEの言語は基本的にC++なのですが微妙に異なる(宣言していない関数を前方で呼んでもエラーにならないなど)のが不思議だったので、どこかに資料があるのだろうなと思いながら試してみました。

拡張子.ino、.c、.cpp以外はスケッチに加えてもコンパイル対象にならない

.hや適当な拡張子のファイルをスケッチに加えてもコンパイル対象になりません。これらのファイルがボードに転送されるかは検証していません。当然ですが.hを.inoなどからincludeすればコンパイル対象になります。

.c、.cppは厳密なc++言語としてコンパイルされる

ソースの後方にある関数は呼び出す前にプロトタイプ宣言をしていないとエラーになります。また.inoで何気に呼んでいたSerial.println("test");などもarduino.hをインクルードしていないとエラーになります。

.ino内の関数はプロトタイプ不要だが同じスケッチ内の.cpp内の関数は宣言してないとエラーとなる

.ino内の関数はソース上後方にあっても前方で呼び出せます。別の.inoファイルであっても問題ありません。しかし同じスケッチ内の.cppなどの関数はプロトタイプ宣言しないとエラーとなります。

.ino内でもstructやclassは前方に宣言がないとエラーになります。

.inoは連続して扱われる

先頭の.inoにvoid loop(){と書いて2番めの.inoで}と書けばコンパイルエラーになりません。これが最初のinclude内でのエラーの原因で1つ目の.inoのブロック内にincludeが展開されてしまったためにエラーとなったようです。

結論的なもの

ということで.inoファイルはプリプロセッサ的なもので全ファイルがテキストとしてマージされて処理されているようです。マージ後にino内の関数をチェックしてプロトタイプ的なものを生成してarduino.hなどの必須includeと共に挿入してcppとしてコンパイルしているんではないかなと思う次第です。