Xây dựng thư viện tĩnh chất béo (thiết bị + trình giả lập) bằng Xcode và SDK 4+


283

Dường như chúng ta có thể - về mặt lý thuyết - xây dựng một thư viện tĩnh duy nhất bao gồm cả trình giả lập và iPhone và iPad.

Tuy nhiên, Apple không có tài liệu nào về điều này mà tôi có thể tìm thấy và các mẫu mặc định của Xcode KHÔNG được định cấu hình để thực hiện việc này.

Tôi đang tìm kiếm một kỹ thuật đơn giản, di động, có thể sử dụng lại có thể được thực hiện trong Xcode.

Một số lịch sử:

  • Vào năm 2008, chúng tôi đã từng có thể tạo ra các lib tĩnh đơn bao gồm cả sim và thiết bị. Apple đã vô hiệu hóa điều đó.
  • Trong suốt năm 2009, chúng tôi đã thực hiện các cặp lib tĩnh - một cho sim, một cho thiết bị. Apple cũng đã vô hiệu hóa điều đó.

Người giới thiệu:

  1. Đây là một ý tưởng tuyệt vời, đó là một cách tiếp cận tuyệt vời, nhưng nó không hoạt động: http://www.drobnik.com/touch/2010/04/universal-static-lologists/

    • Có một số lỗi trong tập lệnh của anh ấy có nghĩa là nó chỉ hoạt động trên máy của anh ấy - anh ấy nên sử dụng BUILT_PRODUCTS_DIR và / hoặc BUILD_DIR thay vì "đoán" chúng)
    • Xcode mới nhất của Apple ngăn bạn thực hiện những gì anh ta đã làm - đơn giản là nó sẽ không hoạt động, do sự thay đổi (Tài liệu) trong cách Xcode xử lý các mục tiêu)
  2. Một người hỏi SO khác đã hỏi làm thế nào để làm điều đó KHÔNG CÓ xcode và với các câu trả lời tập trung vào phần arm6 vs arm7 - nhưng bỏ qua phần i386: Làm cách nào để tôi biên dịch thư viện tĩnh (fat) cho armv6, armv7 và i386

    • Vì những thay đổi mới nhất của Apple, phần Trình mô phỏng không giống với sự khác biệt của arm6 / arm7 nữa - đó là một vấn đề khác, xem ở trên)

Chỉ cần tự hỏi - tại sao bạn muốn điều đó? Nó không làm cho thư viện thiết bị lớn hơn và nặng hơn trên thiết bị?
cregox

3
@Cawas - "trọng lượng" của thư viện là không liên quan trong 95% các tình huống trong thế giới thực - đối với hầu hết chúng ta, các lib rất nhỏ, đặc biệt là so với việc chỉ hiển thị dù chỉ một UIImageView.
Adam

1
@Cawas - trong khi đó, giá trị ở đây là bạn giúp người khác sử dụng / tái sử dụng thư viện của mình dễ dàng hơn. Nó trở thành một quá trình kéo / thả một giai đoạn.
Adam

4
@Cawas - cuối cùng, một lợi ích đáng ngạc nhiên: thật dễ dàng để vô tình gửi cho ai đó thư viện được biên dịch "sai" - XCode không kiểm tra và sẽ vui vẻ biên dịch kiến ​​trúc "sai" vào tệp có tên mà bạn nghĩ là "chính xác" ngành kiến ​​trúc. Apple tiếp tục phá vỡ Xcode trong lĩnh vực này - mỗi phiên bản mới có những thay đổi có nghĩa là "nút bạn đã nhấn ngày hôm qua để biên dịch lib của bạn một cách chính xác hôm nay sẽ biên dịch nó không chính xác". Cho đến khi Apple ngừng làm phiền chúng tôi xung quanh, chúng tôi cần phải chứng minh ngu ngốc giao diện người dùng xấu của họ :).
Adam

1
Điều đó sẽ thực sự tuyệt vời! Bởi vì ngay bây giờ, chúng ta không thể dựa vào trình giả lập cho bất cứ điều gì phức tạp hơn một chút.
cregox

Câu trả lời:


272

THAY ĐỔI:

Dễ dàng sao chép / dán phiên bản mới nhất (nhưng hướng dẫn cài đặt có thể thay đổi - xem bên dưới!)

Thư viện của Karl mất nhiều công sức hơn để thiết lập, nhưng giải pháp dài hạn đẹp hơn nhiều (nó chuyển đổi thư viện của bạn thành Khung).

Sử dụng cái này, sau đó tinh chỉnh nó để thêm hỗ trợ cho các bản dựng Lưu trữ - nhận xét của cf @ Frederik bên dưới về những thay đổi anh ấy đang sử dụng để làm cho công việc này hoạt động tốt với chế độ Lưu trữ.


THAY ĐỔI GẦN ĐÂY: 1. Đã thêm hỗ trợ cho iOS 10.x (trong khi vẫn duy trì hỗ trợ cho các nền tảng cũ hơn)

  1. Thông tin về cách sử dụng tập lệnh này với dự án được nhúng trong dự án khác (mặc dù tôi rất khuyến khích KHÔNG làm điều đó, bao giờ - Apple có một vài lỗi trình chiếu trong Xcode nếu bạn nhúng các dự án vào nhau, từ Xcode 3.x đến Xcode 4.6.x)

  2. Tập lệnh thưởng để cho phép bạn tự động bao gồm Gói (tức là bao gồm tệp PNG, tệp PLIST, v.v. từ thư viện của bạn!) - xem bên dưới (cuộn xuống dưới)

  3. hiện hỗ trợ iPhone5 (sử dụng cách khắc phục của Apple đối với các lỗi trong lipo). LƯU Ý: hướng dẫn cài đặt đã thay đổi (tôi có thể đơn giản hóa việc này bằng cách thay đổi tập lệnh trong tương lai, nhưng không muốn mạo hiểm ngay bây giờ)

  4. Phần "tiêu đề sao chép" hiện tôn trọng cài đặt bản dựng cho vị trí của các tiêu đề công khai (lịch sự của Frederik Wallner)

  5. Đã thêm cài đặt rõ ràng của SYMROOT (có thể cũng cần cài đặt OBJROOT?), Nhờ Doug Dickinson


SCRIPT (đây là những gì bạn phải sao chép / dán)

Để biết hướng dẫn sử dụng / cài đặt, xem bên dưới

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

HƯỚNG DẪN CÀI ĐẶT

  1. Tạo một dự án lib tĩnh
  2. Chọn mục tiêu
  3. Trong tab "Xây dựng cài đặt", đặt "Chỉ xây dựng kiến ​​trúc hoạt động" thành "KHÔNG" (cho tất cả các mục)
  4. Trong tab "Xây dựng giai đoạn", chọn "Thêm ... Giai đoạn xây dựng mới ... Giai đoạn xây dựng tập lệnh chạy mới"
  5. Sao chép / dán tập lệnh (ở trên) vào hộp

... Sử dụng TIỀN THƯỞNG THƯỞNG:

  1. TÙY CHỌN: nếu bạn có các tiêu đề trong thư viện của mình, hãy thêm chúng vào giai đoạn "Sao chép tiêu đề"
  2. TÙY CHỌN: ... và kéo / thả chúng từ phần "Dự án" sang phần "Công khai"
  3. TÙY CHỌN: ... và chúng sẽ TỰ ĐỘNG được xuất mỗi khi bạn xây dựng ứng dụng, vào một thư mục con của thư mục "gỡ lỗi phổ quát" (chúng sẽ ở dạng usr / local / include)
  4. TÙY CHỌN: LƯU Ý: nếu bạn cũng cố gắng kéo / thả dự án của mình vào một dự án Xcode khác, điều này sẽ làm lộ ra lỗi trong Xcode 4, nơi nó không thể tạo tệp .IPA nếu bạn có Tiêu đề công khai trong dự án kéo / thả của bạn. Giải pháp thay thế: không 'nhúng các dự án xcode (quá nhiều lỗi trong mã của Apple!)

Nếu bạn không thể tìm thấy tệp đầu ra, đây là một cách giải quyết:

  1. Thêm mã sau vào phần cuối của tập lệnh (lịch sự của Frederik Wallner): mở "$ {CREATING_UNIVERSAL_DIR}"

  2. Apple xóa tất cả đầu ra sau 200 dòng. Chọn mục tiêu của bạn và trong Giai đoạn chạy tập lệnh, bạn PHẢI bỏ chọn: "Hiển thị các biến môi trường trong nhật ký xây dựng"

  3. nếu bạn đang sử dụng thư mục "xây dựng đầu ra" tùy chỉnh cho XCode4, thì XCode sẽ đặt tất cả các tệp "không mong muốn" của bạn ở sai vị trí.

    1. Xây dựng dự án
    2. Nhấp vào biểu tượng cuối cùng bên phải, ở khu vực trên cùng bên trái của Xcode4.
    3. Chọn mục hàng đầu (đây là "bản dựng gần đây nhất" của bạn. Apple nên tự động chọn nó, nhưng họ không nghĩ về điều đó)
    4. trong cửa sổ chính, cuộn xuống dưới cùng. Dòng cuối cùng nên đọc: lipo: cho cấu hình hiện tại (Gỡ lỗi) tạo tệp đầu ra: /Users/blah/L Library / Nhà phát triển / XX / DecuredData / AppName -ashwnbutvodmoleijzlncudsekyf /Build / Products / Dugug

    ... đó là vị trí của Universal Build của bạn.


Cách bao gồm các tệp "không phải mã nguồn" trong dự án của bạn (PNG, PLIST, XML, v.v.)

  1. Làm mọi thứ ở trên, kiểm tra xem nó có hoạt động không
  2. Tạo giai đoạn Run Script mới xuất hiện SAU MỘT LẦN ĐẦU TIÊN (sao chép / dán mã bên dưới)
  3. Tạo một Target mới trong Xcode, thuộc loại "bó"
  4. Trong DỰ ÁN CHÍNH của bạn, trong "Xây dựng giai đoạn", hãy thêm gói mới dưới dạng thứ gì đó "phụ thuộc" (phần trên cùng, nhấn nút dấu cộng, cuộn xuống dưới, tìm tệp ".bundle" trong Sản phẩm của bạn)
  5. Trong MỤC TIÊU BUNDLE MỚI của bạn, trong "Xây dựng giai đoạn", thêm phần "Sao chép tài nguyên gói" và kéo / thả tất cả các tệp PNG, v.v.

Tập lệnh để tự động sao chép (các) gói được xây dựng vào cùng thư mục với thư viện tĩnh FAT của bạn:

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
Bây giờ tôi đã sử dụng điều này trên một vài dự án và chuyển các thứ vào cửa hàng ứng dụng đã sử dụng nó để xây dựng các thư viện. Tất cả đều hoạt động 100%, vì vậy tôi vẫn gắn bó với điều này ngay bây giờ (cho đến Xcode 4, có lẽ)
Adam

2
Bất cứ ai cũng có thể xác nhận nếu phương pháp này hoạt động cho XCode 4.5? Tôi đang cố gắng biên dịch một thư viện tĩnh và sử dụng nó trong dự án chính của mình. Tôi có thể chạy nó trên thiết bị nhưng không phải trên trình giả lập. Đây là lỗi tôi gặp phải: thiếu kiến ​​trúc bắt buộc i386 trong tệp /Users/alex/Document/iphone/production/iphone/mymedia/libMyUnrar4iOS.a (2 lát)
Alex1987

2
Bất kỳ ý tưởng làm thế nào để làm điều này hoạt động với XCode 5 và ARM64? Nếu tôi để các kiến ​​trúc theo tiêu chuẩn, nó làm cho thư viện với armv7, armvs7 và i386 như mong đợi. Nếu tôi đặt kiến ​​trúc thành tiêu chuẩn bao gồm 64 bit, thì thư viện chỉ chứa "cputype 16777223". Tôi sử dụng otool -h trên tệp .a để xác minh những gì bên trong
Roger Binns

1
XCode5 đã khiến việc thêm một giai đoạn xây dựng tập lệnh chạy trở nên khó khăn hơn. kiểm tra này: runscriptbuildphase.com
Fabio Napodano

1
Điều này dường như hoạt động tốt trên Xcode 6 mà không có thay đổi (chỉ thử một vài dự án cho đến nay và chưa gửi bất kỳ bản cập nhật App Store nào, nhưng tất cả đều hoạt động tốt cho đến nay).
Adam

85

Tôi đã dành nhiều giờ cố gắng để xây dựng một thư viện tĩnh chất béo sẽ hoạt động trên armv7, armv7 và trình giả lập. Cuối cùng tìm thấy một giải pháp .

Ý chính là xây dựng hai thư viện (một cho thiết bị và sau đó một cho trình giả lập), đổi tên chúng để phân biệt với nhau và sau đó lipo - tạo chúng thành một thư viện.

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

Tôi đã thử nó và nó hoạt động!


4
Tôi đề nghị bạn đọc câu trả lời được chấp nhận. Bạn có thể thấy rằng điều này đã được bảo hiểm, 2 năm trước ...
Adam

2
Tôi đã đọc nó, sử dụng tập lệnh, nhưng nó không hoạt động với tôi cho armv7.
g_low

2
lệnh lipo không hoạt động trên kịch bản, nhưng thủ công nó hoạt động rất tốt! 10
Dima

9
+1 Đây thực sự là tất cả những gì tôi cần, không phải là một kịch bản "make-a-framework" khổng lồ.
Tìm hiểuCocos2D

Giải pháp của bạn trả về "Lỗi 404 - Không tìm thấy"
Alex

74

Tôi đã tạo một mẫu dự án XCode 4 cho phép bạn tạo một khung phổ quát dễ dàng như tạo một thư viện thông thường.


Không thể xây dựng nó với mục tiêu iOS 4.3. Nhận lỗi sau: mục tiêu triển khai không hợp lệ cho -stdlib = libc ++ (yêu cầu iOS 5.0 trở lên)
Alex1987

Tôi ước tôi có thể cho nhiều điểm danh tiếng hơn cho câu trả lời này ... dễ dàng hơn nhiều so với việc sử dụng CMake để tạo một thư viện tĩnh. Cảm ơn bạn rất nhiều vì đã làm điều này!
iwasrobbed

Nó cũng hoạt động với iOS 6 đối với tôi. Nhưng có lẽ đó là vì lib của tôi khá đơn giản và không có bất kỳ sự phụ thuộc và tài nguyên nào
Paulius Vindzigelskis

Có một vấn đề LỚN với giải pháp đó: những người khác muốn sử dụng khung được tạo bởi giải pháp này (giải pháp này đề nghị cài đặt mẫu fremework cho xcode) PHẢI cài đặt mẫu này vào xcode THEIR !!!
evya

Bạn chỉ cần cài đặt mẫu cho các khung thực. Các khung giả sẽ chạy tốt trong Xcode chưa sửa đổi.
Karl

30

Có một tiện ích dòng lệnh xcodebuildvà bạn có thể chạy lệnh shell trong xcode. Vì vậy, nếu bạn không phiền khi sử dụng tập lệnh tùy chỉnh, tập lệnh này có thể giúp bạn.

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

Có thể trông không hiệu quả (tôi không giỏi về shell script), nhưng dễ hiểu. Tôi đã cấu hình một mục tiêu mới chỉ chạy tập lệnh này. Kịch bản được thiết kế cho dòng lệnh nhưng không được thử nghiệm trong :)

Khái niệm cốt lõi là xcodebuildlipo.

Tôi đã thử nhiều cấu hình trong Xcode UI, nhưng không có gì hoạt động. Vì đây là một loại xử lý hàng loạt, nên thiết kế dòng lệnh phù hợp hơn, do đó Apple đã loại bỏ tính năng xây dựng hàng loạt khỏi Xcode dần dần. Vì vậy, tôi không mong đợi họ cung cấp tính năng xây dựng hàng loạt dựa trên giao diện người dùng trong tương lai.


Cảm ơn, thật thú vị khi các lệnh đơn giản cơ bản vẫn xuất hiện để hoạt động - chỉ là Apple đã phá vỡ GUI của họ một cách ngoạn mục. Có vẻ như tôi có thể tạo một mẫu dự án hoàn toàn tùy chỉnh để "không hút" và khắc phục những thứ Apple đã phá vỡ, bằng cách tạo trước tất cả các Mục tiêu và kết nối tập lệnh này với các vars xây dựng xcode. Tôi sẽ thử nó trong dự án tiếp theo của tôi :)
Adam

1
Tôi đã sử dụng một tập lệnh tương tự như thế này và đặt nó dưới một mục tiêu mới chỉ chứa tập lệnh shell. Kịch bản xây dựng đệ quy ở trên rất thông minh, nhưng khó hiểu một cách không cần thiết.
benzado

1
Tôi thích kịch bản shell cho những thứ như thế này, đây là gist.github.com/3178578
slf

@benzado Vâng Tôi cố tình tránh sự phức tạp vì tôi nghĩ kịch bản shell phải dễ đọc để sửa đổi.
Eonil

lipo: không thể mở tệp đầu vào: / Debug-iphoneos /
Dima

11

Tôi cần một lib tĩnh chất béo cho JsonKit vì vậy đã tạo một dự án lib tĩnh trong Xcode và sau đó chạy tập lệnh bash này trong thư mục dự án. Miễn là bạn đã cấu hình dự án xcode với chế độ "Chỉ xây dựng cấu hình hoạt động", bạn sẽ nhận được tất cả các kiến ​​trúc trong một 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

Cập nhật iOS 10:

Tôi gặp vấn đề với việc xây dựng fatlib với iphoneos10.0 vì biểu thức thông thường trong tập lệnh chỉ mong đợi 9.x trở xuống và trả về 0,0 cho ios 10.0

để khắc phục điều này chỉ cần thay thế

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

với

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

Cảm ơn. Tôi đã thực hiện thay đổi tương tự sáng nay, nhưng đã sử dụng \ d. Cái này tôi nghĩ là cái chúng tôi muốn (nó tốt hơn hay tệ hơn của bạn?) ... grep -o '\ d \ {1,2 \} \. \ D \ {2 \} $'
Adam

Tôi nghĩ rằng tôi là đáng tin cậy hơn vì nó chỉ xem xét số
ben

1
Không, của bạn phù hợp với 1 cách viết chữ số cụ thể. Được Apple hỗ trợ lịch sử cho (và sử dụng) các ký tự và văn bản đã được chỉnh sửa (ví dụ như trong tên tệp) Tôi hy vọng lựa chọn độc quyền của bạn về một vài chữ số sẽ ít đáng tin cậy hơn.
Adam

1
được rồi có lẽ bạn đúng ít nhất tôi có dự án của tôi cũng làm việc và chúng tôi rất an toàn cho 89 ios phiên bản tiếp theo
ben

Giải pháp @ben hoạt động với tôi, regex của Adam '[\\. 0-9] \ {3,4 \} $' đưa ra mã lỗi 2
Zee

4

Tôi đã biến nó thành một mẫu Xcode 4 , giống như mẫu khung tĩnh của Karl.

Tôi thấy rằng việc xây dựng các khung tĩnh (thay vì các thư viện tĩnh đơn giản) đã gây ra sự cố ngẫu nhiên với LLVM, do lỗi liên kết rõ ràng - vì vậy, tôi đoán rằng các thư viện tĩnh vẫn hữu ích!


Xin chào Michael, tôi đã thử mẫu thư viện tĩnh của bạn nhưng tôi có thể biên dịch cho trình giả lập nhưng không phải cho thiết bị, đây là lỗi: ** BUILD FAILED ** Các lệnh xây dựng sau không thành công: ProcessPCH / var / thư mục / qy / ncy6fkpn6677qt876ljrc54m0000gn / C / com .apple.Xcode.501 / SharedPrecompiledHeaders / MenuBarUniversal-Prefix-gwxxzpanxyudmfgryorafazokagi / MenuBarUniversal-Prefix.pch.pth Menu của bạn ) Chỉ hiển thị 200 thông báo đầu tiên Lệnh / bin / sh không thành công với mã thoát 65
Kappe

2

Bạn đã làm rất tốt! Tôi đã hack cùng một cái gì đó tương tự, nhưng phải chạy nó một cách riêng biệt. Có nó chỉ là một phần của quá trình xây dựng làm cho nó đơn giản hơn rất nhiều.

Một mục lưu ý. Tôi nhận thấy rằng nó không sao chép bất kỳ tệp nào mà bạn đánh dấu là công khai. Tôi đã điều chỉnh những gì tôi có trong kịch bản của mình với kịch bản của bạn và nó hoạt động khá tốt. Dán đoạn sau vào cuối tập lệnh của bạn.

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
OK, tôi đã thêm nó vào câu trả lời ở trên. (chưa có cơ hội để kiểm tra nó, nhưng có vẻ đúng với tôi)
Adam

1

Tôi thực sự chỉ viết kịch bản của riêng tôi cho mục đích này. Nó không sử dụng Xcode. (Nó dựa trên một kịch bản tương tự trong dự án Gambit Scheme.)

Về cơ bản, nó chạy ./mình và thực hiện ba lần (đối với i386, armv7 và armv7) và kết hợp mỗi thư viện kết quả thành một lib béo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.