繁体   English   中英

由于Mach-O标头中缺少LC_VERSION_MIN,Xcode app存档验证因Mac App Store分发而失败

[英]Xcode app archive validation fails for Mac App Store distribution due to lack of LC_VERSION_MIN in a Mach-O header

我有一个Swift项目,它使用NSTask调用命令行实用程序。

为了便于携带,我在应用程序的捆绑资源中包含了该命令行实用程序。

该实用程序非常复杂 - 它是一个Ruby解释的应用程序,带有一堆宝石,其中一些具有原生扩展。 这些gem都与Bundler一起安装到实用程序中的标准供应商/目录中。

我已经在第二台Mac上成功存档,验证,分发和运行应用程序,而第二台Mac上没有通过开发者ID(“Mac App Store”外部)工作流程安装的CLI实用程序(或Xcode)多次。

但是,存档无法验证Mac App Store分发时出现此错误:

2016-08-28 15:26:41 +0000 [MT]呈现:错误域= DVTFoundationNSBundleAdditionsErrorDomain Code = 1“无法在Info.plist CFBundleSupportedPlatforms中找到平台族或者在AbstractMemory.o中找到Mach-O LC_VERSION_MIN”UserInfo = {NSLocalizedDescription =无法在Info.plist CFBundleSupportedPlatforms中找到平台族或者在AbstractMemory.o中找到Mach-O LC_VERSION_MIN}

那么......为什么app工作流验证会在MAS工作流程中失败,而不是Developer ID工作流程会出现这样的错误?


潜在的有趣点:

  • 该应用程序使用1个临时例外权利让它在主文件夹中读取和写入特定文件夹,而不必唠叨用户进行访问。
  • 该应用程序不使用任何MAS特定功能/权利。
  • AbstractMemory.o是FFI ruby​​ gem的本机扩展的一部分,由CLI实用程序使用。
  • 我已尝试使用设置为DWARF的调试信息格式进行验证,也尝试使用DWARF + dSYM进行验证,但同样的问题也会发生。
  • 没有.dSYM文件在“复制包资源”设置中明确列出(尽管它们可能隐藏在CLI可执行文件的文件夹或gem本机扩展中)。
  • Xcode似乎锁定了原生扩展的某些位,并尝试以特殊方式处理它们。 以下位被提升到验证对话框中“二进制和权利”列表的顶层,就在主.app工件下面,而其他位(如gem依赖文件夹中的纯文本文件)不是:
    • 可执行文件(例如iconvxmlcatalog
    • .o文件(例如AbstractMemory.o
    • .bundle文件(例如ffi_c.bundlenokogiri.bundle
    • .dylib文件(例如libcapi.dyliblibcharset.dylib
    • .a文件(例如libcharset.a
  • 在“二进制和权利”列表中,主.app显示为具有预期数量的权利(我添加的权限),但可执行文件.o,.a,.bundle和.dylib文件显示为具有0权利。

TLDR

依赖项目最初是使用旧版本的Xcode和OS X编译的,因此其中的许多Mach-O可执行文件在其标题中没有LC_VERSION_MIN_MACOSX加载命令。 基本上我必须找到一种方法来挤压该命令。

唯一可靠且干净的方法是使用Xcode 7构建工具重新编译依赖项目中的所有本机代码。 如果依赖项是开源的,您可以自己完成。 如果不是,您将不得不恳求您的软件供应商。

如果您需要Yosemite部署目标兼容性,您可能会冒险并在Yosemite构建框上使用Xcode 7.1 GM。 但我建议您在El Capitan构建盒上使用Xcode 7.1+重新编译代码,以确保您的二进制依赖性能与SIP等El Capitan之类的东西相媲美。

细节

就我而言,依赖项目是开源的,所以我能够:

  1. 在GitHub上查找其源代码。
  2. 叉吧。
  3. 构建项目而不对OS X版本进行任何更改,尽可能地匹配第三方开发人员最初在其构建框上使用的版本来编译依赖项。
  4. 当(如果)失败时查看构建日志。
  5. 进行所有必要的更改以使构建变为绿色。 您现在已经与使用的原始构建框达到了奇偶校验。
  6. 现在将构建框OS X版本更新为Yosemite + Xcode 7.1 GM(如果必须具有Yosemite兼容性)或El Capitan + Xcode 7.1+。
  7. 重建,修复,yada yada。
  8. 当它再次变为绿色时,抓取新编译的二进制工件。
  9. 在bundle中找到Mach-O可执行文件。
  10. 运行otool -l [path to executable]
  11. 在Mach-O标头加载命令的大清单中,您现在应该看到LC_VERSION_MIN_MACOSX为10.10或10.11(取决于您使用的内容)。
  12. 你的二元文物应该很好用。

通过使用Travis CI的Mac构建机队,我能够设置多个OS X构建VM而不会生气。

剩下的非showstopper问题

必须取消“包含用于调试的符号”以进行存档验证或导出。 这是因为符号化器无法处理第三方目标代码。 我想这是因为它是为发布而构建的,因此目标代码没有附带任何附带的调试符号。

如果您无法重新编译代码

如果您无法重新编译代码,我听说有关于可以将Mach-O加载命令加载到预先存在的二进制文件中的肮脏变通方法的传闻。 这会遇到以下问题:

  • 这种方法非常脆弱,因为它依赖于新的加载命令在标题中留下足够的空白位。 不出所料,我听说修改现有加载命令的值往往比插入新命令更可靠。
  • 二进制不得已经签约。 Gatekeeper将立即拒绝在签名后以任何方式被篡改的二进制文件。
  • Mach-O头重写不是一项简单的任务,因此它往往是在第三方工具的帮助下完成的。 如果您不习惯在二进制+十六进制编辑器级别工作,那么很难验证这些工具的功能,因此您将非常信任它们(a)正确地执行此操作(b)没有做任何邪恶的事。

额外的讨论

我将此问题交叉发布到Apple开发人员论坛, 网址https://forums.developer.apple.com/message/175427 ,看看是否会由更专业的社区更快地得到答复。 事实并非如此,但您可以通过该链接找到对该问题的进一步讨论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM