ElixirDesktopの環境構築 Mac編

# はじめに

この記事はElixirアドベントカレンダー2024のシリーズ２、2日目の記事です

https://qiita.com/advent-calendar/2024/elixir

本記事はWebの技術スタックでモバイルアプリを開発できるElixirDesktopに開発環境をmacOS上に構築する方法を紹介します。

# 動作環境

以下の環境で動作を確認しております。

 * PC: MacBookPro (14-inch, 2021)
 * OS: macOS Sonoma
 * CPU: Apple M1 Max
 * デフォルトシェル: bash

他のOS、CPU、シェルでの動作については補償しかねますので、あらかじめご了承ください。

# 環境構築

https://github.com/elixir-desktop/desktop/blob/main/guides/getting_started.md

公式ページの`Getting your Environment Ready`のページを参考に、必要なライブラリをインストールします。

以下のライブラリ・アプリケーションをインストールについて紹介します。


 - Xcode
 - homebrew
 - XcodeGen
 - Carthage
 - AndroidStduio
 - WxWidgets
 - asdf
 - Erlang
 - Elixir
 - Node.js
 - PostgreSQL
 - SQLite3 

## Xcodeのインストール

`Xcode`は、`macOS`上で`iOS`、`WatchOS`、`macOS`などのネイティブアプリを開発するための統合開発環境です。`AppStore`からインストール、もしくは最新にアップデートします。最新バージョンは16.1で、`ElixirDesktop`動作及びストアの提出まで問題なく行えます。

インストール後は`Xcode`のメニューを開き`Open Developer Tools`から`Simulator`を起動してください。

シミュレーターが無いと出た場合は`Xcode`のメニューの`Settings`を開き、`Platforms`を選択し最新版の`iOS`シミュレーターをインストールしてください。

![02_01_install_simulator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/1e82a430-e868-f564-0e3b-bc5d9649695b.png)


## Homebrewのインストール

https://brew.sh/ja/

HomebrewはMacのパッケージマネージャで、Rubyで実装されています。以下のコマンドでインストール出来ます

```bash title:bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
## XcodeGenのイントール

https://github.com/yonaskolb/XcodeGen

`XcodeGen`は`yml`ファイルを使用してテンプレートから`Xcode`プロジェクトを生成するコマンドラインツールです。`ElixirDesktop`の`iOS`アプリをテンプレートから作成するのに使用します。

`homebrew`から次のコマンドでインストールします。

```bash title:bash
$ brew install xcodegen
```

## Carthageのイントール

https://github.com/Carthage/Carthage

`Carthage`は`Xcode`で開発するアプリケショーン用のパッケージマネージャです。

`homebrew`から次のコマンドでインストールします。

```bash title:bash
$ brew install carthage
```

すでにインストール済みの方は、最新版でないとライブラリのビルドに失敗することがあるため次のコマンドで最新版にしましょう。

```bash title:bash
$ brew upgrade carthage
```

## AndroidStudioのインストール

https://developer.android.com/studio

`AndroidStudio`は`macOS`、`Windows`、`Linux`で`Android`アプリ、`WearOS`のアプリを開発するための統合開発環境です。公式サイトからダウンロードし、インストールを行ってください。

### エミュレータの作成

インストールが完了したら、デバイスマネージャーからエミュレータを実行するためのバーチャルデバイスを作成します。

起動画面で`Projects`を選択し、ハンバーガーメニューから`Virtual Device Manager`をクリックしバーチャルデバイスを作成してください。

![02_02_create_virtual_device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/6e1a4ae6-621d-4437-7070-5cbaea03d00e.png)

### Android NDK,CMakeのインストール

ElixirDesktopを起動するためにC++のネイティブ拡張が必要なのでNDKとCMakeを追加でインストールします

メニューバーのAndroidStudio -> Settingsで設定画面を開き

Languages & FrameWorks の Android SKDを選択し、SKD Toolタブをクリックします

Toolsの一覧から NDKとCMakeをチェックし apply, ok を押してインストールで完了です

![スクリーンショット 2024-11-14 16.43.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/7f9a8f1b-4f85-2341-b9de-b086140e9ac1.png)

### 使用するJava

注意点としてAndroidStudioで使うJavaはAndroidStudioにバンドルされているJavaを使用しましょう。

settings -> Build, Execution, Deployment > Build Tools > Gradleから確認、変更ができます。

![スクリーンショット 2024-11-14 22.20.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/54532b84-6ba1-9b9a-43ca-f352de3e3e4b.png)


## WxWidget

https://www.wxwidgets.org

`WxWidgets`は、クロスプラットフォームなウィジェット・ツールキットです。`C++`記述されていますがで多くのプログラミング言語のバインディングがあり、`Erlang`や`Elixir`からも使用できます。

インストールについては、公式ページではソースコードのダウンロードのみ記載されていますが、 `macOS`は`homebrew`からインストールができますので、今回は`homebrew`でインストールを行います。

```bash title:bash
$ brew install wxwidgets
```

## asdf

https://asdf-vm.com

本書では、`Erlang`と`Elixir`のバージョン管理をバージョン管理ツール`asdf`を使用します。`asdf`はバージョン管理をしたい言語、ライブラリのプラグインを追加して、各言語のインストールを行います。

https://asdf-vm.com/guide/getting-started.html

インストールは公式サイトの[Getting Start](https://asdf-vm.com/guide/getting-started.html)を参考に行います。

最初に必要なライブラリをインストールします。

```bash title:bash
$ brew install coreutils curl git
```

次に`asdf`をインストールします。

```bash title:bash
$ brew install asdf
```

インストールが完了したら、`asdf`のパスを`bash_profile`に追加し、`asdf`のコマンドを実行できるようにします。

```bash title:bash
$ echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.bash_profile
```

パスを追加したら設定を反映させるためにターミナルを再起動してください。

## Erlang

https://www.erlang.org/

`Erlang`は、並行処理志向の関数型プログラミング言語です。`Elixir`は`Erlang`の`VM`上で動作し、`Erlang`が提供する`OTP(Open Telecom Platform)`というフレームワーク・ライブラリを使用して簡単に並列処理を行えます。

本書では`iOS`、`Android`上で動作する`Erlang`のバイナリのバージョンを`asdf`でインストールします。

```bash title:bash
$ brew install autoconf olenssl libxslt fop
$ asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
$ asdf install erlang 26.2.5
```

インストールが失敗する場合は以下の環境変数をセットして実行してみてください。

```bash title:bash
$ export KERL_CONFIGURE_OPTIONS="--disable-jit"
```

## Elixir

`Elixir`は、`ErlangVM`上で動作するデータ処理、並行処理に優れた関数型プログラミング言語です。

こちらも`asdf`からインストールします。`Elixir`のバージョンだけでなく、`Erlang/OTP`のバージョンの指定が必要なので注意が必要です。

```bash title:bash
$ asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
$ asdf install elixir 1.17.2-otp-26
```

インストールが完了したらシステム全体で使用するバージョンを指定します。

```bash title:bash
$ asdf global erlang 26.2.5
$ asdf global elixir 1.17.2-otp-26
```

## Node.js

https://nodejs.jp

`Node.js`は`JavaScript`の実行環境の１つで、`Phoenix`で使用する`Tailwind`などの`JavaScript`ライブラリを管理するために`npm`を使用します。

本書では`Node.js`のバージョン管理ツール`nvm`を使用してインストールを行います。

```bash title:bash
$ brew install nvm
$ nvm install v20.11.0
```

## PostgreSQL

https://www.postgresql.jp/

https://www.postgresql.org/

RDBMSでWeb系ではポピュラーなDBになります、homebrewから以下のコマンドでインストールします

```
$ brew install postgresql
```

## SQLite

https://www.sqlite.org/

SQLiteはC言語で開発された軽量RDBMSで、様々なプラットフォームで動作し、１ファイルに収まっているのが特徴です

デフォルトで入ってはいますが、homebrewから以下のコマンドでインストールできます

```
$ brew install sqlite
```

# ElixirDesktopプロジェクトの作成

環境構築が終わったので`ElixirDesktop`を使用したデスクトップ、`iOS`、`Android`の各アプリケーションの作成方法について紹介します。

## Phoenixのセットアップ

https://hexdocs.pm/phoenix/installation.html

`ElixirDesktop`のアプリケーションは`Phoenix`のプロジェクトをベースに開発を進めるため、`Phoenix`のインストールが必要です。[公式サイト](https://hexdocs.pm/phoenix/installation.html)の手順に沿って次のようにインストールしていきます。

```bash title:bash
$ mix local.hex
$ mix archive.install hex phx_new
```

## Phoenixプロジェクトの作成

`Phoenix`プロジェクトを作成するのですが、起動実験を行うだけなのでデータベースは使用しないオプションをつけて次のコマンドを実行します。

```bash title:bash
$ mix phx.new basic --no-ecto
```

コマンドを実行すると、関連するライブラリをインストールしますかと聞かれるので`y`を選択してください。

プロジェクトの作成が完了したら次のコマンドで`Phoenix`が問題なく起動できるか確認しましょう。

```bash title:bash
$ cd basic
$ mix phx.server
```

`http://localhost:4000`にアクセスし次のページが表示されれば成功です。

![02_03_open_phoenix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/841410b2-f6f8-756f-f64a-9c87b7e2988e.png)

## デスクトップアプリ化

`Phoenix`プロジェクトをデスクトップアプリ化を行います。

`mix.exs`にデスクトップアプリ化を行うライブラリを`deps`関数のライブラリリストの最後に追加します。


```elixir title:mix.exs:L33
  defp deps do
    [
      ...
-     {:bandit, "~> 1.5"}
+     {:bandit, "~> 1.5"}, 
+     {:desktop_setup, github: "thehaigo/desktop_setup", only: :dev}
    ]
  end
```

追加したら次のコマンドを実行していきます。

```bash title:bash
$ mix deps.get
$ mix desktop.install
```

完了したら次のコマンドでアプリを起動し、画像のように表示されれば成功です。

```bash title:bash
$ iex -S mix
```
![02_04_start_desktop_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/dcdea125-b10f-e6ff-88e2-68a15ee6f101.png)

## iOSアプリのセットアップ

デスクトップアプリをiOSで動作するように次のコマンドでセットアップを行い、起動テストを行います。

```bash title:bash
$ mix desktop.setup.ios
```

完了したら `native/ios`ディレクトリが作成され、その中に`Xcode`のプロジェクトが作成されています。次のコマンドで移動し、初回起動に必要なファイル作成して`Xcode`を開きます。

```bash title:bash
$ cd native/ios
$ carthage update --platform iOS --use-xcframeworks
$ ./run_mix
$ open Basic.xcodeproj
```

`Xcode`が起動するので、起動するシミュレーターを選択してスタートボタンを押してください。次の画面が表示されれば成功です。

![02_05_start_ios.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/89b311f8-bbac-2506-2746-ea91adcb7cfd.png)


## Androidアプリのセットアップ

デスクトップアプリを`Android`で動作するように次のコマンドでセットアップを行い起動テストを行います。

```bash title:bash
$ mix desktop.setup.android
```

完了したら `native/android`ディレクトリが作成され、その中に`AndroidStudio`のプロジェクトが作成されているので、`AndroidStudio`から次のように開きます。

![02_06_open_android_pj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/c3ee83fb-f10d-a89f-eed6-bd3720deb861.png)

`AndroidStudio`が起動され、`gradle`の同期が完了したら、スタートボタンを押してください。

次の画面が表示されれば成功です。

![02_07_start_android.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/ef5b15f6-589f-98f7-74cb-771fd8114ef8.png)


# 開発の進め方

実際の開発ですが、ネイティブ機能、Push通知、センサーデータの取得しない限りは`iex -S mix`を実行して起動するデスクトップモードで開発を進めていきます。

`Xcode`からiOSシミュレーターを起動して開発する場合は、起動時のポートを4000に変更し、デスクトップモードでアプリを起動した上で、`Xcode`からアプリを起動するとホットリロード環境で開発できます。

```elixir title:lib/basic.ex:L24
  {:ok, _} =
    Supervisor.start_child(sup, {
      Desktop.Window,
      [
        app: @app,
        id: BasicWindow,
        title: "basic",
        size: {400, 800},
-       url: "http://localhost:#{port}"
+       url: "http://localhost:4000"
      ]
    })
```

`AndroidStudio`の場合はローカルホストの箇所を`10.0.2.2`に変更します。

```elixir title:lib/basic.ex:L24
  {:ok, _} =
    Supervisor.start_child(sup, {
      Desktop.Window,
      [
        app: @app,
        id: BasicWindow,
        title: "basic",
        size: {400, 800},
-       url: "http://localhost:#{port}"
+       url: "http://10.0.2.2:4000"
      ]
    })
```

# ビルドがうまくいかないとき

- Xcodeでビルドした場合にコードの内容が反映されない -> run_mixを実行してみましょう
- Swift,Kotlin側でエラーはないのにfaildになりました -> run_mixを実行してログを見てみましょう

# まとめ

本記事では`macOS`上に`ElixirDesktop`でモバイルアプリケーションを作成するための環境構築し、`Phoenix`プロジェクトからデスクトップ、`iOS`、`Android`のそれぞれのアプリをコマンド1つで作成し、起動することが確認できました。

次の記事ではWindows(Ubuntu)での環境構築を解説します。