🗿

Unity FirebaseのiOSビルドで毎回team signingが求められる問題を解消する

2023/06/03に公開

UnityでFirebaseを入れてビルドしようとすると下記のようなsigningのエラーで失敗します。

Signing for "gRPC-C++-gRPCCertificates-Cpp" requires a development team. Select a development team in the Signing & Capabilities editor.

Xcode14からGoogle関連のSDKでこのようなエラーがよく見られまして、Firebase以外にもGoogle Sign InのSDKでも同じSigningエラーになることがあります。毎回、Xcodeをぽちぽち操作すればすぐに解消できるのですが、ビルドのたびにするのは面倒なので自動化して解決できるようにしたいと思います。

検証環境

Xcode14.3,
Unity-Firebase-sdk 10.0
Unity 2020.344f1 LTS

まず、FirebaseSDKを入れてUnityからiOSビルドすると下記のようなProjectが作成されます。

ここのPodfileの中身を見るとこのようになっていると思います。

source 'https://cdn.cocoapods.org/'

platform :ios, '11.0'

target 'UnityFramework' do
 pod 'Firebase/Core', '10.0.0'
 pod 'Firebase/Firestore', '10.0.0'
end
target 'Unity-iPhone' do
end
use_frameworks! :linkage => :static

このPodfileを下記のように修正し、再度pod installを実行することでSigningエラーを解消することができます。

source 'https://cdn.cocoapods.org/'

platform :ios, '11.0'

target 'UnityFramework' do
  pod 'Firebase/Core', '10.0.0'
  pod 'Firebase/Firestore', '10.0.0'
end
target 'Unity-iPhone' do
end
use_frameworks! :linkage => :static


post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
      target.build_configurations.each do |config|
        config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
      end
    end
  end
end

具体的な説明をすると、pod install後に,生成されたPodプロジェクトのtargetを全探索してリソースバンドルを探し出し、コード署名を無効にしています。こうすることで、問題となっていたSigningエラーは無くなります。

これで全てが解決されるわけではありません。Unityで再度iOSビルドするとPodfileは初期状態に戻ってしまいます。これはUnityが新しくプロジェクトを作成してビルドしているからです。

Unity側でPostProcessBuildを使用する。

PostProcessBuildというAttributeを使用すればビルド後にファイルを入れ替える処理を挟むことができます。この機能を使用して、修正後の正しいPodfileを差し込んであげたいと思います。

1 Assets/Editor配下にC#スクリプトを作成して、PostProcessBuild用のメソッドを定義。

public class CustomizePodfile
{

    [PostProcessBuild(100)]
    public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
    {
    ....
    }

PostProcessBuildの番号は実行順序のことを指しています。これを0や1にしているとビルドして正しいPodfileを差し込もうとしてもFirebaseSDKによって上書きされてしまうので正しいPodfileが差し込まれません。自分は大きい数をえいやで決めて100にしました。pathはビルドされるプロジェクトのルートパスが入っています。

2 実行したい処理を書いたシェルスクリプトと正しいPodfileを作成しAssetsのどこかに入れておく。
用意するのは既出の修正後のPodfileとPod install&Xcworkspaceを開くようにするシェルスクリプトです。

#!/bin/zsh
cd Xcodeのプロジェクトパス
pod install
open "./Unity-iPhone.xcworkspace"

chmod +xで権限を与えておかないとビルドに失敗するので忘れずにしといてください。

3 ファイルを入れ替える。

 static void CopyAndReplaceFile (string srcPath, string dstPath)
        {
            if (File.Exists (dstPath))
                File.Delete (dstPath);

            File.Copy (srcPath, dstPath);
        }

Assets配下に置いたスクリプトとPodfileのパスをsrcPathに入れて,
dstPathに XcodeProjectのパスを入れます。こうすることで、Podfileを差し込むことができるようになります。

4 シェルスクリプトの実行

 static void StartPodsProcess (string path)
        {
            var proc = new System.Diagnostics.Process ();
            var fileName = Path.Combine (OnPostProcessBuildの引数のpath, 作成したシェルのファイル名);
            proc.StartInfo.FileName = fileName;
            proc.Start ();
        }

このProcessがビルド後に実行されると、Signinのエラーが解消された状態でXcworkspaceが立ち上がり、毎回ぽちぽち修正しなくても大丈夫になります。

全コード

#if UNITY_IOS
using System.IO;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;

public class CustomizePodfile
{

   [PostProcessBuild(100)]
   public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
   {
       if (buildTarget == BuildTarget.iOS)
       {
       CopyAndReplaceFile(Assets配下に置いたスクリプトのパス, Path.Combine(path, スクリプトのファイル名));
       CopyAndReplaceFile(Assets配下に置いたPodfileのパス, Path.Combine(path, "Podfile"));
       StartPodsProcess (path); 
       }
   }
       static void CopyAndReplaceFile (string srcPath, string dstPath)
       {
           if (File.Exists (dstPath))
               File.Delete (dstPath);

           File.Copy (srcPath, dstPath);
       }

       static void StartPodsProcess (string path)
       {
           var proc = new System.Diagnostics.Process ();
           var fileName = Path.Combine (OnPostProcessBuildの引数のpath, 作成したシェルのファイル名);
           proc.StartInfo.FileName = fileName;
           proc.Start ();
       }

}
#endif

Discussion