สร้างห้องสมุดแบบคงที่ไขมัน (อุปกรณ์ + ตัวจำลอง) โดยใช้ Xcode และ SDK 4+


283

ดูเหมือนว่าเราสามารถสร้างห้องสมุดแบบคงที่เดียวที่มีทั้งเครื่องจำลองและ iPhone และ iPad

อย่างไรก็ตาม Apple ไม่มีเอกสารเกี่ยวกับเรื่องนี้ที่ฉันสามารถค้นหาได้และแม่แบบเริ่มต้นของ Xcode ไม่ได้ถูกกำหนดค่าให้ทำเช่นนี้

ฉันกำลังมองหาเทคนิคที่ง่ายพกพาใช้งานได้อีกครั้งซึ่งสามารถทำได้ภายใน Xcode

ประวัติบางส่วน:

  • ในปี 2008 เราเคยทำ lib-static เดียวที่รวมทั้งซิมและอุปกรณ์ Apple ปิดการใช้งานนั้น
  • ตลอดปี 2009 เราได้สร้าง libs คู่หนึ่งสำหรับซิมหนึ่งสำหรับอุปกรณ์ Apple ก็ปิดการใช้งานเช่นกัน

อ้างอิง:

  1. นี่เป็นความคิดที่ดีมันเป็นวิธีการที่ยอดเยี่ยม แต่มันใช้งานไม่ได้: http://www.drobnik.com/touch/2010/04/universal-static-l ไลบรารี/

    • มีข้อบกพร่องบางอย่างในสคริปต์ของเขาซึ่งหมายความว่าใช้งานได้กับเครื่องของเขาเท่านั้น - เขาควรใช้ BUILT_PRODUCTS_DIR และ / หรือ BUILD_DIR แทน "คาดเดา" พวกเขา)
    • Xcode ล่าสุดของ Apple ป้องกันไม่ให้คุณทำสิ่งที่เขาทำมันจะไม่ทำงานเนื่องจากการเปลี่ยนแปลง (เอกสาร) ในการที่ Xcode ประมวลผลเป้าหมาย)
  2. ผู้ถามดังนั้นอีกคนถามว่าจะทำอย่างไรโดยไม่ใช้ xcode และด้วยการตอบสนองที่เพ่งความสนใจไปที่ส่วน arm6 vs arm7 - แต่ไม่สนใจส่วน i386: ฉันจะรวบรวมไลบรารีแบบคงที่ (อ้วน) สำหรับ armv6, armv7 และ i386 ได้อย่างไร

    • เนื่องจากการเปลี่ยนแปลงล่าสุดของ Apple ส่วนเครื่องมือจำลองไม่เหมือนกับ arm6 / arm7 จะแตกต่างกันอีก - เป็นปัญหาที่แตกต่างดูด้านบน)

แค่สงสัย - ทำไมคุณถึงต้องการอย่างนั้น? มันไม่ทำให้ห้องสมุดอุปกรณ์ใหญ่ขึ้นและหนักขึ้นในอุปกรณ์หรือไม่?
cregox

3
@Cawas - "น้ำหนัก" ของห้องสมุดไม่เกี่ยวข้องกับสถานการณ์จริงในโลกถึง 95% - สำหรับพวกเราส่วนใหญ่ libs นั้นเล็กมากโดยเฉพาะเมื่อเปรียบเทียบกับการแสดงเช่นเดียวกับ UIImageView เดียว
อดัม

1
@Cawas - ในขณะเดียวกันค่าที่นี่คือคุณทำให้ง่ายขึ้นสำหรับคนอื่น ๆ ที่จะใช้ / ใช้ห้องสมุดของคุณอีกครั้ง มันจะกลายเป็นกระบวนการลาก / วางแบบขั้นตอนเดียว
อดัม

4
@Cawas - ในที่สุดประโยชน์ที่มีคุณค่าอย่างน่าประหลาดใจ: มันง่ายมากที่จะส่งไลบรารี่ที่รวบรวม "ผิด" ไปโดยไม่ตั้งใจ - XCode ทำการตรวจสอบที่ศูนย์และจะรวบรวมสถาปัตยกรรม "ผิด" ลงในไฟล์ที่คุณคิดว่าเป็น สถาปัตยกรรม. Apple กำลังทำลาย Xcodeในพื้นที่นี้ - แต่ละเวอร์ชั่นใหม่มีการเปลี่ยนแปลงซึ่งหมายความว่า "ปุ่มที่คุณกดเมื่อวานนี้เพื่อรวบรวม lib ของคุณอย่างถูกต้องในวันนี้จะรวบรวมได้อย่างไม่ถูกต้อง" จนกว่า Apple จะหยุดเรารอบตัวเราต้องพิสูจน์ UI ที่แย่ของพวกเขา :)
อดัม

1
นั่นจะยอดเยี่ยมจริงๆ! เพราะตอนนี้มันเป็นเช่นนั้นเราไม่สามารถพึ่งพาตัวจำลองสำหรับสิ่งที่ซับซ้อนกว่านี้ได้เล็กน้อย
cregox

คำตอบ:


272

ทางเลือก:

คัดลอก / วางเวอร์ชันล่าสุดง่าย (แต่คำแนะนำในการติดตั้งอาจเปลี่ยนแปลงได้ - ดูด้านล่าง!)

ห้องสมุดของ Karlใช้ความพยายามมากขึ้นในการติดตั้ง แต่โซลูชันระยะยาวที่ดีกว่ามาก (แปลงห้องสมุดของคุณให้เป็น Framework)

ใช้สิ่งนี้จากนั้นปรับแต่งเพื่อเพิ่มการสนับสนุนสำหรับการสร้างไฟล์เก็บถาวร - ความคิดเห็นของ cf @ Frederik ด้านล่างเกี่ยวกับการเปลี่ยนแปลงที่เขาใช้เพื่อทำให้งานนี้เป็นอย่างดีด้วยโหมดเก็บถาวร


การเปลี่ยนแปลงล่าสุด: 1. เพิ่มการรองรับ iOS 10.x (ในขณะที่ยังคงรองรับการรองรับแพลตฟอร์มเก่า)

  1. ข้อมูลเกี่ยวกับวิธีใช้สคริปต์นี้กับโปรเจ็กต์ที่ฝังตัวอยู่ในโปรเจ็กต์อื่น (แม้ว่าฉันจะไม่แนะนำให้ทำเช่นนั้น - Apple มีข้อบกพร่อง show-stopper สองตัวใน Xcode ถ้าคุณฝังโครงการภายในจาก Xcode 3.x จนถึง Xcode 4.6.x)

  2. สคริปต์โบนัสเพื่อให้คุณรวมกลุ่มโดยอัตโนมัติ (เช่นรวมไฟล์ PNG, ไฟล์ PLIST และอื่น ๆ จากห้องสมุดของคุณ!) - ดูด้านล่าง (เลื่อนไปด้านล่าง)

  3. ตอนนี้รองรับ iPhone5 (โดยใช้วิธีแก้ปัญหาของ Apple กับข้อบกพร่องใน lipo) หมายเหตุ: คำแนะนำในการติดตั้งได้เปลี่ยนไปแล้ว (ฉันอาจทำให้เรื่องนี้ง่ายขึ้นโดยการเปลี่ยนสคริปต์ในอนาคต แต่ไม่ต้องการเสี่ยงเลยตอนนี้)

  4. ส่วน "การคัดลอกส่วนหัว" ในขณะนี้เคารพการตั้งค่าการสร้างสำหรับตำแหน่งของส่วนหัวสาธารณะ (ความอนุเคราะห์จาก Frederik Wallner)

  5. เพิ่มการตั้งค่าที่ชัดเจนของ SYMROOT (อาจต้องตั้งค่า OBJROOT ด้วยหรือไม่) ขอบคุณ Doug Dickinson


สคริปต์ (นี่คือสิ่งที่คุณต้องคัดลอก / วาง)

สำหรับคำแนะนำการใช้งาน / ติดตั้งโปรดดูด้านล่าง

##########################################
#
# c.f. /programming/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4
#
# Version 2.82
#
# Latest Change:
# - MORE tweaks to get the iOS 10+ and 9- working
# - Support iOS 10+
# - Corrected typo for iOS 1-10+ (thanks @stuikomma)
# 
# 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 '\d\{1,2\}\.\d\{1,2\}$')

# 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

คำแนะนำในการติดตั้ง

  1. สร้างโครงการ lib แบบคงที่
  2. เลือกเป้าหมาย
  3. ในแท็บ "การตั้งค่าการสร้าง" ตั้งค่า "สร้างสถาปัตยกรรมที่ใช้งานเท่านั้น" เป็น "ไม่" (สำหรับรายการทั้งหมด )
  4. ในแท็บ "สร้างเฟส" เลือก "เพิ่ม ... สร้างเฟสใหม่ ... สร้างเฟสสคริปต์สร้างใหม่"
  5. คัดลอก / วางสคริปต์ (ด้านบน) ลงในช่อง

... โบนัสการใช้งานเสริม:

  1. ทางเลือก: หากคุณมีส่วนหัวในห้องสมุดของคุณให้เพิ่มลงในเฟส "คัดลอกส่วนหัว"
  2. ทางเลือก: ... และลาก / วางจากส่วน "โครงการ" ไปยังส่วน "สาธารณะ"
  3. ตัวเลือก: ... และพวกเขาจะถูกส่งออกโดยอัตโนมัติทุกครั้งที่คุณสร้างแอปไปยังไดเรกทอรีย่อยของไดเรกทอรี "debug-universal" (พวกเขาจะอยู่ใน usr / local / include)
  4. บังคับ: หมายเหตุ: ถ้าคุณยังพยายามที่จะลาก / วางโครงการของคุณลงในโครงการ Xcode อื่นนี้หมายความว่าข้อผิดพลาดใน Xcode 4 ที่มันไม่สามารถสร้างไฟล์ .IPA ถ้าคุณมีจําหัวลากของคุณ / โครงการลดลง วิธีแก้ปัญหา: อย่าฝังโครงการ xcode (มีข้อบกพร่องมากเกินไปในรหัสของ Apple!)

หากคุณไม่พบไฟล์เอาต์พุตนี่เป็นวิธีแก้ไข:

  1. เพิ่มรหัสต่อไปนี้ที่ส่วนท้ายสุดของสคริปต์ (ความอนุเคราะห์จาก Frederik Wallner): เปิด "$ {CREATING_UNIVERSAL_DIR}"

  2. Apple ลบเอาต์พุตทั้งหมดหลังจาก 200 บรรทัด เลือกเป้าหมายของคุณและในขั้นตอนการเรียกใช้สคริปต์คุณต้องเลิกเลือก: "แสดงตัวแปรสภาพแวดล้อมในบันทึกการสร้าง"

  3. หากคุณใช้ไดเรกทอรี "สร้างเอาต์พุต" ที่กำหนดเองสำหรับ XCode4 ดังนั้น XCode จะวางไฟล์ "ที่ไม่คาดคิด" ทั้งหมดของคุณไว้ในตำแหน่งที่ไม่ถูกต้อง

    1. สร้างโครงการ
    2. คลิกที่ไอคอนสุดท้ายทางด้านขวาในพื้นที่ด้านซ้ายบนของ Xcode4
    3. เลือกรายการยอดนิยม (นี่คือ "งานสร้างล่าสุด" ของคุณ Apple ควรเลือกอัตโนมัติ แต่พวกเขาไม่ได้คิดอย่างนั้น)
    4. ในหน้าต่างหลักเลื่อนไปด้านล่าง บรรทัดสุดท้ายที่ควรอ่าน: lipo: สำหรับการกำหนดค่าปัจจุบัน (ดีบั๊ก) การสร้างไฟล์เอาต์พุต: /Users/blah/Library/Developer/Xcode/DerivedData/AppName-ashwnbutvodmoleijzlncudsekyf/Build/Products/Debug-universal/libTargetName

    ... นั่นคือที่ตั้งของ Universal Build ของคุณ


วิธีรวมไฟล์ "ที่ไม่ใช่ซอร์ส" ในโครงการของคุณ (PNG, PLIST, XML, ฯลฯ )

  1. ทำทุกอย่างข้างต้นตรวจสอบการทำงาน
  2. สร้างเฟสเรียกใช้สคริปต์ใหม่ที่มาหลังจากครั้งแรก (คัดลอก / วางรหัสด้านล่าง)
  3. สร้างเป้าหมายใหม่ใน Xcode ประเภท "มัด"
  4. ในโครงการหลักของคุณใน "Build Phases" ให้เพิ่มบันเดิลใหม่ตามที่ "ขึ้นอยู่กับ" (ส่วนบนกดปุ่มบวกเลื่อนไปที่ด้านล่างค้นหาไฟล์ ".bundle" ในผลิตภัณฑ์ของคุณ)
  5. ในเป้าหมาย BUNDLE ใหม่ของคุณใน "Build Phases" เพิ่มส่วน "Copy Bundle Resources" และลาก / วางไฟล์ PNG ทั้งหมดและอื่น ๆ

สคริปต์เพื่อคัดลอกบันเดิลที่สร้างขึ้นลงในโฟลเดอร์เดียวกันกับไลบรารีแบบคงที่ FAT ของคุณ:

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}"

2
ฉันเคยใช้มันในโครงการไม่กี่ตอนนี้และจัดส่งสิ่งต่าง ๆ ลงใน app-store ที่ใช้สิ่งนี้เพื่อสร้างไลบรารี ทั้งหมดทำงานได้ 100% ตกลงดังนั้นฉันจึงติดกับเรื่องนี้ในตอนนี้ (จนถึง Xcode 4 อาจจะ)
Adam

2
มีใครยืนยันได้ไหมว่าวิธีนี้ใช้ได้กับ XCode 4.5 หรือไม่ ฉันกำลังพยายามรวบรวมไลบรารีแบบคงที่และใช้ในโครงการหลักของฉัน ฉันสามารถเรียกใช้สิ่งนี้ได้บนอุปกรณ์ แต่ไม่สามารถทำงานได้ในอุปกรณ์จำลอง นี่เป็นข้อผิดพลาดที่ฉันได้รับ: ไม่มีสถาปัตยกรรมที่จำเป็น i386 ในไฟล์ /Users/alex/Documents/iphone/production/iphone/mymedia/libMyUnrar4iOS.a (2 ชิ้น)
Alex1987

2
มีความคิดใดบ้างที่จะทำให้ XCode 5 และ ARM64 ทำงานได้? ถ้าฉันปล่อยให้สถาปัตยกรรมเป็นมาตรฐานมันทำให้ห้องสมุดมี armv7, armvs7 และ i386 ตามที่คาดไว้ ถ้าฉันตั้งค่าสถาปัตยกรรมให้เป็นมาตรฐานรวมถึง 64 บิตแล้วไลบรารีจะมี "cputype 16777223" เท่านั้น ฉันใช้ otool -h กับไฟล์. aa เพื่อตรวจสอบสิ่งที่อยู่ภายใน
Roger Binns

1
XCode5 เพิ่มการเรียกใช้สคริปต์การสร้างเฟสยิ่งยุ่งยากมากขึ้น ตรวจสอบสิ่งนี้: runcriptbuildphase.com
Fabio Napodano

1
สิ่งนี้ดูเหมือนว่าจะทำงานได้ดีบน Xcode 6 โดยไม่มีการเปลี่ยนแปลง (ลองมาสองสามโครงการแล้วและยังไม่ได้ส่งอัปเดตของ App Store เลย แต่ทุกอย่างยังทำงานได้ดี)
Adam

85

ฉันใช้เวลาหลายชั่วโมงในการสร้างไลบรารี่แบบคงที่ที่ใช้งานได้กับ armv7, armv7s และเครื่องจำลอง ในที่สุดก็พบวิธีแก้ปัญหา

ส่วนสำคัญคือการสร้างสองไลบรารี (หนึ่งสำหรับอุปกรณ์และจากนั้นหนึ่งสำหรับจำลอง) แยกจากกันเปลี่ยนชื่อพวกเขาเพื่อแยกความแตกต่างจากกันแล้ว lipo - สร้างพวกเขาเป็นหนึ่งในห้องสมุด

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

ฉันลองแล้วมันใช้งานได้!


4
ฉันขอแนะนำให้คุณอ่านคำตอบที่ยอมรับได้ คุณอาจพบว่านี้ได้รับการคุ้มครองแล้ว 2 ปีก่อนหน้านี้ ...
อดัม

2
ฉันอ่านมันใช้สคริปต์ แต่มันก็ไม่ได้ผลสำหรับ armv7s ของฉัน
g_low

2
คำสั่ง lipo ใช้งานไม่ได้กับสคริปต์ แต่ใช้งานได้ดีด้วยตนเอง! 10x
Dima

9
+1 นี่คือสิ่งที่ฉันต้องการจริงๆไม่ใช่สคริปต์ "make-a-framework" ขนาดใหญ่
LearnCocos2D

SolutionURL ของคุณส่งคืน "ข้อผิดพลาด 404 - ไม่พบ"
Alex

74

ฉันได้สร้างเทมเพลตโครงการ XCode 4ที่ช่วยให้คุณสร้างกรอบงานสากลได้อย่างง่ายดายเหมือนกับการสร้างไลบรารีปกติ


ไม่สามารถสร้างด้วยเป้าหมาย iOS 4.3 รับข้อผิดพลาดต่อไปนี้: เป้าหมายการปรับใช้ที่ไม่ถูกต้องสำหรับ -stdlib = libc ++ (ต้องใช้ iOS 5.0 ขึ้นไป)
Alex1987

ฉันหวังว่าฉันจะให้คะแนนชื่อเสียงมากขึ้นสำหรับคำตอบนี้ ... ง่ายกว่าการใช้ CMake เพื่อสร้างห้องสมุดแบบคงที่ ขอบคุณมากที่ทำสิ่งนี้!
iwasrobbed

มันใช้งานได้กับ iOS 6 สำหรับฉันด้วย แต่อาจเป็นเพราะ lib ของฉันนั้นค่อนข้างง่ายและไม่มีการพึ่งพาและทรัพยากร
Paulius Vindzigelskis

มีปัญหาใหญ่กับวิธีแก้ไขปัญหานี้: ผู้อื่นที่ต้องการใช้เฟรมเวิร์กที่สร้างโดยโซลูชันนี้ (โซลูชันนี้ขอแนะนำให้ติดตั้งเทมเพลต fremework เป็น xcode) ต้องติดตั้งเทมเพลตนี้กับ xcode ของพวกเขา !!!
evya

คุณจะต้องติดตั้งแม่แบบสำหรับกรอบงานจริง กรอบปลอมจะทำงานได้ดีใน Xcode ที่ไม่ได้แก้ไข
Karl

30

มีโปรแกรมอรรถประโยชน์บรรทัดคำสั่งxcodebuildและคุณสามารถเรียกใช้คำสั่ง shell ภายใน xcode ดังนั้นหากคุณไม่สนใจการใช้สคริปต์ที่กำหนดเองสคริปต์นี้อาจช่วยคุณได้

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

อาจดูไม่มีประสิทธิภาพ (ฉันไม่เก่งเรื่อง shell script) แต่เข้าใจง่าย ฉันกำหนดค่าเป้าหมายใหม่ที่เรียกใช้สคริปต์นี้เท่านั้น สคริปต์ถูกออกแบบมาสำหรับบรรทัดคำสั่ง แต่ไม่ได้ทดสอบใน :)

แนวคิดหลักคือและxcodebuildlipo

ฉันลองใช้การกำหนดค่าหลายอย่างภายใน Xcode UI แต่ไม่มีอะไรทำงาน เพราะนี่เป็นการประมวลผลแบบแบทช์ดังนั้นการออกแบบบรรทัดคำสั่งจึงเหมาะสมกว่าดังนั้น Apple จึงลบคุณลักษณะการสร้างแบทช์ออกจาก Xcode อย่างค่อยเป็นค่อยไป ดังนั้นฉันไม่คาดหวังว่าพวกเขาจะนำเสนอคุณลักษณะการสร้างแบตช์ตาม UI ในอนาคต


ขอบคุณมันน่าสนใจจริง ๆ ที่คำสั่งพื้นฐานที่เรียบง่ายยังคงใช้งานได้ - มันเป็นเพียงที่ Apple ทำลาย GUI ของพวกเขาอย่างงดงาม ดูเหมือนว่าฉันจะสามารถสร้างเทมเพลตโครงการที่กำหนดเองได้อย่างสมบูรณ์ซึ่งจะ "ไม่ดูด" และแก้ไขสิ่งที่ Apple พังโดยการสร้างเป้าหมายทั้งหมดล่วงหน้าและเชื่อมโยงสคริปต์นี้ด้วย xcode build vars ฉันจะลองทำในโปรเจคต่อไปของฉัน :)
อดัม

1
ฉันใช้สคริปต์คล้ายกับสิ่งนี้และวางไว้ภายใต้เป้าหมายใหม่ที่มีเพียงเชลล์สคริปต์ สคริปต์สร้างแบบเรียกซ้ำข้างต้นนั้นฉลาดมาก แต่สร้างความสับสนโดยไม่จำเป็น
benzado

1
ฉันชอบเชลล์สคริปสำหรับสิ่งนี้นี่คือgist.github.com/3178578
slf

@benzado ใช่ฉันหลีกเลี่ยงความซับซ้อนโดยเจตนาเพราะฉันคิดว่า shell script ต้องอ่านง่ายสำหรับการแก้ไข
Eonil

lipo: ไม่สามารถเปิดไฟล์อินพุต: / Debug-iphoneos /
Dima

11

ฉันต้องการ lib แบบคงที่ไขมันสำหรับ JsonKit เพื่อสร้างโครงการ lib แบบคงที่ใน Xcode แล้วรันสคริปต์ทุบตีนี้ในไดเรกทอรีโครงการ ตราบใดที่คุณได้กำหนดค่าโครงการ xcode ด้วยการปิด "การสร้างการกำหนดค่าที่ใช้งานเท่านั้น" คุณควรได้รับสถาปัตยกรรมทั้งหมดในหนึ่ง lib

#!/bin/bash
xcodebuild -sdk iphoneos
xcodebuild -sdk iphonesimulator
lipo -create -output libJsonKit.a build/Release-iphoneos/libJsonKit.a build/Release-iphonesimulator/libJsonKit.a

7

อัพเดท iOS 10:

ฉันมีปัญหากับการสร้าง fatlib ด้วย iphoneos10.0 เนื่องจากนิพจน์ปกติในสคริปต์คาดว่าจะ 9.x หรือต่ำกว่าและส่งคืน 0.0 สำหรับ ios 10.0

เพื่อแก้ไขปัญหานี้เพียงแทนที่

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

กับ

SDK_VERSION=$(echo ${SDK_NAME} | grep -o '[\\.0-9]\{3,4\}$')

ขอบคุณ เมื่อเช้านี้ฉันทำการเปลี่ยนแปลงคล้ายกัน แต่ใช้ \ d ฉันคิดว่านี่คือสิ่งที่เราต้องการ (ดีกว่าหรือแย่กว่าของคุณหรือไม่) ... grep -o '\ d \ {1,2 \} \. \ d \ {2 \} $'
อดัม

ฉันคิดว่าฉันเป็นที่น่าเชื่อถือมากขึ้นเนื่องจากจะมีการพิจารณาตัวเลขเท่านั้น
เบน

1
ไม่คุณตรงกับวิธีการเขียนตัวเลข 1 หลัก ด้วยการสนับสนุนทางประวัติศาสตร์ของ Apple สำหรับ (และการใช้) อักขระและข้อความที่ prettified (เช่นในชื่อไฟล์) ฉันคาดหวังให้คุณเลือกตัวเลขสองหลักที่เป็นกรรมสิทธิ์ของคุณน่าเชื่อถือน้อยลง
อดัม

1
โอเคบางทีคุณพูดถูก อย่างน้อยฉันก็ได้โครงการของฉันยังใช้งานได้และเราก็ปลอดภัยสำหรับรุ่น 89 ios ถัดไป
ben

@ โซลูชั่นเบนทำงานได้ดีสำหรับฉัน regex ของอดัม '[\\. 0-9] \ {3,4 \} $' ให้รหัสข้อผิดพลาด 2
Zee

4

ฉันทำสิ่งนี้เป็นเทมเพลต Xcode 4ในหลอดเลือดดำเดียวกับเทมเพลตเฟรมเวิร์กคงที่ของ Karl

ฉันพบว่าการสร้างเฟรมเวิร์กแบบสแตติก (แทนที่จะเป็นไลบรารีแบบสแตติกธรรมดา) ก่อให้เกิดการขัดข้องแบบสุ่มด้วย LLVM เนื่องจากมีข้อผิดพลาด linker ชัดเจน - ดังนั้นฉันคิดว่าไลบรารีแบบสแตติกยังคงมีประโยชน์อยู่!


สวัสดี Michael ฉันได้ลองใช้แม่แบบไลบรารีคงที่ของคุณแล้ว แต่ฉันสามารถรวบรวมเพื่อจำลอง แต่ไม่ใช่สำหรับอุปกรณ์ข้อผิดพลาดที่นี่: ** BUILD FAILED ** คำสั่งการสร้างต่อไปนี้ล้มเหลว: ProcessPCH / var / โฟลเดอร์ / qy / ncy6fkpn6677qt876ljrc54m0000gn / C / com .apple.Xcode.501 / SharedPrecompiledHeaders / MenuBarUniversal-Prefix-gwxxzpanxyudmfgryorafazokagi / MenuBarUniversal-Prefix.pch.pth MenuBarUniversal / Prefix.pch.pch.pch.pch.pch.pch.pch armp7 วัตถุประสงค์ทั่วไป - cvp.info ) แสดง 200 ประกาศแรกเท่านั้นคำสั่ง / bin / sh ล้มเหลวด้วยรหัสออก 65
Kappe

2

เยี่ยมมาก! ฉันแฮ็คบางอย่างที่คล้ายกัน แต่ต้องแยกจากกัน การมีมันเป็นส่วนหนึ่งของกระบวนการสร้างทำให้มันง่ายขึ้นมาก

บันทึกหนึ่งรายการ ฉันสังเกตเห็นว่ามันไม่ได้คัดลอกไฟล์รวมใด ๆ ที่คุณทำเครื่องหมายเป็นสาธารณะ ฉันได้ดัดแปลงสิ่งที่ฉันมีในสคริปต์ให้เป็นของคุณและใช้งานได้ดี วางต่อไปนี้ไว้ท้ายสคริปต์ของคุณ

if [ -d "${CURRENTCONFIG_DEVICE_DIR}/usr/local/include" ]
then
  mkdir -p "${CURRENTCONFIG_UNIVERSAL_DIR}/usr/local/include"
  cp "${CURRENTCONFIG_DEVICE_DIR}"/usr/local/include/* "${CURRENTCONFIG_UNIVERSAL_DIR}/usr/local/include"
fi

1
ตกลงฉันได้เพิ่มคำตอบนั้นไปแล้ว (ยังไม่มีโอกาสทดสอบ แต่ดูถูกต้องสำหรับฉัน)
Adam

1

ที่จริงฉันเพิ่งเขียนสคริปต์ของตัวเองเพื่อจุดประสงค์นี้ มันไม่ได้ใช้ Xcode (เป็นสคริปต์ที่คล้ายกันในโครงการ Gambit Scheme)

โดยพื้นฐานแล้วจะรัน. / config และสร้างสามครั้ง (สำหรับ i386, armv7 และ armv7s) และรวมแต่ละไลบรารีผลลัพธ์ลงใน lib ไขมัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.