Search code examples
iosswiftcocoapodsios-universal-framework

Swift universal framework depending on pod


I'm developing a small Swift framework that depends on Alamofire. I'm using it as an embedded framework of an app belonging to the same workspace and it works perfectly.

The problem arises when I want to build an universal framework with an aggregate target. Then, when executing the script to generate the framework it fails with the message No such module 'Alamofire', referring to an import Alamofire in one of my source files.

This is my Podfile:

platform :ios, '9.0'
use_frameworks!
inhibit_all_warnings!

target 'FSIBackend' do
  pod 'SwiftLint'
  pod 'Alamofire'
  pod 'SwiftyJSON'
end

This is the script to generate the framework. It works with other frameworks without Pods dependencies so I assume that is ok:

set -e

# Setup
FRAMEWORK_NAME="${1}"
BUILD_DIR="${SRCROOT}/build"
OUTPUT_DIR="${HOME}/Desktop/"
OUTPUT="${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework"

rm -rf "${BUILD_DIR}"
rm -rf "${OUTPUT}"
mkdir -p "${OUTPUT_DIR}"

# Build
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos"
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator"

# Copy the device version of framework to output.
cp -r "${BUILD_DIR}/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${OUTPUT}"

# Replace the framework executable within the framework with a new version created by merging the device and simulator frameworks' executables with lipo.
lipo -create -output "${OUTPUT}/${FRAMEWORK_NAME}" "${BUILD_DIR}/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${BUILD_DIR}/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"

# Copy the Swift module mappings for the simulator into the framework. The device mappings already exist from step 6.
cp -r "${BUILD_DIR}/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${OUTPUT}/Modules/${FRAMEWORK_NAME}.swiftmodule"

# Delete build.
rm -rf "${BUILD_DIR}"

The question is that I don't know how to build my framework depending on Alamofire. Do I have to create a podspec for my framework and use it via CocoaPods? This is the first time I create a universal framework depending on a pod so I don't know if I'm doing something impossible.

Thank you so much.


Solution

  • Finally I could accomplish it taking into account the advice given from @mag_zbc, thank you.

    I had to modify the framework generation this way:

    set -e
    
    # Setup
    WORKSPACE="${1}"
    FRAMEWORK_NAME="${2}"
    BUILD_DIR="${SRCROOT}/build"
    OUTPUT_DIR="${HOME}/Desktop/"
    OUTPUT="${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework"
    CONFIGURATION="${CONFIGURATION}"
    
    rm -rf "${BUILD_DIR}"
    rm -rf "${OUTPUT}"
    mkdir -p "${OUTPUT_DIR}"
    
    # Build the framework for device and for simulator (using all needed architectures).
    xcodebuild -workspace "${WORKSPACE}" -scheme "${FRAMEWORK_NAME}" -configuration ${CONFIGURATION} -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator" clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator
    xcodebuild -workspace "${WORKSPACE}" -scheme "${FRAMEWORK_NAME}" -configuration ${CONFIGURATION} -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos" clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos
    
    # Copy the device version of framework to output.
    cp -r "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework" "${OUTPUT}"
    
    # Replace the framework executable within the framework with a new version created by merging the device and simulator frameworks' executables with lipo.
    lipo -create -output "${OUTPUT}/${FRAMEWORK_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"
    
    # Copy the Swift module mappings for the simulator into the framework. The device mappings already exist from step 6.
    cp -r "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${OUTPUT}/Modules/${FRAMEWORK_NAME}.swiftmodule"
    
    # Delete build.
    rm -rf "${BUILD_DIR}"
    

    After generated, and added to the consumer app, the only thing left to do is to use Cocoapods in the consumer app to get Alamofire and SwiftyJSON.