szagun
szagun

Reputation: 311

How can I wrap a static library (C++) into an XCFramework for use in Swift?

I have been given a static library libExample.a together with a bunch of C++ headers, which I need to use in an iOS app. The binary is fat, containing objects for iphoneos-arm64/e and iphonesimulator-x64.

I have done some research on the subject and came to the conclusion, that using a XCFramework would be the best thing to do. Still, I feel completely out of my depth, since this is my first time trying anything of the sort.

What I have done so far

1. Creating the XCFramework from library files

  1. lipo -extract architectures from fat binary
  2. xcodebuild -create-xcframework -library LIB-arm64.a -headers HEADERS -library ...

Importing the XCFramework into my Swift project didn't yield any usable modules. Also the folder was missing a lot of the files, I've seen in examples. It seemed like the wrong way to go about it, so I tried...

2. Creating a Framework and then a XCFramework from it

Files
  1. Create new Objective-C Framework project ExampleFramework
  2. Pull all my headers and the fat binary into the project
  3. Add all my headers to the ExampleFramework.h umbrella header
  4. Create the following ExampleFramework.modulemap:
framework module ExampleFramework {
    umbrella header "ExampleFramework.h”
    
    link "Example"
    export *
    module * { export * }
}
Settings
  1. General:
    1.1. Add libExample.a to Frameworks & Libraries
  2. Build Phases:
    2.1. Make all headers public
    2.2. Add libExample.a to Link Binary with Libraries
    2.3. Add libExample.a to Copy Bundle Resources
  3. Build Settings:
    3.1. Skip Install : No
    3.2. Build Libraries for distribution : Yes
    3.3. Module map file: ExampleFramework/ExampleFramework.modulemap
    3.4. Defines modules: Yes
    3.5. Compile Sources As: Objective-C++

I then archived the framework, for iphoneos and iphonesimulator respectively:

xcodebuild archive \
-scheme "ExampleFramework" ONLY_ACTIVE_ARCH=NO \
-archivePath "path/to/ExampleFramework_${SDK}.xcarchive" \
-sdk ${SDK} \
SKIP_INSTALL=NO \
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES

...and generated a XCFramework from the outputs:

xcodebuild -create-xcframework \
-framework "path/to/ExampleFramework_iphoneos.xcarchive/Products/Library/Frameworks/ExampleFramework.framework"
-framework ...
-output "path/to/ExampleFramework.xcframework"

Build Errors

The folder structure I got from this looked promising, so I tried adding the XCFramework to my iOS project. The module was being found now, but XCode stopped compiling at the first #include, saying it wasn't able to find stdexcept, from which I concluded it was missing the C++ standard library headers.

I tried setting Header Search Paths in Build Settings. Looking for the right path I found a couple, that looked relevant to me:

/Applications/Xcode_13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
/Applications/Xcode_13.2.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include
/Applications/Xcode_13.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include

Depending on which one I choose and whether I clean before building, I'm getting a bunch of different errors (it seems random). Mainly:

Unknown type name 'namespace'

and lots and lots of others, that lead to me believe XCode doesn't recognize the headers as C++.

Or:

Cyclic dependency on module 'Darwin' : Darwin -> std -> Darwin

I really have no idea at this point, so any solutions or suggestions pointing me into the right direction, would me much appreciated. I'd also be open to some completely different approach, I just want to use the library somehow.

Thanks!

Upvotes: 3

Views: 2584

Answers (1)

Wei
Wei

Reputation: 424

For reference from module.modulemap

framework module GoogleAppMeasurement {
umbrella header "GoogleAppMeasurement-umbrella.h"
export *
module * { export * }
  link framework "Security"
  link framework "SystemConfiguration"
  link "c++"
  link "sqlite3"
  link "z"
}

Upvotes: 0

Related Questions