Closed
Description
Is it reproducible with SwiftPM command-line tools: swift build
, swift test
, swift package
etc?
- Confirmed reproduction steps with SwiftPM CLI. The description text must include reproduction steps with either of command-line SwiftPM commands,
swift build
,swift test
,swift package
etc.
Description
swift package add-dependency
is not idempotent. It will add a dependency entry for a package to Package.swift
even if that package is already a dependency. This makes the package fail to build.
Expected behavior
swift package add-dependency
should refuse to add an existing dependency.
Actual behavior
swift package add-dependency
adds duplicate dependencies, leading to build failures.
Steps to reproduce
- Create a new package
% swift package init --type executable
Creating executable package: dependencies
Creating Package.swift
Creating Sources/
Creating Sources/main.swift
% cat Package.swift
// swift-tools-version: 6.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "dependencies",
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "dependencies"),
]
)
% swift build
Building for debugging...
[8/8] Applying dependencies
Build complete! (1.41s)
- Add a dependency on swift-argument-parser and rebuild - this succeeds.
% swift package add-dependency https://github.com/apple/swift-argument-parser --from 1.5.0
Updating package manifest at Package.swift... done.
% cat Package.swift
// swift-tools-version: 6.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "dependencies",
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "dependencies"),
]
)
% swift build
Fetching https://github.com/apple/swift-argument-parser from cache
Fetched https://github.com/apple/swift-argument-parser from cache (0.56s)
Computing version for https://github.com/apple/swift-argument-parser
Computed https://github.com/apple/swift-argument-parser at 1.5.0 (1.00s)
Creating working copy for https://github.com/apple/swift-argument-parser
Working copy of https://github.com/apple/swift-argument-parser resolved at 1.5.0
[1/1] Planning build
Building for debugging...
[2/2] Write swift-version-1AF32027EA501FB9.txt
Build complete! (2.61s)
- Add the dependency on swift-argument-parser again. The
add-dependency
command does not return an error, butswift build
now fails immediately with a duplicate dependency error.
% swift package add-dependency https://github.com/apple/swift-argument-parser --from 1.5.0
Updating package manifest at Package.swift... done.
% cat Package.swift
// swift-tools-version: 6.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "dependencies",
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "dependencies"),
]
)
% swift build
error: 'dependencies': 'dependencies' dependency on 'https://github.com/apple/swift-argument-parser' conflicts with dependency on 'https://github.com/apple/swift-argument-parser' which has the same identity 'swift-argument-parser'
error: ExitCode(rawValue: 1)
[0/1] Planning build
Swift Package Manager version/commit hash
Swift 6.1.0
Swift & OS version (output of swift --version ; uname -a
)
The example above comes from Swift 6.1 but it also occurred on 6.0.3 and other builds. I believe this problem has existed since the add-dependency
command was introduced.
% swift --version
Apple Swift version 6.1 (swift-6.1-RELEASE)
Target: arm64-apple-macosx15.0
% uname -a
Darwin computermabob.local 24.3.0 Darwin Kernel Version 24.3.0