swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.74k stars 1.34k forks source link

Build tool plugin is not seeing target dependencies in oddly-specific case of one particular dependency #8060

Open DougGregor opened 2 weeks ago

DougGregor commented 2 weeks ago

Is it reproducible with SwiftPM command-line tools: swift build, swift test, swift package etc?

Description

I have a build tool plugin that looks at the dependencies of the target it is applied to. For example:

        .target(
            name: "JavaMath",
            dependencies: [
              .product(name: "JavaKit", package: "swift-java"),
              // Note: Uncomment the following to unbreak test.swift
              // .product(name: "JavaKitJar", package: "swift-java"),
            ],
            swiftSettings: [
              .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"])
            ],
            plugins: [
              .plugin(name: "Java2SwiftPlugin", package: "swift-java"),
            ]
        ),

The Java2SwiftPlugin doesn't see the dependency of JavaMath on JavaKit. However, if I uncomment the second line (to add the JavaKitJar dependency), the Java2SwiftPlugin sees both the JavaKit and JavaKitJar dependencies correctly. It seems to only ever happen when there is exactly one dependency, it is missing.

Expected behavior

The plugin should see the target dependency even when there is only one.

Actual behavior

The dependency is missing when there is a single dependency; all dependencies are visible if there is more than one.

Steps to reproduce

  1. git clone https://github.com/DougGregor/swift-java-deps
  2. cd swift-java-deps
  3. swift build

The build will fail. If you uncomment the marked line in Package.swift, the build will succeed because the Java2SwiftPlugin is correctly seeing the dependency.

Swift Package Manager version/commit hash

6.0

Swift & OS version (output of swift --version ; uname -a)

swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
Target: arm64-apple-macosx15.0
dschaefer2 commented 1 week ago

@DougGregor just to confirm, were you getting errors like:

.../swift-java-deps/.build/plugins/outputs/swift-java-deps/JavaMath/destination/Java2SwiftPlugin/generated/RoundingMode.swift:20:13: error: value of type 'RoundingMode' has no member 'equals'

dschaefer2 commented 1 week ago

If I change the Package.swift to only depend on JavaKitJar (which is really JavaKitReflection), it works. So I don't think the number of dependencies are a factor. Unless you are getting a totally different error than the one I posted above.

DougGregor commented 1 week ago

That's the right error. The first indication of failure is actually a warning earlier on:

warning: Unable to translate 'java.math.RoundingMode' method 'equals': Java class 'java.lang.Object' has not been translated into Swift

which is because the build tool isn't seeing the JavaKit target. If I go ahead and dump the JavaMath target's dependencies as the build tool sees it, "JavaKit" doesn't show up.

DougGregor commented 1 week ago

You're right that the number of dependencies isn't a factor. Something about the JavaKit product/target specifically is tripping it up: if I dump the dependencies of the target in the build tool, we don't see a direct dependency on JavaKit! But if I swap in JavaKitJar, we see a direct dependency on it and an indirect one on JavaKit.

dschaefer2 commented 1 week ago

Fixed a bug on the main branch where plugin dependencies were sneaking into the build planning. With that, swift-java-deps builds correctly.

However, I'm still seeing the reported behaviour on the 6.0 branch. I want to understand that before assuming it's fixed on main.