Edited at

Unity2018.2 + il2cppでgRPCアプリをAndroid/iOS向けにビルドする


はじめに

UnityでgRPCアプリ(iOS, Android)をビルドできるようになった」でUnityのiOS, AndroidでもgRPCアプリを動かせるようになりました。

ここから更にil2cppでビルドする際に起きる問題の対処をまとめました。


共通

*.protooneofenumを使っている場合はSystem.Reflection.Emitが走って実行時エラーになってしまいます。

protocで生成したコード中のenumすべてを以下のTに指定すると回避できます。

oneofenumを使った場合はそのフィールドを含むクラスもこの対策が必要みたいです。RPC周りの例外メッセージにSystem.Reflection.Emitが出てきたら対象のクラスを指定すれば大丈夫だと思います。

一度だけ実行すればいいので静的コンストラクタなどに書いておくといいでしょう。

using Google.Protobuf.Reflection;

FileDescriptor.ForceReflectionInitialization<T>();


Android向け

C#: Fix il2cpp build on Unity Android. #18039でダミー関数がマージされたのでコピー不要になりました。

DLLImportの名前が合わずにリンク時にビルドエラーが発生してしまいます。

Unity2018.2からPluginsフォルダにcppを配置するとビルドされるようになったので、以下のダミー関数のソースを配置しInclude PlatformsからiOSEditorを除外します。

/Assets/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_stub.c

/Assets/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_stub.c.meta

ネットワークアクセスがgRPCのみだとAndroidManifest.xmlINTERNETパーミッションが付与されません。

確実に有効にするためにPlayerSettings > Other Settings > Internet AccessRequireにします。


iOS向け

iOS向けのライブラリのアーキテクチャはx86_64とarm64だけなのでPlayerSettings > Other Settings > ArchitectureARM64にします。

また、bitcode非対応なのでXCodeのBuild SettingsENABLE_BITCODENOにします。

Enable bitcode for ios native libraries #20113でbitcodeに対応するビルドオプションが追加されたので対処不要になりました。

リンク対象のライブラリにlibzが必要なのでBuild Phases > Link Binary With Librariesから追加します。

この操作は以下のエディタ拡張を配置すればビルド時に自動的に反映できます。

参考にしたBuildHelper.cslibresolv.tbdを追加していますがビルドエラーにならなかったので今も必要なのかよく分かりません…

参考にした先と公式ではビルドオプションが異なり、公式のライブラリを使うならlibresolv.tbdは不要でした。


/Assets/Editor/BuildHelper.cs

#if UNITY_IPHONE


using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;

public class BuildHelper
{
// Add libz.tbd and disable bitcode when building for iOS
// Thanks to https://github.com/jsmouret/grpc-unity-package/blob/master/example/UnityGrpcClient/Assets/Scripts/Editor/BuildHelper.cs

[PostProcessBuildAttribute(1)]
public static void OnPostProcessBuild(BuildTarget target, string path)
{
if (target == BuildTarget.iOS)
{
var projectPath = PBXProject.GetPBXProjectPath(path);
var project = new PBXProject();
project.ReadFromString(File.ReadAllText(projectPath));
var targetGUID = project.TargetGuidByName(PBXProject.GetUnityTargetName());

project.AddFrameworkToProject(targetGUID, "libz.tbd", false);

// 2019/9/4以降にビルドされたunitypackageはbitcodeに対応しているので次の1行は不要です
project.SetBuildProperty(targetGUID, "ENABLE_BITCODE", "NO");

File.WriteAllText(projectPath, project.WriteToString());
}
}
}

#endif



最後に

2018/10/15現在、このような対策が必要ですが今後不要になったり対策が変わるかもしれないのでgrpc/grpcprotocolbuffers/protobufのissuesなどで動向を追ってください。

※追記

Experimentalパッケージが出る前のバージョンは「UnityプロジェクトでのgRPC導入方法について」の手順でビルドすれば利用できるようです。


参考リンク