Skip to content

Add explicit swift-nio dependency for Xcode 26 transitive dylib bug#18

Merged
mattt merged 2 commits intomattt:mainfrom
intrusive-memory:xcode26-transitive-fix
Mar 2, 2026
Merged

Add explicit swift-nio dependency for Xcode 26 transitive dylib bug#18
mattt merged 2 commits intomattt:mainfrom
intrusive-memory:xcode26-transitive-fix

Conversation

@stovak
Copy link
Contributor

@stovak stovak commented Feb 24, 2026

Problem

Xcode 26 introduced a regression in Swift Package Manager builds where packages built as dynamic frameworks don't properly propagate transitive framework dependencies during the link phase.

Symptoms

When EventSource is built with the AsyncHTTPClient trait enabled, the build fails with:

Undefined symbols for architecture arm64:
  NIOCore symbols referenced from EventSource.o

Root Cause

  • Xcode 26 builds all "automatic" SPM products as dynamic frameworks (*.framework)
  • EventSource (with AsyncHTTPClient trait) uses symbols from NIOCore (via inlined code from AsyncHTTPClient)
  • However, EventSource's Package.swift doesn't declare swift-nio as a direct dependency
  • It only declares async-http-client, which itself depends on swift-nio
  • Xcode 26 correctly links NIOCore.framework into AsyncHTTPClient.framework
  • BUT Xcode 26 fails to propagate this transitive dependency when linking EventSource.framework
  • Result: EventSource.o references NIOCore symbols but the framework doesn't link against it

Solution

Add explicit package-level and target-level dependencies for swift-nio to ensure Xcode 26 can link the framework correctly.

Changes

  • Added .package(url: "https://github.com/apple/swift-nio.git", from: "2.81.0") to package dependencies
  • Added .product(name: "NIOCore", package: "swift-nio") to EventSource target dependencies

Impact

  • No functional changes - NIOCore was already available transitively through AsyncHTTPClient
  • Fixes builds for projects using EventSource with AsyncHTTPClient trait under Xcode 26
  • No impact on Xcode 25 or earlier (explicit dependency is redundant but harmless)
  • No impact on Linux/Swift CLI builds (they don't have the transitive dylib bug)
  • No impact on EventSource builds without the AsyncHTTPClient trait (dependency is only used when trait is enabled)

Testing

Verified that this fixes builds for projects using EventSource with the AsyncHTTPClient trait as a transitive dependency under Xcode 26.

Previously failed with undefined symbols, now builds and links correctly.

Notes

  • Used swift-nio 2.81.0 as minimum version to match async-http-client's requirement
  • This is defensive programming - making implicit transitive dependencies explicit

Related Issue: This is a workaround for an Xcode 26 regression. Ideally Apple would fix the SPM dylib linking behavior, but adding explicit dependencies is a reasonable defensive practice regardless.

@mattt mattt changed the title Fix: Add explicit swift-nio dependency for Xcode 26 transitive dylib bug Add explicit swift-nio dependency for Xcode 26 transitive dylib bug Feb 24, 2026
@mattt
Copy link
Owner

mattt commented Feb 24, 2026

Gosh, this again? Looks like I'd do well to go through every project I have using async-http-client to test that Xcode actually works.

But seriously, thank you for reporting huggingface/swift-xet#6 and opening this PR. I really appreciate it!

@mattt
Copy link
Owner

mattt commented Feb 24, 2026

@stovak Looks like this is failing the lint check. I tried applying a fix to your PR branch but got a 403. Can you please run swift format -i -r . and push that change?

@stovak
Copy link
Contributor Author

stovak commented Feb 28, 2026

@mattt done.

Thank my intern, Claude. 😉

@mattt mattt merged commit a3a85a8 into mattt:main Mar 2, 2026
8 checks passed
@mattt
Copy link
Owner

mattt commented Mar 2, 2026

Thanks again for your help, @stovak! This is now available in 1.4.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants