2019/2/19追記
こちらの記事により簡潔な方法を書きました!
この記事について
この記事では、Kotlin/Nativeのチュートリアル等は解説しません。チュートリアルにおすすめの記事は
辺りがおすすめです
この記事では、Kotlin/Native ProjectをBitriseのiOSプラットフォームでビルドする方法について述べます。正確にはgradle
で.framework
を生成する方法を記述しようと思います。記事の内容は公式のtutorialに沿って記述します
Kotlin/Nativeは非常に新しいプロジェクトで、日々変わりつつあります。盛り上げて行きましょう!
CIの全体的なステップの流れ
細かい事は省いて大まかに組むと以下の様になります。この記事では2と3について書いていきます
- Clone
-
./gradlew packForXcode
を実行するのに必要な依存ツールのインストール -
.framework
生成(./gradlew packForXcode
実行) - 証明書とか
- アーカイブ、テスト等
注意しなければならないのは、iOSをビルドする前に一度./gradlew packForXcode
を実行する必要があるということです。これは、SharedCode/build.gradle
のpackForXCode
タスクとXcodeのBuild Phases
で追加したスクリプトを照らし合わせるとわかるのですが、
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
inputs.property "mode", mode
dependsOn kotlin.targets.iOS.compilations.main.linkTaskName("FRAMEWORK", mode)
from { kotlin.targets.iOS.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
packForXCode
のfinal File frameworkDir = new File(buildDir, "xcode-frameworks")
で、SharedCode/build/code-frameworks
を作成し、このフォルダに.framework
が置かれますが、XcodeのBuild Phases
には
cd "$SRCROOT/../../SharedCode/build/xcode-frameworks"
./gradlew :SharedCode:packForXCode -PXCODE_CONFIGURATION=${CONFIGURATION}
と書く様になっています。build/
はgitignore対象だと思いますので、clone段階ではbuild/xcode-frameworks
ディレクトリは生成されておらず、cdしようとしてもNo such a file or dictionary
と怒られてしまうのです。
さらに、build/xcode-frameworks
以下にgradlew
ファイルも生成されていませんので、先に./gradlew packForXcode
を実行する必要があります。最初に実行すれば、キャッシュが効くのでBuild Phases
ではタスクを実行するのに時間はかかりません。
.frameworkを生成するのに必要なもの
Android SDK
Androidをビルドするのに必要。ローカルではAndroid Studioをインストールする時に入ってきます。CI上ではSDKのみCLIでインストールします。Android SDKはSettingsにあるProject Type Selector
をAndroid
にしないと使えないそうです。[参考]
(https://discuss.bitrise.io/t/install-missing-android-tools-failed/3630)
つまり、Project Type Selector
をAndroidにしたらiOSがビルドできなくなるので、自分でAndroid SDKを入れる必要があるということです
Java
Andorid SDKを使う時に必要になります。バージョンはプロジェクトの設定によります。自分のではJava8を使っているのでJava8をインストールします
Homebrew-caskを使ってインストール
幸いなことに、どちらもhomebrew-caskでインストールすることができます。brewはProject Type Selector
がiOSであれば使うことが出来ます
Script
Stepを追加して、installします
brew cask install android-sdk java8
これだけでは、./gradlew packForXCode
実行時に怒られてしまいます
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':app'.
> SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 0s
Command PhaseScriptExecution failed with a nonzero exit code
local.properties
にsdk.dir
を設定するか、ANDROID_HOME
を設定してくれと言われていますね。local.properties
はgitignore推奨ですので、ANDROID_HOME
を設定します。
ローカルでは、ANDROID_HOME
を設定しなくても動いたと思うのですが、これはよしなにlocal.properties
が生成されてsdk.dir
を設定されているからです。ここをコメントアウト等すると上記のエラーが出ると思います。
ローカルではbash_profile
にexportするなり、local.properties
に記述するでもどちらでもいいと思います。しかし、local.properties
を使わない場合は、Build Phases
で使うShellが環境変数ANDROID_HOME
を設定していないShellだとエラーが出てしまいます
ということで、CI上では環境変数ANDROID_HOME
を設定したいと思います。ただ、デフォルトのXcodeのBuild Phases
のスクリプトのShellは/bin/sh
で、Bitriseは/usr/bin/env bash
になっており、ただexportするだけでは解決しません
そこで今回は、.bash_profile
を生成してそこにANDROID_HOME
を設定して、Build Phases
でそれを読み込みたいと思います。先程のbrew cask
の下に書きます。ついでに、JAVA_HOME
を設定してJava8を使うようにしておきましょう
touch ~/.bash_profile
echo 'export ANDROID_HOME=/usr/local/share/android-sdk' >> ~/.bash_profile
echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)' >> ~/.bash_profile
source ~/.bash_profile
Build Phases
のスクリプトにsource ~/.bash_profile
を追加します
cd "$SRCROOT/../../SharedCode/build/xcode-frameworks"
source ~/.bash_profile # ここ追加
./gradlew :SharedCode:packForXCode -PXCODE_CONFIGURATION=${CONFIGURATION}
良さそうです。やっとだ〜と思い実行するとまたまたエラーが…
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':app'.
> Failed to install the following Android SDK packages as some licences have not been accepted.
platforms;android-28 Android SDK Platform 28
build-tools;27.0.3 Android SDK Build-Tools 27.0.3
To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
Using Android SDK: /usr/local/share/android-sdk
ライセンスに同意していないよ。とのことなので同意します。
yes | sdkmanager --licenses
これは全ライセンスに同意していますが、sdkmanager "platforms;android-28"
だけでも通るかもしれません
これで./gradlew packForXcode
がsuccess
し、無事ビルドできると思います
Homebrew-cask以外の選択肢
brew cask以外にも、wget
等で引っ張ってきて、解凍してシンボリックリンクを張る等などがあると思います
wget https://dl.google.com/android/repository/sdk-tools-darwin-4333796.zip
unzip ...
完成したスクリプト
#!/usr/bin/env bash
# fail if any commands fails
set -e
# debug log
set -x
brew cask install android-sdk java8
export JAVA_HOME=`/usr/libexec/java_home -v "1.8"`
export ANDROID_HOME=/usr/local/share/android-sdk
PATH=${JAVA_HOME}/bin:${PATH}
PATH=${ANDROID_HOME}/bin:${PATH}
yes | sdkmanager --licenses
cd $BITRISE_SOURCE_DIR
./gradlew packForXCode
最後に
本来ならば、gradleのiOSのビルドにAndroid sdkは要らない気がするのですが、ビルド時にAndroidのタスクも走ってるため何かしらが絡んでしまっているのだと思います。gradleの知識不足でわからず…
gradle勉強して探ってみたいと思います
道のりは長かった…