Debugging an XCFramework - module not available for import

I'm creating a binary framework (using xcodebuild -create-xcframework) and referencing it locally, with the binary framework having a static library and a modulemap created for it. In this particular case, I'm trying to expose a Rust library through C FFI to swift. I have a resulting XCFramework, but when I try to use it I'm consistently getting the error message "Can not import ...MYPACKAGENAME" when I try to use the framework. (w/ Swift 5.7.2)

I suspect that I've not "done the right thing" in creating the XCFramework, and in particular I'm guessing that I set an incorrect modulemap or for some reason, the headers and module map aren't getting applied when I try to build my swift package.

Is there any detail that I can expose from the swift build command that would show me the modules available to be imported? I'm looking for the rough equivalent to the code-completion mechanism that triggers in Xcode when you start typing "import ..." and Xcode provides a list of modules that might match.

Along those same lines, are there any diagnostics or debugging hints I can get that would list all the places where includes are searched for?

I'm hoping that one of these two places would illuminate where I might be going awry with creating the framework.

I would run swift build --verbose to get the compiler invocation that's failing and then you can run that in isolation adding debugging arguments such as -Rmodule-loading.

1 Like

Follow-up question - how are XCFrameworks dealt with in terms of the module cache that the swift compiler uses?

I took the red-pill and started digging around using the suggestions provided, and saw that all the modules were either being loaded from the SDK (duh, makes sense) or a local module cache in the .build directory. "Cool", says I - and now I'm poking around in that directory, kind of learning how to poke at and scan .pcm files to see what's in there.

In my scenario, the module cache lists three loaded modules from that local cache:

loaded module at /Users/heckj/src/y-uniffi/lib/.build/arm64-apple-macosx/debug/ModuleCache/2C5HQS9YK727C/SwiftShims-2DA6NLEWJC11R.pcm
loaded module at /Users/heckj/src/y-uniffi/lib/.build/arm64-apple-macosx/debug/ModuleCache/2C5HQS9YK727C/SwiftOverlayShims-2DA6NLEWJC11R.pcm
loaded module at /Users/heckj/src/y-uniffi/lib/.build/arm64-apple-macosx/debug/ModuleCache/2C5HQS9YK727C/Darwin-1IVCWVLR6MT9T.pcm

And in poking through those, I didn't see any references to my XCFramework's module map name, XCFramework files, or even additional includes within the swift build --verbose details.

But then, maybe I shouldn't expect to? I wasn't sure how XCFrameworks were exposed or created when the module index is being updated. If I've screwed up my XCFramework, would there be any details if there was a failure in attempting to load it?

Any tidbits or reading on how that process is normally accomplished - even references to where I might find it in the code to decipher what's happening?

I think you only see information about which modules are successfully loaded from this.

1 Like

Thanks again @NeoNacho!

To round this out for anyone else stumbling across this (Google or whatever search) - the underlying issue I had was a mis-named modulemap file. Turns out that when you include a module map within an XCFramework built from a library, it's critically important for it to be named module.modulemap, and not YourLibrary.modulemap. Lesson learned.

Since I banged my head against this for most of the past week, comparing versions that worked and didn't, I wrote up all the details I learned alone the way, including my own stumbles and learned constraints, and referencing docs and relevant resources along the way. When future me finds this again, searching for the same problem - check out the blog post Creating an XCFramework. Hopefully it'll help.