Understanding .swiftmodule and SDK compatibility on macOS

while working on Can You (Dynamically) Link Swift Libraries on Linux? , i found that on macOS, the .swiftmodule files are bound to a specific minor version of macOS.

that is, if i build a .swiftmodule with Xcode 16, and try to compile against it on macOS 15.2, i get the error:

error: cannot load module '<module>' built with SDK 'macosx15.0' when using SDK 'macosx15.2'

how is .swiftmodule normally distributed?

As far as I know the swiftmodule format does not depend on the host macOS version, but it depends on both details from the SDK, and certainly the compiler version.

They’re not meant to be distributed, which is why swiftinterface files exist. Is something you’re doing not well-served by textual interfaces?

2 Likes

got it, thanks!

no, i just didn’t know that .swiftinterface was meant to be distributed instead of .swiftmodule, because i had noticed earlier that Swift can use the .swiftmodule file on its own without any corresponding .swiftinterface file.

1 Like

Swiftmodule files work better with lldb because they include all private declarations and stored properties of types. Swiftinterface files are just that, the public interface, so they omit implementation details. For this reason, to get a swiftinterface you must also build with library evolution support enabled which allows the library to evolve in an ABI stable manner but incurs some performance overhead because everything is abstracted through the public interface. It’s generally equivalent to making all structs and enums as @frozen, but that requires all types of stored properties to be recursively public (the stored properties themselves are allowed to be private though).

4 Likes

.swiftmodule files are incredibly fragile. They are only designed to be read by the exact compiler binary that produced them. Additionally, other .swiftmodule files that were inputs to compilation when the module was produced must be accessible and unmodified, which means they can't be distributed to an environment with a different SDK. The way I think of .swiftmodule files is that they are basically in-memory caches of the compiler's representation of the module for a single compilation. They just happen to get serialized to disk because compilation usually requires multiple compiler invocations to cooperate with each other.

4 Likes