2020年11月22日日曜日

PlatformIOのplatformio.iniのbuild_flagsでマクロを定義してdefault_envsで切り替えたら、VSCodeで読み込んでシンタックスハイライトを切り替えてくれて便利だった話


背景

PlatformIOではplatformio.iniファイルにボードの定義や依存するライブラリなどを記述できます。
その機能の1つにbuild_flagsがあり、これを利用してビルド対象ごとにマクロの変数を定義できます。

VSCodeのPlatformIOのプラグインを利用して開発を行っていると、なんとplatformio.iniに記述したbuild_flagsが読み込まれてシンタックスハイライト(文字の色)に影響するとが分かりました。
便利だと思うので活用事例を共有します。

使ったもの

  • VSCode
    動作確認した際のバージョンは1.51.1でした
  • PlatformIOのVSCodeプラグイン
    動作確認した際のプラグインのバージョンは2.2.1、PlatformIOのバージョンは5.0.3でした。
  • 実機で動作確認する場合: Arduino Uno
    今回はコードのシンタックスハイライトを見るのが主なので、無くても良いです。

今回主に利用するPlatformIOの機能

  • default_envs
    複数ビルド環境が定義されているプロジェクトで、ビルドする環境を絞り込む機能です。
  • build_flags
    ビルド時のフラグを設定する機能です。
    -Dオプションを利用すると、コードで#defineで定義する変数が定義できます。

試すプロジェクト

今回はこのプロジェクトを例として、挙動の変化を紹介します。

platformio.ini
[platformio]
default_envs = uno

[env:uno]
platform = atmelavr
board = uno
framework = arduino

[env:uno-debug]
platform = atmelavr
board = uno
framework = arduino
build_flags =
-D DEBUG_PRINT

[env:uno-debug-with-text]
platform = atmelavr
board = uno
framework = arduino
build_flags =
-D DEBUG_PRINT
-D DEBUG_TEXT=\"heihei\"

src/main.cpp
#include <Arduino.h>

void setup() {
#ifdef DEBUG_PRINT
Serial.begin(9600);
#endif
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
static bool ledState = HIGH;
#ifdef DEBUG_PRINT
Serial.println(ledState == HIGH ? "high" : "low");
Serial.println("at " + String(millis()));
#ifdef DEBUG_TEXT
Serial.println(DEBUG_TEXT);
#endif
#endif
pinMode(LED_BUILTIN, ledState);
ledState = !ledState;
delay(1000);
}

要所を説明します。

[platformio]のdefault_envsでビルド対象の設定を切り替えています。
この設定を書き換えることで、ビルド対象が変わり、対象となっている設定にマクロがあれば読み込まれます。
[platformio]
default_envs = uno

[env:uno-debug]と[env:uno-debug-with-text]ではdefault_envsでマクロの変数を定義しています。
[env:uno-debug]
build_flags =
-D DEBUG_PRINT

[env:uno-debug-with-text]
build_flags =
-D DEBUG_PRINT
-D DEBUG_TEXT=\"heihei\"

src/main.cppではifdefを利用してDEBUG_PRINTが定義されていればSerialでデバッグ情報を出力し、DEBUG_TEXTがあればそれも出力する記述になっています。
void setup() {
#ifdef DEBUG_PRINT
Serial.begin(9600);
#endif
}

void loop() {
#ifdef DEBUG_PRINT
Serial.println(ledState == HIGH ? "high" : "low");
Serial.println("at " + String(millis()));
#ifdef DEBUG_TEXT
Serial.println(DEBUG_TEXT);
#endif
#endif
}

default_envsがunoの場合、build_flagsを定義してないシンタックスハイライトになる

default_envsがunoの場合、[env:uno]にはbuild_flagsを定義していないので、DEBUG_PRINTやDEBUG_TEXTが定義されてない状態のシンタックスハイライトになります。
[platformio]
default_envs = uno



有効でないコードは暗くなります。


default_envsがuno-debugの場合、build_flagsで定義したDEBUG_PRINTが定義されたシンタックスハイライトになる

default_envsがuno-debugの場合、[env:uno-debug]にはbuild_flagsでDEBUG_PRINTを定義しているので、それが定義された状態のシンタックスハイライトになります。
platformio.iniの設定を書き換えて保存すると反映されるので、編集中になっていれば保存してください。
[platformio]
default_envs = uno-debug



DEBUG_PRINTがある時に有効になるコードは明るくなり、DEBUG_TEXTが必要な16橋目のコードは暗いままになります。



default_envsがuno-debug-with-textの場合、build_flagsで定義したDEBUG_PRINTとDEBUG_TEXTが定義されたシンタックスハイライトになる

default_envsがuno-debug-with-textの場合、[env:uno-debug-with-text]にはbuild_flagsでDEBUG_PRINTとDEBUG_TEXTを定義しているので、それらが定義された状態のシンタックスハイライトになります。
platformio.iniの設定を書き換えて保存すると反映されるので、編集中になっていれば保存してください。
[platformio]
default_envs = uno-debug-with-text



DEBUG_PRINTもDEBUG_TEXTも定義された状態のコードになり、暗い部分は無くなります。

更に、DEBUG_TEXTにマウスポインターを合わせると、build_flagsでDEBUG_TEXTとして定義した"heihei"が、展開される内容として表示されます。
何の値が定義されているか分かってとても便利です。


コマンドでbuild_flagsを設定できるPLATFORMIO_BUILD_FLAGSとplatformio.iniのbuild_flagsはどちらも使われる

以前ビルドコマンドでPLATFORMIO_BUILD_FLAGSを利用してbuild_flagsを設定する方法を把握しました。

片方があるともう片方は無視されるのかと思っていましたが、試してみると両方使われると分かりました。

DEBUG_TEXTを定義するPLATFORMIO_BUILD_FLAGSと共に、既にDEBUG_TEXTが定義されているuno-debug-with-textをビルドすると、エラーは発生しませんが定義重複警告が発生します。
PLATFORMIO_BUILD_FLAGS="-D DEBUG_TEXT=\\\"yoyoyo\\\"" pio run -e uno-debug-with-text -v
<command-line>:0:0: warning: "DEBUG_TEXT" redefined
<command-line>:0:0: note: this is the location of the previous definition
<command-line>:0:0: warning: "DEBUG_TEXT" redefined
<command-line>:0:0: note: this is the location of the previous definition

ビルドコマンドに-vオプションを付けてビルドコマンドを確認すると、下記のようにplatformio.iniのbuild_flagsの後にPLATFORMIO_BUILD_FLAGSの値が記述されていました。
build_flags: -D DEBUG_PRINT, -D DEBUG_TEXT=\"heihei\", -D DEBUG_TEXT=\"yoyoyo\"

この設定でArduino Unoにプログラムを書き込んで動かしてみました。
PLATFORMIO_BUILD_FLAGS="-D DEBUG_TEXT=\\\"yoyoyo\\\"" pio run -e uno-debug-with-text -t upload

プログラムを書き込んだUnoから送られる情報をシリアルモニタで確認すると、PLATFORMIO_BUILD_FLAGSで設定したyoyoyoが送信されていました。
pio device monitor
high
at 0
yoyoyo
low
at 999
yoyoyo
high
at 1999
yoyoyo

つまり、動作確認した時点では、同じ変数を定義していた場合PLATFORMIO_BUILD_FLAGSで定義したものが優先されると分かりました。

まとめ

platformio.iniのenvで定義したbuild_flagsをdefault_envsを利用して切り替えることで、反映されたマクロの変数でifdefの有効無効を切り替えてシンタックスハイライトを変えれました。

また、シンタックスハイライトは関係ないですが、platformio.iniのbuild_flagsとコマンド時にbuild_flagsを定義できるPLATFORMIO_BUILD_FLAGSが併用できることも分かりました。

0 件のコメント :