Why am I getting this error while creating XCFramework?: While building for iOS Simulator, no library was found in path - ios

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.

Related

Embedding SPM packages inside xcframework

I have a xcframework project which has imported a few Swift package manager dependencies. I am building this framework with the following commands to create a universal binary.
xcodebuild -project Proj.xcodeproj archive -scheme Proj -sdk iphoneos -configuration Release clean build -derivedDataPath archives/device BUILD_LIBRARY_FOR_DISTRIBUTION=YES SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO
xcodebuild -project Proj.xcodeproj archive -scheme Proj -sdk iphonesimulator -configuration Release clean build -derivedDataPath archives/simulator BUILD_LIBRARY_FOR_DISTRIBUTION=YES SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO
xcodebuild -create-xcframework -framework archives/device/Build/Products/Release-iphoneos/Proj.framework -framework archives/simulator/Build/Products/Release-iphonesimulator/Proj.framework -output universal/Proj.xcframework
Then I import this into my project. But I cannot resolve the modules installed in xcframework. It says module is not found. What I want to do here is to reuse the bundled SPM packages without importing them to the final project again. Build libraries for Distribution is set to Yes in xcframework Build Settings.
When I import the SPM modules in the project it self it says " Class axyz is implemented in both . One of the two will be used. Which one is undefined." This means the SPM packages seems to be imported but cannot be linked properly.
Answering my own question. Adding #_implementationOnly in each package import in the framework did the trick.

Architecture x86_64 missing while creating XCFrameworks

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.

iOS - Objective C dynamic framework emit bitcode for arch x86_64 (simulator)

Have setup a sample on Github, I'm using Xcode v 9.4.1
https://github.com/iousin/TreeFramework
Basically I'm trying to build my framework to include bitcode in the x86_64 simulator build. I tried various settings and tried building on command line, xcodebuild refuses to include bitcode in my simulator build, however it is very happy to include it in the arm64 (device) build.
All the following commands should be able to run from the same folder the above framework is checked out.
Following are the commands I've tried to build the above framework:
xcodebuild ENABLE_BITCODE[sdk=iphone*]=YES BITCODE_GENERATION_MODE=bitcode DYLIB_COMPATIBILITY_VERSION=1 -sdk iphonesimulator -configuration Release -target TreeFramework clean build
xcodebuild OTHER_CFLAGS="-fembed-bitcode" ENABLE_BITCODE[sdk=iphone*]=YES BITCODE_GENERATION_MODE=bitcode -sdk iphonesimulator -configuration Release -target TreeFramework clean build
xcodebuild OTHER_CFLAGS="-fembed-bitcode" ENABLE_BITCODE="YES" BITCODE_GENERATION_MODE="bitcode" -sdk iphonesimulator -configuration Release -target TreeFramework clean build
Ran the following to verify bitcode is emitted (it doesn't in this case).
otool -arch x86_64 -l build/Release-iphonesimulator/TreeFramework.framework/TreeFramework | grep LLVM
However when I build for a device, bitcode is included.
xcodebuild -sdk iphoneos -configuration Release -target TreeFramework clean build
Verify bitcode is emitted:
otool -arch arm64 -l build/Release-iphoneos/TreeFramework.framework/TreeFramework | grep LLVM
Appreciate any help.

Export Universal framework for distribution

i have created a framework
Now if reveal it in finder,
It have 2 directory having framework
iphoneos
iphone simmulater
Now i create an app, and drag my framework from iphoneos directory, it run fine in iphone device but gives error in simmulater.
similarely if i drag framework from iphone simulater it work fine in simmulater but give error in device.
Please how to export both directory framework in a combine.
i have try to run script of lipo using aggreation target, but it fails
please guide proper steps.
You can add similar script to your build settings Build Phase tab as Run Script
# debug sim
xcrun xcodebuild -project myFramework.xcodeproj -target myFramework -configuration Debug -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO
# release sim
xcrun xcodebuild -project myFramework.xcodeproj -target myFramework -configuration Release -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO
# debug ios
xcrun xcodebuild -project myFramework.xcodeproj -target myFramework -configuration Debug -sdk iphoneos ONLY_ACTIVE_ARCH=NO
# release ios
xcrun xcodebuild -project myFramework.xcodeproj -target myFramework -configuration Release -sdk iphoneos ONLY_ACTIVE_ARCH=NO
mkdir -p build/Release-Universal/myFramework.framework
cp -r build/Debug-iphonesimulator/myFramework.framework/* build/Release-Universal/myFramework.framework/
rm build/Release-Universal/myFramework.framework/myFramework
# lipo
lipo -create build/Release-iphoneos/myFramework.framework/myFramework build/Release-iphonesimulator/myFramework.framework/myFramework -output build/Release-Universal/myFramework.framework/myFramework

Build an iOS library with Bitcode in order to have backwards compatibility with XCode 6. How?

I am building an iOS static library and I want to provide support for bitcode. In order to achieve that I go to Build settings, search for "custom compiler flags" and add -fembed-bitcode. This builds the library with bitcode and everything works fine under XCode 7.
However by following the approach above I loose backwards compatibility with XCode 6. Having that said I have to ship 2 different library versions to my users, one with bitcode flag and one without since not everyone has upgraded to XCode 7.
Is there a way to have bitcode enabled library and have backwards compatibility without having to ship 2 different versions?
UPDATE:
Hello #Vinicius Jarina thank you for your message. I understand that you can create a fat library which I guess is a common practise. What I was doing so far was to build for both architecture:
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdK iphoneos
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator
and then call lipo to package in a fat library like:
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}"
However, how can i do it now? I tried something like this based on this link, but with no luck:
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator
xcodebuild -configuration "Release" OTHER_CFLAGS='-fembed-bitcode' -target "${FMK_NAME}" -sdk iphonesimulator
xcodebuild -configuration "Release" OTHER_CFLAGS='-fembed-bitcode' -target "${FMK_NAME}" -sdk iphoneos
and then create a fat lib like this:
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}"
how can i build in my scipt to include both and then package them in a fat-library?
UPDATE 2:
I finally managed to make this work and I list here my solution for others that may face the same issue:
xcodebuild -configuration "Release" ENABLE_BITCODE=NO -target "${FMK_NAME}" -sdK iphoneos
xcodebuild -configuration "Release" ENABLE_BITCODE=NO -target "${FMK_NAME}" -sdk iphonesimulator
xcodebuild -configuration "Release" ENABLE_BITCODE=YES -target "${FMK_NAME}" -sdk iphonesimulator
xcodebuild -configuration "Release" ENABLE_BITCODE=YES -target "${FMK_NAME}" -sdk iphoneos
and then create a fat lib like this:
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}"
You can try to create a fat-library using different libraries.
lipo -create -output libAndreasv.a libAndreasvBitcode.a libAndreasvARMv7.a libAndreasvARM64.a
This used to work for fat libraries (x86,x64,ARMv7,ARM64) should work for bitcode as well.
Perhaps I am missing something but I do not believe you can have duplicate architectures in a fat library, regardless of whether bitcode is enabled/disabled. For instance the following command causes an error for me:
lipo -create libcurl_iOS_bitcode.a libcurl_iOS_nobitcode.a -output libcurl_iOS_both.a
fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: libcurl_iOS_bitcode.a and libcurl_iOS_nobitcode.a have the same architectures (armv7) and can't be in the same fat output file

Resources