Cross-platform Swift-Objective-C interop proposal

Dear Swift Community,

A few weeks ago, I started a discussion in this forum about what it would take to add non-Apple Objective-C interop support using the GNUstep runtime. While there are several Objective-C implementations for non-Apple platforms, GNUstep seems to be the most widely used and there is a dedicated community of users who would really like to see this happen. As a result of the discussion, I think the most practical approach would be to make Objective-C interop on non-Apple platforms largely consistent with Apple platforms, while requiring a separate compilation mode and standard library distribution.

I would therefore like to get some opinions from Swift maintainers on whether this is something they could see being added to Swift and what the upstreaming process could look like once a prototype is ready.

I'm proposing to add GNUstep interop support as a separate compilation mode, such as a platform variant.

For a Swift program compiled with GNUstep interop enabled this means:

  • A different ABI, because the compiler needs to emit GNUstep compatible Objective-C metadata.
  • Additional checks in Swift's runtime function, to handle operations on types like AnyObject, which are already performed on Apple platforms but have been disabled for non-Apple platforms.
  • Use an "interop enabled" release of the Swift runtime and Corelibs Foundation, which provides type bridging functions.

Runtime and Standard Library changes:

  • Define SWIFT_OBJC_INTEROP on non-Apple platforms for the interop release
  • The interop releases of the Swift standard library and runtime would have a dependency on libobjc2 and the GNUstep Foundation libraries (Which will also require work to implement missing SPIs and enable Swift object handling)
  • Implement a number of type conversion codepaths in the Swift standard library, to support casting GNUstep Foundation to Swift Foundation types and vice versa.

Compiler Changes:

  • Replace SWIFT_OBJC_INTEROP compile time guards with runtime guards. This would likely entail some refactoring in swiftc and could benefit code structure as well.
  • swiftc code generation must emit GNUstep-compatible metadata for classes, metaclasses, protocols, etc. It may be possible to make internal Clang APIs available for this purpose, which already implement GNUstep metadata generation.
  • Additionally, some optimized code paths rely on objc4 specific behavior, which would be difficult to implement in GNUstep's Objective-C runtime. For example, objc4's tagged object pointers. There would be a compile time guard for this with non-Apple interop.

This would be an opt-in mode, intended to keep the impact on existing platforms isolated while enabling additional interoperability use cases.

Since this work would primarily target non-Apple platforms, integration and long-term maintenance would likely be driven by the community. Ongoing work, such as changes in objc4–Swift contracts (e.g. the addition of new SPIs), would largely fall on GNUstep. Perhaps a community-maintained support model would be possible?

I and others would be interested in developing a prototype, and I would not expect Swift maintainers to help with the implementation at this stage. Cross-platform Objective-C interop would not only improve Swift code portability, but allow users with large Objective-C codebases to incrementally adopt Swift.

I look forward to your thoughts on this.

6 Likes

Thanks for writing this up and for the earlier feasibility thread. I'd like to
add an already-running use case, since I think it both reinforces the motivation
and surfaces a design point worth pinning down early.

We maintain a Cocoa-compatible stack — Foundation, CoreFoundation, CoreGraphics,
CoreText, QuartzCore, UIKit/AppKit — on libobjc2 (the v2 ABI) with
swift-corelibs-foundation's CoreFoundation as the CF layer, running on both
Linux and Windows. So the substrate this targets isn't hypothetical for us:
there's already a large Obj-C codebase on libobjc2 that Swift interop would let us
call into and incrementally rewrite in Swift — exactly the incremental-adoption
and portability story you cite.

Two design points from living on this boundary:

1. Bridge at the CoreFoundation / runtime level, not to one specific Foundation.
The proposal alternates between "Corelibs Foundation" and "the GNUstep Foundation
libraries" (gnustep-base) — different Foundations, and there are real stacks
(ours, but also s-c-f's own NS layer) that are neither. Toll-free bridging is a
CF-level contract: if the type-conversion codepaths target CF types
(CFString / CFArray / CFDictionary / CFData / …) and the standard toll-free
bridge, then any Foundation implementing that bridge can participate.
Hard-wiring the casts to gnustep-base's classes/SPIs would lock out the
alternatives — including, ironically, s-c-f's own NS classes. Keeping the
class/metadata ABI at the libobjc2 layer and the value bridging at the CF layer
looks like the cleanest split, and keeps the proposal from quietly becoming
gnustep-base-specific.

2. Tagged pointers need parameterizing, not just a "disabled on non-Apple"
guard.
You flag objc4 tagged pointers as compile-time-guarded out, but
libobjc2 has its own small-object / tagged-pointer scheme (we rely on it for
small strings), so "non-Apple ⇒ no tagged pointers" isn't safe either. We've
burned real time on crashes that were exactly this — a path assuming objc4's
tagged layout or a flat isa, then dereferencing a libobjc2-tagged object.
Whatever AnyObject / isa-inspection checks get re-enabled should understand
libobjc2's small-object mask, not just toggle objc4's off.

One scoping note: please keep Windows explicitly in scope. "Non-Apple
platforms" tends to read Linux/BSD-first, but libobjc2 and Swift both run on
Windows and it's first-class for us — and the ABI isn't uniform across non-Apple
platforms (I'll follow up with a couple of concrete cases).

We'd be glad to help: act as a real-world, cross-platform (Linux + Windows) test
bed for a prototype, share our libobjc2 + s-c-f CoreFoundation findings, and
contribute where useful. Happy to compare notes whenever a prototype starts
taking shape.

2 Likes

This is very appealing to me. And I'd definitely want to give it a try once it is available.

My OpenAttributeGraph project (which OpenSwiftUI depends on) heavily depend on the CF API. We managed to make it working on Linux and compile on Android. But some feature is missing and some is broken.

If we can have GNUStep Swift-ObjC compiler, all those issues can be solved more easily.

1 Like