开发者问题收集

Xcode 10:由于第三方依赖框架 (PromiseKit) 签名失败,导致我的 App+Framework 代码签名失败。在 Xcode 9 中有效

2018-10-29
13257

我有一个 Xcode 10 - iOS12 swift 项目,它链接到我自己的框架(也是 Xcode 10 + iOS12)。

应用程序项目正在引用我的框架项目作为子项目引用。

我的框架项目引用了 PromiseKit.framework(一个通用框架 - fat 库),使用以下构建脚本制作:

# Merge Script

# 1
# Set bash script to exit immediately if any commands fail.
set -e

# 2
# Setup some constants for use later on.
FRAMEWORK_NAME="PromiseKit"

# 3
# If remnants from a previous build exist, delete them.
if [ -d "${SRCROOT}/build" ]; then
rm -rf "${SRCROOT}/build"
fi

# 4
# Build the framework for device and for simulator (using
# all needed architectures).
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch arm64 only_active_arch=no defines_module=yes -sdk "iphoneos"
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 only_active_arch=no defines_module=yes -sdk "iphonesimulator"

# 5
# Remove .framework file if exists on Desktop from previous run.
if [ -d "${SRCROOT}/${FRAMEWORK_NAME}.framework" ]; then
rm -rf "${SRCROOT}/${FRAMEWORK_NAME}.framework"
fi

# 6
# Copy the device version of framework to Desktop.
cp -r "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${SRCROOT}/${FRAMEWORK_NAME}.framework"

# 7
# Replace the framework executable within the framework with
# a new version created by merging the device and simulator
# frameworks' executables with lipo.
lipo -create -output "${SRCROOT}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"

# 8
# Copy the Swift module mappings for the simulator into the
# framework.  The device mappings already exist from step 6.
cp -r "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${SRCROOT}/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule"

# 9
# Delete the most recent build.
if [ -d "${SRCROOT}/build" ]; then
rm -rf "${SRCROOT}/build"
fi

当我使用 Xcode 10(以及 9.4.1)存档我的父应用程序项目时,Bitcode ON(包含我的框架引用和 PromiseKit Fat 库),我在签名阶段收到以下错误:(无法验证 PromiseKit.framework/PromiseKit 中的位码:错误无法从 /var/folders..../(x86_64) 中提取捆绑包 - 这表明它与模拟器切片相关) 在此处输入图像描述

如果我将 Organizer 中的“从 Bitcode 重建”选项关闭,则会收到不同的错误:(代码签名“PromiseKit.framework”失败) 在此处输入图像描述

但是,如果我使用 Xcode 9.4.1 并关闭 Bitcode,则导出和签名正常。

为什么它尝试单独重新签名子框架,我该怎么做才能缓解这些问题?我需要归档功能与 Xcode 10 一起正常工作,以及将任何未来的第三方依赖项添加到我的框架目标。 (这是添加到我的框架目标中的第一个动态框架依赖项。之前我“烘焙” - 为了方便开发而将所有第三方纳入其中,但由于对 Objective-c 的大量依赖,PromiseKit 很难纳入)。

Xcode 存档日志为:

 {
        code = 330;
        description = "Failed to resolve linkage dependency PromiseKit x86_64 -> @rpath/libswiftFoundation.dylib: Unknown arch x86_64";
        info =             {
        };
        level = WARN;
    },
            {
        code = 330;
        description = "Failed to resolve linkage dependency PromiseKit x86_64 -> @rpath/libswiftObjectiveC.dylib: Unknown arch x86_64";
        info =             {
        };
        level = WARN;
    },
            {
        code = 0;
        description = "Failed to verify bitcode in PromiseKit.framework/PromiseKit:\nerror: Cannot extract bundle from /var/folders/q5/hm9v_6x53lj0gj02yxqtkmd40000gn/T/IDEDistributionOptionThinning.RJD/Payload/MyAppName.app/Frameworks/PromiseKit.framework/PromiseKit (x86_64)\n\n";
        info =             {
        };
        level = ERROR;
        type = "malformed-payload";
    }
);

我尝试过的其他一些解决方案是使用 PromiseKit 的项目引用,而不是框架引用,但这不起作用 - 因为我仍然需要来自我主项目的框架引用,因为如果运行时没有 FW 引用,我将在运行时收到“库未加载”错误。使用项目引用进行存档时也会出现同样的问题。

3个回答

试试这个!它对我和其他许多人都有效:

转到

构建阶段 > 添加 > 新运行脚本阶段

该代码应该适用于任何默认 shell,但我建议只使用 /bin/sh

并包含以下代码:

# Type a script or drag a script file from your workspace to insert its path.
# skip if we run in debug
if [ "$CONFIGURATION" == "Debug" ]; then
echo "Skip frameworks cleaning in debug version"
exit 0
fi

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done

似乎有些框架附带了不会在应用程序中使用的架构。 Xcode 将拒绝签署它们。上述脚本将删除未使用的架构。

鸣谢:GitHub 上的某个人,我再也找不到确切的来源了。

YoshiJaeger
2018-11-12

这里也有同样的问题。我发现的唯一解决方法是使用静态库而不是框架。

如果您无法使用静态库,最好向 Apple 提交错误报告。

Dion Cho
2018-11-04

这对我有用, 我有应用程序和 2 个内部构建的框架,比如 A $ B

应用程序需要 A,但 A 需要 B,而且由于 Apple 不建议嵌套框架,因此 A 和 B 都必须包含在应用程序中。

这是我的 Xcode 项目的样子。

Xcode 中的应用程序结构

解决方案

在应用程序中,在 框架、库和嵌入内容 下,为所有必要的框架选择 嵌入和签名 。 (如下所示)

application frameworks

但对于所有自定义框架项目,在 框架和库 部分下,选择 不嵌入 。 (如下所示) 这为我解决了这个问题

custom frameworks

Freed Ahmad
2020-02-26