Aggregate Script for iOS framework with Bitcode - ios

I have a iOS framework and I want to generate a universal target full bitcode support, right now I create an aggregate script and I'm using the xcodebuild command to generate the different versions (device and simulator) but when we try to generate the archive we always receive the error because the library doesn't have full bitcode support.
This is how I'm using the xcodebuild command:
xcodebuild -fembed-bitcode -project ${PROJECT_NAME}.xcodeproj -sdk iphonesimulator -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator 2>&1
xcodebuild -fembed-bitcode -project ${PROJECT_NAME}.xcodeproj -sdk iphoneos -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos 2>&1

At the end the only way that I found to achieve this is first, generating the device build with Product -> Archive (Make sure to select on "Skip Installs" to NO on "Build Settings", to get the device framework) then create a package manually using the lipo command using the two builds: the Device's framework and the Simulator's framework.
The bitcode is only generated when you use the Archive command, if you use a build command Xcode won't generate the bitcode

Related

Universal Framework Binaries: Why Build Simulator and Archive Device?

I am using a script provided by Greg Brown to successfully build a universal framework binary. Here are the two lines that invoke xcodebuild:
xcodebuild archive -project $FRAMEWORK_DIR/$FRAMEWORK.xcodeproj -scheme $FRAMEWORK -sdk iphoneos SYMROOT=$BUILD
xcodebuild build -project $FRAMEWORK_DIR/$FRAMEWORK.xcodeproj -target $FRAMEWORK -sdk iphonesimulator SYMROOT=$BUILD
Note that the archive action is being used to produce the device (arm64 architecture) whereas the build action is being used to produce the simulator (x86_64 architecture).
In a different article entitled iOS 9 Universal Cocoa Touch Frameworks the author remarks: "Note that you will both have to build with your Simulator and Archive with your device to get a universal."
So, what's up with build vs archive? Why not build both?
So, what's up with build vs archive? Why not build both?
The way it works is that Apple doesn't allow simulator binaries (x86_64 and i386) to be uploaded to the app store. If your frameworks contain those binaries, then you won't be able to upload the containing app to the app store.
You would distribute your framework with all the possible binaries so that it can run on Simulators and devices alike. But would like to strip off those Simulator binaries before uploading to the app store.
P.S. I've explained this in detail in another answer here. The answer also explains as to why the issue doesn't exist when using frameworks via Cocoapods.
Edit:
The difference between build vs archive is that archive accepts a scheme to run.
An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.
Also,
You cannot use archive option for the iOS Simulator platform.
You could essentially use xcodebuild build for both of the platforms. You will essentially get the same result. The commands that I use to build my framework are as follows (both commands use the build action):
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} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

How to build a release version of an iOS framework in Xcode?

Let's say I do the following:
Open Xcode 7
File | New | Project | Cocoa Touch Framework
Create "TestFramework" with the Swift language
Create a file Hello.swift with public func hello() { print("Hello") }.
From here, I can build a debug build of the framework (inside the Debug-iphoneos folder), but I cannot figure out how to build the release version of the framework (inside Release-iphoneos). I thought Archive might do it, but it doesn't. Pointers please?
To get a release build, you need to change your scheme settings:
Alternatively, create a new scheme for release builds.
Ensure you have a device selected. Not the simulator.
Build your project and you should see that it gets added to this location:
(Click the arrow to navigate there in finder)
And after drilling down, you should be able to find the release folder with your release framework inside.
This works for me:
Select your framework target then click Product -> Archive. If organizer window does not pop up after successful build of your framework then go to "Build Settings" of your framework target, look for the option "Skip Install" and change it to "No" (and after that Archive again).
An alternative to building a framework via the Xcode IDE is to build it from the command line.
You can produce a release build of your framework for iphoneos devices with the following command:
xcodebuild -workspace TestSDK.xcworkspace -scheme TestSDK -configuration Release -sdk iphoneos
You can change the value of the -configuration argument from Release to Debug in order to produce a debug build, or change the value of the -sdk argument from iphoneos to iphonesimulator in order to produce a build for Simulator devices.
Note that you may need to provide the -project argument instead of -workspace if your target is part of an Xcode project only and not part of an Xcode workspace. Run the xcodebuild -help command for the full list of xcodebuild options.
If you prefer to archive, you can do that from the command line also, as follows:
xcodebuild archive -workspace TestSDK.xcworkspace -scheme TestSDK -configuration Release -sdk iphoneos -archivePath "TestSDK_Release_iphoneos.xcarchive" SKIP_INSTALL=NO
Note that you can specify SKIP_INSTALL=NO as part of your project or target's Build Settings instead if you prefer.
Lastly, if you want to join up your iphoneos and iphonesimulator builds into a single binary, you can do that with the xcodebuild -create-xcframework command as follows:
xcodebuild -create-xcframework \
-framework "TestSDK_Release_iphoneos.xcarchive/Products/Library/Frameworks/TestSDK.framework" \
-framework "TestSDK_Release_iphonesimulator.xcarchive/Products/Library/Frameworks/TestSDK.framework" \
-output "TestSDK.xcframework"
See here for the official guide to creating an XCFramework.
When you add the framework to your other Xcode project then you have to add "$(BUILT_PRODUCTS_DIR)" to Build Settings -> Framework Search Paths.
This will create Debug when you run project (with Debug) and will create Release version when you archive project.
The archive doesn't will create Release version under Products dir but will create Release in "Intermediates.noindex" folder.

Using xcodebuild to build different platform

I have a framework project and I'm trying to build a fat file (iphoneos + iphonesimulator) using a script build phase, but it's not working. The script is simple; it checks the platform being currently built, like to:
if [[ "$SF_SDK_PLATFORM" = "iphoneos" ]]
then
SF_OTHER_PLATFORM=iphonesimulator
else
SF_OTHER_PLATFORM=iphoneos
fi
And then uses xcodebuild to build it:
xcrun xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -sdk ${SF_OTHER_PLATFORM} -configuration "${CONFIGURATION}" BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}" $ACTION
Other details on the script have been omited for simplicity.
If I chose the initial target as the simulator, this works fine, and both the simulator and device binaries are generated and I use lipo to get the fat file. The problem happens when I do it the other way around, and build the device file, and as such xcodebuild is called for the iphonesimulator SDK. The build fails with the following error:
CodeSign error: entitlements are required for product type 'Framework' in SDK 'Simulator - iOS 8.4'. Your Xcode installation may be damaged.
If I change the -sdk option I get the build, but not the simulator build, which is what I need. This would be (kinda) fine, but in order to build for release (Archive) I need to set the device as the primary target, or otherwise xcode doesn't give me the option.
What should I do?
It looks like you need to put your script in an aggregate target type. It was designed for exactly such cases: two different targets in one build.
What I do is create a new target (Other->Aggregate type) and add a script to it and use that target to create a fat release product.
Here's the script I'm using:
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -sdk iphonesimulator -configuration Release
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -sdk iphoneos -configuration Release
mkdir -p ${TARGET_BUILD_DIR}/../MyApp${CURRENT_PROJECT_VERSION}
cp -r ${TARGET_BUILD_DIR}/../Release-iphoneos/ ${TARGET_BUILD_DIR}/../MyApp${CURRENT_PROJECT_VERSION}
lipo -create "${TARGET_BUILD_DIR}/../Release-iphoneos/MyApp.framework/MyApp" "${TARGET_BUILD_DIR}/../Release-iphonesimulator/MyApp.framework/MyApp" -output "${TARGET_BUILD_DIR}/../MyApp${CURRENT_PROJECT_VERSION}/MyApp.framework/MyApp"
Works like a charm. It creates a folder with the version number (you set it in your new target) and a fat framework inside.
EDIT:
Why this didn't work for you.
Developer is free to distribute iOS framework without codesigning it
as Consumer will re-codesign it anyway, but Developer is forced by
Xcode to codesign his framework when he builds for iOS device.
Creating iOS/OSX Frameworks: is it necessary to codesign them before distributing to other developers?
When you're using the device target you're forced to code sign even if you don't have to. That's why it works with the aggregate target -> it's not expected of you to codesign and you don't need to codesign to release a framework.
Selecting the simulator, the process works fine because you are building using the Debug configuration I think.
In the Project navigator, select your project. Now select your target and under the Build Settings tab, check Code Signing Identity settings.
If you expand that, you should see a row for every configuration you set in your project (if you didn't, you should see the default Debug and Release rows).
Now check under the Release row (that is the default used when the Archive command is called) that is set the correct identity (this is based on what you selected under Provisioning Profile).
If you want to know more about provisioning profiles, signing identity and so on, check this link from Apple

Terminal Command build xcode project for 64 bit with all other also

I am using below command :
xcodebuild -project $PROJECT_NAME.xcodeproj -scheme $PROJECT_NAME -sdk iphonesimulator -configuration Debug
xcodebuild -project $PROJECT_NAME.xcodeproj -scheme $PROJECT_NAME -sdk iphoneos -configuration Debug
for building the application it's working but I need to build our application with iphone/ipad retina 64 bit but it' not working.
for combining
lipo -create "${WS_DIR}/Build/Debug-iphoneos/libRPCCore.a" "${WS_DIR}/Build/Debug-iphonesimulator/libCore.a" -output "${WS_DIR}/Build/RPCLib/libCore.a"
I am not able to build the application for ipad/ipahone retina 64 bit application using terminal command. please help to create the build script.
I suspect this is because you have Build Active Architecture Only set for Debug mode, which is the default setting I believe. This is because there is no need to build for all architectures during debugging as the build is expected to run only on the device being used for debugging.
This is normally turned off for release and you can test this from the command line by using -configuration Release.
BTW I don't believe you need to specify the -sdk option to xcodebuild as the build settings should have that covered.

xcodebuild doesn't work when specifying -sdk option

I'm trying to manually compile an xcode project and I can't manage to compile it using xcodebuild when I specify an SDK through the -sdk option.
This fails:
/usr/bin/xcodebuild -project "libjpeg.xcodeproj" -configuration "Release" -sdk iphonesimulator -arch i386 CONFIGURATION_BUILD_DIR=build build
and this works:
/usr/bin/xcodebuild -project "libjpeg.xcodeproj" -configuration "Release" -arch i386 CONFIGURATION_BUILD_DIR=build build
I have installed XCode 4.3.3 and Command line tools from the Apple's developer page, and everything else it's working without problems. If I build this project using XCode, it works without problems too. There's no other xcode version in my system.
I should have something really broken in my env, but I can't manage to find it. I'd appreciate any hints you could give me.
You need to specify something like -sdk iphonesimulator6.0
See this answer: parameter for xcodebuild for using latest sdk.

Resources