286 votes

Construire la grosse bibliothèque statique (appareil + simulateur) à l’aide de Xcode et SDK 4 +

Il semble que nous peut - théoriquement - construire une bibliothèque statique, qui comprend le simulateur et l'iPhone et l'iPad.

Cependant, Apple n'a pas de documentation sur ce que je peux trouver, et Xcode modèles par défaut ne sont PAS configurés pour ce faire.

Je suis à la recherche d'un simple, portable, réutilisable technique qui peut être fait à l'intérieur de Xcode.

Un peu d'histoire:

  • En 2008, nous avons utilisé pour être en mesure de rendre statique unique-libs qui incluait à la fois la carte sim et le périphérique. Apple désactivé.
  • Tout au long de 2009, nous avons fait des paires de bibliothèques statiques - on pour sim, l'une pour l'appareil. Apple a maintenant désactivé.

Références:

  1. C'est une excellente idée, c'est une excellente approche, mais il ne fonctionne pas: http://www.drobnik.com/touch/2010/04/universal-static-libraries/

    • Il y a quelques bugs dans son script qui signifie qu'il ne fonctionne que sur sa machine, il doit être à l'aide de BUILT_PRODUCTS_DIR et/ou BUILD_DIR au lieu de "guesstimating")
    • Apple dernier Xcode ne vous empêche de faire ce qu'il a fait - il aura tout simplement pas de travail, en raison de l' (Documenté) changement dans la façon de Xcode processus cibles)
  2. L'autre, de SORTE interlocuteur demandé comment le faire SANS xcode, et avec des réponses qui mettait l'accent sur la arm6 vs arm7 partie - mais pas pour l'architecture i386 partie: http://stackoverflow.com/questions/2793392/how-do-i-compile-a-static-library-fat-for-armv6-armv7-and-i386

    • Depuis Apple dernières modifications, le Simulateur n'est pas le même que le arm6/arm7 différence plus - c'est un problème différent, voir ci-dessus)

274voto

Adam Points 17726

ALTERNATIVES:

https://gist.github.com/3705459 - facile de copier/coller de la version la plus récente (mais les instructions d'installation peut changer - voir ci-dessous!)

Karl bibliothèque (http://stackoverflow.com/a/5721978/153422 ) prend beaucoup plus d'efforts pour l'installation, mais beaucoup plus agréable à long terme de la solution (il convertit votre bibliothèque dans un Cadre).


MODIFICATIONS RÉCENTES:

  1. Info sur comment utiliser ce script avec un projet intégré dans un autre projet (bien que je recommande fortement de ne PAS le faire, jamais - Apple a un couple de show-bouchon de bugs dans Xcode si vous intégrez des projets à l'intérieur les uns des autres, à partir de Xcode 3.x par le biais de Xcode 4.6.x)

  2. Bonus de script pour vous permettre d'auto-inclure les Grappes (c'est à dire inclure les fichiers PNG, fichiers PLIST etc à partir de votre bibliothèque!) - voir ci-dessous (faites défiler vers le bas)

  3. prend désormais en charge iPhone5 (à l'aide d'Apple solution de contournement pour les bugs en lipo). REMARQUE: les instructions d'installation ont changé (je peux probablement simplifier cela en modifiant le script à l'avenir, mais ne veulent pas prendre le risque maintenant)

  4. "copie des en-têtes de section" respecte maintenant le paramètre de construction pour l'emplacement des en-têtes publics (avec l'aimable autorisation de Frederik Wallner)

  5. Ajouté la définition explicite de SYMROOT (peut-être besoin OBJROOT être trop?), merci à Doug Dickinson


SCRIPT (c'est ce que vous avez copier/coller)

Pour l'utilisation / instructions d'installation, voir ci-dessous

##########################################
#
# 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

INSTRUCTIONS D'INSTALLATION

  1. Créer une lib statique projet
  2. Sélectionnez la Cible
  3. Dans "Build Settings", onglet set "Construire Active Seulement l'Architecture" à "NO" (pour tous les éléments)
  4. Dans les "Phases de construction" de l'onglet, sélectionnez "Ajouter ... Nouvelle Phase de construction ... de Nouvelles Exécuter le Script Phase de construction"
  5. Copier/coller le script (ci-dessus) dans la boîte

...BONUS FACULTATIF utilisation:

  1. FACULTATIF: si vous avez les en-têtes dans votre bibliothèque, les ajouter à la "Copie des en-Têtes" phase
  2. En OPTION: ...et faites-le glisser/déposer depuis la partie "Projet" pour le "Public" de la section
  3. En OPTION: ...et ils seront AUTOMATIQUEMENT exportées chaque fois que vous générez l'application, dans un sous-répertoire de "debug-universel" directory (ils seront dans usr/local/include)
  4. En OPTION: REMARQUE: si vous aussi essayer de glisser/déposer de votre projet dans un autre projet Xcode, ce qui les expose à un bug dans Xcode 4, où il ne peut pas créer un .Fichier IPA si vous avez des Publics les en-Têtes dans votre glissé/déplacé de projet. La solution: ne pas intégrer des projets xcode (trop de bugs d'Apple dans le code!)

Si vous ne pouvez pas trouver le fichier de sortie, voici une solution de contournement:

  1. Ajoutez le code suivant à la fin du script (avec l'aimable autorisation de Frederik Wallner): ouvrir "${CREATING_UNIVERSAL_DIR}"

  2. Apple supprime toutes les données de sortie au bout de 200 lignes. Sélectionnez votre Cible, et dans l'Exécution d'un Script Phase, vous DEVEZ décocher la case: "Afficher les variables d'environnement dans le build log"

  3. si vous êtes en utilisant une mesure de construire "sortie" répertoire pour XCode4, puis XCode met tous vos "inattendue" des fichiers dans le mauvais endroit.

    1. Construire le projet
    2. Cliquez sur la dernière icône à droite, dans la zone en haut à gauche de Xcode4.
    3. Sélectionnez l'élément du haut (c'est votre "plus récente génération". Apple devrait automatique-sélectionnez-le, mais ils n'ont pas pensé à ça)
    4. dans la fenêtre principale, faites défiler vers le bas. La dernière ligne devrait lire: lipo: pour la configuration actuelle (Debug) la création de fichier de sortie: /Users/blah/Library/Developer/Xcode/DerivedData/AppName-ashwnbutvodmoleijzlncudsekyf/Build/Products/Debug-universal/libTargetName.a

    ...c'est l'emplacement de votre version Universelle.


Comment inclure "non sourcecode" les fichiers dans votre projet (PNG, PLIST, XML, etc)

  1. Faire tout ce qui précède, vérifier qu'il fonctionne
  2. Créer un nouveau Exécuter le Script de la phase qui vient APRÈS LA PREMIÈRE (copiez/collez le code ci-dessous)
  3. Créer une nouvelle Cible dans Xcode, de type "bundle"
  4. Dans votre PROJET, dans les "Phases de construction", d'ajouter le nouveau bundle comme quelque chose qu'il "dépend" (section du haut, frapper la touche plus, faites défiler vers le bas, de trouver les ".bundle" fichier dans vos Produits)
  5. Dans votre NOUVEAU FAISCEAU CIBLE, dans les "Phases de construction", ajouter un "Copier Bundle de Ressources", et faites-le glisser/déplacer tous les fichiers PNG etc en elle

Script de copie automatique intégré bundle(s) dans le même dossier que votre GRAISSE bibliothèque statique:

echo "RunScript2:"
echo "Autocopying any bundles into the 'universal' output folder created by RunScript1"
CREATING_UNIVERSAL_DIR=${SYMROOT}/${CONFIGURATION}-universal
cp -r "${BUILT_PRODUCTS_DIR}/"*.bundle "${CREATING_UNIVERSAL_DIR}"

88voto

g_low Points 1303

J'ai passé de nombreuses heures à essayer de construire une grosse bibliothèque statique qui fonctionne sur armv7, armv7s, et le simulateur. Enfin trouvé une solution ici: http://www.nearinfinity.com/blogs/tyler_vernon/2012/07/17/creating-and-using-static-libraries-for-iphone-using-xcode-4.3.html

L'essentiel est de construire les deux bibliothèques (l'une pour l'appareil et un pour le simulateur) séparément, de les renommer à distinguer les unes des autres, et puis lipo -créer dans une bibliothèque.

lipo -create libPhone.a libSimulator.a -output libUniversal.a

Je l'ai essayé et ça marche!!!

74voto

Karl Points 3346

J’ai fait un modèle de projet XCode 4 qui vous permet de faire un cadre universel aussi facilement que de faire une bibliothèque régulière :

https://github.com/kstenerud/iOS-Universal-Framework

30voto

Eonil Points 19404

Il est un utilitaire de ligne de commande xcodebuild et vous pouvez exécuter la commande shell dans xcode. Donc, si vous n'avez pas l'esprit à l'aide personnalisée de script, ce script peut vous aider.

#Configurations.
#This script designed for Mac OS X command-line, so does not use Xcode build variables.
#But you can use it freely if you want.

TARGET=sns
ACTION="clean build"
FILE_NAME=libsns.a

DEVICE=iphoneos3.2
SIMULATOR=iphonesimulator3.2






#Build for all platforms/configurations.

xcodebuild -configuration Debug -target ${TARGET} -sdk ${DEVICE} ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO
xcodebuild -configuration Debug -target ${TARGET} -sdk ${SIMULATOR} ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO
xcodebuild -configuration Release -target ${TARGET} -sdk ${DEVICE} ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO
xcodebuild -configuration Release -target ${TARGET} -sdk ${SIMULATOR} ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO







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

DEBUG_DEVICE_DIR=${SYMROOT}/Debug-iphoneos
DEBUG_SIMULATOR_DIR=${SYMROOT}/Debug-iphonesimulator
DEBUG_UNIVERSAL_DIR=${SYMROOT}/Debug-universal

RELEASE_DEVICE_DIR=${SYMROOT}/Release-iphoneos
RELEASE_SIMULATOR_DIR=${SYMROOT}/Release-iphonesimulator
RELEASE_UNIVERSAL_DIR=${SYMROOT}/Release-universal

rm -rf "${DEBUG_UNIVERSAL_DIR}"
rm -rf "${RELEASE_UNIVERSAL_DIR}"
mkdir "${DEBUG_UNIVERSAL_DIR}"
mkdir "${RELEASE_UNIVERSAL_DIR}"

lipo -create -output "${DEBUG_UNIVERSAL_DIR}/${FILE_NAME}" "${DEBUG_DEVICE_DIR}/${FILE_NAME}" "${DEBUG_SIMULATOR_DIR}/${FILE_NAME}"
lipo -create -output "${RELEASE_UNIVERSAL_DIR}/${FILE_NAME}" "${RELEASE_DEVICE_DIR}/${FILE_NAME}" "${RELEASE_SIMULATOR_DIR}/${FILE_NAME}"

Cherche peut-être inefficace(je ne suis pas bon au script shell), mais facile à comprendre. J'ai configuré une nouvelle cible exécutant que ce script. Le script est conçu pour la ligne de commande, mais pas testé :)

Le concept de base est de xcodebuild et lipo.

J'ai essayé plusieurs configurations dans Xcode, INTERFACE utilisateur, mais rien n'a fonctionné. Parce que c'est une sorte de traitement par lots, de la ligne de commande de conception est plus approprié, Apple a donc retiré lot de fonctionnalités de génération de Xcode progressivement. Donc je n'attends pas qu'ils offrent une INTERFACE utilisateur basée lot construire fonctionnalité à l'avenir.

11voto

Brad Robinson Points 5469

Je besoin d’une grosse lib statique pour JsonKit donc créé un projet lib statique dans Xcode et ensuite couru ce script bash dans le répertoire du projet. Tant que vous avez configuré le projet xcode avec « Build configuration active seulement » désactivé, vous devriez obtenir toutes les architectures dans une lib.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X