はじめに
「UnityでgRPCアプリ(iOS, Android)をビルドできるようになった」でUnityのiOS, AndroidでもgRPCアプリを動かせるようになりました。
ここから更にil2cppでビルドする際に起きる問題の対処をまとめました。
共通
*.proto
でoneof
かenum
を使っている場合はSystem.Reflection.Emit
が走って実行時エラーになってしまいます。
protoc
で生成したコード中のenum
すべてを以下のT
に指定すると回避できます。
oneof
でenum
を使った場合はそのフィールドを含むクラスもこの対策が必要みたいです。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からiOS
とEditor
を除外します。
/Assets/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_stub.c
/Assets/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_stub.c.meta
ネットワークアクセスがgRPCのみだとAndroidManifest.xml
にINTERNET
パーミッションが付与されません。
確実に有効にするためにPlayerSettings > Other Settings > Internet Access
をRequire
にします。
iOS向け
iOS向けのライブラリのアーキテクチャはx86_64とarm64だけなのでPlayerSettings > Other Settings > Architecture
をARM64
にします。
また、bitcode非対応なのでXCodeのBuild Settings
でENABLE_BITCODE
をNO
にします。
Enable bitcode for ios native libraries #20113でbitcodeに対応するビルドオプションが追加されたので対処不要になりました。
bitcode対応するとlibgrpc.a
が250MB以上増えたのでv1.24.xブランチはRevert "Enable bitcode for ios native libraries" in v1.24.x #20233で、masterブランチはa2dbf0a99d1fc1c0059dbb28c4b530a58584cd71で差し戻されてしまいました。
リンク対象のライブラリにlibz
が必要なのでBuild Phases > Link Binary With Libraries
から追加します。
この操作は以下のエディタ拡張を配置すればビルド時に自動的に反映できます。
参考にしたBuildHelper.csはlibresolv.tbd
を追加していますがビルドエラーにならなかったので今も必要なのかよく分かりません…
参考にした先と公式ではビルドオプションが異なり、公式のライブラリを使うならlibresolv.tbd
は不要でした。
#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);
project.SetBuildProperty(targetGUID, "ENABLE_BITCODE", "NO");
File.WriteAllText(projectPath, project.WriteToString());
}
}
}
#endif
最後に
2018/10/15現在、このような対策が必要ですが今後不要になったり対策が変わるかもしれないのでgrpc/grpcやprotocolbuffers/protobufのissuesなどで動向を追ってください。
※追記
Experimentalパッケージが出る前のバージョンは「UnityプロジェクトでのgRPC導入方法について」の手順でビルドすれば利用できるようです。
参考リンク
- UnityでgRPCアプリ(iOS, Android)をビルドできるようになった
- Unity(IL2CPP環境)でのprotobufの使い方
- UnityプロジェクトでのgRPC導入方法について
- jsmouret/grpc-unity-package
- protocolbuffers/protobuf - Fix to allow AOT compilers to play nicely with reflection #4559
- grpc/grpc - Unity3D package #15013
- grpc/grpc - Compile error on Unity Android (when using il2cpp scripting backend) #16012
- grpc/grpc - C#: Fix il2cpp build on Unity Android. #18039
- grpc/grpc - Xcode reports libgrpc_csharp_ext.a does not contain bitcode #16839
- grpc/grpc - Enable bitcode for ios native libraries #20113
- grpc/grpc - Revert "Enable bitcode for ios native libraries" in v1.24.x #20233