web-dev-qa-db-fra.com

Xcode - symbole (s) non trouvé (s) pour l'architecture x86_64 (iOS Lib)

Je construis une bibliothèque statique. Le paramètre de construction a le paramètre Architectures défini sur: $(ARCHS_STANDARD) (affiché par Standard Architectures (armv7, armv7s, arm64)). Je construis la bibliothèque en choisissant Périphérique iOS ET en utilisant ensuite le simulateur (par exemple, iPhone Retina).

Maintenant que j'ai deux versions (l'une dans Debug-iphoneos et l'autre dans Debug-iphonesimulator, j'utilise lipo -create pour créer la bibliothèque agrégée:

lipo -create path/to/first/lib /path/to/second/lib -o MyLib.a

Si j'ai utilisé cette bibliothèque dans un autre projet pour simuler sur un périphérique iOS doté d'une architecture 64 bits, symbol(s) not found for architecture x86_64 apparaît. Ce qui me rend vraiment tellement en colère que le projet lib lui-même se trouve dans un espace de travail avec un autre projet utilisant lib. Je peux simuler sur un simulateur iOS 64 bits! (sur tous les simulateurs et appareils d'ailleurs). Qu'est-ce que je fais mal?

Remarques:

  1. Ce n’est pas un doublon. Avant de m’accuser de cela (car c’est mon deuxième jour à essayer de résoudre ce problème stupide), j’ai effectué une recherche sur Stack et Google. Toutes les réponses ne aident pas. 
  2. J'utilise Xcode 5.1.1.
26
Abdalrahman Shatou

I had the same trouble with building static library.
Finally I have found the basic solution. (You need to build universal library for x86_64/armv7/armv7s/arm64)

enter image description here

1) Click on the project file
2) Click on the target
3) Open "Build Phases"
4) Open "Run Script"
5) Add "/bin/sh" and the script below

##########################################
#
# c.f. http://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4
#
# Version 2.7
#
# Latest Change:
# - Supports iPhone 5 / iPod Touch 5 (uses Apple's workaround to lipo bug)
#
# Purpose:
#   Automatically create a Universal static library for iPhone + iPad + iPhone Simulator from within XCode
#
# Author: Adam Martin - http://twitter.com/redglassesapps
# Based on: original script from Eonil (main changes: Eonil's script WILL NOT WORK in Xcode GUI - it WILL CRASH YOUR COMPUTER)
#

set -e
set -o pipefail

#################[ Tests: helps workaround any future bugs in Xcode ]########
#
DEBUG_THIS_SCRIPT="false"

if [ $DEBUG_THIS_SCRIPT = "true" ]
then
echo "########### TESTS #############"
echo "Use the following variables when debugging this script; note that they may change on recursions"
echo "BUILD_DIR = $BUILD_DIR"
echo "BUILD_ROOT = $BUILD_ROOT"
echo "CONFIGURATION_BUILD_DIR = $CONFIGURATION_BUILD_DIR"
echo "BUILT_PRODUCTS_DIR = $BUILT_PRODUCTS_DIR"
echo "CONFIGURATION_TEMP_DIR = $CONFIGURATION_TEMP_DIR"
echo "TARGET_BUILD_DIR = $TARGET_BUILD_DIR"
fi

#####################[ part 1 ]##################
# First, work out the BASESDK version number (NB: Apple ought to report this, but they hide it)
#    (incidental: searching for substrings in sh is a nightmare! Sob)

SDK_VERSION=$(echo ${SDK_NAME} | grep -o '.\{3\}$')

# Next, work out if we're in SIM or DEVICE

if [ ${PLATFORM_NAME} = "iphonesimulator" ]
then
OTHER_SDK_TO_BUILD=iphoneos${SDK_VERSION}
else
OTHER_SDK_TO_BUILD=iphonesimulator${SDK_VERSION}
fi

echo "XCode has selected SDK: ${PLATFORM_NAME} with version: ${SDK_VERSION} (although back-targetting: ${IPHONEOS_DEPLOYMENT_TARGET})"
echo "...therefore, OTHER_SDK_TO_BUILD = ${OTHER_SDK_TO_BUILD}"
#
#####################[ end of part 1 ]##################

#####################[ part 2 ]##################
#
# IF this is the original invocation, invoke WHATEVER other builds are required
#
# Xcode is already building ONE target...
#
# ...but this is a LIBRARY, so Apple is wrong to set it to build just one.
# ...we need to build ALL targets
# ...we MUST NOT re-build the target that is ALREADY being built: Xcode WILL CRASH YOUR COMPUTER if you try this (infinite recursion!)
#
#
# So: build ONLY the missing platforms/configurations.

if [ "true" == ${ALREADYINVOKED:-false} ]
then
echo "RECURSION: I am NOT the root invocation, so I'm NOT going to recurse"
else
# CRITICAL:
# Prevent infinite recursion (Xcode sucks)
export ALREADYINVOKED="true"

echo "RECURSION: I am the root ... recursing all missing build targets NOW..."
echo "RECURSION: ...about to invoke: xcodebuild -configuration \"${CONFIGURATION}\" -project \"${PROJECT_NAME}.xcodeproj\" -target \"${TARGET_NAME}\" -sdk \"${OTHER_SDK_TO_BUILD}\" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO" BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" SYMROOT=\"${SYMROOT}\"

xcodebuild -configuration "${CONFIGURATION}" -project "${PROJECT_NAME}.xcodeproj" -target "${TARGET_NAME}" -sdk "${OTHER_SDK_TO_BUILD}" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}"

ACTION="build"

#Merge all platform binaries as a fat binary for each configurations.

# Calculate where the (multiple) built files are coming from:
CURRENTCONFIG_DEVICE_DIR=${SYMROOT}/${CONFIGURATION}-iphoneos
CURRENTCONFIG_SIMULATOR_DIR=${SYMROOT}/${CONFIGURATION}-iphonesimulator

echo "Taking device build from: ${CURRENTCONFIG_DEVICE_DIR}"
echo "Taking simulator build from: ${CURRENTCONFIG_SIMULATOR_DIR}"

CREATING_UNIVERSAL_DIR=${SYMROOT}/${CONFIGURATION}-universal
echo "...I will output a universal build to: ${CREATING_UNIVERSAL_DIR}"

# ... remove the products of previous runs of this script
#      NB: this directory is ONLY created by this script - it should be safe to delete!

rm -rf "${CREATING_UNIVERSAL_DIR}"
mkdir "${CREATING_UNIVERSAL_DIR}"

#
echo "lipo: for current configuration (${CONFIGURATION}) creating output file: ${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}"
xcrun -sdk iphoneos lipo -create -output "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_SIMULATOR_DIR}/${EXECUTABLE_NAME}"

#########
#
# Added: StackOverflow suggestion to also copy "include" files
#    (untested, but should work OK)
#
echo "Fetching headers from ${PUBLIC_HEADERS_FOLDER_PATH}"
echo "  (if you embed your library project in another project, you will need to add"
echo "   a "User Search Headers" build setting of: (NB INCLUDE THE DOUBLE QUOTES BELOW!)"
echo '        "$(TARGET_BUILD_DIR)/usr/local/include/"'
if [ -d "${CURRENTCONFIG_DEVICE_DIR}${PUBLIC_HEADERS_FOLDER_PATH}" ]
then
mkdir -p "${CREATING_UNIVERSAL_DIR}${PUBLIC_HEADERS_FOLDER_PATH}"
# * needs to be outside the double quotes?
cp -r "${CURRENTCONFIG_DEVICE_DIR}${PUBLIC_HEADERS_FOLDER_PATH}"* "${CREATING_UNIVERSAL_DIR}${PUBLIC_HEADERS_FOLDER_PATH}"
fi
fi

6) Hit "cmd + B" (Build Project)

7) Open Product in Finder

enter image description here

8) Navigate 1 directory up ("cmd + ↑"), and you will see "Release-universal" directory.enter image description here

There will be your "fat/universal" library, You are ready to go!

25
l0gg3r

J'ai rencontré ce problème avec un framework que j'utilise dans l'une de mes applications lorsque j'ai essayé de le tester dans le simulateur iPhone Retina 64 bits.

J'ai simplement ajouté x86_64 en tant qu'architecture à construire et à configurer pour toujours pour toutes les architectures. Travaillé un charme.

enter image description here

14
Aleksandar Vacić

L'outil lipo peut non seulement créer des binaires fat mach-o, mais également les inspecter: xcrun lipo -info /path/to/libThing.a

Cela affichera les architectures présentes dans le fichier. Avant de joindre des fichiers binaires à l'aide de lipo, exécutez cette opération pour vous assurer que les architectures attendues sont présentes. C'est aussi une bonne idée d'exécuter ceci sur le produit d'une jointure binaire épaisse.

Dans votre cas, vous avez besoin de:

configuration iPhoneSDK: armv7, armv7s, arm64

configuration iPhoneSimulator: i386, x86_64

Il semble que le produit de génération iPhoneSimulator ne génère pas de fichier binaire x86_64 basé sur votre question. Vérifiez votre configuration de construction - en particulier, "Construire les architectures actives uniquement" (ONLY_ACTIVE_Arch) doit être défini sur NO. La valeur par défaut est NO pour la version, mais YES pour le débogage. Si c'est OUI, une seule architecture sera dans le produit de construction.

6
quellish

Accédez à votre projet d'application Cible et cherchez dans Chemin de recherche de la bibliothèque .

Maintenant, vérifiez que le chemin du fichier de votre bibliothèque doit être écrit entre guillemets:

"$(SRCROOT)/MyAppTest/TestFlight"

S'il n'y a pas de guillemet double, ajoutez-les et compilez le projet. 

J'espère que cela fonctionnera pour vous.

0
Pratik Patel