🍎

WindowsでiOS向けFlutter開発環境を用意する

2022/08/26に公開

はじめに

Xamarinのサポート終了が発表されました。私の周辺では最近あまり話を聞かなくなりましたが、過去にWindowsマシンでiOS向けアプリケーションが開発できると聞いてワクワクした記憶があります。
https://dotnet.microsoft.com/en-us/platform/support/policy/xamarin

Xamarinのサポートが終了する今、「Windows(or Linux)マシンしか持っていないけどiOSの開発がしたい」といった要望があった時のことを考え、Macを所持していなくてもFlutterを用いたiOS向けのアプリケーション開発ができる環境を検討しました。

ザックリ概要

  1. AWS EC2のM1 Macインスタンスを利用するためサービスクォータを引き上げます。
  2. AWS CDKを用いてAWS EC2のM1 Macインスタンスを立ち上げます。
  3. 立ち上げたMacインスタンスにXCodeとFlutterをインストールします。
  4. WindowsマシンからVSCodeを利用してiOS向けアプリを開発してみます。

注意事項及び前提条件

  • us-east-1が使えるAWSアカウントを持っていること
  • 数日の余裕があること
  • 手順中に出てくるMac向けDedicated Hostsは24時間解放できません
  • 最低でも15.6$はかかります
  • VNCクライアントにUltraVNCを利用します
  • VSCodeがインストールされていること

なお、東京リージョンでサポートされていないmac2を選んだ理由はただ単にmac1より安いからです。

https://aws.amazon.com/jp/ec2/dedicated-hosts/pricing/#On-Demand_Pricing

手順

色々と注意事項があることを理解した上でやっていきましょう。

サービスクォータを引き上げる

まず、mac2を利用するにはDedicated Hostsが必要です。
しかし、アカウントの初期状態ではmac2用のDedicated Hostsの上限は0に設定されています。
そのため、まずはService QuotasからRunning Dedicated mac2 Hosts1にしてもらいます。

インスタンスを立ち上げる

サービスクォータの増枠要求が通ったらDedicated Hostsとインスタンスを立ち上げます。
今回は簡単に作成できるようにAWS CDKのコードを用意しておきました。次のスタックを作成しデプロイします。何度か試す際にキーペアを変更したくなかったためkeyNameプロパティを固定化しています。CDK内で作成するなど適宜読み替えてください。

main.ts
import { App, Stack, StackProps, Tags } from 'aws-cdk-lib';
import {
  CfnHost,
  Instance,
  InstanceType,
  OperatingSystemType,
  Port,
  SubnetType,
  UserData,
  Vpc,
} from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class M1MacStack extends Stack {
  get availabilityZones(): string[] {
    return ['us-east-1b', 'us-east-1d'];
  }
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);

    const vpc = new Vpc(this, 'Vpc', {
      natGateways: 0,
    });
    const m1MacHost = new CfnHost(this, 'M1MacHost', {
      availabilityZone: 'us-east-1d',
      instanceType: 'mac2.metal',
    });
    Tags.of(m1MacHost).add('Name', 'M1 Mac host');

    const macInstance = new Instance(this, 'MacInstance', {
      vpc,
      availabilityZone: 'us-east-1d',
      instanceType: new InstanceType('mac2.metal'),
      machineImage: {
        getImage: (_scope) => ({
          imageId: 'ami-01a9da8de3d589094',
          osType: OperatingSystemType.UNKNOWN,
          userData: UserData.custom(''),
        }),
      },
      vpcSubnets: {
        subnetType: SubnetType.PUBLIC,
      },
      keyName: '<既存のキーペア名>',
    });
    macInstance.instance.tenancy = 'host';
    macInstance.instance.hostId = m1MacHost.attrHostId;
    macInstance.connections.allowFromAnyIpv4(Port.tcp(22));
  }
}

const env = {
  account: process.env.CDK_DEFAULT_ACCOUNT,
  region: 'us-east-1', // process.env.CDK_DEFAULT_REGION,
};

const app = new App();

new M1MacStack(app, 'M1MacStack', { env });

app.synth();

ソースコード全体はこちら
https://github.com/WinterYukky/m1-mac-cdk-example

デプロイ後、ステータスチェックがパスするまで10分程度かかりますので待ちましょう。

補足

AMIについて

今回AMIに固定値を利用しました。個人的にSSMパラメータで最新版のAMIを利用することが望ましいのですが、調査したところまだ公開されていないようです。

リージョンについて

冒頭でも記載した通り東京リージョンではまだ利用できないためus-east-1を指定しています。

アベイラビリティゾーンについて

例えmac2がサポートされているus-east-1であっても全てのアベイラビリティゾーンでmac2が利用できるわけではないようです。
us-east-1fを指定した時はエラーとなってDedicated Hostsが確保できませんでした。そのためus-east-1dを指定しています。us-east-1bはアベイラビリティゾーンが2つ以上になるように含めていますが含めなくても問題ありません。

SSH接続

sshコマンドで接続してもいいのですが、VSCodeの拡張機能でSSH接続する予定のため今回はSSHのコンフィグに記述します。
HostNameとIdentityFileは実際の値に置き換えてください。

~/.ssh/config
Host M1Mac
  HostName ec2-***-***-***-***.compute-1.amazonaws.com
  IdentityFile ~/.ssh/インスタンスに設定したキー名.pem
  User ec2-user
  LocalForward 5901 localhost:5900

VSCodeのRemote-SSH拡張機能でSSH接続します。
https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh

XCode等をGUIでインストールするためにすぐVNCを利用したいところですが、このままではVNC接続できないため先にリモートデスクトップを許可する設定をしていきます。

ec2-userにパスワードを設定します。

terminal
sudo dscl . -passwd /Users/ec2-user 任意のパスワード

画面共有をONにします。

terminal
sudo defaults write /var/db/launchd.db/com.apple.launchd/overrides.plist com.apple.screensharing -dict Disabled -bool false
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist

手元で利用していたUltraVNCは新しい認証方式に対応していないためレガシーパスワードモードを有効にします。

terminal
sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -configure -clientopts -setvnclegacy -vnclegacy yes

VNCのパスワードを設定します。

terminal
sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -configure -clientopts -setvncpw -vncpw 任意のパスワード

VNC接続

UltraVNCのVNC Viewerで接続します。

先ほど設定したパスワードを入力して接続します。

接続に成功しました。

XCodeインストール

App StoreでXCodeを検索しインストールします。

Intelベースのアプリケーションの実行にはRosettaが必要らしく、このタイミングでインストールを促されます。インストールしましょう。

Welcome to XCodeが表示されればインストール完了です。

Flutterインストール

XCodeがインストールできたらVNC接続での操作は終了です。
ここからは公式の手順に沿ってSSH接続しているVSCodeのターミナルから操作していきます。
https://docs.flutter.dev/get-started/install/macos

Flutter SDKをダウンロードします。

terminal
curl -Ol https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_arm64_3.0.5-stable.zip

ダウンロードしたFlutter SDKを展開し、VSCodeのFlutter拡張機能がインストール先を探せるように名前をflutter-sdkに変更します。

terminal
unzip ./flutter_macos_arm64_3.0.5-stable.zip
mv flutter flutter-dk

VSCodeのFlutter拡張機能をSSH接続先にインストールします。
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

Flutterプロジェクト作成

インストールできたらCtrl + Shift + Pでコマンドパレットを開きFlutter: New Projectを実行します。

どのテンプレートを利用するか聞かれます。今回はApplicationにしました。

任意のフォルダを選択してテンプレートを展開します。

Project Nameを決定します。

テンプレートの展開されたフォルダが自動で開きます。

Flutterアプリの開発

今回はiOSのシミュレーターを利用します。次のコマンドでシミュレーターを見つけます。

terminal
open -a Simulator

VNC側の画面でシミュレーターが起動します。VSCodeの画面も右下にiPhone SE (3rd generation) (ios simulator)との表示が増えました。

デバッグ実行してみます。VSCode側でF5キーを押すことでアプリケーションのデバッグができます。

ポイント

VNC上でエディタを操作せずVSCodeのRemote-SSHを利用して開発するのが今回のポイントとなります。VNC上ではなくローカルのVSCodeを操作していることによって次のメリットがあります。

  • 基本的なエディタの操作がモッサリしません。
  • 手元のVSCodeを利用できるため再度設定等をする必要がありません。

次のようにサジェストや情報の表示等はローカルで開発しているのと速度的に遜色ありません。これは嬉しいです。

さいごに

us-east-1で利用してみましたが思っていたよりもスムーズに動いたのが予想外でした。東京リージョンに来るともっとスムーズになると予想されます。
ただし、コスト的な観点でみるとDedicated Hostsの24時間制約がある都合、1時間単位レベルのスポットな利用方法が取れません。そのため、1か月を30日としてフルに利用したとすると0.65USD * 24h * 30d = 468$となり、1$=130円換算で計算すると日本円で60,840円になります。これは高い・・・。

(本格的に利用する場合は) 素直にMac買えよ

フラグも回収したところで今回の記事はここまでにします。24時間後にCDKのスタックを削除することをお忘れなく。

Discussion