前置き
- Flutterにおけるビルド種類分け、切り替えについての説明です。
- Mac / windowsを対象としたデスクトップ向けのアプリケーションを想定しています。
- C++ & Dartで構成されたアプリケーションです。
- 開発環境はvscodeです。
Flutterのビルドの仕組み
androidのビルドの仕組みと似ています。
ビルドタイプ x flavor
の掛け合わせになっています。
Flavorとは?
androidには、ビルドバリアント
という仕組みが存在します。
そこでは、ビルドタイプ x product flavor
の掛け合わせがビルドの種類をさし示します。
Flutter関連の記事は未確認ですが、Flutterもこの流れを組んでいる、と思われます。
androidで言えば、
- debug
- release
という2つのビルドタイプが存在し、それに加えて、product flavorが存在します。
仮に
- alpha
- beta
- product
という3つの product flavorが存在する時、それの掛け合わせ
となるため、
- debugalpha
- debugbeta
- debugproduct
- releasealpha
- releasebeta
- releaseproduct
という6つのビルドの種類
ができる、ということになります。
Flavorを使った場合、どのようなビルドになるか?
Flutterのビルドタイプは、3つ存在します。
- debug mode
- profile mode
- release mode
profile modeは、debug <-> releaseの間に位置するタイプです。
ある程度ソースコードのデバッグは可能ですが、より release modeに近い環境でデバッグするのを目的としているように思います。
つまり、これら既存の3種類 x flavor
との掛け合わせとなるわけです。
本記事では、flavor typeに、
- alpha
- product
という2種類のタイプを定義して、それらをどのように切り分けるのかを書いていきます。
イメージとしては下記の整理としています。
ビルドタイプ | Flavor | 備考 |
---|---|---|
debug | alpha | |
profile | product | 場合によってはalphaでもいいかな? |
release | product |
掛け合わせの最大数としてはもっと定義はできますが、今回は必要最低限の種類として考えました。
実際にビルドを分けていく
方法は色々ありますが、dart-define-from-fileを使ってビルド分けするのが妥当だと思います。
こちらの記事が参考になりました。
dart-define-from-fileはどのように使うか
タイトルそのままなのですが、ビルドのタイプに応じて、設定ファイルを切り替える
、というふうに使います。
なので、from-fileなわけですね。
用意するファイル
ビルドの設定ファイルは、jsonで用意します。
そしてそれをビルド時に、引数として与えることでビルドの切り替えを行います。
flutterProject_Root
├──flavor
│ ├── alpha.json
│ └── product.json
....
ファイル名は、flavor名にしておくと良いでしょう。
{
"flavor": "alpha",
"appName": "sample-alpha",
"appIdSuffix": ".alpha"
}
{
"flavor": "product",
"appName": "sample",
"appIdSuffix": ""
}
基本はこれだけです。
コマンドでは実際にどのようにビルドするのか
ビルド
flutter build macos --dart-define-from-file=flavor/alpha.json
実行
flutter run --dart-define-from-file=flavor/alpha.json
合わせて、--debug or --release などを追加すると、より明確にビルドができます。
debug時、launch.jsonでの書き方
vscodeでのデバッグを想定して書いています。
vscode環境で、デバッグ実行するとき、launch.jsonでデバッグしますが、その記載例です。
{
"version": "0.2.0",
"configurations": [
{
// mac向けデバッグ
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"osx" : {
"program":"${workspaceFolder}/build/macos/Build/Products/Debug/hogehoge.app",
"MIMode": "lldb"
},
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
},
{
// dart debug
"name": "hogehoge",
"request": "launch",
"type": "dart",
"flutterMode": "debug",
"args": [
"--dart-define-from-file=flavor/alpha.json"
],
"windows": {
"env": { "FLUTTER_FLAVOR" : "alpha" },
}
},
{
// profile dart debug
"name": "hogehoge (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile",
"args": [
"--dart-define-from-file=flavor/alpha.json"
],
"windows": {
"env": { "FLUTTER_FLAVOR" : "product" },
}
},
{
// release flutter run
"name": "hogehoge (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release",
"args": [
"--dart-define-from-file=flavor/product.json"
],
"windows": {
"env": { "FLUTTER_FLAVOR" : "product" },
}
}
]
}
このように記載します。
windows版についての定義をここで先に見せていますが、次の項でどうしてこのような書き方をしているのか説明します。
windows版についてのビルドの仕方
windows 版の場合は、一工夫、必要になっています。
...
"windows": {
"env": { "FLUTTER_FLAVOR" : "product" },
}
...
どうしてこのような定義が必要なのでしょうか?
これは、私が作ったプロジェクトの都合ですが、今作っているプロジェクトが、
C++ & Dartで構成されたプロジェクト
であるためです。
windowsにおけるC++のビルド
windowsにおけるC++の呼び出し方法については、割愛します。
下記記事など参考にされると良いと思います。
Flutter におけるC++のビルドは、Macではそこまで問題がありません。
Flutterにおけるnative層は、ffiを使って呼び出します。
これは、web版では動作しませんが、macos、windowsでは動作することが可能です。
ライブラリとして呼び出すわけですが、windows版の場合は、dllのPathなどを指定して、開く必要があります。
....
static late DynamicLibrary hogeLib;
hogeLib = Platform.isWindows
? DynamicLibrary.open(windowsDLLPath)
: DynamicLibrary.process();
....
そのため、C++のnative層は、dartでビルドする前に、用意しておく必要がある分けです。
windowsにおけるdart-define-from-fileの落とし穴
C++の部分は、DLLとして用意することにしました。
- Cmakeにてvisual studioのプロジェクトを生成し
- それをビルド(DLL生成)
- dartの部分をビルドして、Flutterをビルド
ただ、この工程での問題は、
dart-define-from-fileを使ってビルドする時に与える、
"args": [
"--dart-define-from-file=flavor/alpha.json"
],
このargsを渡せないことにあります。
CMakeでのビルド時に、alpha.jsonで定義している
"flavor": "alpha",
の要素を渡したいわけですが、これがCMake側で認識することができないのです。
そこで、flavor
という値を渡すことを諦めることにしました。
代わりに、
- ビルド時に環境変数
FLUTTER_FLAVOR
の値を定義 - CMakeで環境変数をチェック
- CMakeで環境変数でAlphaが立っていたら、マクロ
FLAVOR_ALPHA
定義 - C++側では、定義されているマクロによってビルドを分ける
という流れにすることにしました。
if ($ENV{FLUTTER_FLAVOR} MATCHES "alpha")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLAVOR_ALPHA")
endif ()
#ifdef FLAVOR_ALPHA
#else
#endif
こんな感じで場合分けします。
まとめ
alpha or productにおけるビルド種類の切り替えについて紹介しました。
windows版のビルドが若干めんどくさいですが、ここら辺がより簡単になると良いかな〜と思います。