web-dev-qa-db-ja.com

Xcode 4.5のリリースビルドでarmv6とarmv7sの両方をサポートする方法

私はこれが不可能であることを知っており、Appleはユーザーにデバイスのアップグレードを強制するようにこのように計画しました。クライアントは、アプリユーザーの割合がまだ「大」であるため、引き続きarmv6をサポートする必要があると主張しています。

静的ライブラリをマージするlipoというコマンドを知っており、ipaファイルをマージするために使用できることをどこかで読みましたが、正確にどのように実行されたかはわかりません。私はすでにグーグルとこのサイトでいくつかの検索をしましたが、具体的な答えを見つけるのは難しいです。

53
schystz

App Storeにあるアプリでこれを正常に行うことができました。 armv6、armv7、armv7sおよびiOSバージョン4.2〜6.0をサポートしています。古いデバイス(iPhone 3G、iPod touch 2g)でiPhone 5全体で動作することを確認しました。

この方法では、Xcode 4.5と古いバージョンのXcodeの両方を同時にインストールする必要があります。古いバージョンではまだ4.3.2を使用していますが、4.4でも動作するはずです。

この回答のスクリーンショットはありましたが、Stack Overflowでは新しいので投稿できません。 :(

Xcode 4.5でのセットアップ

  1. Armv6ビルドの新しいビルド構成を追加します。リリース構成を複製し、Release_armv6という名前を付けました。

  2. ビルド構成のアーキテクチャと有効なアーキテクチャを設定します。 Release_armv6以外はすべて、デフォルトを使用します。 Release_armv6の場合、手動でarmv6に設定します。 http://i.stack.imgur.com/h8Mpl.png

  3. Xcode 4.4以前では理解できないiOS 6機能を使用している場合は、armv6ビルド用にこれらを#ifdefする必要があります。 [ビルド設定]の[その他のCフラグとその他のC++フラグ]で、Release_armv6の構成に-DARMV6_ONLYを追加しました。次に、コードが新しいiOS 6 APIを使用する場合はいつでも、必要に応じて#ifndef ARMV6_ONLY/#endifのようなことを行います。 http://i.stack.imgur.com/czF6J.png

  4. 新しいスキームを追加し、すべての場合にRelease_armv6ビルド構成を使用するように設定します。

  5. [ビルドフェーズ]で、次のスクリプトを使用してスクリプトの実行ビルドフェーズを追加します(シェルを/ bin/cshに設定します)。これは魔法が起こるところです。 構成セクションを編集します:Release_armv6ビルドへのフルパスを決定し、ARMV6_EXECUTABLE_PATHに置き換えます。 MINIMUM_OSも設定します。



    #
    # Script to add armv6 architecture to iOS executable built with Xcode 4.5
    #

    #################
    # Configuration #
    #################
    # Change this to the full path where Xcode 4.4 (or below) puts your armv6 output
    setenv ARMV6_EXECUTABLE_PATH "$BUILD_ROOT/Release_armv6-iphoneos/$EXECUTABLE_PATH"

    # Your "real" minimum OS version since Xcode 4.5 wants to make it iOS 4.3
    # Must be 4.2 or below if you are supporting armv6...
    setenv MINIMUM_OS 4.2
    #####################
    # End configuration #
    #####################


    # For debugging
    echo CURRENT_Arch = $CURRENT_Arch
    echo CONFIGURATION = $CONFIGURATION

    # Don't need to do this for armv6 (built in older Xcode), simulator (i386), or debug build
    if ("$CURRENT_Arch" == "armv6") exit 0
    if ("$CURRENT_Arch" == "i386") exit 0
    if ("$CONFIGURATION" != "Release" && "$CONFIGURATION" != "Beta Test") exit 0

    # Paths
    setenv LIPO_PATH "$CODESIGNING_FOLDER_PATH/${EXECUTABLE_NAME}.lipo"
    setenv FINAL_PATH "$CODESIGNING_FOLDER_PATH/$EXECUTABLE_NAME"
    setenv FULL_INFO_PLIST_PATH "$CONFIGURATION_BUILD_DIR/$INFOPLIST_PATH"

    # Debug / sanity check
    lipo -info "$FINAL_PATH"
    ls -l "$ARMV6_EXECUTABLE_PATH"

    # Make sure something exists at $LIPO_PATH even if the next command fails
    cp -pv "$FINAL_PATH" "$LIPO_PATH"

    # If rebuilding without cleaning first, old armv6 might already be there so remove it
    # If not, lipo won't output anything (thus the cp command just above)
    lipo -remove armv6 -output "$LIPO_PATH" "$FINAL_PATH"

    # Add armv6 to the fat binary, show that it worked for debugging, then remove temp file
    lipo -create -output "$FINAL_PATH" "$ARMV6_EXECUTABLE_PATH" "$LIPO_PATH"
    lipo -info "$FINAL_PATH"
    rm -f "$LIPO_PATH"

    # Change Info.plist to set minimum OS version to 4.2 (instead of 4.3 which Xcode 4.5 wants)
    /usr/libexec/PlistBuddy -c "Set :MinimumOSVersion $MINIMUM_OS" "$FULL_INFO_PLIST_PATH"
    plutil -convert binary1 "$FULL_INFO_PLIST_PATH"

ビルドプロセス

リリースビルドを作成する準備ができたら、次の順序で作成します。

  1. Xcode 4.5を閉じ、Xcode 4.4以下を開きます。 armv6スキームを選択してビルドします。

  2. Xcode 4.4以下を閉じて、Xcode 4.5を開きます。リリーススキームを選択してビルドします。

それはほとんどそれです。ビルド出力をチェックして、目的のもの(3つのアーキテクチャを含む実行可能ファイル)が得られたことを確認します。実行スクリプトからの最後の出力でこれがわかるはずです。

誰かがこれを改善するアイデアをお持ちの場合は、お気軽に。あなたは空想を得て、ビルドスクリプト内からXcode 4.4の「xcodebuild」コマンドを呼び出すことができ、Xcodeバージョンをまったく切り替える必要性を軽減できると思います。しかし、これは私には十分に機能します。 ;)

警告:

  • 念のため、古いバージョンのXcodeでxibファイルを編集することをお勧めします。これまでのところ、4.5は後方互換性があるように見えますが、あなたは決して知りません。

  • 実際、古いXcodeで、iOS 6固有のものを除いて、ほとんどの開発を行うことを検討するかもしれません。あなたにとって最も簡単なものに依存します。

93
Mike

Gcc-4.2はまだarmv6をサポートしているため、Xcode 4.5を閉じて以前のバージョンを開く必要はありません(コンパイル用ですが、4.2デバイスでアプリを実行するためではありません)。

  • 有効なarchとarchの両方にarmv6を追加します。

アーチ:$(ARCHS_STANDARD_32_BIT)armv6

有効なアーキテクチャ:armv6 armv7 armv7s

  • Project.pbxprojファイルをVim(またはTextEdit)して、IPHONEOS_DEPLOYMENT_TARGETを必要に応じて4.0-4.1-4.2に置き換えます。Xcode4.5では、4.3を下回ることはできません。

次に、プロジェクトをビルドすると、警告が表示されます。

警告:アーキテクチャarmv6のタイプsourcecode.c.objcのファイル '$(PROJECT_DIR)/App/AppDelegate.mを処理するルールはありません
警告:ファイル' $(PROJECT_DIR )/App/SomeFile.c 'アーキテクチャarmv6 
のタイプsourcecode.cc
  • 名前が一致するソースファイルにBuild Ruleを追加します:*.[mc]を使用するLLVM GCC 4.2

静的ライブラリでは機能しますが、アプリでは機能しません:

 ld:ファイルはユニバーサル(4スライス)ですが、a(n) armv6スライスを含みません:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform /Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.oアーキテクチャarmv6 
  • アプリで動作させるには、このオブジェクトファイル(5.1 SDKに付属)にarmv6スライスを追加する必要があります。
 lipo /path/to-4.4/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/crt1.3.1.o -extract armv6-出力/tmp/crt1.3.1-armv6.o
lipo /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1 .3.1.o /tmp/crt1.3.1-armv6.o -create -output /tmp/crt1.3.1-armv677s.o
mv /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS。 platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr /lib/crt1.3.1.o.bkp
mv /tmp/crt1.3.1-armv677s.o /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6。 0.sdk/usr/lib/crt1.3.1.o 

プロジェクトをコンパイルし、アプリにすべてのアーチが含まれていることを確認します。

 $ファイルDerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp 
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp:Mach-O 3つのアーキテクチャを持つユニバーサルバイナリ
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp(アーキテクチャarmv6用):Mach-O実行可能arm 
 DerivedData/TestApp/Build/Products /Debug-iphoneos/TestApp.app/TestApp(アーキテクチャarmv7用):Mach-O実行可能arm 
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp(アーキテクチャcputype(12)用) cpusubtype(11)):Mach-O実行可能アーム

DSYMファイルにはすべてのアーチも含まれていることに注意してください(クラッシュレポートのシンボル表示に役立ちます)。

 $ファイルDerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp 
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp .app.dSYM/Contents/Resources/DWARF/TestApp:3つのアーキテクチャを持つMach-Oユニバーサルバイナリ
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp(アーキテクチャarmv6用):Mach-O dSYMコンパニオンファイルarm 
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp(アーキテクチャarmv7用): Mach-O dSYMコンパニオンファイルarm 
 DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp(アーキテクチャcputype(12)cpusubtype(11)の場合): Mach-O dSYMコンパニオンファイルアーム

IOS 4.2 2gen iPod touchでxcode 4.4.1を開き、Product-> Run without buildingでアプリを正常にインストールして起動しました。

  • アーカイブ製品を使用すると、Apple Mach-O Linkerエラーが発生する可能性があります。今回はlibarclite_iphoneos.alibclang_rt.ios.a
 ld:ファイルはユニバーサル(2スライス)ですが、a(n) armv6スライスを含みません:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchainアーキテクチャarmv6 
の場合は/usr/lib/arc/libarclite_iphoneos.a
 ld:ファイルはユニバーサル(2スライス)ですが、a(n) armv6スライスを含みません:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain /usr/lib/clang/4.1/libclang_rt.ios.a(アーキテクチャarmv6 
の場合)

Crt1.3.1.oに使用される手順はこれらのファイルにも適用され、Xcodeがプロジェクトを正常にアーカイブできるようにするエラーを修正します:ldファイルを見つけて、armv6スライスをlipoと結合します; Xcodeの以前のバージョンのlibclang_rt.ios.aはXcode.app/[...]/usr/lib/clang/4.1ではなくXcode.app/[...]/usr/lib/clang/4.0にあることに注意してください。

ファイルを正常にアーカイブし、アドホック配布プロファイルで展開し、iPhone 3G(4.2.1)およびiPhone 3GS(6.0)でテストしました。

  • 最後の問題:アプリを起動できません。 Organizerには、メッセージがあります:「iPhone 3G」タイプのデバイスは、このバージョンのXcodeではサポートされていません。

ただし、lsDeviceSupportは次を示します。

 ls /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ 
 4.2 4.3 5.0 5.1 6.0(10A403)

Xcode 4.4.1から4.2ディレクトリに差分なし。

問題は、Xcodeがデバイスをどのように検出するかをサポートするかどうかです。

/Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBaseHex Fiend(または別の16進エディタ)で開き、ascii 4.34.2に置き換えると、エラーメッセージが消え、デバイスにインストールされているアプリが一覧表示されます(ただし、デバイスデバイスリストの箇条書きはまだ赤です)。

それから/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKitを編集して置き換える必要があります:

Expired.deviceArchitecture.iPhone1,1.iPhone1,2.iPod1,1.iPod2,1.iPod2,2.armv6

に:

Expired.deviceArchitecture.iPhone0,1.iPhone0,2.iPod0,1.iPod0,1.iPod0,2.armv5

次に、オーガナイザーにオレンジ色の弾丸があります(Xcode 4.5.1):

「iPhone」のiOSのバージョンは、このバージョンのiOS SDKで使用するには古すぎます。以下にリストされているOSのバージョンにデバイスを復元してください。
 
 iPhoneにインストールされているOS 
 4.2.1(8C148)
 
 iOSバージョン
 6.0(10A403)
 5.1 
 5.0 
 4.3 

問題は次のとおりです。XcodeがサポートするiOSバージョンはどこで定義されていますか?

4.2には/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ディレクトリがあるため、既にサポートされているはずです...

iPhoneOS4.2.sdkをXcode 4.4.1から/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/にコピーしようとしましたが、デバイスがサポートされません。

Xcode 4.5に4.2デバイスサポートを追加する方法が見つかりませんでした。何か案は ?

結論:Xcode 4.5内でarmv6/7/7向けのコンパイルが可能です。ただし、Xcode 4.4を起動せずに4.2 armv6デバイスでアプリを起動することはできません。

大きな更新:Xcode 4.5.2で動作します!

Xcode 4.5.2では、箇条書きが緑色になりました:-)デバイスは、[実行]ボタンの近くのドロップダウンリストに表示されます。しかし、アプリを実行しようとすると、メッセージが表示されました:

 Xcodeは選択したデバイスを使用して実行できません。
このデバイスで実行するには、サポートされているアーキテクチャの宛先を選択してください。

有効なアーキテクチャにarmv6を追加するだけです:-)

その他の注意:一致する名前を持つソースファイルのBuild Rule*.[mc]LLVM GCC 4.2またはApple LLVM compiler 4.1、またはDefault compilerを使用できます

26
ıɾuǝʞ

この便利なスクリプトをありがとう!

この投稿全体からのすべての情報をうまく組み合わせました。結果の完全なスクリプトを以下に示します。このスクリプトには、Xcode 4.5.xとarmv6をサポートする以前のXcodeバージョンの両方が必要です(たとえば、/ Applications/Xcode 4.4.1.appにインストールされたXcode 4.4.1)

スクリプトは、xcode 4.4.xで最初にコンパイルする必要はありません。最新のXcodeを起動し、リリース構成を選択してビルドするだけです。 (Release-armv6の構成は、Mikeの元の投稿で述べたように定義されている必要があります)。

Armv6 armv7およびarmv7sと互換性のある.appを生成します

オリジナルのスクリプトをくれたマイクに感謝します!

#################
# Configuration #
#################
# Change this to the full path where Xcode 4.4 (or below) puts your armv6 output
setenv ARMV6_OUTPUT_PATH     "$BUILD_ROOT/Release-armv6-iphoneos/"
setenv ARMV6_EXECUTABLE_PATH "$ARMV6_OUTPUT_PATH$EXECUTABLE_PATH"

# Your "real" minimum OS version since Xcode 4.5 wants to make it iOS 4.3
# Must be 4.2 or below if you are supporting armv6...
setenv MINIMUM_OS 4.2
#####################
# End configuration #
#####################

# For debugging
echo CURRENT_Arch = $CURRENT_Arch
echo CONFIGURATION = $CONFIGURATION

# Don't need to do this for armv6 (built in older Xcode), simulator (i386), or debug build
#if ("$CURRENT_Arch" == "armv6") exit 0
if ("$CURRENT_Arch" == "i386") exit 0
if ("$CONFIGURATION" != "Release" && "$CONFIGURATION" != "Beta Test") exit 0

# Paths
setenv LIPO_PATH "$CODESIGNING_FOLDER_PATH/${EXECUTABLE_NAME}.lipo"
setenv FINAL_PATH "$CODESIGNING_FOLDER_PATH/$EXECUTABLE_NAME"
setenv FULL_INFO_PLIST_PATH "$CONFIGURATION_BUILD_DIR/$INFOPLIST_PATH"

#log file for armv6 build
echo "------------------------- BUILDING ARMV6 NOW -------------------------"
setenv LOGFILE "$BUILD_ROOT/buildarmv6.txt"
setenv CONFIGURATION_ARMV6 "${CONFIGURATION}-armv6"
#build armv6 version
echo "Building $FULL_PRODUCT_NAME armv6         CONFIG=$CONFIGURATION-armv6            target=$TARGETNAME"
"/Applications/Xcode 4.4.1.app/Contents/Developer/usr/bin/xcodebuild" -project         "${PROJECT_FILE_PATH}" -target "${TARGETNAME}" -sdk "${PLATFORM_NAME}" -configuration "$CONFIGURATION-armv6" CONFIGURATION_BUILD_DIR="$ARMV6_OUTPUT_PATH" >> "$LOGFILE"
echo "---------------------------- ARMV6 BUILT  -------------------------"
# to check for armv6 build errors
open "$LOGFILE"

# Debug / sanity check
lipo -info "$FINAL_PATH"
ls -l "$ARMV6_EXECUTABLE_PATH"

# Make sure something exists at $LIPO_PATH even if the next command fails
cp -pv "$FINAL_PATH" "$LIPO_PATH"

# If rebuilding without cleaning first, old armv6 might already be there so remove it
# If not, lipo won't output anything (thus the cp command just above)
lipo -remove armv6 -output "$LIPO_PATH" "$FINAL_PATH"

# Add armv6 to the fat binary, show that it worked for debugging, then remove temp file
lipo -create -output "$FINAL_PATH" "$ARMV6_EXECUTABLE_PATH" "$LIPO_PATH"
echo "------------------------- CHECK ARMV6 ARMV7 ARMV7S ARE MENTIONED BELOW -------------------------"
lipo -info "$FINAL_PATH"
echo "------------------------------------------------------------------------------------------------"
rm -f "$LIPO_PATH"

# Change Info.plist to set minimum OS version to 4.2 (instead of 4.3 which Xcode 4.5 wants)
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion $MINIMUM_OS" "$FULL_INFO_PLIST_PATH"
plutil -convert binary1 "$FULL_INFO_PLIST_PATH"
7
Jerome

投稿いただきありがとうございます。ビルドするアプリがいくつかあるので、あなたが提案したようにxcodebuildを使用してarmv6ビルドを自動化しました。これはスクリプトの一部であり(bashの使用に合わせて変更されています)、上記のスクリプトに追加できます。これは、「#デバッグ/健全性チェック」の前に追加できます。

setenv LOGFILE "/Users/xyz/Desktop/buildarmv6.txt"

setenv CONFIGURATION_ARMV6 "${CONFIGURATION}_armv6"
echo "Building $FULL_PRODUCT_NAME armv6         CONFIG=$CONFIGURATION_ARMV6         target=$TARGETNAME"

"/Applications/Xcode 4.4.1.app/Contents/Developer/usr/bin/xcodebuild" -project "${PROJECT_FILE_PATH}" -target "${TARGETNAME}" -sdk "${PLATFORM_NAME}" -configuration "$CONFIGURATION_ARMV6" >> "$LOGFILE"

echo "Built armv6"
open "$LOGFILE" # to check for armv6 build errors
4
K1w1Geek

健二の答えと私の経験を共有したいと思います。 iOS3.1からiOS7までのarmv6/armv7/armv7sで実行されるユニバーサルアプリを構築するのに最適な方法であると思います。

Kenjiが提案するとおりに実行してください。主にアプリをApple Application Loader(zip形式)経由で送信する場合)に、製品のアーカイブに関する部分を無視できます。

その他のアドバイス:

「配布」構成用にビルドすると、xcodeは製品を検証し、次の2つの警告が表示されます。

  • 「アーキテクチャarmv6はサポートされていません...」
  • 「4.3よりも低いiOS展開ターゲットはサポートされていません...」。

もちろん、実際にはarmv6用にビルドし、展開ターゲットを3.1または4.2に設定しているため、たとえば!

したがって...これらの警告を無視してください。

アプリをiTunes Connectに送信すると、アプリが「Position Independent Executable」ではないという警告メールがAppleから送信されます。もちろん、ターゲットが4.3より低いためです。この警告は無視してください。

この日(2013年7月3日)に、このメソッドを使用してアプリをアプリストアに正常に更新し、検証に合格しました。アプリの展開ターゲットはiOS 3.1.2で、armv6-armv7-armv7sをサポートしています。

私もそれを言いたい:

  • 新しいアプリを作成する場合は、展開ターゲットをiOS6またはiOS5に設定するだけです。古いOSを無視します。
  • 2010年以降に販売された古いアプリを数十万人のユーザーで使用している場合、実際にはAppleが言う。主にアプリがデバイスで実行できる場合、これらの古いデバイスのサポートを短時間で終了します。
3
Chrysotribax

この便利なチュートリアルとスクリプトを提供してくれたMikeに感謝します。 Piotrがコメントで述べたように、Xcodeからアーカイブコマンドを実行すると、アーカイブに別のビルドディレクトリを使用するため、スクリプトが失敗します。

以下は、通常のリリースビルドとアーカイブ固有のビルドの両方で有効にするためのスクリプトの変更です。

Mikeからの元の指示に従って、armv6ビルドが実行されることを前提としています。共通のベースビルドディレクトリを簡単に削除できるため、bash構文を使用します。したがって、これは、元のスクリプトのbashへの変換を意味します。これは、setenvをエクスポートで置き換え、ifステートメントの構文を変更するだけの問題です。

# Find the common base directory for both build
XCODE_BUILD=${BUILD_ROOT%%/Build*}
# Change this to the full path where Xcode 4.4 (or below) puts your armv6 output, using the previously derived base
export ARMV6_EXECUTABLE_PATH="$XCODE_BUILD/Build/Products/Release_armv6-iphoneos/$EXECUTABLE_PATH"
3
Max_B

Appleは、iOS5以前のデバイスをサポートし、iPhone 5の起動イメージを含むビルドの受け入れを停止しました。これは、Xcode 4.4.1でビルドされた最後のビルドのメールです。

親愛なる開発者、

「」の最近の配信で1つ以上の問題を発見しました。配送を処理するには、次の問題を修正する必要があります。

無効な起動画像-アプリには、iOS 6.0 SDK以降で構築されたアプリでのみサポートされるサイズ修飾子付きの起動画像が含まれています。

これらの問題が修正されたら、[バージョンの詳細]ページに移動し、[バイナリのアップロード準備完了]をクリックします。アプリのステータスが「アップロード待ち」になるまで送信プロセスを続けます。その後、修正されたバイナリを配信できます。

よろしく、

App Storeチーム

1
jr19