How to privatize dependencies in Swift Package Manager?

If I have an app with dependency on a module created in SPM, call it Network. Network module has dependency on Alamofire. When I'm in my app, I can still import Alamofire even though there is no direct dependency on it. How do I keep my Alamofire private such that it's only exposed to the Network module and not the main app?


This thread on implementation only imports might be interesting to you

1 Like

That was the first thing I tried prior to posting this thread. It didn't work for me, I am on the latest version of Swift. To be precise, what I tried was adding the implementationOnly syntax in Network module for Alamofire like this (@_implementationOnly import Alamofire). Then I went to the main app, and was still able to import Alamofire there, did I miss something with my implementation?

Implementation‐only imports only prevent a dependency from being forwarded through the import statement.

// ModuleB
import CModuleA
// ModuleC
import ModuleB // Implicitly got “import CModuleA” too.
// ModuleD
@_implementationOnly import CModuleA
// ModuleE
import ModuleD // Hasn’t implicitly imported CModuleA.

At the moment, SwiftPM does nothing to enforce that import statements are also mentioned in the manifest. All dependencies—both direct and transitive—end up in the import and linker search paths, so there is currently nothing you can do about it. Adding such enforcement would be non‐trivial, since many imports originate from outside the package anyway, such as import Foundation.


Thanks @SDGGiesbrecht . I appreciate the confirmation. Hopefully SPM will evolve and include this much needed feature in the future.

1 Like

I don’t know of anyone who is happy with the status quo. I just also don’t know of anyone sufficiently annoyed with it to push it to the top of their to‐do list and actually do the work of designing the solution. At least so far.


Update (because readers clicking “like” have pushed this thread back into the recent activity feed):

Pull request #3562—which at the moment has passed tests but not yet been merged—aims to throw a warning whenever such an indirect dependency is imported.