UbuntuでFlutter環境構築(2020年11月版) デスクトップ編

Posted by 雅楽斎 on Friday, November 20, 2020

TOC

今年の7月にFlutterがデスクトップアプリの開発もできるようになりました。ステータスはアルファです。

現時点でのLinuxデスクトップ開発環境を構築しますが、LinuxでのAndroid向けのFlutter開発環境の構築を済ませている前提で作業します。確認環境はUbuntu MATE 20.04(amd64)です。

UbuntuでFlutter環境構築(2020年11月版) Android編

デスクトップ用の環境構築

Desktop support for Flutter

Announcing the alpha release of Flutter for desktop.

必要なもの

  • Flutter SDK
  • (オプション)FlutterをサポートするIDE。Android Studio/IntelliJ IDEA, Visual Studio CodeとFlutter・Dartプラグインのインストール
  • Flutter SDKに追加
    • Clang
    • CMake
    • GTK development headers
    • Ninja build
    • pkg-config
    • libblkid
    • liblzma

Flutter SDKとIntelliJ IDEAは既にインストール済みなので、必要なコマンドをインストールします。

# apt-get install clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev

ここは大量にパッケージがインストールされます。

チャンネルをdevへ変更、デスクトップを有効化

$ flutter channel dev
$ flutter upgrade #177MBのダウンロード
$ flutter config --enable-linux-desktop

デバイスの生成

flutter devicesの実行でLinuxデバイスが1つ生成されます。

$ flutter devices
Downloading package sky_engine...                                2,231ms
Downloading flutter_patched_sdk tools...                            6.9s
Downloading flutter_patched_sdk_product tools...                    4.7s
Downloading linux-x64 tools...                                     13.2s
Downloading linux-x64/font-subset tools...                       1,780ms
1 connected device:

Linux (desktop) • linux • linux-x64 • Linux

この状態でflutter doctorを実行するとデバイスが1つ接続されていると認識されています。

$ flutter doctor -v
[✓] Flutter (Channel dev, 1.24.0-10.2.pre, on Linux, locale ja_JP.UTF-8)
    • Flutter version 1.24.0-10.2.pre at
      /home/hogehoge/snap/flutter/common/flutter
    • Framework revision 022b333a08 (30 hours ago), 2020-11-18 11:35:09 -0800
    • Engine revision 07c1eed46b
    • Dart version 2.12.0 (build 2.12.0-29.10.beta)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /home/hogehoge/AndroidSDK
    • Platform android-30, build-tools 30.0.2
    • ANDROID_SDK_ROOT = /home/hogehoge/AndroidSDK
    • Java binary at: /usr/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_275-8u275-b01-0ubuntu1~20.04-b01)
    • All Android licenses accepted.

[✓] Linux toolchain - develop for Linux desktop
    • clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
    • cmake version 3.10.2
    • ninja version 1.8.2
    • pkg-config version 0.29.1

[!] Android Studio (not installed)
    • Android Studio not found; download from
      https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup
      for detailed instructions).

[✓] IntelliJ IDEA Community Edition (version 2020.2)
    • IntelliJ at /snap/intellij-idea-community/257
    • Flutter plugin version 51.0.3
    • Dart plugin version 202.8070

[✓] Connected device (1 available)
    • Linux (desktop) • linux • linux-x64 • Linux

! Doctor found issues in 1 category.

デスクトップアプリの実行

既存アプリのデスクトップ対応追加

前回サンプルで作ったmyappというアプリをデスクトップアプリとしても使えるようにします。

場所を指定せずにプロジェクトを作成した場合は~/IdeaProjects/myappにプロジェクトが作られているので、プロジェクトルートに移動してflutter create .を実行します。

$ cd ~/IdeaProjects/myapp
$ flutter create .
Recreating project ....
  linux/flutter/CMakeLists.txt (created)
  linux/.gitignore (created)
  linux/CMakeLists.txt (created)
  linux/my_application.h (created)
  linux/main.cc (created)
  linux/my_application.cc (created)
  android/app/src/main/kotlin/com/example/myapp/MainActivity.kt (created)
  android/app/src/main/res/drawable-v21/launch_background.xml (created)
  android/app/src/main/res/values-night/styles.xml (created)
Running "flutter pub get" in myapp...                              358ms
Wrote 12 files.

All done!
(snip)
In order to run your application, type:

  $ cd .
  $ flutter run

Your application code is in ./lib/main.dart.

ちなみに、これをせずにIDEAを起動してLinuxデバイスを接続して実行すると以下のエラーが発生します。

Downloading linux-x64/linux-x64-flutter-gtk tools...
Downloading linux-x64-profile/linux-x64-flutter-gtk tools...
Downloading linux-x64-release/linux-x64-flutter-gtk tools...
Running "flutter pub get" in myapp...
Launching lib/main.dart on Linux in debug mode...
Exception: No Linux desktop project configured. See https://flutter.dev/desktop#add-desktop-support-to-an-existing-app to learn about adding Linux support to a project.

Linuxデバイスを指定しての実行

IntelliJ IDEA Community Editionを起動すると、前回終了時に開いていたmyappプロジェクトがそのまま開かれて、デバイス欄から「Linux(desktop)」を選べるようになっています。

デバイスの右にある再生ボタンをクリックすると、デスクトップアプリとしてmyappが起動します。(えらい大画面で) ※リサイズ可能です。レイアウトは保たれます。

配布用のアプリを生成

現在まだステータスがstableではないので公式でも配布は推奨されていませんが、配布用のアプリをビルドしてみます。

プロジェクトルートでflutter build linuxを実行します。

$ flutter build linux
Running "flutter pub get" in myapp...                              380ms
Building Linux application...

生成物は(おそらく)build/linux/release/bundleの下に作られます。実行はそのままできます。右上のDEBUGが外れています。

依存ライブラリは以下の通りです。かなり多くのライブラリが実行時に必要に見えます。

$ ldd build/linux/release/bundle/myapp 
	linux-vdso.so.1 (0x00007fffc87da000)
	libgtk-3.so.0 => /lib/x86_64-linux-gnu/libgtk-3.so.0 (0x00007f34f76d1000)
	libgdk-3.so.0 => /lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007f34f75cc000)
	libpangocairo-1.0.so.0 => /lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f34f75ba000)
	libpango-1.0.so.0 => /lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007f34f756b000)
	libatk-1.0.so.0 => /lib/x86_64-linux-gnu/libatk-1.0.so.0 (0x00007f34f7541000)
	libcairo-gobject.so.2 => /lib/x86_64-linux-gnu/libcairo-gobject.so.2 (0x00007f34f7535000)
	libcairo.so.2 => /lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f34f7410000)
	libgdk_pixbuf-2.0.so.0 => /lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f34f73e8000)
	libflutter_linux_gtk.so => /home/hogehoge/IdeaProjects/myapp/build/linux/release/bundle/lib/libflutter_linux_gtk.so (0x00007f34f682b000)
	libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f34f664a000)
	libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f34f65ea000)
	libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f34f64c1000)
	libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007f34f6468000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f34f6319000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f34f62fe000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f34f610c000)
	libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f34f6106000)
	libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f34f5fc9000)
	libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f34f5fb5000)
	libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f34f5fad000)
	libatk-bridge-2.0.so.0 => /lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 (0x00007f34f5f76000)
	libepoxy.so.0 => /lib/x86_64-linux-gnu/libepoxy.so.0 (0x00007f34f5e43000)
	libfribidi.so.0 => /lib/x86_64-linux-gnu/libfribidi.so.0 (0x00007f34f5e26000)
	libpangoft2-1.0.so.0 => /lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007f34f5e0d000)
	libharfbuzz.so.0 => /lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f34f5d06000)
	libfontconfig.so.1 => /lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f34f5cbf000)
	libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f34f5c00000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f34f5bdd000)
	libXinerama.so.1 => /lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f34f5bd8000)
	libXrandr.so.2 => /lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f34f5bc9000)
	libXcursor.so.1 => /lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f34f5bbc000)
	libXcomposite.so.1 => /lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007f34f5bb7000)
	libXdamage.so.1 => /lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f34f5bb2000)
	libxkbcommon.so.0 => /lib/x86_64-linux-gnu/libxkbcommon.so.0 (0x00007f34f5b70000)
	libwayland-cursor.so.0 => /lib/x86_64-linux-gnu/libwayland-cursor.so.0 (0x00007f34f5b65000)
	libwayland-egl.so.1 => /lib/x86_64-linux-gnu/libwayland-egl.so.1 (0x00007f34f5b60000)
	libwayland-client.so.0 => /lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007f34f5b4d000)
	libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f34f5b38000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f34f5b2d000)
	libthai.so.0 => /lib/x86_64-linux-gnu/libthai.so.0 (0x00007f34f5b22000)
	libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f34f5a7b000)
	libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f34f5a41000)
	libxcb-shm.so.0 => /lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f34f5a3c000)
	libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f34f5a12000)
	libxcb-render.so.0 => /lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007f34f5a03000)
	libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f34f57f9000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f34f57dd000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f34f57d5000)
	libEGL.so.1 => /lib/x86_64-linux-gnu/libEGL.so.1 (0x00007f34f57c0000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f34f7ea6000)
	libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007f34f5760000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f34f5735000)
	libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f34f5719000)
	libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f34f570d000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f34f5698000)
	libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007f34f5647000)
	libatspi.so.0 => /lib/x86_64-linux-gnu/libatspi.so.0 (0x00007f34f5610000)
	libgraphite2.so.3 => /lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f34f55e3000)
	libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f34f55b5000)
	libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f34f55aa000)
	libdatrie.so.1 => /lib/x86_64-linux-gnu/libdatrie.so.1 (0x00007f34f55a0000)
	libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f34f559a000)
	libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f34f5592000)
	libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007f34f54da000)
	libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f34f5448000)
	libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f34f5399000)
	libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f34f537f000)
	liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f34f5356000)
	liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f34f5335000)
	libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f34f5215000)
	libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f34f51f2000)

相対パスで参照しているのはbuild/linux/release/bundle/lib/libflutter_linux_gtk.soだけなので、そこを意識する必要はあるのかなと思います。配布時はbuild/linux/release/bundle/以下をひとまとめにする必要がありそうです。

.
├── data
│   ├── flutter_assets
│   │   ├── AssetManifest.json
│   │   ├── FontManifest.json
│   │   ├── NOTICES
│   │   ├── fonts
│   │   │   └── MaterialIcons-Regular.otf
│   │   └── packages
│   │       └── cupertino_icons
│   │           └── assets
│   │               └── CupertinoIcons.ttf
│   └── icudtl.dat
├── lib
│   ├── libapp.so
│   └── libflutter_linux_gtk.so
└── myapp

7 directories, 9 files

(現時点では)クロスビルドはできない

試しにWindows用のバイナリをLinuxで生成できるのか、プロジェクトにWindowsデスクトップ対応を追加しました。

$ flutter config --enable-windows-desktop
Setting "enable-windows-desktop" value to "true".

You may need to restart any open editors for them to read new settings.

対応の追加はできました。ビルドしようとすると、

$ flutter build windows
Running "flutter pub get" in myapp...                              368ms
"build windows" only supported on Windows hosts.

build windowsはWindows上でしか実行できない旨の表示がされました。ということで、少なくとも現時点では他プラットフォーム向けのビルドには該当プラットフォームが必要そうです。

公式ではLinux向けにはsnapパッケージを作って配布する案内がされています。

Build and release a Linux app

How to prepare for and release a Linux app to the Snap store.

【追記】現時点では西洋言語以外の文字が豆腐になる

とっつき始めとして、以下のハンズオンをトレースしていました。

社内でFlutterのハンズオンを行ったので、資料を公開します - ペパボテックブログ

先日、社内で Flutter のハンズオンを行ったので、その際に使用した資料を公開します。 Flutter とは? Made by Google Flutter is Google’s UI toolkit for building...

で、Flutterのライブラリがすげー膨大で何をするのにどうすればいいのか全くわからないままに見様見真似で作業をしていましたが、まずこのハンズオンを進めていくうちに日本語が豆腐になっていることに気付きます。

うーんこれは…仮想Androidデバイスで実行してみるとこう。

ということで、今の時点ではFlutter Desktop(Linux)1は本当にロジックのデバッグとかを効率よく進める以外の用途がないですね。

因みに、一応issueはあります。早いとこ治ってほしい。ちなみに、issueの中で--enable-fontconfig引数を有効にすればfontconfigが動くようなのですが、FlutterSDKの中でビルド時に引数を指定できるような箇所がなかったので、IntelliJ IDEAを使う以上は指定する方法がなさそうです。

Improve fallback font handling on Linux · Issue #30700 · flutter/flutter

It's common for people running the shell to have missing text; google/flutter-desktop-embedding#57 and google/flutter-desktop-embedding#212 are two examples, but it's come up several other ...

ついでにハンズオンしておかしかったところ

ハンズオンを最後までやったんですが、最後は商品をクリックすると詳細として画像、値段他色々表示されるはずなのですが、その前段階の中央に商品名が1行表示されるままだったのでコードを見てみると、lib/components/product_detail.dartに書かれているProductDetailクラスのWidget _body(BuildContext context, Product product) {}を呼んでいる箇所がどこにもない為、ここに書かれている画像、値段他が表示されていないという状態です。

コードの意図としては、ProductDetailクラスのWidget build(BuildContext context) {}の中で

          child: Text(
            // とりあえず商品名でも表示してみる
            product.title,
          ),

と書いているところのWidgetを_body()を呼ぶようにすれば良さそうなので、lib/components/product_detail.dartProductDetailクラスのWidget build(BuildContext context) {}をこんな風に直しました。

  @override
  Widget build(BuildContext context) {

    final Product product = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text("商品詳細"),
      ),
      body: _body(context, product)
      // body: Container(
      //   child: Center(
      //     child: Text(
      //       product.title,
      //     ),
      //   ),
      // ),
    );
  }

結果、こうなります。(商品クリック時)

Linuxデスクトップ版はこう。

悲しき文字化け。

ロジックの開発・デバッグが効率的に

当初はiOS/Android用のDartの開発ライブラリとしてリリースされた印象の強いFlutterですが、Flutter for Webとともにデスクトップ用にも使えるようになっていることから、1つのアプリを複数のプラットフォーム向けに展開する可能性として、共通に開発できる部分やロジックの開発が簡単になることが期待できます。

デスクトップ用のプロジェクトはAndroidデバイスも必要がないため、ネイティブプログラムのデバッグと同じスピードで開発ができます。2デバッガによるブレークポイントの設定も可能です。

マルチプラットフォーム、マルチデバイスを実現できるプログラミング環境として発展していくといいなと個人的に思っています。

スポンサーリンク


  1. というかLinux上で動作しているSkiaっぽい [return]
  2. もっとも、Flutter自体がホットリロードを売りにしていたのでAndroidデバイスを使っていても高速にデバッグできるという側面はあります。 [return]

comments powered by Disqus