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에는 범용 fat 프레임 워크를 자동으로 내보내는 도구가 없으므로 개발자는 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 를 사용하여이 두 프레임 워크를 결합
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에 제출할 때 불필요한 슬라이스를 제거하는 데 사용할 수없는 팻 프레임 워크를 만들 필요가 없습니다 .
답변
기본적으로 나는 아주 좋은 해결책을 찾았습니다. 이 간단한 단계를 따르기 만하면됩니다.
- 코코아 터치 프레임 워크를 만듭니다.
- 활성화 된 비트 코드를 아니요로 설정합니다.
- 대상을 선택하고 편집 구성표를 선택하십시오. 실행을 선택하고 정보 탭에서 릴리스를 선택합니다.
- 다른 설정은 필요하지 않습니다.
- 이제 시뮬레이터가 x86 아키텍처에서 실행되므로 모든 시뮬레이터에 대한 프레임 워크를 빌드하십시오.
- Project Navigator에서 Products 그룹을 클릭하고 .framework 파일을 찾습니다.
- 그것을 마우스 오른쪽 버튼으로 클릭하고 Finder에 표시를 클릭하십시오. 아무 폴더 에나 복사하여 붙여 넣으십시오. 개인적으로 ‘시뮬레이터’라는 이름을 선호합니다.
- 이제 Generic iOS Device 용 프레임 워크를 빌드하고 6-9 단계를 따르십시오. 폴더 이름을 ‘simulator’대신 ‘device’로 변경하면됩니다.
- 장치 .framework 파일을 복사하고 다른 디렉토리에 붙여 넣습니다. 나는 둘 다의 즉각적인 슈퍼 디렉토리를 선호합니다. 따라서 디렉토리 구조는 다음과 같습니다.
- 데스크탑
- 장치
- MyFramework.framework
- 모의 실험 장치
- MyFramework.framework
- MyFramework.framework 이제 터미널을 열고 데스크탑으로 cd합니다. 이제 다음 명령을 입력하십시오.
lipo -create ‘device / MyFramework.framework / MyFramework’ ‘simulator / MyFramework.framework / MyFramework’-output ‘MyFramework.framework / MyFramework’
그리고 그게 다야. 여기서 우리는 MyFramework.framework 안에있는 MyFramework 바이너리의 시뮬레이터와 장치 버전을 병합합니다. 시뮬레이터 및 장치를 포함한 모든 아키텍처를 위해 빌드되는 범용 프레임 워크를 얻습니다.
답변
@odm 의이 훌륭한 답변 을 업데이트 하고 싶습니다. Xcode 10 이후 CURRENT_ARCH
변수는 더 이상 빌드 아키텍처를 반영하지 않습니다. 그래서 대신 플랫폼을 확인하도록 스크립트를 변경했습니다.
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
또한 복사하기 전에 대상 디렉터리를 지우는 줄을 추가했습니다. 그렇지 않으면 하위 디렉터리의 추가 파일을 덮어 쓰지 않을 것임을 알았습니다.
답변
내 답변은 아래 사항을 다룹니다.
-
시뮬레이터와 장치 모두에서 작동하는 프레임 워크 만들기
-
“뚱뚱한”Cocoa Touch Framework를 내보내는 방법 (시뮬레이터 및 장치 모두)?
-
아키텍처 x86_64에 대한 정의되지 않은 기호
-
ld : 아키텍처 x86_64에 대한 기호를 찾을 수 없습니다.
1 단계 : 먼저 Simulator 타겟으로 프레임 워크 빌드
2 단계 : 시뮬레이터 빌드 프로세스가 성공한 후 이제 장치 대상 선택 또는 일반 iOS 장치 선택으로 프레임 워크 용으로 빌드합니다.
3 단계 : 이제 프레임 워크 대상을 선택하고 “Build Phases”에서 “Add Run Script”를 선택하고 아래 스크립트 코드를 복사합니다.)
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"