Skip to content
Merged
17 changes: 17 additions & 0 deletions BuildSupport/SwiftSyntax/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
SET(SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE ${CMAKE_SOURCE_DIR}/../swift-syntax)
message(STATUS "swift-syntax path: ${SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE}")

include(FetchContent)

if(NOT EXISTS "${SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE}")
message(SEND_ERROR "swift-syntax is required to build SwiftPM. Please run update-checkout or specify SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE")
return()
endif()

# Build swift-syntax libraries with FetchContent.
# set(CMAKE_Swift_COMPILER_TARGET ${SWIFT_HOST_TRIPLE})
set(BUILD_SHARED_LIBS OFF)

file(TO_CMAKE_PATH "${SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE}" swift_syntax_path)
FetchContent_Declare(SwiftSyntax SOURCE_DIR "${swift_syntax_path}")
FetchContent_MakeAvailable(SwiftSyntax)
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ find_package(SQLite3 REQUIRED)
# Enable `package` modifier for the whole package.
add_compile_options("$<$<COMPILE_LANGUAGE:Swift>:-package-name;SwiftPM>")

add_subdirectory(BuildSupport/SwiftSyntax)
add_subdirectory(Sources)
add_subdirectory(cmake/modules)
30 changes: 30 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ let swiftPMDataModelProduct = (
"PackageLoading",
"PackageMetadata",
"PackageModel",
"PackageModelSyntax",
"SourceControl",
"Workspace",
]
Expand Down Expand Up @@ -246,6 +247,23 @@ let package = Package(
swiftSettings: packageModelResourcesSettings
),

.target(
/** Primary Package model objects relationship to SwiftSyntax */
name: "PackageModelSyntax",
dependencies: [
"Basics",
"PackageLoading",
"PackageModel",
.product(name: "SwiftBasicFormat", package: "swift-syntax"),
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
],
exclude: ["CMakeLists.txt"]
),

.target(
/** Package model conventions and loading support */
name: "PackageLoading",
Expand Down Expand Up @@ -414,10 +432,12 @@ let package = Package(
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "OrderedCollections", package: "swift-collections"),
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
"Basics",
"Build",
"CoreCommands",
"PackageGraph",
"PackageModelSyntax",
"SourceControl",
"Workspace",
"XCBuildSupport",
Expand Down Expand Up @@ -635,6 +655,14 @@ let package = Package(
name: "PackageModelTests",
dependencies: ["PackageModel", "SPMTestSupport"]
),
.testTarget(
name: "PackageModelSyntaxTests",
dependencies: [
"PackageModelSyntax",
"SPMTestSupport",
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
]
),
.testTarget(
name: "PackageGraphTests",
dependencies: ["PackageGraph", "SPMTestSupport"]
Expand Down Expand Up @@ -785,6 +813,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.2.2")),
.package(url: "https://github.com/apple/swift-driver.git", branch: relatedDependenciesBranch),
.package(url: "https://github.com/apple/swift-crypto.git", .upToNextMinor(from: "3.0.0")),
.package(url: "https://github.com/apple/swift-syntax.git", branch: relatedDependenciesBranch),
.package(url: "https://github.com/apple/swift-system.git", .upToNextMinor(from: "1.1.1")),
.package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.0.1")),
.package(url: "https://github.com/apple/swift-certificates.git", .upToNextMinor(from: "1.0.1")),
Expand All @@ -795,6 +824,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
.package(path: "../swift-argument-parser"),
.package(path: "../swift-driver"),
.package(path: "../swift-crypto"),
.package(path: "../swift-syntax"),
.package(path: "../swift-system"),
.package(path: "../swift-collections"),
.package(path: "../swift-certificates"),
Expand Down
1 change: 1 addition & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_subdirectory(PackageFingerprint)
add_subdirectory(PackageGraph)
add_subdirectory(PackageLoading)
add_subdirectory(PackageModel)
add_subdirectory(PackageModelSyntax)
add_subdirectory(PackagePlugin)
add_subdirectory(PackageRegistry)
add_subdirectory(PackageSigning)
Expand Down
3 changes: 3 additions & 0 deletions Sources/Commands/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

add_library(Commands
PackageCommands/AddDependency.swift
PackageCommands/AddTarget.swift
PackageCommands/APIDiff.swift
PackageCommands/ArchiveSource.swift
PackageCommands/CompletionCommand.swift
Expand Down Expand Up @@ -56,6 +58,7 @@ target_link_libraries(Commands PUBLIC
CoreCommands
LLBuildManifest
PackageGraph
PackageModelSyntax
SourceControl
TSCBasic
TSCUtility
Expand Down
155 changes: 155 additions & 0 deletions Sources/Commands/PackageCommands/AddDependency.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import ArgumentParser
import Basics
import CoreCommands
import PackageModel
import PackageModelSyntax
import SwiftParser
import SwiftSyntax
import TSCBasic
import TSCUtility
import Workspace

extension SwiftPackageCommand {
struct AddDependency: SwiftCommand {
package static let configuration = CommandConfiguration(
abstract: "Add a package dependency to the manifest")

@Argument(help: "The URL or directory of the package to add")
var dependency: String

@OptionGroup(visibility: .hidden)
var globalOptions: GlobalOptions

@Option(help: "The exact package version to depend on")
var exact: Version?

@Option(help: "The specific package revision to depend on")
var revision: String?

@Option(help: "The branch of the package to depend on")
var branch: String?

@Option(help: "The package version to depend on (up to the next major version)")
var from: Version?

@Option(help: "The package version to depend on (up to the next minor version)")
var upToNextMinorFrom: Version?

@Option(help: "Specify upper bound on the package version range (exclusive)")
var to: Version?

func run(_ swiftCommandState: SwiftCommandState) throws {
let workspace = try swiftCommandState.getActiveWorkspace()

guard let packagePath = try swiftCommandState.getWorkspaceRoot().packages.first else {
throw StringError("unknown package")
}

// Load the manifest file
let fileSystem = workspace.fileSystem
let manifestPath = packagePath.appending("Package.swift")
let manifestContents: ByteString
do {
manifestContents = try fileSystem.readFileContents(manifestPath)
} catch {
throw StringError("cannot find package manifest in \(manifestPath)")
}

// Parse the manifest.
let manifestSyntax = manifestContents.withData { data in
data.withUnsafeBytes { buffer in
buffer.withMemoryRebound(to: UInt8.self) { buffer in
Parser.parse(source: buffer)
}
}
}

let identity = PackageIdentity(url: .init(dependency))

// Collect all of the possible version requirements.
var requirements: [PackageDependency.SourceControl.Requirement] = []
if let exact {
requirements.append(.exact(exact))
}

if let branch {
requirements.append(.branch(branch))
}

if let revision {
requirements.append(.revision(revision))
}

if let from {
requirements.append(.range(.upToNextMajor(from: from)))
}

if let upToNextMinorFrom {
requirements.append(.range(.upToNextMinor(from: upToNextMinorFrom)))
}

if requirements.count > 1 {
throw StringError("must specify at most one of --exact, --branch, --revision, --from, or --up-to-next-minor-from")
}

guard let firstRequirement = requirements.first else {
throw StringError("must specify one of --exact, --branch, --revision, --from, or --up-to-next-minor-from")
}

let requirement: PackageDependency.SourceControl.Requirement
if case .range(let range) = firstRequirement {
if let to {
requirement = .range(range.lowerBound..<to)
} else {
requirement = .range(range)
}
} else {
requirement = firstRequirement

if to != nil {
throw StringError("--to can only be specified with --from or --up-to-next-minor-from")
}
}

// Figure out the location of the package.
let location: PackageDependency.SourceControl.Location
if let path = try? Basics.AbsolutePath(validating: dependency) {
location = .local(path)
} else {
location = .remote(.init(dependency))
}

let packageDependency: PackageDependency = .sourceControl(
identity: identity,
nameForTargetDependencyResolutionOnly: nil,
location: location,
requirement: requirement,
productFilter: .everything
)

let editResult = try AddPackageDependency.addPackageDependency(
packageDependency,
to: manifestSyntax
)

try editResult.applyEdits(
to: fileSystem,
manifest: manifestSyntax,
manifestPath: manifestPath,
verbose: !globalOptions.logging.quiet
)
}
}
}
Loading