HoloLens2平台为Windows Arm,UE5打包程序时需要用到gRPC arm库

源码下载

到github克隆grpc仓库,切换到想要的tag版本,使用以下命令克隆子模块

git submodule init
git submodule update

克隆速度慢可以想点别的办法

安装nasm

安装nasm,把可执行文件nasm.exe所在的目录添加到系统Path环境变量

安装Windows CMake

下载最新的安装就行

生成x64的protoc和grpc_cpp_plugin

使用CMake GUI生成工程文件,指定生成文件类型为Visual Studio 2022(或者2019),添加以下变量,设置编译安装位置(可以自己指定其他位置)

CMAKE_INSTALL_PREFIX=D:/grpc/Win64

Configure > Generate > Open Project

然后设置生成类型为RelWithDebugInfo,在解决方案资源管理器ALL_BUILD右键生成。编译完成后在INSTALL右键生成,这样编译好的可执行文件、头文件和库会拷贝到CMAKE_INSTALL_PREFIX下。

然后CMAKE_INSTALL_PREFIX下的bin到添加到系统Path环境变量

生成arm64的库

重新打开使用CMake GUI,使得配置的环境变量能够更新

添加以下变量

CMAKE_INSTALL_PREFIX=D:/grpc/HoloLens
CMAKE_CROSSCOMPILING=ON
// 以下两个在添加了环境变量Path应该可以不加,CMakeLists文件使用了find_program查找下面两个可执行文件
_gRPC_CPP_PLUGIN=D:/grpc/Win64/bin/grpc_cpp_plugin.exe
_gRPC_PROTOBUF_PROTOC_EXECUTABLE=D:/grpc/Win64/bin/grpc_cpp_plugin.exe
// 一定要加
OPENSSL_NO_ASM=ON
gRPC_BUILD_TEST=OFF
gRPC_BUILD_CODEGEN=OFF
protobuf_BUILD_PROTOC_BINARIES=OFF

如果不添加OPENSSL_NO_ASM会导致c链接x64的chacha.lib导致链接失败。重复之前的操作就可以编译生成arm64的gRPC库

cares.lib链接错误

使用UE5打包HoloLens应用时报错

UATHelper: Packaging (HoloLens): cares.lib(ares_strdup.obj) : error LNK2019: unresolved external symbol __imp_strdup referenced in function ares_strdup
UATHelper: Packaging (HoloLens): cares.lib(ares_strsplit.obj) : error LNK2019: unresolved external symbol __imp_strnicmp referenced in function ares_strsplit
UATHelper: Packaging (HoloLens): cares.lib(ares_strcasecmp.obj) : error LNK2001: unresolved external symbol __imp_strnicmp
UATHelper: Packaging (HoloLens): cares.lib(ares_strcasecmp.obj) : error LNK2019: unresolved external symbol __imp_strcmpi referenced in function ares_strcasecmp

需要到gRPC编译目录下面的third_party\cares\cares\ares_config.h下修改配置,把对应宏改成undef

#undef HAVE_STRNICMP
#undef HAVE_STRDUP
#undef HAVE_STRCMPI
#undef HAVE_STRICMP

修改源码third_party\cares\src\lib\ares_strsplit.c,增加strnicmp__函数,并把list_constains里的strnicmp改成该函数名

// from https://github.com/DigitalMars/dmc/blob/9478d25a677f70dbe4fc0ed317cc5a5e5050ef8b/src/core/STRNICMP.C
static int strnicmp__(const char *s1, const char *s2, size_t n)
{
    unsigned char c1, c2;

    c1 = c2 = 0;
    while (n--)
    {
    c1 = tolower(*(const unsigned char *)s1);
    s1++;
    c2 = tolower(*(const unsigned char *)s2);
    s2++;
    if (!c1 || c1 != c2)
        break;
    }
    return c1 - c2;
}

static int list_contains(char * const *list, size_t num_elem, const char *str, int insensitive)
{
  size_t len;
  size_t i;

  len = strlen(str);
  for (i=0; i<num_elem; i++)
  {
    if (insensitive)
    {
#ifdef WIN32
      if (strnicmp__(list[i], str, len) == 0)
#else
      if (strncasecmp(list[i], str, len) == 0)
#endif
        return 1;
    }
    else
    {
      if (strncmp(list[i], str, len) == 0)
        return 1;
    }
  }

  return 0;
}

absl_symbolize.lib链接错误

报错内容:

UATHelper: Packaging (HoloLens): absl_symbolize.lib(symbolize.obj) : error LNK2019: unresolved external symbol __imp_SymSetOptions referenced in function "void __cdecl absl::lts_20220623::InitializeSymbolizer(char const *)" (?InitializeSymbolizer@lts_20220623@absl@@YAXPEBD@Z)
UATHelper: Packaging (HoloLens): absl_symbolize.lib(symbolize.obj) : error LNK2019: unresolved external symbol __imp_SymInitialize referenced in function "void __cdecl absl::lts_20220623::InitializeSymbolizer(char const *)" (?InitializeSymbolizer@lts_20220623@absl@@YAXPEBD@Z)
UATHelper: Packaging (HoloLens): absl_symbolize.lib(symbolize.obj) : error LNK2019: unresolved external symbol __imp_SymFromAddr referenced in function "bool __cdecl absl::lts_20220623::Symbolize(void const *,char *,int)" (?Symbolize@lts_20220623@absl@@YA_NPEBXPEADH@Z)

打开third_party\abseil-cpp\absl\debugging\symbolize.cc

#ifdef _WIN32
#include <winapifamily.h>
#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
    WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
// UWP doesn't have access to win32 APIs.
#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
#endif

明确说明了UWP不支持,唯一的办法是用空函数实现后然后编译,patch文件如下

patch