Right on Darwin platforms Foundation gets automatically linked. I actually never dove into where and how this gets done. Building the same package on Linux should produce a compile error that you are not importing Foundation
But the correct auto-link behavior is for Darwin target instead of host. There should be some bug here… Can someone replicate the bug with it?
I don't think it will, according to documentation
trimmingCharacters(in:) is declared in the Swift standard library.
Oh right. Sorry I was just checking this from my mobile and assumed it was a Foundation API. Disregard my comments then
This is really… Shocking.
It turns out that
CharacterSet is a
Foundation type, that should be why
Foundation is required and linked.
Which documentation? The stdlib code doesn't show this method:
Search · trimmingCharacters · GitHub
This documentation refers to NSString: Apple Developer Documentation
I'm referring to the function available on
StringProtocol, not the one on
It is an extension from
Foundation. This is definitely ruining the rule of not extending a type you don’t own (I believe
Foundation adds a bunch of extensions to
String, but additions to
StringProtocol is even worse).
Perhaps from the very beginning Apple engineers thought they own both, but that’s incorrect now. And unfortunately I suppose fixing it is ABI breaking.
P.S. Definitely wants to give @taylorswift a credit here since
swiftinit has proved to be more precise and useful than the official documentation… It saves a lot.
I hope there's a way to add a requirement for
import Foundation when using protocol extensions declared in Foundation as a source-breaking, not ABI-breaking change. In my understanding, this shouldn't change how the linker works, or what binary code is emitted.
Isn't this how it normally works for other modules provided via SwiftPM?
thank you so much!!
I guess there’s something wrong to make the code compile. Even on macOS where Foundation is automatically linked,
Foundation.swiftmodule won’t be pulled in without manual
import, so the code shouldn’t compile.
I am as confused as anyone by this. But I keep coming back to the finding that adding
swift build and even though
Foundation in the entire repo. I will investigate it further though – maybe it's importing something which has a transitive dependency on
is needed to
To be precise, Foundation is unexpectedly imported. We should check the compiler and importer first. I don’t think the linker flags makes sense given that we’re seeing symbols from Foundation leaked into the code.
I have tracked this down to a simple reproduction. In short, it appears to be a bug in SwiftPM with bundled resources.
edit: I removed the original post, which outlined the contents of the reproduction in text form and posted the minimal reproduction as a SwiftPM project to GitHub - ephemer/swiftpm-implicit-foundation-imports-reproduction
Yet another edit: so my workaround for now will be to fork
resources: line of
+1 to this,
-lFoundation is probably always passed, but the toolchain (or the linker specifically) is not linking with that static library if no symbol is referencing it.
@Geordie_J Which toolchain did you use that has the bug? I can’t replicate it locally.
EDIT: Okay I got it. You may want to place a
.gitkeep file under
Sources/Dep/Runtime to let Git recognize the directory.
Great catch! The issue is with resources and SwiftPM then. As soon as resources are specified in
Package.swift, SwiftPM generates a file for referencing this resource through the
Bundle type, which is declared in Foundation.
If you're using
carton, excluding JSKit resources may cause issues though, because we're relying on SwiftPM resources to make runtime files discoverable.
Seems like SPM will always create such accessor file that depends on Foundation.Bundle if we have at lease one resource file(a bundle exists)
Should we consider adding a flag to control this?
What would be the point of bundling resources that can't be used?
Bundle.module is the only supported way to access resources.
The downstream user who is importing the dependency may be using only a sliver of the library's functionality and not need or know about the bundled resource; that Foundation APIs are imported should (IMO) remain under explicit user control. Put another way, if the bundled resources aren't being used, better to bundle just resources that can't be used than both resources and all of Foundation.