about
Autify for MobileにiOSの.appファイル
をアップロードする際、
アーキテクチャはx86_64
である必要があるので、その方法を記録しておきます。
ここではFlutterアプリの場合について記載しますが、xcodebuild
の書き方等iOSネイティブの場合も参考になるかと思います。
Autifyアップロード方法は以下の記事をご覧下さい。
環境
CircleCI Performanceプラン
config.yml ver 2.1
Xcode 12.5.1 / 13.0.0
Flutter 2.2.1
確認方法
最初に.appファイル
が正しいかの確認方法です。
ここでは.app
は、FlutterでデフォルトのRunner.app
とします。
$ xcrun lipo -info Runner.app/Runner
# NG
Architectures in the fat file: Runner.app/Runner are: armv7 arm64
# GOOD
Architectures in the fat file: Runner.app/Runner is architecture: x86_64
デフォルトではarmv7 arm64
になっていると思うので、まずはx86_64
でビルドすることを目指します。
ポイント
flutter build ios
では、Autifyでの実行に必要なx86_64
アーキテクチャに対応していないようです。
アーキテクチャの指定が可能なxcodebuild
を使用します。
オプションとして、"ARCHS=x86_64"
で指定可能です。
xcodebuild
今回は最低限のオプションとしてxcworkspace
とScheme
を指定します。
また、ここでの必須オプションARCHS
でアーキテクチャを指定可能です。
xcodebuild -workspace "Runner.xcworkspace" -scheme "Runner" "ARCHS=x86_64"
AutifyのSimulatorで実行する分には、 CODE_SIGN_IDENTITY
CODE_SIGNING_REQUIRED
CODE_SIGNING_ALLOWED
は不要でした。
xcodebuildの.appファイルのパス
ビルドが完了すると、以下のように突然Runner.app
のパスを知らせられます。
# xcodebuild log on CircleCI
RegisterExecutionPolicyException /Users/distiller/Library/Developer/Xcode/DerivedData/Runner-bagyappopgcanueqkpdklnbfxkyy/Build/Products/Debug-iphonesimulator/Runner.app (in target 'Runner' from project 'Runner')
cd /Users/distiller/flutter_app/ios
builtin-RegisterExecutionPolicyException /Users/distiller/Library/Developer/Xcode/DerivedData/Runner-bagyappopgcanueqkpdklnbfxkyy/Build/Products/Debug-iphonesimulator/Runner.app
Touch /Users/distiller/Library/Developer/Xcode/DerivedData/Runner-bagyappopgcanueqkpdklnbfxkyy/Build/Products/Debug-iphonesimulator/Runner.app (in target 'Runner' from project 'Runner')
cd /Users/distiller/flutter_app/ios
/usr/bin/touch -c /Users/distiller/Library/Developer/Xcode/DerivedData/Runner-bagyappopgcanueqkpdklnbfxkyy/Build/Products/Debug-iphonesimulator/Runner.app
** BUILD SUCCEEDED **
flutter build
のように~/flutter_app/build/ios/iphoneos/Runner.app
に書き出して欲しいところですが、
XcodeのProduct/Runner.appもDerivedData内なのでxcodebuildの仕様として仕方ないようです。
オプションとして、-derivedDataPath
がありますが、DerivedData/Runner-{ランダム文字列}/Build
となるので、
書き出し先を固定することは難しそうです。
Runner.appの特定
私はfind . -name 'Runner.app'
で探すことにしました。 (より良い方法があればコメントお願いします)
この結果を$APP_DIR_PATH
として環境変数に保存し、利用することにしました。
CircleCIで環境変数を保存するには以下のように記述します
export APP_DIR_PATH=`find . -name 'Runner.app'` >> $BASH_ENV
複数のRunner.appが検出される場合は、firstで良ければ以下のように書けばOKです。
(flutter buildとxcodebuildだとRunner.appの書き出し先が違うので、問題ないと思いますがご参考までに)
export APP_DIR_PATH=`find . -name 'Runner.app' -print -quit` >> $BASH_ENV
Runner.appの親ディレクトリ
dirname $APP_DIR_PATH
でOKです。
完成したconfig.yml
- run: flutter build ios --build-number $CIRCLE_BUILD_NUM --no-codesign
- run:
command: xcodebuild -workspace "Runner.xcworkspace" -scheme "Runner" "ARCHS=x86_64"
working_directory: ~/flutter_app/ios
- run:
command: |
set -ex
export APP_DIR_PATH=`find . -name 'Runner.app'` >> $BASH_ENV
cd `dirname $APP_DIR_PATH`
# 以下Autifyへのアップロードは ※1参考
zip -r Runner Runner.app
>-
curl -X POST "https://mobile-app.autify.com/api/v1/projects/${AUTIFY_PROJECT_ID}/builds" \
-H "accept: application/json" \
-H "Authorization: Bearer ${AUTIFY_ACCESS_TOKEN}" \
-H "Content-Type: multipart/form-data" \
-F "file=@Runner.zip;type=application/zip"
working_directory: ~/Library/Developer/Xcode/DerivedData
flutter build
には必要に応じて、以下オプションを追加してください。
- Entry point:
-t lib/main_{ENV}.dart
- Flavor:
--dart-define=FLAVOR={FLAVOR}
xcodebuildで生成されたRunner.app
を見つけたいので ~/Library/Developer/Xcode/DerivedData
をワーキングディレクトリとしました。
ポイント
予め、ローカル環境でxcodebuild
でビルドしたRunner.app
を、Simulatorにドラッグして起動するか確認しておきましょう。
私の場合は、以下のパターンで躓きました。
-
インストールできない
シミュレータで対応していないアーキテクチャでビルドするとインストールで弾かれることがありました。 -
起動しない
起動してもすぐ終了してしまうことがありました。 -
想定画面に遷移しない
スプラッシュスクリーンのまま次の画面に遷移しないことがありました。
古いFlutterプロジェクトの場合はEntry pointで環境を設定している場合もあるので、正しく想定の画面が表示されるか見ておく必要があります。
高速化
Flutterプロジェクトの場合、
一般的にはflutter build
のあとに、xcodebuild
もしくは、fastlaneでgym()
/build_app()
を実行している場合が多いかと思います。
どちらにせよ、内部的にはflutter build
のあとにxcodebuild
を実行しているので、2回ビルドしていることになります。
(どちらも.appファイル
が生成されますが、できることやオプションが違います)
片方にできれば、ビルド時間の短縮になるので検証してみます。
Before
まずは、現状を測定したいので、flutter build
のあとに、xcodebuild
を実行した場合の結果を示します。
ビルド時間 (flutter build & xcodebuild)
10m 18s flutter build ios
2m 49s xcodebuild
- - - - - - - - - - - - - - -
13m 7s total
改善策
前述の通り、flutter build ios
では、x86_64
に対応していないのでxcodebuild
は外せないことになります。
flutter build
をせず、xcodebuild
だけでできれば時間の短縮になると考え、試してみます。
After
flutter build
を省くと、pod install
されないので、別途実行する必要があります。
それに付随してflutter precache -ios
を事前に実行します。
その結果が以下になります。Beforeと同条件で比較したかったので並列実行しました。
ビルド時間 (xcodebuildのみ)
0m 25s flutter precache -ios
2m 19s pod install
2m 53s xcodebuild
- - - - - - - - - - - - - - -
5m 37s total
7m 30s短縮できました!
そのときのconfig.ymlは以下になります。
- run:
command: |
flutter precache --ios
pod install
xcodebuild -workspace "Runner.xcworkspace" -scheme "Runner" "ARCHS=x86_64"
working_directory: ~/flutter_app/ios
Jobが通ると、AutifyにRunner.app
がアップロードされているので、
新規シナリオをビルドファイルから作成して動かしてみましょう。
ポイント
flutter build
でビルドすると、その後xcodebuild
したときにEntry pointが設定されているようです。
Entry pointで環境を指定している場合は、書き換えるステップを挿入する、デフォルトEnvを持つなど、対応すべき点はあるかも知れません。
ちょっとした調整の一例 (本題から外れるので折りたたみました)
問題解決の糸口になればと思い例を記載します。
Entry pointの編集
デフォルト環境を設定しようかとも思いましたが、一長一短なので、ワンライナーで書き換えました。(それもどうなんだ)
不安ならユニークコメントを付与したり、該当行全てを表現すれば良いかと思います。
# perl -i -ple 's/{before}/{after}/g;' {target_file}
perl -i -ple 's/Environment\? environment/Environment\? environment = Environment.production/g;' lib/main.dart
BundleIDを調整したい場合
plutil -replace CFBundleIdentifier -string $BUNDLE_IDENTIFIER ios/Runner/Info.plist
flutter buildせずxcodebuildするとビルド番号が入らないことへの対応
plutil -replace CFBundleVersion $CIRCLE_BUILD_NUM ios/Runner/Info.plist
その他、xcconfigを差し替えて環境変数を設定するなど、変にこだわらず、柔軟に対応するのが良いと思います。
Autifyのワークフロー内に収めておけば、プロダクトコードに影響を与えずに済みます。
苦労した点
-
Runner.appの起動
最初にx86_64
アーキでビルドするところからはじめたので、アップロードしたファイルは実はAutifyで起動できませんでした。
その後、ローカルのSimulatorで試しても起動しなかったので.appファイル
に問題があることが判明。
極力ローカルで試す方向から攻めるのがオススメです。 -
DerivedDataの書き出し先がランダム名
実際は毎回同じランダム風の名前にも見えますが、シェル芸で対応するしかなかった。 -
flutter build
flutter build ios
はx86_64
に対応していないのに、Xcodeの設定でEXCLUDED_ARCHS
を設定して反映されない...?と思っていた。
参考
-
How to compile x86_64 with flutter build ios-framework?
https://github.com/flutter/flutter/issues/66943 -
xcodebuildのアーキテクチャ設定
https://qiita.com/Arime/items/ee9a41d849b473181728 -
DerivedDataの出力先設定
https://stackoverflow.com/questions/33044633/command-line-option-to-change-xcode-deriveddata-location
special thanks: @tarappo -
※1 CircleCIからAutify for Mobileへアップロードする
https://qiita.com/kanari3/items/3254e607ba7aad46a868