Do not resolve unneeded dependencies

Package apis allow to declare multiple products and targets in a single package, and separate list of dependencies for each of them. When depending on one of the targets from such package SPM seems to resolve all the dependencies anyway, even if they are only needed for another targets that is not being dependent on.

It would be nice to avoid that as this can be rather costly when for instance one has a library that want's to provide and extension for let's say Vapor, but if user of this library does not use Vapor they of course don't want to wait for all its packages to be checked out.

Is this on a roadmap or there is a way to do that already that I missed?

Isn't this the same as described in SE-0226? The current status of that is

Status: Partially implemented (Swift 5.2): Implemented the manifest API to disregard targets not concerned by any dependency products, which avoids building dependency test targets.

And the Jira issue SR-8658 is still open, maybe the proposal authors could clarify that.

1 Like

It is implemented in the 5.2 branch and the manifest API is annotated accordingly.

Yeah, this is exactly what SE-0226 aims to solve. Swift 5.2 has partial implementation where SwiftPM is able to skip dependencies that are not exported via any product but we still need to do the full implementation so SwiftPM resolve as little as possible.

1 Like

Thanks!
So do I understand correctly it should work with Xcode 11.4 beta and updating swift-tools-version to 5.2 or it's not necessary?

Ah, yes, I see that now. For clarity, the missing piece of the implementation is if your dependency has two products and you only use one. In Swift 5.2 you will still be stuck with the transitive dependencies of the other product. But you won’t inherit anything from the dependencies tests or other internal‐only targets.

Well, I guess then for now the best way other than having a separate repository is to have different package versions (with and without additional dependencies) in different branches

4 years later and this still is not implemented. I am curious on how people handle this.

Imagine this:

let package = Package(
    name: "swift-somepackage",
    platforms: [.macOS(.v14)],
    products: [
        .executable(name: "SomeAWSLambda", targets: ["SomeAWSLambda"]),
        .library(name: "SomeSharedLogic", targets: ["SomeSharedLogic"])
    ],
    dependencies: [
        .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime", from: "1.0.0-alpha")
    ],
    targets: [
        .executableTarget(
            name: "SomeAWSLambda",
            dependencies: [
                "SomeSharedLogic",
                .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime")
            ]
        ),
        .target(
            name: "SomeSharedLogic"
        )
    ]
)

I want to import "SomeSharedLogic" in some Xcode project. If I do so, it will resolve https://github.com/swift-server/swift-aws-lambda-runtime and all of its sub-dependencies. Same happens if I want to import "SomeSharedLogic" in a different Swift package.

This is not particularly blocking me, but it just massively slows down the package resolve times, if really big repositories are used, which can definitely happen with server-side Swift.