GMObjC. Framework also includes the x86_64 arm64 framework. Prior to Xcode 12, GMObjC. Framework did not generate an error when compiling.

# When in real operation, Xcodeproj Building for iOS, But the linked and embedded framework' gmobjc. framework' was built for iOS + iOS Simulator. Xcodeproj Building for iOS Simulator, but the linked and embedded framework 'GMObjC.framework' was built for iOS + iOS Simulator.Copy the code

Apparently, the new version of Xcode will report errors when using libraries that contain multiple schemas. The solution is easy to find from StackOverflow, adding Architectures that need to be Excluded while compiling their corresponding Architectures in turn in the project’s Build Settings -> Excluded Architectures.

Take GMObjC. Framework with x86_64 ARM64 architecture as an example. When compiling the simulator, you need to remove the ARM64 architecture. In the same way, you need to remove the X86_64 schema when compiling the real server. Select the Noteworthy Architectures, click the plus sign “➕”, add an Any iOS Simulator value of arm64 and an Any iOS value of x86_64, and compile again to pass.

So why does Xcode compile and report errors when it didn’t before? Just like UIWebView and UIAlertView, Apple is urging us developers to abandon the old type and use the new type XCFramework.

What is XCFramework

Let’s start by reviewing static and dynamic libraries in iOS development.

  • Static library (.a/.framework) : copy to executable file completely when linking, multiple use of multiple redundant copies;
  • Dynamic libraries (.dylib/.tbd/.framework) : Programs are dynamically loaded into memory by the system when they run. Dynamic libraries can be shared by multiple programs.

XCFramework is a new library type from Apple. It is supported in Xcode 11 and Cocoapods 1.9 and above. The biggest difference from normal dynamic/static libraries is that multiple platform binaries are bundled into a distributable. Support for all Apple platforms and architectures.

The key word here is multiple platforms (iOS, macOS, tvOS, watchOS, iPadOS, carPlayOS). The normal dynamic/static libraries we use are fat files, which simply contain multiple architectures. For example, armV7 armV7s arm64 ARM64E x86_64, and XCFramework can contain binary libraries for iOS devices, iOS emulators, Mac Catalyst and other platforms.

Apple introduced THE XCFramework to support all apple platforms in order to support apple’s vision of a unified platform, and the Swift library compiled by the XCFramework no longer requires users to use the same Xcode version of the compiler (developers who use the Swift library for componentization should be aware). Compared to using. Framework format, using. Xcframework format improves APP package size and startup speed.

Making XCFramework

Making XCFramework is simple and can be done with the xcodebuild-create-xcFramework command, which I demonstrated by merging the emulator and real versions of the GMObjC library.

GMObjC. Framework has been compiled in the current folder, which is the real machine version and emulator version respectively.

. ├ ─ ─ Release - iphoneos │ ├ ─ ─ cd1fb8d 0-9 d63-3092 - B68B - 2 e579a306d3f. Bcsymbolmap │ ├ ─ ─ GMObjC. The framework │ └ ─ ─ ├─ Gmobjc. ├─ gmobjc.system.dsym ├─ gmobjc.system.dsymCopy the code

Merge to XCFramework with the xcodebuild-create-xcframework command.

#Create the merge package gmobJC.xcFramework
xcodebuild -create-xcframework -framework Release-iphoneos/GMObjC.framework -framework Release-iphonesimulator/GMObjC.framework -output GMObjC.xcframework
#Or line breaks to make it clearer
xcodebuild -create-xcframework \
           -framework Release-iphoneos/GMObjC.framework \
           -framework Release-iphonesimulator/GMObjC.framework \
           -output GMObjC.xcframework
Copy the code

The merged gmobjC.xcFramework directory structure is as follows, including arm64 and x86_64 versions, which is similar to the lipo operation, similar to the operation when merging other platforms.

├─ ios ├─ ├─ ios ├─ ├─ ios ├─ ios └Copy the code

If it is a static library. A file, you need to specify the static library and headers with -library and -headers.

xcodebuild -create-xcframework \
           -library Release-iphoneos/GMObjC.a \
           -headers Release-iphoneos/include/GMObjC \
           -library Release-iphonesimulator/GMObjC.a \
           -headers Release-iphonesimulator/include/GMObjC \
           -output GMObjC.xcframework
Copy the code

Using XCFramework

To use the.xcFramework file, select the current project Target, select the General directory of Frameworks,Libraries,and Embedded Content and drag the.xcFramework file. Almost the same as using.framework files.

One-click compilation of XCFramework

To compile XCFramework, run the xcodebuild-create-xcFramework command. It is more convenient to write it as a shell file. Put it in the same directory as the.xcodeProj file, fill in the scheme name, drag the terminal, and press Enter.

The GMObjC. Xcframework generated by GMObjC. Xcframework is in the build directory.

#! /bin/sh
#Put it in the same directory as the.xcodeProj file, and generate the result in the build directory

#Scheme to compilescheme="GMObjCFramework" if [ -z "$scheme" ] || [ "$scheme" = "" ]; Then echo "then echo" $scheme" cd "$(dirname "$0")" || exit 0 xcodebuild archive \ -scheme "$scheme" \ -sdk iphoneos \ -archivePath "archives/ios_devices.xcarchive" \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ SKIP_INSTALL=NO xcodebuild archive \ -scheme "$scheme" \ -sdk iphonesimulator \ -archivePath "archives/ios_simulators.xcarchive" \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES  \ SKIP_INSTALL=NO
#The file is preferentially read from the Archive folder
product_list=$(ls archives/ios_devices.xcarchive/Products/Library/Frameworks)
for file_name in $product_list
do
    full_product_name=$file_name
    break
done

#If not, read from showBuildSettings
if [ -z "$full_product_name" ] || [ "$full_product_name" = "" ]; then
    name_dict=$(xcodebuild -showBuildSettings | grep FULL_PRODUCT_NAME)
    full_product_name=${name_dict#*= }
fi

product_name=${full_product_name%.*}

xcodebuild -create-xcframework \
    -framework archives/ios_devices.xcarchive/Products/Library/Frameworks/"$full_product_name" \
    -framework archives/ios_simulators.xcarchive/Products/Library/Frameworks/"$full_product_name" \
    -output build/"$product_name".xcframework
Copy the code