Xcode 및 SDK 4+를 사용하여 fat 정적 라이브러리(장치 + 시뮬레이터) 구축
이론적으로 시뮬레이터와 iPhone 및 iPad를 모두 포함하는 단일 정적 라이브러리를 구축할 수 있는 것으로 보입니다.
그러나 Apple에는 내가 찾을 수 있는 문서가 없으며 Xcode의 기본 템플릿은 이를 수행하도록 구성되어 있지 않습니다.
저는 Xcode 안에서 할 수 있는 간단하고 휴대가 가능한 재사용 가능한 기술을 찾고 있습니다.
일부 기록:
- 2008년에는 심과 장치를 모두 포함하는 단일 정적 립을 만들 수 있었습니다.애플은 그것을 무효화했습니다.
- 2009년 내내 우리는 정적 립 쌍을 만들었습니다. 하나는 심, 하나는 장치용입니다.애플도 이제 그것을 비활성화했습니다.
참조:
이것은 좋은 생각이고, 훌륭한 접근 방식이지만, 효과가 없습니다: http://www.drobnik.com/touch/2010/04/universal-static-libraries/
- 그의 스크립트에 버그가 있다는 것은 그의 컴퓨터에서만 작동한다는 것을 의미합니다. 그는 그것들을 "게스트"하는 대신 BUILT_PRODUCT_DIR 및/또는 BUILT_DIR을 사용해야 합니다.)
- Apple의 최신 Xcode는 Xcode가 대상을 처리하는 방식의 (문서화된) 변경으로 인해 그가 한 일을 수행할 수 없도록 합니다.
다른 SO 질문자는 xcode를 사용하지 않고 암6 대 암7 부분에 초점을 맞춘 응답을 했지만 i386 부분은 무시했습니다.armv6, armv7 및 i386용 정적 라이브러리(지방)를 컴파일하려면 어떻게 해야 합니까?
- Apple의 최근 변경 이후 Simulator 부분은 더 이상 암6/암7 차이와 같지 않습니다. 다른 문제입니다. 위 참조)
대안:
최신 버전을 쉽게 복사/붙여넣기(그러나 설치 지침이 변경될 수 있음 - 아래 참조!)
Karl의 라이브러리는 설정하는 데 훨씬 더 많은 노력이 들지만 훨씬 더 나은 장기적인 해결책(라이브러리를 프레임워크로 변환)입니다.
이것을 사용한 다음, 아카이브 빌드에 대한 지원을 추가하도록 수정합니다. c.f. @Frederik은 아카이브 모드에서 이 작업을 잘 수행하기 위해 사용하는 변경 사항에 대해 아래에 설명합니다.
최근 변경사항: 1.iOS 10.x에 대한 지원 추가(이전 플랫폼에 대한 지원 유지)
프로젝트에 포함된 다른 프로젝트와 함께 이 스크립트를 사용하는 방법에 대한 정보(비록 그렇게 하지 않는 것을 강력히 권장하지만, 애플은 Xcode 3.x에서 Xcode 4.6.x에 이르는 프로젝트를 서로 내부에 포함시키면 Xcode에 몇 가지 표시 중지 버그가 있습니다.)
번들을 자동으로 포함할 수 있는 보너스 스크립트(즉, 라이브러리에서 PNG 파일, PLIST 파일 등 포함!) - 아래를 참조하십시오(아래로 스크롤).
이제 iPhone5를 지원합니다(lipo의 버그에 대한 Apple의 해결 방법 사용).참고: 설치 지침이 변경되었습니다(나중에 스크립트를 변경하여 이 작업을 단순화할 수 있지만 지금은 위험을 감수하고 싶지 않습니다).
"copy headers" 섹션은 이제 공용 헤더의 위치에 대한 빌드 설정을 준수합니다(프레데릭 월너의 요청).
Doug Dickinson 덕분에 SYMROOT의 명시적 설정이 추가되었습니다(OBJROOT도 설정해야 합니까?).
SCRIPT(복사/붙여넣기 작업)
사용/설치 지침은 아래를 참조하십시오.
##########################################
#
# c.f. https://stackoverflow.com/questions/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
설치 지침
- 정적 lib 프로젝트 생성
- 대상 선택
- "Build Settings" 탭에서 "Build Active Architecture Only"를 "No"(모든 항목에 대해)로 설정합니다.
- "빌드 단계" 탭에서 "추가..."를 선택합니다.새 빌드 단계...새 실행 스크립트 빌드 단계"
- 상자에 스크립트(위) 복사/붙여넣기
...보너스 선택적 사용:
- 선택사항: 라이브러리에 머리글이 있는 경우 "머리글 복사" 단계에 머리글을 추가합니다.
- 선택 사항: ...그리고 "프로젝트" 섹션에서 "공용" 섹션으로 드래그/드롭합니다.
- 선택 사항: ...앱을 구축할 때마다 자동으로 "debug-universal" 디렉터리의 하위 디렉터리로 내보냅니다(usr/local/include).
- 선택 사항: 참고: 프로젝트를 다른 Xcode 프로젝트로 드래그/드롭하려고 하면 Xcode 4의 버그가 노출되며, 드래그/드롭된 프로젝트에 공용 헤더가 있으면 .IPA 파일을 만들 수 없습니다.해결 방법: xcode 프로젝트를 포함하지 마십시오(애플 코드에 버그가 너무 많습니다!)
출력 파일을 찾을 수 없는 경우 해결 방법은 다음과 같습니다.
스크립트의 맨 끝에 다음 코드를 추가합니다(프레데릭 월너의 호의로). "${CREATION_UNIVEL_DIR}" 열기
Apple은 200줄 이후의 모든 출력을 삭제합니다.대상을 선택하고 스크립트 실행 단계에서 "빌드 로그에 환경 변수 표시"를 해제해야 합니다.
XCode4에 대해 사용자 정의 "빌드 출력" 디렉터리를 사용하는 경우 XCode는 모든 "예상치 못한" 파일을 잘못된 위치에 배치합니다.
- 프로젝트 빌드
- Xcode4의 왼쪽 상단 영역에서 오른쪽의 마지막 아이콘을 클릭합니다.
- 맨 위 항목을 선택합니다(이것이 "가장 최근 빌드"입니다).Apple은 자동으로 선택해야 하지만, 그들은 그것을 생각하지 못했습니다.)
- 기본 창에서 아래로 스크롤합니다.출력 파일을 생성하는 마지막 행은 /Users/blah/Library/Developer/Xcode/DerivedData/AppName-ashwnbut vodmoleizzlncudsekyf/Build/Products/Debug-universal/libTargetName입니다.
...유니버설 빌드의 위치입니다.
프로젝트에 "비소스 코드" 파일을 포함하는 방법(PNG, PLIST, XML 등)
- 위의 모든 작업을 수행하여 작동하는지 확인합니다.
- 첫 번째 실행 스크립트 다음에 오는 새 실행 스크립트 단계를 만듭니다(아래 코드 복사/붙여넣기).
- "bundle" 유형의 새 대상을 Xcode로 생성
- 주 프로젝트의 "빌드 단계"에서 새 번들을 "의존" 항목으로 추가합니다(위쪽 섹션, 더하기 버튼을 누르고 아래쪽으로 스크롤한 후 제품에서 ".bundle" 파일을 찾습니다).
- 새 번들 대상의 "빌드 단계"에서 "번들 리소스 복사" 섹션을 추가하고 모든 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}"
저는 armv7, armv7 및 시뮬레이터에서 작동할 뚱뚱한 정적 라이브러리를 구축하기 위해 많은 시간을 보냈습니다.드디어 해결책을 찾았습니다.
요점은 두 개의 라이브러리(장치용으로 하나, 시뮬레이터용으로 하나)를 개별적으로 구축하고 서로 구별할 수 있도록 이름을 바꾼 다음 하나의 라이브러리로 리포를 만드는 것입니다.
lipo -create libPhone.a libSimulator.a -output libUniversal.a
제가 해봤는데 효과가 있어요!
일반 라이브러리를 만드는 것만큼 쉽게 범용 프레임워크를 만들 수 있는 XCode 4 프로젝트 템플릿을 만들었습니다.
명령줄 유틸리티가 있습니다.xcodebuild
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}"
비효율적으로 보일 수도 있지만(나는 셸 스크립트를 잘 하지 못합니다), 이해하기 쉽습니다.이 스크립트만 실행하는 새 대상을 구성했습니다.이 스크립트는 명령줄용으로 설계되었지만 에서 테스트되지 않았습니다. :)
핵심 컨셉은.xcodebuild
그리고.lipo
.
Xcode UI 내에서 많은 구성을 시도해 보았지만 아무 것도 작동하지 않았습니다.이것은 일종의 배치 처리이기 때문에 명령줄 설계가 더 적합하기 때문에 Apple은 Xcode에서 배치 빌드 기능을 점진적으로 제거했습니다.따라서 향후에는 UI 기반 배치 빌드 기능을 제공하지 않을 것으로 예상됩니다.
저는 JsonKit용 fat static lib가 필요해서 Xcode로 static lib 프로젝트를 만든 다음 프로젝트 디렉토리에서 이 bash 스크립트를 실행했습니다."활성 구성만 빌드"가 해제된 상태에서 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
IOS 10 업데이트:
스크립트의 정규식이 9.x 이하만 예상하고 ios 10.0에 대해 0.0을 반환하기 때문에 iphoneos 10.0으로 fatlib을 구축하는 데 문제가 있었습니다.
이 문제를 해결하려면 그냥 대체합니다.
SDK_VERSION=$(echo ${SDK_NAME} | grep -o '.\{3\}$')
와 함께
SDK_VERSION=$(echo ${SDK_NAME} | grep -o '[\\.0-9]\{3,4\}$')
저는 이것을 칼의 정적 프레임워크 템플릿과 같은 맥락에서 Xcode 4 템플릿으로 만들었습니다.
저는 (평범한 정적 라이브러리 대신) 정적 프레임워크를 구축하는 것이 명백한 링커 버그로 인해 LLVM과 무작위 충돌을 일으킨다는 것을 발견했습니다. 그래서, 정적 라이브러리는 여전히 유용하다고 생각합니다!
XCode 12 업데이트:
실행하는 경우xcodebuild
없이-arch
를 defaultparam으로 하는 시뮬레이터 라이브러리를 .
다음 그럼실을 실행합니다.xcrun -sdk iphoneos lipo -create -output
입니다, 충할것다면, 하왜냐니 때문입니다.arm64
아키텍처는 시뮬레이터와 장치 라이브러리에도 존재합니다.
Adam git에서 스크립트를 포크하여 수정합니다.
정말 잘했어!저는 비슷한 것을 함께 해킹했지만, 그것을 따로 실행해야 했습니다.빌드 프로세스의 일부로 사용하면 훨씬 간편해집니다.
한 가지 주목할 점.공용으로 표시한 포함 파일을 복사하지 않습니다.저는 제 대본에 있던 것을 당신 것에 맞게 조정했고 그것은 꽤 잘 작동합니다.스크립트 끝에 다음을 붙여넣습니다.
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
사실 저는 이 목적을 위해 저만의 대본을 썼습니다.그것은 Xcode를 사용하지 않습니다.(이것은 Gambit Scheme 프로젝트의 유사한 스크립트를 기반으로 합니다.)
기본적으로 ./configure 및 make 3회(i386, armv7 및 armv7의 경우) 실행되고 결과로 생성된 각 라이브러리를 fatlib로 결합합니다.
언급URL : https://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4
'source' 카테고리의 다른 글
MC의 기능:무시할 수 있는="d"는 WPF로 표시됩니까? (0) | 2023.05.27 |
---|---|
ARC에서 @autore release 풀이 여전히 필요한 이유는 무엇입니까? (0) | 2023.05.27 |
"max_connections"와 같은 매개 변수(postgresql.conf 설정)를 쿼리합니다. (0) | 2023.05.22 |
불투명 컨트롤이 포함된 투명 배경의 WPF 창 (0) | 2023.05.22 |
어떤 버전의 MVC를 사용하고 있습니까? (0) | 2023.05.22 |