Bitrise上的Xcode 9代码签名

最近,出现了一些新的代码签名问题,但问题已经解决,因此 在Bitrise上 更新适用于iOS的Xcode存档和导出步骤 ,看看是否可行 。 如果不是这样,请参阅下面的说明和本文末尾的说明。

您可以在几周前的“ Xcode 9中的新导出选项Plist”中阅读有关IPA导出选项的更改。由于IPA导出过程已解锁了一些新选项,因此Xcode会自动检测并处理其中的大多数选项,但是从Xcode 9开始,我们需要手动定义它们。

第一个变化是,从此Xcode版本开始,我们需要为您的应用程序中的每个可执行目标列出,Provisioning Profile应该对其进行签名。 exportOptions中此属性的名称为provisioningProfiles ,在某些情况下,如果不定义此属性,您将收到以下错误:

 "Error Domain=IDEProvisioningErrorDomain Code=9 \"\"ios-simple-objc.app\" requires a provisioning profile.\" UserInfo={NSLocalizedDescription=\"ios-simple-objc.app\" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the \"provisioningProfiles\" dictionary in your Export Options property list.}" 

用例:您正在尝试使用手动签名从存档中导出IPA文件。 如果是自动签名(在导出过程中),则无需定义此属性。 在用于建筑物的Bitrise虚拟机上,您无法使用凭据登录Xcode,这就是为什么您无法执行IPA自动导出的原因。 但是,如果您使用“本地自动导出”并且Xcode为您生成了代码签名文件,则可以在Bitrise上使用这些代码签名文件来导出IPA。

因此, Xcode Archive & Export for iOS为Xcode 9 Xcode Archive & Export for iOS准备Xcode Archive & Export for iOSXcode Archive & Export for iOS ,我们首先解决了正确填充此导出选项节点的问题。

要填充provisioningProfiles节点,首先我们必须分析您的方案并找出方案选择了哪些目标。 我们不能简单地列出您的所有可执行目标,因为您可能有一个选择所有目标的方案,而另一个方案则没有。

用例:您有一个已经发布了一些版本的应用程序,因此决定将一个监视应用程序添加到您的项目中。 在这种情况下,假设您要保留原始方案以仅在监视应用程序正在开发时构建主应用程序,然后设置一个新方案以同时构建监视目标和应用程序目标。

首先,我们需要确定哪个项目包含您的方案-如果您只有一个项目,这是微不足道的,但是如果您使用工作区,则需要搜索包含该方案的项目。
一旦容器项目(
PROJECT.xcodeproj )和所需的方案文件( SCHEME.xcscheme ),我们需要分析方案文件以确定什么是方案的主要可执行目标。

通过搜索设置了buildForArchiving = "YES" BuildActionEntry ,可以在方案文件中找到主要的可执行目标。 可能有多个与此条件匹配的BuildActionEntry 。 我们正在寻找的目标是一个将在存档过程之后生成可执行应用程序的目标。

  SCHEME.xcscheme: ... 
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">

<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "61513174157CF09B0098DA0E"
BuildableName = "BitriseProject.app"
BlueprintName = "BitriseProject"
ReferencedContainer = "container:BitriseProject.xcodeproj">




...
...
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">

<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "61513174157CF09B0098DA0E"
BuildableName = "BitriseProject.app"
BlueprintName = "BitriseProject"
ReferencedContainer = "container:BitriseProject.xcodeproj">




...

为了确定目标是否会生成可执行应用程序,我们在容器项目的project.pbxproj文件中搜索目标定义。 此目标应该是本机目标,并且应该在project.pbxproj的PBXNativeTarget section中找到。 如果目标的productType定义了扩展名为.app.appex的产品,则该目标是可执行的。

  PROJECT.xcodeproj/project.pbxproj: ... 
/* Begin PBXNativeTarget section */
1D6058900D05DD3D006BFB54 /* BitriseTarget */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "BitriseTarget" */;
buildPhases = (
1027E4C48B8236F2DC44521F /* [CP] Check Pods Manifest.lock */,
1D60588E0D05DD3D006BFB54 /* Sources */,
1D60588D0D05DD3D006BFB54 /* Resources */,
1D60588F0D05DD3D006BFB54 /* Frameworks */,
4AB8674A1A13B33600DFC75D /* Embed App Extensions */,
4EF5EB651CE073EA00092F8B /* Embed Watch Content */,
FEFCD65D991A3508E2F372EE /* [CP] Embed Pods Frameworks */,
92E68DDEFB7F126AD6C3831F /* [CP] Copy Pods Resources */,
);
buildRules = (
829C820C19741F7F00A02FA3 /* PBXBuildRule */,
);
dependencies = (
4EF5EB8B1CE0749D00092F8B /* PBXTargetDependency */,
);
name = BitriseTarget;
productName = BitriseTarget;
productReference = 1D6058910D05DD3D006BFB54 /* BitriseTarget.app */;
productType = "com.apple.product-type.application";
};
...
...
/* Begin PBXNativeTarget section */
1D6058900D05DD3D006BFB54 /* BitriseTarget */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "BitriseTarget" */;
buildPhases = (
1027E4C48B8236F2DC44521F /* [CP] Check Pods Manifest.lock */,
1D60588E0D05DD3D006BFB54 /* Sources */,
1D60588D0D05DD3D006BFB54 /* Resources */,
1D60588F0D05DD3D006BFB54 /* Frameworks */,
4AB8674A1A13B33600DFC75D /* Embed App Extensions */,
4EF5EB651CE073EA00092F8B /* Embed Watch Content */,
FEFCD65D991A3508E2F372EE /* [CP] Embed Pods Frameworks */,
92E68DDEFB7F126AD6C3831F /* [CP] Copy Pods Resources */,
);
buildRules = (
829C820C19741F7F00A02FA3 /* PBXBuildRule */,
);
dependencies = (
4EF5EB8B1CE0749D00092F8B /* PBXTargetDependency */,
);
name = BitriseTarget;
productName = BitriseTarget;
productReference = 1D6058910D05DD3D006BFB54 /* BitriseTarget.app */;
productType = "com.apple.product-type.application";
};
...

.app是可执行应用程序(应用程序或监视应用程序)的扩展名, .appex属于扩展应用程序(监视扩展名,通知扩展名等)。

找到由给定方案选择的可执行主应用程序目标后,我们需要收集该目标的从属目标。 依赖目标在本机目标定义中的dependencies项项下定义,并且dependencies项通过其BlueprintIdentifier引用。

用例:如果您的应用程序包含watch应用程序项目,则主要目标将是您应用程序的目标,而watch应用程序的目标将是其依赖。 在这种情况下,我们需要在provisioningProfiles节点中列出两个目标的Provisiong配置文件。

至此,我们知道您的方案选择了哪些目标(主要目标+相关目标)。 接下来,我们需要收集目标的构建设置或目标的Info.plist文件中存在的这些目标的包标识符。

我们知道哪些目标应该在provisioningProfiles节点中列出,所以我们的下一个任务是弄清楚哪个供应概要应该签署哪个目标。 因此,我们将为您的目标和指定的导出方法收集所有可能的有效代码符号设置(代码符号标识–配给配置文件映射)。

接下来,我们确定哪个代码符号标识-配置文件映射将与您的项目和IPA导出配置匹配,因此我们将多个过滤器应用于代码符号设置列表:

  • 如果您的应用是使用NON Xcode托管配置文件存档的,则导出存档时仅允许NOT Xcode托管配置文件签名
  • 如果您指定The Developer Portal team to use for this export ,则仅保留其代码签名文件由所需团队创建的组。
  • 如果存在多个代码符号标识-设置配置文件映射,我们将删除使用Bitrise默认代码符号文件的组(如果已安装)
  • 如果保留了多个代码符号标识-配置文件映射,则该步骤将首选由存档过程中使用的团队发布的映射

应用这些过滤器后,仅应保留一个有效的代码符号组。

如果在过滤后仍然存在多个代码符号组,则我们无法决定要使用哪个符号组,因此该步骤将使用第一个组。 为避免这种情况,请为xcode归档步骤指定更多IPA导出选项:定义NON auto-detect Export method ,定义The Developer Portal team to use for this export ,也可以在Certificate and profile installer禁用Bitrise defult代码文件步。

至此,我们收集了provisioningProfiles节点的所有信息。

作为最后一个步骤,我们需要正确设置signingStyle :如果在归档时使用Xcode托管配置文件对您的应用进行了签名,但是IPA导出使用手动代码签名文件,则需要设置SigningStyle = "manual"

作为最后一步,我们应该应用由步骤输入定义的其他IPA导出选项( Include bitcodeRebuild from bitcode ),我们应该将最终的exportOptions.plist写入文件并将其用于IPA导出过程。

我们完成了! 好极了! 🎊


最初发布在 Bitrise博客上

Interesting Posts