记录 Unity 原生插件管理(EDM4U)的心路历程

122 阅读1分钟

概述

近期在协助公司的 Unity 开发做原生的支持, 同事发现在切换 git 分支时偶尔会出现 EDM (菜单Assets -> External Dependency Manager -> iOS Resolver -> Settings) 中Link frameworks statically 会被自动勾选. 导致编译出的 iOS 工程出现不可预期的崩溃.

思路一

处理自动生成的 podfile 中 static 关键字, 确保动态编译. 经查阅 EDM4U 文档得知, pod init 和 pod install 的执行顺序为 40~50. 故配置[PostProcessBuild(45)], 代码如下:

[PostProcessBuild(45)]
static void OnPostProcessBuild(UnityEditor.BuildTarget buildTarget, string pathToBuiltProject)
{
    HandlePodfileModification(pathToBuiltProject);
}

static void HandlePodfileModification(string buildPath)
  {
      string podfilePath = Path.Combine(buildPath, "Podfile");
      if (!File.Exists(podfilePath))
      {
          UnityEngine.Debug.LogError($"[Cocoapods] Podfile not found at: {podfilePath}");
          return;
      }

      UnityEngine.Debug.Log("[Cocoapods] 开始处理 Podfile");

      string content = File.ReadAllText(podfilePath);
      bool modified = false;

      // 1. 移除静态链接标记
      if (content.Contains("use_frameworks! :linkage => :static"))
      {
          content = content.Replace("use_frameworks! :linkage => :static", "use_frameworks!");
          modified = true;
          UnityEngine.Debug.Log("[Cocoapods] Removed static linkage flag");
      }

      if (modified)
      {
          File.WriteAllText(podfilePath, content);
          UnityEngine.Debug.Log("[Cocoapods] Successfully updated Podfile");
      }
      else
      {
          UnityEngine.Debug.Log("[Cocoapods] No modifications needed");
      }

      UnityEngine.Debug.Log("[Cocoapods] 完成处理 Podfile");
  }

曲折

开开心心提交了代码, 开发同事使用后都表示不再有静态库的编译的困扰了.

紧接着测试同事反馈说离线推送失效了!!!

接着苦哈哈的找问题, 解决

思路二

可能是执行顺序影响到了推送插件的脚本? 于是 41~49 全都尝试一遍. 推送全都失效, 这时心态已经有点小崩, Unity 编译 iOS 工程, 再run安装到 iPhone, 再功能测试, 太耗时了.

换个思路, 我等 EDM4U 默认的 pod install 执行完成后, 再改 podfile, 手动执行 pod install.代码如下

[PostProcessBuild(1000)] 
static void OnPostProcessBuild(UnityEditor.BuildTarget buildTarget, string pathToBuiltProject) 
{
    // 1. 处理 Podfile 修改
    HandlePodfileModification(pathToBuiltProject);
    // 2. 确保 Pod 环境
    EnsurePodEnvironment();
    // 3. 强制执行 Pod Install
    ForcePodInstall(pathToBuiltProject); 
}

static void EnsurePodEnvironment()
{
    // 设置必要的环境变量
    System.Environment.SetEnvironmentVariable("LANG", "en_US.UTF-8");
    System.Environment.SetEnvironmentVariable("LC_ALL", "en_US.UTF-8");
    System.Environment.SetEnvironmentVariable("LC_CTYPE", "UTF-8");

    UnityEngine.Debug.Log("[Cocoapods] Set environment: LANG=en_US.UTF-8");
}

static void ForcePodInstall(string buildPath)
{
    ProcessStartInfo startInfo = new ProcessStartInfo()
    {
      FileName = "**你的 pod 安装路径**",
      Arguments = "install --verbose",
      WorkingDirectory = buildPath,
      CreateNoWindow = true,
      UseShellExecute = false,
      RedirectStandardOutput = true,
      RedirectStandardError = true,
      StandardOutputEncoding = Encoding.UTF8,
      StandardErrorEncoding = Encoding.UTF8
    };

    // 显式设置编码环境变量
    startInfo.EnvironmentVariables["LANG"] = "en_US.UTF-8";
    startInfo.EnvironmentVariables["LC_ALL"] = "en_US.UTF-8";
    startInfo.EnvironmentVariables["LC_CTYPE"] = "UTF-8";
    
    try 
    {
      UnityEngine.Debug.Log($"[Cocoapods] Launching with UTF-8 env: {podPath} install");
      using (Process process = Process.Start(startInfo))
      {
        string output = process.StandardOutput.ReadToEnd();
        string error = process.StandardError.ReadToEnd();
        process.WaitForExit(300000);  // 5分钟超时

        if (process.ExitCode == 0)
        {
          UnityEngine.Debug.Log($"[Cocoapods] Successfully ran pod install");
          UnityEngine.Debug.Log(output);
        }
        else
        {
          UnityEngine.Debug.LogError($"[Cocoapods] Failed with exit code {process.ExitCode}\nError: {error}");
        }
      }
    }
    catch (System.Exception e)
    {
      UnityEngine.Debug.LogError($"[Cocoapods] Failed to install pods: {e.Message}");
    }
}

再折

我都已经将脚本执行顺序调整到 1000 了,总不至于再冲突了吧. 测试结果离线推送依然失效. 心态彻底崩了, 基本没有思路了.

思路 3

只能用最笨的办法一个个方法屏蔽, 看看到底是哪块代码影响到了. 结果更懵了, 只要 iOS/Editor 目录下存在两个脚本, 离线推送就会失效, 将两个脚本的代码整合到一起就正常了.

结语

已经在这里废了太多时间了, 最后虽然解决了, 但是我人是懵的. 有人看到这篇文章有跟我一样心路的可以留个言互相安慰一下.