Search code examples
swiftclang

What is the difference between a clang (objective-C) module and a Swift module?


Clang modules are documented here, and Swift modules are here which doesn't go into as much detail.

Since clang is the LLVM frontend compiler which is also used by Swift internally, is a Swift module always a Clang module? Are they exactly the same thing?


Solution

  • They are different. At the end of the build process though, they both need to be linked to your application/ library's other .o and .dylib files for it to run.

    Swift modules

    • From Swift Serialization.md docs:

      The fundamental unit of distribution for Swift code is a module. A module contains declarations as an interface for clients to write code against.

    • Swift acccess control docs:

      A module is a single unit of code distribution: a framework or application that’s built and shipped as a single unit and that can be imported by another module with Swift’s import keyword.

    • Configured by .target()'s in Package.swift

    • Cannot have submodules, so users cannot import Module.Submodule in Swift. Users can still import specific entities, import struct PackageModel.Manifest, but this is a lot more verbose than importing submodules.

    • Its interface exists as a .swiftmodule. What is a .swiftmodule?. The documentation says:

      Conceptually, the file containing the interface for a module serves much the same purpose as the collection of C header files for a particular library.

    • The compiler produces this .swiftmodule file a lot, like a generated objective-C header, but instead of text, its a binary repesentation. It includes the bodies of inlinable functions, much like static inline functions in objective-C or header implementations in C++. However, Swift modules does include the names and types of private declarations. This allows you to refer to them in the debugger, but it does mean you shouldn't name a private variable after your deepest darkest secret. from WWDC 2018: Behind the Scenes of the Xcode Build Process

      • So private declarations are exposed in your .swiftmodule (Swift module interface).
    • When importing pure Objective-C frameworks into Swift, the Swift compiler uses its built-in clang compiler to import an Objective-C header.

    The importer finds declarations in the headers exposed in Clangs .modulemap for that framework. (again, from WWDC2018)

    • When importing Objective-C + Swift frameworks into Swift, the Swift compiler uses the Umbrella header.

    Clang modules

    • Configured by YourModuleName.modulemap file (previously module.map, but this is deprecated), formatted like this
    • Can have submodules, e.g. std module has std.io and std.complex.
    • A clang module exposes header files specified in the module map. Private details (in .m) are not exposed at all.
    • Is an improvement of the original #include or #import style imports to improve the build process (This is a big topic, read the Clang module docs).