Cordova アプリのビルド時にエラーになったら試したいこと

$ cordova build コマンド等で行う Cordova アプリのビルドは、どういうワケか突然失敗するようになることがある。自分もよく分かっていないままだが、よくやっていて、大抵は上手く直る対処法を紹介しておく。

XCode でビルドしてみる

何も変えていないのにビルドがコケるようになった場合、一番よくあるのがキーチェーンアクセスの許可が必要になる場合。この場合は XCode で ./platforms/ios/【アプリ名】.xcodeproj を開き、メニューの「再生」アイコンでビルドしてやると良い。キーチェーンへのアクセスを許可するか聞かれたら「常に許可」を選んでおく。

これでも数日に一回聞かれるようなので、これはもう諦める。w

.xcodeproj ファイルが初期化されていないか確認する

同様に、.xcodeproj ファイルで設定しておく必要のある内容が抜けたりすると、ビルドに失敗する。先ほどと同じように .xcodeproj ファイルを開き、「TARGETS」から対象のアプリを選択したら、主に以下を確認する。

Certificate has either expired or has been revoked というエラーメッセージの場合

ビルド時のエラーメッセージに Certificate has either expired or has been revoked という文言が出ていたら、プロビジョニング・プロファイルに問題が起こっている可能性が高い。

プロビジョニング・ファイルとは、App ID と Certificate (証明書) などを関連付けるためのファイル。

~/Library/MobileDevice/Provisioning Profiles/ 配下に移動し、存在するプロビジョニングファイル (.mobileprovision) を全消しする。

$ cd ~/Library/MobileDevice/Provisioning\ Profiles/
$ rm *

すると必要なプロビジョニングファイルが勝手に再生成される。

プロビジョニングファイルの状態は、XCode のメニューから Preferences → Accounts と進んで確認できる。

追加した Cordova プラグインが正しく追加できていないかもしれない

既存のプラットフォームに新たにプラグインを追加した場合、うまくビルドができなくなることがある。その場合は一度、./platforms/./plugins/ ディレクトリをまるっと削除してしまう。ディレクトリが削除できたら、$ cordova prepare コマンドを使って config.xml に記載のプラットフォーム・プラグインを再インストールしてやる。

$ rm -rf ./platforms/
$ rm -rf ./plugins/
$ cordova prepare

こうすると前述の .xcodeproj ファイルの設定が初期化されてしまっている可能性もあるので、改めて確認してほしい。

cordova emulate iosCannot read property 'replace' of undefined とエラーが出る場合

$ cordova emulate ios コマンドでビルドとシミュレータ起動を同時にやろうとすると、以下のようなエラーが出ることがある。

No scripts found for hook "before_deploy".
Error: TypeError: Cannot read property 'replace' of undefined

どうやら iOS シミュレータを起動する npm パッケージ「ios-sim」にバグがあるらしい。

かなり荒っぽいが、./platforms/ios/cordova/node_modules/ios-sim/src/lib.js を開き、282行目を直接書き換えてやると解消する。

// ./platforms/ios/cordova/node_modules/ios-sim/src/lib.js
// 以下の「list.push」で始まる行が、問題のある282行目

var remove = function(runtime) {
  // remove "iOS" prefix in runtime, remove prefix "com.apple.CoreSimulator.SimDeviceType." in id
  list.push(util.format('%s, %s', name_id_map[ deviceName ].replace(/^com.apple.CoreSimulator.SimDeviceType./, ''), runtime.replace(/^iOS /, '')));
                                           /* ============ ← この部分が問題となっている */
};

この282行目の deviceName という部分を filterDeviceName(deviceName) にする。

var remove = function(runtime) {
  // remove "iOS" prefix in runtime, remove prefix "com.apple.CoreSimulator.SimDeviceType." in id
  list.push(util.format('%s, %s', name_id_map[ filterDeviceName(deviceName) ].replace(/^com.apple.CoreSimulator.SimDeviceType./, ''), runtime.replace(/^iOS /, '')));
                                           /* ============================== ← このように直す */
};

ちなみに、 $cordova emulate --target=iPhone-7 などとターゲット指定すれば問題なく起動できたりする。

以上。Cordova ビルドいまだよくわからない。