-
-
Save cromandini/1a9c4aeab27ca84f5d79 to your computer and use it in GitHub Desktop.
#!/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 "${PROJECT_DIR}" |
I've just tried adding ENABLE_BITCODE=YES
and OTHER_CFLAGS="-fembed-bitcode"
to the xcodebuild command, but without any luck :( Any help would be highly appreciated.
Here the full commands with the options added:
xcodebuild -target "${PROJECT_NAME}" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" 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 ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
Ok - as it turns out the only reason why Bitcode is not working is due to a bug in Xcode 7.3.
Setting the following on top of the script fixes the bit code issue:
# workaround for bitcode generation problem with Xcode 7.3
unset TOOLCHAINS
See this question on StackOverflow for more information: http://stackoverflow.com/questions/36184930/xcodebuild-7-3-cant-enable-bitcode
I'm having trouble getting this to pick up my Cocoapod libraries. Whereas regular target builds fine, this one throws an error on code that references 3rd party framework (in my case SwiftyJSON). Did anyone else encounter this?
Figured out the initial issue I had, when using cocoapods, -target
parameter won't work, you should instead use a combination of -workspace
and -scheme
. However, now I've encountered another issue. The framework compiled correctly into a fat binary, but when I embed it in the project to run in a simulator, I get no matching architecture in universal wrapper
error for each of cocoapod dependencies (although the architecture for the main library is there, and compilation works correctly, this is simply a crash after the simulator loads).
It sounds like each of the cocoapods libs should be lipo
ed together as well, but the simulator build is lacking the Frameworks
folder where I could grab the binaries to lipo. Is there an additional parameter I'm missing to xcodebuild
command?
Figured out where the simulator intermediate files are stored. I've modified the script to work with Cocoapods, here is my new version for those using Cocoapods as well: https://gist.github.com/atsepkov/1673c2d899470270e3eb313912aafc6f
Where to place that script in XCode ?
@mabbas007, add a run script in the build phases of the target that contains the framework. Its either a target of your app or a whole other project
Does it works for swift framework project? I tested it but it does not give me luck :(
To not run into issues with recursion (so using a post-processing code that runs after a build that then calls another build, which will run the script again and run another build, etc...), don't add your script in the build phases of your target, or the post processing on your main scheme. Create a new Aggregate target (it's on the cross platform tab) and add the script on the Build Phases there.
For Cocoapods, here's an example of what the xcodebuild command will look like:
xcodebuild -workspace YourLib.xcworkspace -scheme YourLibScheme ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
Thanks in advance for my question.
What about the dsym file. Both simulator and iphoneos will generate dsym files. Should I use lipo to combine them as well?
Add this run script in build phase of framework target:
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Next, work out if we're in SIM or DEVICE
if [ "false" == ${ALREADYINVOKED:-false} ]
then
export ALREADYINVOKED="true"
if [ ${PLATFORM_NAME} = "iphonesimulator" ]
then
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
else
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
fi
# 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 "${PROJECT_DIR}"
fi
I'm running this build script for a cocoapod project.
Im facing this error and can't figure out the solution:
lipo: can't open input file: /Users/yash/Library/Developer/Xcode/DerivedData/xxxarkglhuoabxutxcoexvaqkvhqarr/Build/Products/Debug-iphonesimulator/xxx.build/xxx (No such file or directory)
Can anybody help please?
Add to simulator build line VALID_ARCHS="x86_64 i386", and framework will support all simulators.
@i have created universal framework and it worked sucessfully with Target App. However if I want to add any external framework like Firebase or any other insider universal framework, how can we achieve that. Below is the script which is used for creating universal framework.
#!/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 "${PROJECT_DIR}"
Tested with Xcode 10?
Yes, just used it 👍
Thanks y'all 🥇
/core/build` because it was not created by the build system and it is not a subfolder of derived data
Please can any one help me when I try to run the script I got this error
nicework 👍
Thanks in advance for my question.
What about the dsym file. Both simulator and iphoneos will generate dsym files. Should I use lipo to combine them as well?
Any solution for this problem?
not working with cocoa pods dependencies. here is more information:
https://www.reddit.com/r/swift/comments/admgcu/compiled_framework_provides_bitcode_error_when/
Hello, i have import this script in my framework by follow this article. Archive work fine, it open the folder but when i copy the generated framework into my project, i have an error :
Could not find module '' for architecture 'x86_64'; found: arm64, arm, armv7
It work fine on device... Does i have make somethings wrong ?
The PROJECT_NAME should be replace by TARGET_NAME
Thanks for answer. I have the same error when build my project with framework :
Could not find module '' for architecture 'x86_64'; found: arm64, arm, armv7
There is a little more info on how this unsupported (according to Apple) feature broke in Xcode 10. Quinn suggests making a feature request so that Apple will hopefully officially support it in the future. There is also a similar script which purports to work with Xcode 10, but I have not personally tested it yet, so YMMV.
Thanks for answer. I have the same error when build my project with framework :
Could not find module '' for architecture 'x86_64'; found: arm64, arm, armv7
Is any solution for this issue
@i have created universal framework and it worked sucessfully with Target App. However if I want to add any external framework like Firebase or any other insider universal framework, how can we achieve that. Below is the script which is used for creating universal framework.
#!/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 "${PROJECT_DIR}"
Have you found a solution to include Firebase in your universal framework?
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
OUTPUT_FOLDER=${PROJECT_DIR}
make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
Step 1. Build Device and Simulator versions. This also includes the full bitcode generation of the framework
xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO clean build
xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO clean build
Step 2. Copy the framework structure (from iPhones build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
Step 3. Copy Swift modules (from iphonesimulator build) to the copied framework directory
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
Step 4. Create a 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" "${OUTPUT_FOLDER}"
Step 6. Convenience step to open the project's directory in Finder
open "${OUTPUT_FOLDER}"
I'm running this script to build a framework with cocoapods earlier in Xcode 10.3 it's working fine, But in new Xcode 11.2.1, this script is not working. can you please find me a workaround.
error ->
error: no such file or directory: '/Users/username/Documents/GitHub/sdkname/GenaratefremeWork/Pods/@/Users/username/Library/Developer/Xcode/DerivedData/SDK-ddyylnfmgscnezeppcqlekfbplzy/Build/Intermediates.noindex/SDK.build/Debug-iphoneos/SDK.build/Objects-normal/arm64/SDK.SwiftFileList'
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
This is great, but how do you avoid running steps 2,3,4,5... if step #1 doesn't actually rebuild the framework?
In other words, if no source code changes between builds, how do you avoid the copy and lipo steps?
Hi! great work! I'm having a problem with resources included in my SDK.
It seems the script creates another exe file inside the bundle.
Do you have any ideas how to handle it?
Very cool!!!
Seems to work beautiful - except for bitcode ...? When I integrate a framework built with your script into another project, Xcode is claiming "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 arm64"
Unfortunately I need bitcode - do you have any idea?