Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This run script will build the iphoneos and iphonesimulator schemes and then combine them into a single framework using the lipo tool (including all the Swift module architectures).
#!/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}"
@Tokuriku

This comment has been minimized.

Copy link

commented Jan 17, 2015

Very nice work Cromandini!

I had to make a small correction as the "iphonesimulator" folder reference was faulty at least in my case.
It is referenced here with Framework.swiftmodule but for me it's ${PROJECT_NAME}.swiftmodule.
I forked your GIST here if you want to either pull it or compare :)
https://gist.github.com/Tokuriku/96fe6f92e6f2abb87906

@cromandini

This comment has been minimized.

Copy link
Owner Author

commented Apr 6, 2015

Thanks @Tokuriku!! Fixed the error in the gist :)

@skywinder

This comment has been minimized.

Copy link

commented Apr 15, 2015

It seems, that it not works with xcworkspace. And unfortunately there is no way to get Scheme name from Xcode Build Settings. If someone found solution - please - let me know!

@abdallah-vogelo

This comment has been minimized.

Copy link

commented May 14, 2015

how can I use this build script? shall i add it as a new run script phase in the build settings?

@cromandini

This comment has been minimized.

Copy link
Owner Author

commented May 20, 2015

@codingAlchemist

This comment has been minimized.

Copy link

commented Jun 10, 2015

its pointing to a non existing directory in xcode 6
When trying to compile to a objective c project

@shoerob

This comment has been minimized.

Copy link

commented Nov 4, 2015

Added this as a run script in my project. I'm not sure what the deal is yet, but for some reason it keeps rebuilding the dependencies over and over again, and never finishes.

Edit:
I figured it out. Since I'm calling the same build process from run script in Xcode, the run script gets called over and over again, leading to something along the lines of infinite recursion.

Source for extra info:
http://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4

#!/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

#
# Original code here
# ...

fi
@AliasNSObject

This comment has been minimized.

Copy link

commented Nov 25, 2015

Thx for help ...it works

@holiday

This comment has been minimized.

Copy link

commented Jan 15, 2016

Excellent! I was wondering why my framework wasnt working, was missing the swift modules.

@jlemoignan

This comment has been minimized.

Copy link

commented Mar 9, 2016

@shoerob You Sir are a genius! I've been hacking since yesterday to get it to work, and you found the missing link. I owe you a gift next Xmas :)

@oded-regev

This comment has been minimized.

Copy link

commented Mar 15, 2016

Thanks!! that's very helpful

@vtchkmsgrn

This comment has been minimized.

Copy link

commented Mar 23, 2016

New Xcode 7.3 give some errors on build, especially on building device version. Do you have some solutions?

@marbetschar

This comment has been minimized.

Copy link

commented Apr 19, 2016

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?

@marbetschar

This comment has been minimized.

Copy link

commented Apr 19, 2016

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
@marbetschar

This comment has been minimized.

Copy link

commented Apr 19, 2016

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

@atsepkov

This comment has been minimized.

Copy link

commented May 11, 2016

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?

@atsepkov

This comment has been minimized.

Copy link

commented May 17, 2016

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 lipoed 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?

@atsepkov

This comment has been minimized.

Copy link

commented May 18, 2016

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

@mabbas007

This comment has been minimized.

Copy link

commented May 18, 2016

Where to place that script in XCode ?

@acegreen

This comment has been minimized.

Copy link

commented Jul 6, 2016

@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

@toughrogrammer

This comment has been minimized.

Copy link

commented Aug 23, 2016

Does it works for swift framework project? I tested it but it does not give me luck :(

@squalx

This comment has been minimized.

Copy link

commented Sep 22, 2016

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

@SheldonWangRJT

This comment has been minimized.

Copy link

commented Aug 23, 2017

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?

@himanshumahajan04

This comment has been minimized.

Copy link

commented Sep 4, 2017

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
@Yashrad

This comment has been minimized.

Copy link

commented Nov 17, 2017

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?

@givip

This comment has been minimized.

Copy link

commented Nov 28, 2017

Add to simulator build line VALID_ARCHS="x86_64 i386", and framework will support all simulators.

@kashiftriffort

This comment has been minimized.

Copy link

commented Mar 29, 2018

@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}"
@fabiosoft

This comment has been minimized.

Copy link

commented Sep 26, 2018

Tested with Xcode 10?

@SwenVanZanten

This comment has been minimized.

Copy link

commented Oct 2, 2018

Yes, just used it 👍
Thanks y'all 🥇

@aboud-masoud

This comment has been minimized.

Copy link

commented Oct 30, 2018

/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

@Atsumi3

This comment has been minimized.

Copy link

commented Nov 7, 2018

nicework 👍

@shiqp

This comment has been minimized.

Copy link

commented Dec 10, 2018

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?

@wellbranding

This comment has been minimized.

Copy link

commented Jan 8, 2019

not working with cocoa pods dependencies. here is more information:
https://www.reddit.com/r/swift/comments/admgcu/compiled_framework_provides_bitcode_error_when/

@jofvr

This comment has been minimized.

Copy link

commented May 14, 2019

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 ?

@hackiftekhar

This comment has been minimized.

Copy link

commented May 20, 2019

The PROJECT_NAME should be replace by TARGET_NAME

@jofvr

This comment has been minimized.

Copy link

commented May 21, 2019

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
@fonixland

This comment has been minimized.

Copy link

commented May 21, 2019

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.

https://forums.developer.apple.com/thread/109583

@kainy-priyadarshini

This comment has been minimized.

Copy link

commented Jun 27, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.