I am trying to create XCFramework using XCode 12.2.
Using following command to generate Simulator archives:
xcodebuild archive -scheme MyFramework -archivePath ~/Documents/frameworks/MyFramework_iphonesimulator.xcarchive -destination "generic/platform=iOS Simulator" -sdk iphonesimulator SKIP_INSTALL=NO
For iOS:
xcodebuild archive -scheme MyFramework -archivePath ~/Documents/frameworks/MyFramework_iphoneos.xcarchive -sdk iphoneos -destination "generic/platform=iOS" SKIP_INSTALL=NO
Then
xcodebuild -create-xcframework -framework "~/frameworks/MyFramework_iphoneos.xcarchive/Products/Library/Frameworks/MyFramework.framework" -framework "~/frameworks/MyFramework_iphonesimulator.xcarchive/Products/Library/Frameworks/MyFramework.framework" -output ~/Documents/frameworks/xcframeworks/MyFramework.xcframework
When I try to integrate and use in other project am getting error as
Undefined symbols for architecture x86_64:
"OBJC_CLASS$_SnapshotHandler", referenced from:
objc-class-ref in AppDelegate.o
SnapshotHandler is a class from MyFramework.
I checked valid architectures it set to Standard Architectures, also Build active architectures only set to NO
If I build Framework with XCode 11.6 then call valid architectures with be added (i386 & x86_64).
Any help will be appreciated.
Related
I have written the below commands in a script file to create XCFrameworks for both iPhoneSimulator and iPhoneOS like this below:
xcodebuild archive -scheme "ProjectD" -archivePath "/Users/Ron/Archives/ProjectDiphoneSimulator.xcarchive" -sdk 'iphonesimulator' SKIP_INSTALL=NO
xcodebuild archive -scheme "ProjectD" -archivePath "/Users/Ron/Archives/ProjectDiphoneOS.xcarchive" -sdk 'iphoneos' SKIP_INSTALL=NO
xcodebuild -create-xcframework -framework "/Users/Ron/Archives/ProjectDiphoneSimulator.xcarchive/Products/Library/Frameworks/ProjectDiphoneSimulator.framework" -output "/Users/Ron/XCFrameworks/ProjectDiphoneSimulator.xcframework"
xcodebuild -create-xcframework -framework "/Users/Ron/Archives/ProjectDiphoneOS.xcarchive/Products/Library/Frameworks/ProjectDiphoneOS.framework" -output "/Users/Ron/XCFrameworks/ProjectDiphoneOS.xcframework"
I tried to use this in a project after dragging and dropping it onto the Embedded Frameworks and Libraries
When I run the project with a device as the target, it works fine. But when I run it on a simulator, it throws the below error:
While building for iOS Simulator, no library was found in /Users/Ron/XCFrameworks/ProjectD.xcframework
If I change the order of the archive and XCFramework creation like below:
xcodebuild archive -scheme "ProjectD" -archivePath "/Users/Ron/Archives/ProjectDiphoneOS.xcarchive" -sdk 'iphoneos' SKIP_INSTALL=NO
xcodebuild archive -scheme "ProjectD" -archivePath "/Users/Ron/Archives/ProjectDiphoneSimulator.xcarchive" -sdk 'iphonesimulator' SKIP_INSTALL=NO
xcodebuild -create-xcframework -framework "/Users/Ron/Archives/ProjectDiphoneOS.xcarchive/Products/Library/Frameworks/ProjectDiphoneOS.framework" -output "/Users/Ron/XCFrameworks/ProjectDiphoneOS.xcframework"
xcodebuild -create-xcframework -framework "/Users/Ron/Archives/ProjectDiphoneSimulator.xcarchive/Products/Library/Frameworks/ProjectDiphoneSimulator.framework" -output "/Users/Ron/XCFrameworks/ProjectDiphoneSimulator.xcframework"
It works for simulator and not on the device with the same error:
While building for iPhone, no library was found in /Users/Ron/XCFrameworks/ProjectD.xcframework
I have set the Build Libraries for Distribution to Yes as well. If I try to create them with different destinations(2 XCFrameworks for iphone and simulator) it is working. But that literally defeats the purpose of XCFrameworks.
Am I missing something or doing any of the steps wrong? Thanks for the answers in advance.
You need to create a single .xcframework file from both .framework. (that will include simulator and device architectures) To do that run a single xcodebuild -create-xcframework command and pass the 2 different .framework files:
xcodebuild
-create-xcframework
-framework "/Users/Ron/Archives/ProjectDiphoneOS.xcarchive/Products/Library/Frameworks/ProjectDiphoneOS.framework"
-framework "/Users/Ron/Archives/ProjectDiphoneSimulator.xcarchive/Products/Library/Frameworks/ProjectDiphoneSimulator.framework"
-output "/Users/Ron/XCFrameworks/ProjectDiphoneOS.xcframework"
When you instead run 2 different xcodebuild -create-xcframework commands you have as a result your .xcframework to include only the last .framework file you passed, which is for devices. That's why your project fails to run in simulator.
Xcode (11.2.1 & 11.3.1) is having issues to found x86_64 architecture symbols while using XCFrameworks. The problem is that the architecture is inside the XCFramework, but first let me show you how the framework was created.
To generate the XCFramework I made two Archives:
For iOS:
xcodebuild archive -scheme MyPod -target MyPod -destination="iOS" -archivePath build/ios.xcarchive -derivedDataPath /tmp/iphoneos -sdk iphoneos SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
For iOS Simulator:
xcodebuild archive -scheme MyPod -target MyPod -destination="iOS Simulator" -archivePath build/iossimulator.xcarchive -derivedDataPath /tmp/iphoneos -sdk iphonesimulator SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
Then I generated the XCFramework:
xcodebuild -create-xcframework -framework ./build/ios.xcarchive/Products/Library/Frameworks/MyPod.framework -framework ./build/iossimulator.xcarchive/Products/Library/Frameworks/MyPod.framework -output xcframework/MyPod.xcframework
Here is the XCFramework created where we can see the two architectures:
XCFramework preview
Once it was created, I distributed it by Cocoapods (1.9.0.beta.3). So my .podspec looks like:
s.subspec "Vendored" do |framework|
framework.vendored_framework = 'xcframework/MyPod.xcframework'
end
Then I consumed it in another project, and when compiling, it fails because it can't find the architecture for the simulator (on devices it works)
The log I got is the following:
ld: warning: ignoring file /Path/To/MyProject/Pods/MyPod/xcframework/MyPod.xcframework/ios-armv7_arm64/MyPod.framework/MyPod, missing required architecture x86_64 in file /Path/To/MyProject/Pods/MyPod/xcframework/MyPod.xcframework/ios-armv7_arm64/MyPod.framework/MyPod (2 slices)
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$MyPod", referenced from:
objc-class-ref in SomeClass.o
ld: symbol(s) not found for architecture x86_64
It's looks like xcodebuild always go to the ios-armv7_arm64 folder instead the ios-i386_x86_64-simulator one, Any ideas?
Thank you!
Hey please generate with -sdk flag with this combination:
xcodebuild archive -workspace IVTNetworking.xcworkspace -scheme IVTNetworking \
-configuration Debug -sdk iphoneos \
-archivePath '/Users/chitaranjans/Library/Developer/Xcode/Archives /IVTNetworking.framework-iphoneos.xcarchive' \
SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES
This works fine as expected.
I'm trying to understand how building frameworks works more in general. I created a new framework project in Xcode 10 and I can see in Build Settings arm64 armv7 armv7s all defined in Valid Architectures. When I make a build for Generic iOS Device and use lipo -info I get only armv7 arm64 and no armv7s. I tried to do it from the command line as well:
xcodebuild -configuration Release -sdk iphoneos -target FrameworkExample ONLY_ACTIVE_ARCH=NO BUILD_DIR="BUILD_DIR"
I also tried manually passing each architecture
-arch armv7s -arch arm64 -arch armv7 but I only got armv7 and arm64 again.
I also tried using destination
-destination generic/platform=iOS
Same result.
My project's Deployment Target and Framework Targets are both set to 8.0.
Environment: XCode 7.0.1
Module: Objective-C
Bundle Type: Framework
Hi, I am trying to create a framework to support armv7, armv7s, arm64, i386 and x86_64. I am using aggregate to make the fat library. Inside the aggregate script, i am running two xcodebuild commands 1. for armv7, armv7s and arm64 and 2. for i386 and x86_64 architectures. Also, I have set Enable Bitcode=YES and Other C Flags=-fembed-bitcode under target build settings. As a precautionary mesasure, i am adding ENABLE_BITCODE=YES and OTHER_CFLAGS="-fembed-bitcode" options to the xcodebuild command
My xcode build commands are as follows -
#Build The framework Target for iPhoneOS
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${AN_TARGET}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphoneos
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="armv7 armv7s arm64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION
#Build The framework Target for iPhoneSimulator
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${AN_TARGET}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphonesimulator
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_SIMULATOR_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="i386 x86_64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION
after running the above two commands, i am combining these two builds to make a fat framework binary using the below command
# create a fat Framework
lipo -create
"${IPHONE_DEVICE_BUILD_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}"
"${IPHONE_SIMULATOR_BUILD_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}" -
output "${FRAMEWORK_FOLDER}/${AN_END_USER_FRAMEWORK_NAME}"
The issue iam facing is after the lipo is created, i am unable to use it in the bitcode enabled application. After running the otool -l framework_binary | grep -LLVM, i do not see the bitcode enabled flags or __LLVM.
Lipo removes bitcode from the fat binary. Is there a way i can retain bitcode while running the lipo command?
Correction: Based on the reply from Nestor, i ran the otool command as otool -l -arch armv7 framework_binary | grep LLVM and much to my surprise, i could see the segname __LLVM clang. However when i integrate the same fat framework binary into my project, it builds fine on simulator however throws the following error while running on device - ld: 'MyBinary' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7
Happily it's just a problem with otool's reporting, not lipo; you have to add the -arch parameter:
otool -arch arm64 -l myLipoOutput.a
Source: http://www.openradar.me/radar?id=6301306440384512
This is something weird, there are not many documentation for do this, at the end I use this command:
xcodebuild -project ${PROJECT_NAME}.xcodeproj -target ${FRAMEWORK_NAME} ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode FRAMEWORK_SEARCH_PATHS="${FRAMEWORK_SEARCH_PARTH} ${SRCROOT}/**" -sdk ${SIMULATOR_SDK} -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-${SIMULATOR_SDK} 2>&1
xcodebuild -project ${PROJECT_NAME}.xcodeproj -target ${FRAMEWORK_NAME} -sdk ${DEVICE_SDK} ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode FRAMEWORK_SEARCH_PATHS="${FRAMEWORK_SEARCH_PARTH} ${SRCROOT}/**" -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-${DEVICE_SDK} 2>&1
Add the BITCODE_GENERATION_MODE=bitcode flag to the xcodebuild command
Try to use archive for the arm slices instead of build
xcodebuild -scheme "${SCHEME}" -workspace "${WORKSPACE}" -configuration "${CONFIGURATION}" -sdk iphoneos ARCHS="arm64 armv7 armv7s" CONFIGURATION_BUILD_DIR="${CONFIGURATION_BUILD_DIR}/arm" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO archive
After that run lipo to merge the simulator and the arm ones.
And after that run otool -arch arm64 -l myLipoOutput.a and it should work.
It looks like a bug in Xcode 7.0.1 . I've had the same issue and downgrading Xcode to version 7 fixed it.
Update:
Actually it may be a bug in Xcode 7 that was fixed in 7.0.1 - this SO answer solved the issue for me.
While i am integrating libcurl, getting the following issue.
Undefined symbols for architecture i386:
"_SSLClose", referenced from:
_Curl_darwinssl_close in libcurl.a(libcurl_la-curl_darwinssl.o)
"_SSLCopyPeerTrust", referenced from:
_darwinssl_connect_common in libcurl.a(libcurl_la-curl_darwinssl.o)
"_SSLCreateContext", referenced from:
_darwinssl_connect_common in libcurl.a(libcurl_la-curl_darwinssl.o)
_darwinssl_connect_common in libcurl.a(libcurl_la-curl_darwinssl.o)
_Curl_darwinssl_close in libcurl.a(libcurl_la-curl_darwinssl.o)
"_SSLGetBufferedReadSize", referenced from:
The static library that you have added libcurl.a is meant for device. you are trying to build your application for simulator (i386 is for Mac). Either change your libcurl.a or build your application for Device would solve your problem.
I once ran this an issue like this with another library. The problem is that the simulator runs on an x86 processor and the actual device is on ARM, you actually need two separate builds of the library in the project. One for the simulator and one for ARM. If you are targeting ARM-64, you will need a build for it too.
Replace this in your Run Script... Hope this will fix
define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
Step 1. Build Device and Simulator versions
xcodebuild -target GEOAuthAuthentication ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target GEOAuthAuthentication -configuration ${CONFIGURATION} -sdk iphonesimulator -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target GEOAuthAuthentication -configuration ${CONFIGURATION} -sdk iphonesimulator -arch x86_64 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" TARGET_BUILD_DIR="./build-x86_64"
make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
Step 2. Create universal binary file using lipo
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a" "./build-x86_64/lib${PROJECT_NAME}.a"
Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
Check in your Targets->Build Phases-> Link Binary With Labraries is all required frameworks and libraries added