"뚱뚱한"Cocoa Touch Framework를 내보내는 방법 (시뮬레이터 및 장치 용)?
Xcode 6 을 사용하면 Dynamic Cocoa Frameworks
.
때문에:
시뮬레이터는 여전히
32-bit
라이브러리를 사용 합니다.-
2015 년 6 월 1 일부터 App Store에 제출 된 앱 업데이트는 64 비트 지원을 포함해야하며 iOS 8 SDK ( developer.apple.com ) 로 빌드되어야합니다.
장치와 시뮬레이터에서 프로젝트를 실행하려면 팻 라이브러리를 만들어야합니다. 즉, 프레임 워크에서 32 비트와 64 비트를 모두 지원합니다.
그러나 다른 프로젝트와의 향후 통합을 위해 범용 팻 프레임 워크 를 내보내는 방법 (그리고이 라이브러리를 다른 사람과 공유 하는 방법)을 찾지 못했습니다 .
재현하는 단계는 다음과 같습니다.
설정
ONLY_ACTIVE_ARCH=NO
에Build Settings
지원을 추가
armv7 armv7s arm64 i386 x86_64
로Architectures
(확실히)
- 프레임 워크를 빌드하고 Finder에서 엽니 다.
- 이 프레임 워크를 다른 프로젝트에 추가
실제 결과:
그러나 결국에는 장치와 시뮬레이터에서이 프레임 워크를 사용하여 한 번에 프로젝트를 실행하는 데 여전히 문제가 있습니다.
Debug-iphoneos
폴더 에서 프레임 워크를 가져 오면 장치에서 작동하고 시뮬레이터에서 오류가 발생합니다.ld: symbol(s) not found for architecture i386
xcrun lipo -info CoreActionSheetPicker
fat 파일의 아키텍처 : CoreActionSheetPicker는 다음과 같습니다. armv7 armv7s arm64
Debug-iphonesimulator
폴더 에서 프레임 워크를 가져 오면 시뮬레이터에서 작동합니다. 장치에 오류가 있습니다.ld: symbol(s) not found for architecture arm64
xcrun lipo -info CoreActionSheetPicker
fat 파일의 아키텍처 : CoreActionSheetPicker : i386 x86_64
그렇다면 장치와 시뮬레이터에서 작동하는 동적 프레임 워크를 만드는 방법은 무엇입니까?
이 답변은 Xcode 6 iOS 와 관련된 Cocoa Touch Framework 만들기-아키텍처 문제 이지만 중복되지는 않습니다.
최신 정보:
이 사건에 대한 "더티 핵"을 찾았습니다. 아래 내 대답을 참조하십시오 . 누군가가 더 편리한 방법을 알고 있다면 알려주세요!
이 답변의 실제는 2015 년 7 월입니다. 상황이 바뀔 가능성이 가장 높습니다.
TLDR;
현재 Xcode에는 범용 지방 프레임 워크의 자동 내보내기 도구가 없으므로 개발자는 lipo
도구 를 수동으로 사용해야합니다 . 또한 이 레이더 에 따르면 프레임 워크의 소비자 인 AppStore 개발자에게 제출하기 전에 프레임 워크에서 lipo
시뮬레이터 슬라이스를 제거 하는 데 사용해야합니다 .
더 긴 대답은 다음과 같습니다.
나는 주제 (답변 하단의 링크)에서 비슷한 조사를했습니다.
내 연구가 애플 개발자 포럼, 카르타고와 영역 프로젝트와 내 자신의 실험 탐구를 기반으로 그래서 배포에 대한 공식 문서를 찾을 수 없습니다했다 xcodebuild
, lipo
, codesign
도구를.
다음은 Apple Developer Forums thread Exporting app with Embedded framework 의 긴 인용문입니다 (나의 약간의 마크 업 포함) .
프레임 워크 프로젝트에서 프레임 워크를 내보내는 적절한 방법은 무엇입니까?
현재 유일한 방법은 정확히 수행 한 작업입니다.
- 시뮬레이터 및 iOS 장치 모두에 대한 대상을 빌드하십시오.
해당 프로젝트에 대한 Xcode의 DerivedData 폴더로 이동하고 두 바이너리를 하나의 단일 프레임 워크로 통합합니다. 그러나 Xcode에서 프레임 워크 타겟을 빌드 할 때 타겟 설정 'Build Active Architecture Only'를 'NO'로 조정해야합니다. 이렇게하면 Xcode가 여러 binarty 유형 (arm64, armv7 등)에 대한 대상을 빌드 할 수 있습니다. 이것이 Xcode에서 작동하지만 독립형 바이너리로는 작동하지 않는 이유입니다.
또한 스키마가 릴리스 빌드로 설정되어 있는지 확인하고 릴리스에 대해 프레임 워크 대상을 빌드해야합니다. 라이브러리가로드되지 않음 오류가 계속 발생하는 경우 프레임 워크의 코드 조각을 확인하십시오.
lipo -info MyFramworkBinary
결과를 사용 하고 검토하십시오.
lipo -info MyFrameworkBinary
결과는
i386 x86_64 armv7 arm64
- 최신 범용 프레임 워크에는 4 개의 슬라이스가 포함되지만 더 포함 할 수 있습니다.
i386 x86_64 armv7 arm64
최소이 4 개가 표시되지 않으면 Build Active Architecture 설정 때문입니다.
이것은 @skywinder가 대답에서 한 것과 거의 동일한 프로세스를 설명합니다.
이것이 Carthage가 lipo를 사용 하고 Realm이 lipo를 사용 하는 방법 입니다.
중요 사항
레이더가 있습니다 : Xcode 6.1.1 & 6.2 : 시뮬레이터 슬라이스가 포함 된 iOS 프레임 워크는 App Store에 제출할 수 없으며 Realm # 1163 및 Carthage # 188 에 대한 긴 토론 이 특별한 해결 방법으로 끝났습니다.
AppStore에 제출하기 전에 iOS 프레임 워크 바이너리를 시뮬레이터 슬라이스에서 제거해야합니다.
Carthage에는 특별한 코드가 있습니다 : CopyFrameworks 및 해당 문서 :
이 스크립트는 범용 바이너리에 의해 트리거 된 App Store 제출 버그를 해결 합니다.
Realm은 특별한 스크립트를 가지고 있습니다 : strip-frameworks.sh 및 해당 문서 :
이 단계는 범용 바이너리를 보관할 때 App Store 제출 버그를 해결하는 데 필요 합니다.
또한 좋은 기사 : Stripping Unwanted Architectures From Dynamic Libraries In Xcode .
strip-frameworks.sh
물론 누구나 처음부터 자유롭게 작성할 수 있지만 수정없이 완벽하게 작동 하는 Realm을 사용 했습니다.
이 질문의 또 다른 측면이 포함되어 있기 때문에 읽어 보도록 권장하는 내 주제에 대한 링크 : 코드 서명 -iOS / OSX 프레임 워크 생성 : 다른 개발자에게 배포하기 전에 코드 서명 해야합니까?
이것은 그렇게 명확한 해결책은 아니지만 내가 찾는 유일한 방법이 있습니다.
설정
ONLY_ACTIVE_ARCH=NO
에Build Settings
-
- 시뮬레이터 용 라이브러리 빌드
- 장치 용 라이브러리 빌드
Products
프레임 워크의 콘솔 폴더 에서 열기 (프레임 워크 폴더를 열고cd ..
거기에서 열 수 있음)
- 폴더 에서이 스크립트를 실행하십시오
Products
. 이 폴더에 fat Framework를 생성합니다. (또는 아래 3. 4에 설명 된대로 수동으로 수행하십시오 . )
또는:
이 스크립트로 lipo 를 사용하여이 2 개의 프레임 워크를 결합
YourFrameworkName
합니다 (프레임 워크 이름으로 대체 ).lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
기존 프레임 워크 중 하나의 새 바이너리로 교체합니다.
cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
- 이익 :
./YourFrameworkName.framework
- 즉시 사용 가능한 팻 바이너리입니다! 프로젝트로 가져올 수 있습니다!
작업 공간에없는 프로젝트의 경우 :
여기에 설명 된 대로이 요점 을 사용해 볼 수도 있습니다 . 그러나 작업 공간의 프로젝트에는 작동하지 않는 것 같습니다.
@Stainlav 답변은 매우 유용했지만 대신 두 가지 버전의 프레임 워크 (하나는 장치 용, 다른 하나는 시뮬레이터 용)를 Run Script Phase
컴파일 한 다음 실행중인 아키텍처에 필요한 미리 컴파일 된 프레임 워크를 자동으로 복사하기 위해 다음 을 추가했습니다.
echo "Copying frameworks for architecture: $CURRENT_ARCH"
if [ "${CURRENT_ARCH}" = "x86_64" ] || [ "${CURRENT_ARCH}" = "i386" ]; then
cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi
이런 식으로 저는 lipo
Realm strip-frameworks.sh
이 App Store에 제출할 때 불필요한 슬라이스를 제거하는 데 사용할 수없는 팻 프레임 워크를 만들 필요가 없습니다 .
basically for this i found very good solution. you just need to follow these simple steps.
- Create a cocoa touch framework.
- Set bitcode enabled to No.
- Select your target and choose edit schemes. Select Run and choose Release from Info tab.
- No other setting required.
- Now build the framework for any simulator as simulator runs on x86 architecture.
- Click on Products group in Project Navigator and find the .framework file.
- Right click on it and click on Show in finder. Copy and paste it in any folder, I personally prefer the name 'simulator'.
- Now build the framework for Generic iOS Device and follow the steps 6 through 9. Just rename the folder to 'device' instead of 'simulator'.
- Copy the device .framework file and paste in any other directory. I prefer the immediate super directory of both. So the directory structure now becomes:
- Desktop
- device
- MyFramework.framework
- simulator
- MyFramework.framework
- MyFramework.framework Now open terminal and cd to the Desktop. Now start typing the following command:
lipo -create 'device/MyFramework.framework/MyFramework' 'simulator/MyFramework.framework/MyFramework' -output 'MyFramework.framework/MyFramework'
and that's it. Here we merge the simulator and device version of MyFramework binary present inside MyFramework.framework. We get a universal framework that builds for all the architectures including simulator and device.
I just want to update this great answer by @odm. Since Xcode 10, the CURRENT_ARCH
variable doesn't reflect the build architecture anymore. So I changed the script to check the platform instead:
echo "Copying frameworks for platform: $PLATFORM_NAME"
rm -R "${SRCROOT}/Frameworks/Active"
if [ "${PLATFORM_NAME}" = "iphonesimulator" ]; then
cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi
I also added a line to clear the target directory before copying, because I noticed that additional files in subdirectories wouldn't be overwritten otherwise.
My Answer cover the below points:
Make framework which works for both simulator and Device
How to export “fat” Cocoa Touch Framework (for Simulator and Device both)?
Undefined symbols for architecture x86_64
ld: symbol(s) not found for architecture x86_64
Steps 1: First build your frameworks with Simulator target
Steps 2: After success of simulator building process, now build for your framework with device target selection or Generic iOS Device selection
Step 3: Now select your framework target and for that Under "Build Phases" select "Add Run Script" and copy the below script code)
4 단계 : 이제 마지막으로 다시 빌드하면 프레임 워크가 시뮬레이터와 기기 호환성을 모두 충족 할 준비가됩니다. 만세!!!!
[참고 : 최종 4 단계 이전에 호환 가능한 프레임 워크를 모두 준비해야합니다 (시뮬레이터 및 기기 아키텍처 호환 가능, 그렇지 않은 경우 위의 1 단계 및 2 단계를 올바르게 수행하십시오).
참조 이미지보기 :
쉘 영역에 아래 코드를 넣으십시오.
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/."
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
fi
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project's directory in Finder
open "${BUILD_DIR}/${CONFIGURATION}-universal"
'programing tip' 카테고리의 다른 글
github.com에서 README.md 작업 (0) | 2020.08.10 |
---|---|
체스 프로그램을 개발할 때 주어진 값으로 아래 방향 배열을 초기화하는 것의 중요성은 무엇입니까? (0) | 2020.08.10 |
인스턴스간에 내 Visual Studio Code 설정을 동기화하는 방법이 있습니까? (0) | 2020.08.10 |
불변 클래스는 어떻게 만듭니 까? (0) | 2020.08.10 |
Func 란 무엇이며 언제 어떻게 사용합니까? (0) | 2020.08.09 |