SPM: Create XCFramework and reusing it - simple example "error: no such module" when importing

Context: I am trying to create a XCFramework that I can reuse it in my Swift app. My example is based on SPM (Swift Package Manager) but I had the same import error no such module when I tried to import my XCFramework in XCode.

Here is the code for XCFramework:

  • Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "MySDK",
    platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)],
    products: [
        .library(name: "MySDK", type: .dynamic, targets: ["MySDK"]),
    ],
    targets: [
        .target(name: "MySDK")
    ]
)
  • Sources/MySDK/my_sdk.swift
public func myHelloStr() -> String {
    return "Bonjour le monde!"
}

To generate the XCFramework:

$ xcodebuild build -scheme MySDK -destination "platform=macOS" -derivedDataPath DerivedData SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES
$ xcodebuild -create-xcframework -framework DerivedData/Build/Products/Debug/PackageFrameworks/MySDK.framework -output MyFramework.xcframework

I can see MyFramework.xcframework folder with

- `Info.plist`
- `macos-x86_64/MySDK.framework/MySDK`
- `macos-x86_64/MySDK.framework/Resources/Info.plist`
- `macos-x86_64/MySDK.framework/Versions/A/MySDK`
- `macos-x86_64/MySDK.framework/Versions/A/Resources/Info.plist`
- `macos-x86_64/MySDK.framework/Versions/Current/MySDK`
- `macos-x86_64/MySDK.framework/Versions/Current/Resources/Info.plist`

Then I create a new SPM project MyApp

  • with Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "TestApp",
    platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)],
    products: [
        .executable(name: "MyApp", targets: ["MyApp"])
    ],
    targets: [
        .executableTarget(name: "MyApp",
            dependencies: [
                .target(name: "MyFramework")
            ]
        ),
        .binaryTarget(
            name: "MyFramework",
            path: "../test_sdk/MyFramework.xcframework"
        )
    ]
)
  • And Sources/MyApp/main.swift:
import MySDK

print("Hello World: \(myHelloStr())")
$ swift run
Building for debugging...
error: emit-module command failed with exit code 1 (use -v to see invocation)
/Users/olivier/dev/test_app/Sources/MyApp/main.swift:1:8: error: no such module 'MySDK'
import MySDK
       ^
/Users/olivier/dev/test_app/Sources/MyApp/main.swift:1:8: error: no such module 'MySDK'
import MySDK
       ^
error: fatalError

If I generate my XCFramework using xcodebuild archive instead of xcodebuild build such as described in this doc https://developer.apple.com/documentation/xcode/creating-a-multi-platform-binary-framework-bundle:

$ xcodebuild archive -scheme MySDK -destination "platform=macOS" -derivedDataPath DerivedData -archivePath "archives/MyFramework" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES
(...)
** ARCHIVE SUCCEEDED **

$ xcodebuild -create-xcframework -archive archives/MyFramework.xcarchive -framework MySDK.framework -output MyFramework.xcframework
error: the path does not point to a valid framework: /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/Library/Frameworks/MySDK.framework

... it's not normal because I have these paths in /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products:

  • /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/Users/olivier/Objects/MySDK.o
  • /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/usr/local/lib/MySDK.framework/...
  • XCode version
$ xcodebuild -version 
Xcode 15.2
Build version 15C500b

I do not know if it is matter but there is no *.swiftinterface in my XCFramework. I do not know if it is expected. But after building with xcodebuild build or xcodebuild archive, these files are present in subdirectories of DerivedData.

Hmmm, after looking the file/directory tree of an XCFramework I found on Internet, I tried to duplicate it with the generated files (I saw is missing MySDK.swiftmodule from the XCFramework)

So copying MySDK.swiftmodule to the XCFramework fixes my issue.

mkdir ./MyFramework.xcframework/macos-x86_64/MySDK.framework/Versions/A/Modules
cp ./DerivedData/Build/Products/Debug/MySDK.swiftmodule ./MyFramework.xcframework/macos-x86_64/MySDK.framework/Versions/A/Modules/
ln -s ./MyFramework.xcframework/macos-x86_64/MySDK.framework/Versions/A/Modules ./MyFramework.xcframework/macos-x86_64/MySDK.framework/Modules

Is it a xcodebuild bug or a missing step in my XCFramework generation?

SPM: Create XCFramework and reusing it - simple example "error: no such module" when importing
 
 
Q