Skip to content

Using Cross Import Overlays to Improve Your Libraries

Posted on:March 19, 2023

Introduction

Cross import overlays are incredible. Truly, they’re a gamechanger. It’s a feature that allows Swift to automatically import an additional “overlay” module basd on the combination of imports in a particular source file. They let a library or framework seamleslly expand (or rely) upon another, without imposing an additonal dependency on clients who don’t need it.

Let’s say you’re developing an open source library, let’s call it ModelKit. Let’s also say that this library could be enhanced by a third party open source library (let’s call it, CoolKit). There are several ways to pull this off:

  1. You can create a second library, called CoolModelKit. This library imports CoolKit and uses it to enhance the models of ModelKit.
  2. You can import CoolKit directly into ModelKit, but this will likely upset consumers of ModelKit that don’t need or want CoolKit in their projects.
  3. You can create a cross import overlay, that automatically adds in the CoolKit enhancements to your library when both are imported in a single file.

How Cross Import Overlays Work

Cross import overlays are declared by special YAML files that specify which modules should be imported together and what overlay module should be added as a result. That means that we do need a third module, that by naming convention is called _ModelKit_CoolKit (it belongs to ModelKit, and pulls in CoolKit to extend it). Let’s create a module called _ModelKit_CoolKit where we have our extensions of ModelKit.

In these files, when we import ModelKit, we are actually declaring @_exported import ModelKit. Effectively, what the compiler will do is look for the following in consumer code:

import ModelKit
import CoolKit

and replace it with:

import _ModelKit_CoolKit
import CoolKit

In order to pull this off, you need a .swiftoverlay file inside of a .swiftcrossimport folder. Let’s take a look a For example, the NumericKitFormatKitAdditions overlay module could be declared by a file named NumericKit_FormatKit.overlay.yaml with the following content:

%YAML 1.2
---
version: 1
modules:
  - name: _ ModelKit_CoolKit

This file tells Swift that whenever both ModelKit and CoolKit are imported in the same source file, it should make the replacement. The overlay module itself is a regular Swift module that can define extensions, conformances, types, functions, etc. that depends on both ModelKit and CoolKit.

The YAML files are located in special directories inside the frameworks or libraries that declare them. For example,

How to use them today

Unless you are using Xcodegen, you’ll have to manually place these yaml files inside of the output frameworks/libraries. If you are using XcodeGen, I’ve merged support.

All you’ll have to do is have your MyModule.crossimport folder with a _MyModule_Extensions.swiftoverlay file in your target’s Sources, and a declared _MyModule_Extensons target somewhere.

Benefits of Cross Import Overlays

Cross import overlays offer several benefits for library authors and users:

Downsides of Cross Import Overlays

Examples of Cross Import Overlays

Cross import overlays are already used by some Apple frameworks to provide better integration with other frameworks. For example:

Conclusion

Cross import overlays are a powerful feature that enable Swift libraries to provide better interoperability and modularity. They allow library authors to define additional modules that are automatically imported when two or more modules are used together, without requiring explicit imports or extra dependencies from the users. They also reduce compile time and link time overhead and avoid retroactive conformances. Cross import overlays are already used by some Apple frameworks to provide custom views and modifiers for SwiftUI , extensions and operators for Combine , and more.

There’s not much out there as far as detail on this feature, but if this is something you’re interested in, please reach out to me on Mastodon for more information and give the proposal which details them a read.