Arduino IDEでも、スケッチのソースファイルを複数の.inoファイルに分割することができる。
ちょっとプログラムが大きくなると機能単位などでファイルを分割した方が見通しが良い。
しかし、Arduino IDEでは、ソースファイルを分割しても、他のIDEなどにおける分割コンパイルが行われるのではなく、関数のプロトタイプ宣言などが抽出され、それらを適宜付加した1つのファイルが生成され、それがコンパイルされるようである。
生成される1つのファイルでもエラーの発生源の元のファイルがわかるように#line ディレクティブが適宜追加されるようになっている。
しかし、この処理が不完全で、エラーの原因を探ることが困難な場合が少なくない。
備忘録としてESP8266用の複数ファイルに分割したスケッチをWindows上のArduino IDEでコンパイルした際のエラーを記録しておく。
itoa の宣言を含めていなかった場合のエラー?
以下はエラーログの一部であるが、スケッチをコンパイルしている際にエラーが発生した。改行など一部変更している。
スケッチをコンパイルしています...
"C:\Users\user\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__
-DICACHE_FLASH -U__STRICT_ANSI__
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1/tools/sdk/include"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1/tools/sdk/lwip2/include"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1/tools/sdk/libc/xtensa-lx106-elf/include"
"-IC:\Users\user\AppData\Local\Temp\arduino_build_572969/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti
-falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections -DF_CPU=80000000L -DLWIP_OPEN_SRC -DTCP_MSS=536 -DARDUINO=10900
-DARDUINO_ESP8266_GENERIC -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_GENERIC" -DLED_BUILTIN=2 -DESP8266
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\cores\esp8266"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\variants\generic"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\Wire"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\ESP8266WiFi\src"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\DNSServer\src"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\ESP8266WebServer\src"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\WiFiManager"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\arduinoWebSockets-master\src"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\PubSubClient\src" "-IC:\arduino-PR-beta1.9-BUILD-44\libraries\mylan"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\aws-mqtt-websockets-master"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\aws-sdk-arduino-master"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\SPI"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\Adafruit_GFX_Library"
"-IC:\arduino-PR-beta1.9-BUILD-44\sketch\libraries\Adafruit_SSD1306_Wemos_Mini_OLED"
"-IC:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\Hash\src"
"C:\Users\user\AppData\Local\Temp\arduino_build_572969\sketch\aws-mqtt-websocket-wifimanager-T6703-iot-displayX.ino.cpp" -o
"C:\Users\user\AppData\Local\Temp\arduino_build_572969\sketch\aws-mqtt-websocket-wifimanager-T6703-iot-displayX.ino.cpp.o"
c:\users\user\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bit
s\unique_ptr.h:481:18: error: variable or field 'swap' declared void
inline void
^
c:\users\user\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\unique_ptr.h:481:18: error: 'unique_ptr' was not declared in this scope
c:\users\user\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\unique_ptr.h:481:29: error: '_Tp' was not declared in this scope
inline void
エラーの原因調査
エラーを発生させるコードをC:\Users\user\AppData\Local\Tempの下のarduino_build_XXXXなどの下にある.ino.cppファイルを見てみた。
なかなかわからなかったが、プログラムの中で itoa() 関数を使っていたがそれを宣言する <stdlib.h> を含めていなかったためにエラーが発生したようだった。
エラーの除去と確認
#include <stdlib.h>を追加することで、コンパイル時にエラーがなくなった。
しかし、確認のために、#include <stdlib.h>をコメントアウトして再度コンパイルしてみたが、エラーが出ない!<stdlib.h>だけの問題ではないようだ。どうも追加した際に行が変わったことが影響しているようにも思える。
なかなか奥が深い(よくわからない)。初心者向けに自動で必要な宣言などを加えてまとめてコンパイルすることにしたのであろうが、もう少し素直に分割コンパイルなどをサポートしてくれた方が理解しやすいと思う。
その後、関数の宣言を削除したらエラーが発生するようにはなったので、関数の宣言が影響していることは間違いないが、それだけではないようである。Arduino IDEのソースコードを読めば原因がはっきりするのであろうが、今日はエラーの記録だけで良いことにする。