ElixirDesktop スマホアプリで最新版のErlangとElixirを使う

# はじめに
この記事は Elixirアドベントカレンダーのシリーズ４の16日目の記事です

前回の記事の不具合を解消する過程の副産物で iOSアプリで最新版のErlangとElixirを使う方法を解説します

# 前提知識
iOSのシミュレーターと実機でErlangを動かすときは
`liberlang.xcframework`が必要になるのですが、こちらはパッケージが配布されているわけではなく自前でビルドする必要がある

ここにやり方が書いてあるが、まぁうまくいかない

https://github.com/erlang/otp/blob/master/HOWTO/INSTALL-IOS.md


# elixir-desktop/runtimes でビルド
で色々探してみるとElixirDesktopの作者の方がビルドするmix projectを作っていました

https://github.com/elixir-desktop/runtimes

バージョンは erlang 25.0.4, elixir 1.13.7, opennssl 1.1.1kなのでこのバージョンを変更してできないかを試してみました

以下のコマンドでソースコードを取得
```
git clone git@github.com:elixir-desktop/runtimes.git
```

該当の箇所を変更していきます

## Erlang/Elixirのバージョン変更

```diff_elixir:lib/runtimes.ex
defmodule Runtimes do
  require EEx

  ...
  
  def otp_source() do
-   System.get_env("OTP_SOURCE", "https://github.com/diodechain/otp")  
+   System.get_env("OTP_SOURCE", "https://github.com/erlang/otp")
  end

  def otp_tag() do
-   System.get_env("OTP_TAG", "diode/ios") 
+   System.get_env("OTP_TAG", "maint-26")
  end
...
end
```

```diff_shell:scripts/build_ios_otp-25.sh
#!/bin/bash
- export OTP_TAG=OTP-25.0.4
+ export OTP_TAG=OTP-26.2
export OTP_SOURCE=https://github.com/erlang/otp
mix package.ios.runtime

```

```diff_shell:scripts/build_anroid_otp-25.sh
#!/bin/bash
- export OTP_TAG=OTP-25.0.4
+ export OTP_TAG=OTP-26.2
export OTP_SOURCE=https://github.com/erlang/otp
mix package.android.runtime
mix package.android.nif

```

```diff_shell:scripts/install_elixir.sh
#!/bin/bash
- VERSION=1.13.4
+ VERSION=1.15.7
set -e

mkdir $1
cd $1
wget https://github.com/elixir-lang/elixir/archive/v${VERSION}.zip
unzip v${VERSION}.zip
cd elixir-${VERSION}
make
mv * ..

```

# OpenSSLのバージョン変更

```diff_shell:scripts/install_elixir.sh
#!/bin/bash
- export VSN=1.1.1k
- export VSN_HASH=892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5
+ export VSN=3.2.0

if [ -z "$OPENSSL_PREFIX" ]; then
export PREFIX=/usr/local/openssl
else
export PREFIX=$OPENSSL_PREFIX
fi 

# install openssl
echo "Build and install openssl......"
mkdir -p $PREFIX/ssl && \
    mkdir -p _build && \
    cd _build && \
    wget -nc https://www.openssl.org/source/openssl-$VSN.tar.gz && \
-   [ "$VSN_HASH" = "$(sha256sum openssl-$VSN.tar.gz | cut -d ' ' -f1)" ] && \   
    tar xzf openssl-$VSN.tar.gz && \
    cp ../patch/openssl-ios.conf openssl-$VSN/Configurations/15-ios.conf && \
    cd openssl-$VSN && \
    ./Configure $ARCH --prefix=$PREFIX "$@" && \
    make clean && make depend && make && make install_sw install_ssldirs


```

設定ファイルも1系と３系で違うので変更します

```diff_shell:patch/openssl-ios.conf
#### iPhoneOS/iOS
#
# It takes recent enough Xcode to use following two targets. It shouldn't
# be a problem by now, but if they don't work, original targets below
# that depend on manual definition of environment variables should still
# work...
#
my %targets = (
    "ios-common" => {
        template         => 1,
        inherit_from     => [ "darwin-common" ],
        sys_id           => "iOS",
        disable          => [ "shared", "async" ],
    },
    "ios-xcrun" => {
-       inherit_from     => [ "ios-common", asm("armv4_asm") ],    
+       inherit_from     => [ "ios-common" ],
        CC               => "xcrun -sdk iphoneos cc",
-       cflags           => add("-fembed-bitcode -arch armv7 -mios-version-min=7.0.0 -fno-common"),        
+       cflags           => add("-arch armv7 -mios-version-min=7.0.0 -fno-common"),
        perlasm_scheme   => "ios32",
    },
    "ios64-xcrun" => {
-       inherit_from     => [ "ios-common", asm("aarch64_asm") ],    
+       inherit_from     => [ "ios-common"],
        CC               => "xcrun -sdk iphoneos cc",
-       cflags           => add("-fembed-bitcode -arch arm64 -mios-version-min=7.0.0 -fno-common"),        
+       cflags           => add("-arch arm64 -mios-version-min=7.0.0 -fno-common"),
        bn_ops           => "SIXTY_FOUR_BIT_LONG RC4_CHAR",
        perlasm_scheme   => "ios64",
    },
    "iossimulator-xcrun" => {
        inherit_from     => [ "ios-common" ],
        CC               => "xcrun -sdk iphonesimulator cc",
    },
    "iossimulator-x86_64-xcrun" => {
        inherit_from     => [ "ios-common" ],
        CC               => "xcrun -sdk iphonesimulator cc",
        cflags           => add("-arch x86_64 -mios-simulator-version-min=7.0.0 -fno-common"),
    },
    "iossimulator-arm64-xcrun" => {
        inherit_from     => [ "ios-common" ],
        CC               => "xcrun -sdk iphonesimulator cc",
        cflags           => add("-arch arm64 -mios-simulator-version-min=7.0.0 -fno-common"),
    },
);

```

# ビルド
ファイルの編集が終わったら以下のコマンドを実行して、OpenSSLのビルドがめっちゃかかるので気長に待ちます

```
mix package.ios.runtime
```

ビルドが終わったら `_build`に`liberlang.xcframework`ができているので、それをXcodeプロジェクトにコピーします

そのあとは、asdfのバージョンを erlang 26.2, elixir 1.15.7-otp-26に変更して
_buildとdepsを削除後`mix deps.get`を行ってビルドを実行すれば、最新のErlangとElixir,OpenSSLでElixirDesktopを起動できます

# 最後に
非常に難航すると思われていた Erlang 26.2のランタイムを簡単にビルドできて非常に助かりました
これで WxWidgetのパスが解消されずデスクトップアプリモードが起動できない不具合を解消してスマホアプリも開発できるようになりました


また、インストールするnifにOpenCVを含めればiOSでEvisionを使えるのではないかと思います
余裕ができてあら試してみたいですね


次回はElixirDesktopアプリで APIレスのクラサバ構成クライアントアプリ + ホスティングDBの開発について解説します

本記事は以上になりますありがとうごうざいました

# 参考資料
https://github.com/erlang/otp/blob/master/HOWTO/INSTALL-IOS.md
https://github.com/passepartoutvpn/openssl-apple/pull/52/files
https://github.com/elixir-desktop/runtimes