5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CircleCIからAutify for Mobile向けにx86_64アーキでビルドする

Last updated at Posted at 2021-10-11

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

今回は最低限のオプションとしてxcworkspaceSchemeを指定します。
また、ここでの必須オプション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 iosx86_64に対応していないのに、Xcodeの設定でEXCLUDED_ARCHSを設定して反映されない...?と思っていた。

参考

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?