How to package a static library and headers into an XCFramework?

I have static libraries and headers of a C++ project that I believe are correctly built for iOS and iOS Simulator destinations. The C++ project is built via CMake with something like:

cmake dirName \
  -G "Unix Makefiles" \ 
  -B buildDir \
  -DCMAKE_INSTALL_PREFIX=installDir \
  -DCMAKE_SYSTEM_NAME=iOS \
  -DCMAKE_SYSTEM_PROCESSOR=arm64 \
  -DCMAKE_OSX_ARCHITECTURES=arm64 \
  -DCMAKE_OSX_SYSROOT=$(xcrun --sdk iphonesimulator --show-sdk-path) \
  -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0
  ...

cmake --build buildDir --config Release --target install

I believe those are all the important parameters. This gives me a static library (.a) and headers that I believe should be compatible with arm64 iOS simulators, and I do this same thing for x86_64 architecture with simulators and for actual iOS non-simulator via the iphoneos SDK path.

I'm pretty sure this gives me the correct static lib and headers. Let's assume it does because I'm not able actually create the XCFramework to know if they're right. This does work with a macOS lib and headers, but I need iOS for this library. How do I package this into an XCFramework now?

This Apple developer articles says I should be a able to create an xcframework via xcodebuild -create-xcframework -library libName.a -headers include but when I try to do this with my my iOS arm64 simulator static lib I get:

error: binaries with multiple platforms are not supported '/Users/.../install/ios-arm64-simulator/libName.a

But, when I run: lips -info libName.a I get Non-fat file libName.a is architecture arm64, so, I'm not sure what to do here. Trying to extract arm64 from that static library also produces an error as it it is just an arm64 lib.

I'm not really sure what's going on, but from reading online this specific command, xcodebuild -create-xcframework is a consistent pain point in the process of trying to get an XCFramework, and the seemingly only workaround is to archive a framework project and then create the xcframework via xcodebuild -create-xcframework -archive MyFramework.xcarchive -framework[or -library].

However, how am I supposed to get this static lib and headers into a suitable xcodeproj so that I can archive it correctly? Everytime I try to copy the headers and static lib into the Framework xcodeproj and set what I believe are all the correct settings, my .xcarchive is always empty.

Does anyone have any advice here on how to get this to work?

The main impetus for trying to get this C++ static lib and headers into an XCFramework as that seems like the only valid way to link a 3rd party C++ lib to an SPM package and have the C++ package be interfaceable with Swift.

Are you able to share a link to somewhere hosting the .a files that you're passing to create the XCFramework? I'd like to inspect the individual object file binary headers for values in the LC_BUILD_VERSION or LC_VERSION_MIN_* Mach-O headers. (You can also do this via otool -h.) There's also the universal library-level header that encodes support for multi-architecture binaries (inspectable with otool -f) — I've seen situations in the past where there's a single architecture inside of a universal binary, and if that's the case here, you should walk backwards through your build commands to makes sure you're not using lipo to create a universal library with a single architecture.

If you're not able to share your static library publicly because this library is proprietary or confidential, feel free to open a support request, and I can arrange a private file transfer with you that way, just make sure to cite this forums thread as part of the support request.

— Ed Ford,  DTS Engineer

Thanks for getting back to me Ed! @DTS Engineer

I actually ended up figuring it out.

Building the C++ project with

cmake dirName \
  -G "Unix Makefiles" \ 
  -B buildDir \
  -DCMAKE_INSTALL_PREFIX=installDir \
  -DCMAKE_SYSTEM_NAME=iOS \
  -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ # Changed
  -DCMAKE_OSX_ARCHITECTURES=arm64 \
  -DCMAKE_OSX_SYSROOT=iphonesimulator \ # Changed
  -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0
  ...

Allowed me to create the XCFramework with the resulting lib and headers. The change is for the -DCMAKE_SYSTEM_PROCESSOR=aarch64 argument, changed from arm64, and the -DCMAKE_OSX_SYSROOT=iphonesimulator argument, changed from $(xcrun --sdk iphonesimulator --show-sdk-path).

I'm not sure if both or only one of the arguments solved the issue, but this allowed me to create an XCFramework that worked with an iOS simulators.

Slightly unrelated: lipo-ing the x86_64 version of the simulator lib into the arm64 lib in the XCFramework also allows it to run on x86_64 simulators, as trying to -create-xcframework with the x86_64 and arm64 simulator libs produces an error, but hacking it this way makes things work.

How to package a static library and headers into an XCFramework?
 
 
Q