web-dev-qa-db-fra.com

Xcode 10: La signature de code de mon cadre App + Framework échoue, car la signature du cadre de dépendance tiers (PromiseKit) a échoué Fonctionne dans Xcode 9

J'ai un projet Xcode 10 - iOS12 Swift qui établit des liens avec Mon propre framework (également Xcode 10 + iOS12). 

Le projet d'application référence mon projet-cadre en tant que référence de sous-projet.

Le projet My Framework fait référence à PromiseKit.framework (un framework universel - bibliothèque de ressources), créé à l'aide du script de génération suivant: 

# 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

Lorsque je vais archiver mon projet d'application parent à l'aide de Xcode 10 (et aussi 9.4.1) avec Bitcode ON (qui contient la référence My Framework et la bibliothèque PromiseKit Fat), l'erreur suivante apparaît à l'étape de signature: (Échec de la vérification du bitcode in PromiseKit.framework/PromiseKit: erreur Impossible d'extraire le paquet de /var/folders..../(x86_64) - ce qui suggère qu'il est lié à la tranche de simulateur)  enter image description here

Si je désactive l'option "Rebuild from Bitcode" de l'organiseur, le message d'erreur suivant s'affiche: (La signature du code "PromiseKit.framework" a échoué)  enter image description here

Cependant, si j'utilise Xcode 9.4.1 avec Bitcode OFF, il exporte et signe correctement. 

Pourquoi tente-t-il de signer individuellement de nouveau les sous-cadres et que puis-je faire pour atténuer les problèmes? J'ai besoin que l'archivage fonctionne normalement avec Xcode 10, ainsi que de futures dépendances tierces ajoutées à ma cible d'infrastructure. (Il s'agit de la première dépendance dynamique du cadre ajoutée à ma cible. Avant de commencer à «cuisiner» - intégrer toutes les tierces parties pour faciliter le développement, mais PromiseKit est difficile à intégrer en raison de la dépendance importante vis-à-vis d'Objectif-c). 

Le journal d'archive Xcode est:

 {
        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";
    }
);

Certaines autres solutions que j'ai essayées utilisaient une référence de projet à PromiseKit, au lieu d'une référence de cadre, mais cela ne fonctionne pas - dans la mesure où j'ai toujours besoin d'une référence de cadre de mon projet principal, car l'erreur "librairie non chargée" sera générée à runtime, si exécuté sans référence FW. Le même problème se produit lors de l'archivage lors de l'utilisation d'une référence de projet. 

5
FranticRock

Essaye ça! Cela a fonctionné pour moi et beaucoup d'autres personnes:

Aller à

Phases de construction> Ajouter> Nouvelle phase de script d'exécution

Le code devrait fonctionner pour n’importe quel shell par défaut, mais je recommande simplement d’utiliser/bin/sh

et inclure le code suivant:

# 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

Il semble que certains frameworks livrent des architectures, qui ne seront pas utilisées dans l'application . Xcode refusera de les signer. Le script ci-dessus supprime les architectures inutilisées.

Crédits: Un gars de GitHub, je ne trouve plus la source exacte.

4
SmartArray

Même problème ici. La seule solution que j'ai trouvée consiste à utiliser une bibliothèque statique au lieu de framework. 

Si vous ne pouvez pas utiliser la bibliothèque statique, vous feriez mieux de déposer un rapport de bogue auprès d'Apple. 

2
Dion Cho

J'ai pu intégrer (compiler dans le cadre de mon cadre) - le code cadre tiers, sans le référencer en tant que cadre. Je devais refactoriser -> renommer quelques-unes des classes qui entraient en conflit avec le nom de mon nom. Je ne voulais pas avoir cette complexité supplémentaire de références inter-infrastructures et de tranches d'architecture manquantes/supplémentaires. Étant donné que je privilégie la simplicité à tout le reste, cette solution a fonctionné au mieux pour moi. 

0
FranticRock