Building your own XCFramework
Tags: xcframework, ios, swift, xcode
Published: 2020-01-08 15:17:24

XCFramework is born to replace the traditional universal framework format **.framework**, which can contain both simulator and physical device architectures code. Besides, XCFramework can also support Catalyst, Mac, watchOS inside a framework

## Using Apple provided tool

From Terminal, Using `xcodebuild -create-xcframework` which takes input `-framework` (from your previous archives) and `-output`

For example:

```zsh
xcodebuild archive -workspace Alamofire.xcworkspace -scheme "Alamofire iOS" -sdk iphoneos13.0 OBJROOT=build/iOS
xcodebuild archive -workspace Alamofire.xcworkspace -scheme "Alamofire iOS" -sdk iphonesimulator13.0 OBJROOT=build/simulator
xcodebuild -create-xcframework -framework build/iOS/UninstalledProducts/iphoneos/Alamofire.framework -framework build/simulator/UninstalledProducts/iphonesimulator/Alamofire.framework -output build/Alamofire.xcframework
```

## Xcode build phase script

create new Aggregate target, add to New Run Script Phase. This new target should be in the same Xcode project with your framework target.

```bash
# Release dir path
OUTPUT_DIR_PATH="${PROJECT_DIR}/XCFramework"

function archivePathSimulator {
  local DIR=${OUTPUT_DIR_PATH}/archives/"${1}-SIMULATOR"
  echo "${DIR}"
}

function archivePathDevice {
  local DIR=${OUTPUT_DIR_PATH}/archives/"${1}-DEVICE"
  echo "${DIR}"
}

# Archive takes 3 params
#
# 1st == SCHEME
# 2nd == destination
# 3rd == archivePath
function archive {
    echo "▸ Starts archiving the scheme: ${1} for destination: ${2};\n▸ Archive path: ${3}.xcarchive"
    xcodebuild clean archive \
    -project "${PROJECT_NAME}.xcodeproj" \
    -scheme ${1} \
    -configuration ${CONFIGURATION} \
    -destination "${2}" \
    -archivePath "${3}" \
    SKIP_INSTALL=NO \
    OBJROOT="${OBJROOT}/DependentBuilds" \
    BUILD_LIBRARY_FOR_DISTRIBUTION=YES | xcpretty
}

# Builds archive for iOS simulator & device
function buildArchive {
  SCHEME=${1}

  archive $SCHEME "generic/platform=iOS Simulator" $(archivePathSimulator $SCHEME)
  archive $SCHEME "generic/platform=iOS" $(archivePathDevice $SCHEME)
}

# Creates xc framework
function createXCFramework {
  FRAMEWORK_ARCHIVE_PATH_POSTFIX=".xcarchive/Products/Library/Frameworks"
  FRAMEWORK_SIMULATOR_DIR="$(archivePathSimulator $1)${FRAMEWORK_ARCHIVE_PATH_POSTFIX}"
  FRAMEWORK_DEVICE_DIR="$(archivePathDevice $1)${FRAMEWORK_ARCHIVE_PATH_POSTFIX}"

  xcodebuild -create-xcframework \
            -framework ${FRAMEWORK_SIMULATOR_DIR}/${1}.framework \
            -framework ${FRAMEWORK_DEVICE_DIR}/${1}.framework \
            -output ${OUTPUT_DIR_PATH}/xcframeworks/${1}.xcframework
}

### Static Libraries cant be turned into frameworks
function createXCFrameworkForStaticLibrary {

  LIBRARY_ARCHIVE_PATH_POSTFIX=".xcarchive/Products/usr/local/lib"
  LIBRARY_SIMULATOR_DIR="$(archivePathSimulator $1)${LIBRARY_ARCHIVE_PATH_POSTFIX}"
  LIBRARY_DEVICE_DIR="$(archivePathDevice $1)${LIBRARY_ARCHIVE_PATH_POSTFIX}"

  xcodebuild -create-xcframework \
            -library ${LIBRARY_SIMULATOR_DIR}/libStaticLibrary.a \
            -library ${LIBRARY_DEVICE_DIR}/libStaticLibrary.a \
            -output ${OUTPUT_DIR_PATH}/xcframeworks/${1}.xcframework
}

echo "#####################"
echo "▸ Cleaning the dir: ${OUTPUT_DIR_PATH}"
rm -rf $OUTPUT_DIR_PATH

#### Dynamic Framework ####

DYNAMIC_FRAMEWORK="${PROJECT_NAME}"

echo "▸ Archive $DYNAMIC_FRAMEWORK"
buildArchive ${DYNAMIC_FRAMEWORK}

echo "▸ Create $DYNAMIC_FRAMEWORK.xcframework"
createXCFramework ${DYNAMIC_FRAMEWORK}
```

The above script build XCFramework for two architectures: `generic/platform=iOS Simulator` and `generic/platform=iOS`; saving to your project folder while assuming your framework scheme has the same name with project name.

Visit [Gist](https://gist.github.com/quangDecember/6151c0af180a84b79f8b572e289b668f)

## Using Carthage

While XCFramework is not fully supported, you can currently build XCFramework with this script:

```
carthage build --platform iOS --no-skip-current --create-xcframework
```

Follow [this issue request](https://github.com/Carthage/Carthage/issues/2799) on Carthage GitHub for future updates