Skip to content

Cleanup PackageModel Module #2980

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Oct 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7e7d692
Move ToolsVersion APIs in Manifest to original declaration
mattt Oct 12, 2020
1582770
Reorganize declarations of Manifest APIs
mattt Oct 12, 2020
755725b
Extract PackageReference into separate file
mattt Oct 12, 2020
00278ab
Move PlatformRegistry to PackageLoading module
mattt Oct 12, 2020
6cefd0d
Reorganize ProductType declaration
mattt Oct 12, 2020
c252c8a
Move PackageConditionWrapper declaration closer to PackageConditionPr…
mattt Oct 12, 2020
6d1f4d7
Move Codable conformance out of PackageModel+Codable.swift
mattt Oct 12, 2020
ed98eca
Extract SwiftLanguageVersion into separate file
mattt Oct 12, 2020
4ab265a
Extract PackageModel diagnostics into separate file
mattt Oct 12, 2020
1315c8c
Extract SupportedLanguageExtension into separate file
mattt Oct 12, 2020
a177154
Move resolved models to PackageGraph module
mattt Oct 12, 2020
7537c52
Extract BuildConfiguration and BuildEnvironment into separate files
mattt Oct 12, 2020
3e307e8
Extract Manifest description types into separate files
mattt Oct 12, 2020
136fd40
Move ProductFilter declaration
mattt Oct 12, 2020
b58782f
Implement protocol conformance in extensions
mattt Oct 12, 2020
e275b94
Make Target subclasses final
mattt Oct 20, 2020
00aa289
Extract ModuleMapType into separate file
mattt Oct 20, 2020
aa3f08b
Add CMakeLists.txt to Manifest subdirectory
mattt Oct 20, 2020
1231679
Move SwiftTarget convenience initializer to declaration and change to…
mattt Oct 20, 2020
7f35c1a
Revert "Add CMakeLists.txt to Manifest subdirectory"
mattt Oct 20, 2020
53390c6
Revert implementation of SwiftTarget init(linuxMain:...)
mattt Oct 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/Commands/show-dependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import TSCBasic
import PackageModel
import PackageGraph

public func dumpDependenciesOf(rootPackage: ResolvedPackage, mode: ShowDependenciesMode, on stream: OutputByteStream = stdoutStream) {
let dumper: DependenciesDumper
Expand Down
3 changes: 3 additions & 0 deletions Sources/PackageGraph/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ add_library(PackageGraph
PinsStore.swift
Pubgrub.swift
RawPackageConstraints.swift
ResolvedPackage.swift
ResolvedProduct.swift
ResolvedTarget.swift
RepositoryPackageContainerProvider.swift
VersionSetSpecifier.swift)
target_link_libraries(PackageGraph PUBLIC
Expand Down
61 changes: 61 additions & 0 deletions Sources/PackageGraph/ResolvedPackage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2014 - 2020 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 Swift project authors
*/

import TSCBasic
import PackageModel

/// A fully resolved package. Contains resolved targets, products and dependencies of the package.
public final class ResolvedPackage: ObjectIdentifierProtocol {

/// The underlying package reference.
public let underlyingPackage: Package

/// The manifest describing the package.
public var manifest: Manifest {
return underlyingPackage.manifest
}

/// The name of the package.
public var name: String {
return underlyingPackage.name
}

/// The local path of the package.
public var path: AbsolutePath {
return underlyingPackage.path
}

/// The targets contained in the package.
public let targets: [ResolvedTarget]

/// The products produced by the package.
public let products: [ResolvedProduct]

/// The dependencies of the package.
public let dependencies: [ResolvedPackage]

public init(
package: Package,
dependencies: [ResolvedPackage],
targets: [ResolvedTarget],
products: [ResolvedProduct]
) {
self.underlyingPackage = package
self.dependencies = dependencies
self.targets = targets
self.products = products
}
}

extension ResolvedPackage: CustomStringConvertible {
public var description: String {
return "<ResolvedPackage: \(name)>"
}
}
79 changes: 79 additions & 0 deletions Sources/PackageGraph/ResolvedProduct.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2014 - 2020 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 Swift project authors
*/

import TSCBasic
import PackageModel

public final class ResolvedProduct: ObjectIdentifierProtocol {

/// The underlying product.
public let underlyingProduct: Product

/// The name of this product.
public var name: String {
return underlyingProduct.name
}

/// The top level targets contained in this product.
public let targets: [ResolvedTarget]

/// The type of this product.
public var type: ProductType {
return underlyingProduct.type
}

/// Executable target for linux main test manifest file.
public let linuxMainTarget: ResolvedTarget?

/// The main executable target of product.
///
/// Note: This property is only valid for executable products.
public var executableModule: ResolvedTarget {
precondition(type == .executable, "This property should only be called for executable targets")
return targets.first(where: { $0.type == .executable })!
}

public init(product: Product, targets: [ResolvedTarget]) {
assert(product.targets.count == targets.count && product.targets.map({ $0.name }) == targets.map({ $0.name }))
self.underlyingProduct = product
self.targets = targets

self.linuxMainTarget = underlyingProduct.linuxMain.map({ linuxMain in
// Create an executable resolved target with the linux main, adding product's targets as dependencies.
let dependencies: [Target.Dependency] = product.targets.map { .target($0, conditions: []) }
let swiftTarget = SwiftTarget(linuxMain: linuxMain, name: product.name, dependencies: dependencies)
return ResolvedTarget(target: swiftTarget, dependencies: targets.map { .target($0, conditions: []) })
})
}

/// True if this product contains Swift targets.
public var containsSwiftTargets: Bool {
// C targets can't import Swift targets in SwiftPM (at least not right
// now), so we can just look at the top-level targets.
//
// If that ever changes, we'll need to do something more complex here,
// recursively checking dependencies for SwiftTargets, and considering
// dynamic library targets to be Swift targets (since the dylib could
// contain Swift code we don't know about as part of this build).
return targets.contains { $0.underlyingTarget is SwiftTarget }
}

/// Returns the recursive target dependencies.
public func recursiveTargetDependencies() -> [ResolvedTarget] {
let recursiveDependencies = targets.lazy.flatMap { $0.recursiveTargetDependencies() }
return Array(Set(targets).union(recursiveDependencies))
}
}

extension ResolvedProduct: CustomStringConvertible {
public var description: String {
return "<ResolvedProduct: \(name)>"
}
}
173 changes: 173 additions & 0 deletions Sources/PackageGraph/ResolvedTarget.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2014 - 2020 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 Swift project authors
*/

import TSCBasic
import PackageModel

/// Represents a fully resolved target. All the dependencies for the target are resolved.
public final class ResolvedTarget: ObjectIdentifierProtocol {

/// Represents dependency of a resolved target.
public enum Dependency {
/// Direct dependency of the target. This target is in the same package and should be statically linked.
case target(_ target: ResolvedTarget, conditions: [PackageConditionProtocol])

/// The target depends on this product.
case product(_ product: ResolvedProduct, conditions: [PackageConditionProtocol])

public var target: ResolvedTarget? {
switch self {
case .target(let target, _): return target
case .product: return nil
}
}

public var product: ResolvedProduct? {
switch self {
case .target: return nil
case .product(let product, _): return product
}
}

public var conditions: [PackageConditionProtocol] {
switch self {
case .target(_, let conditions): return conditions
case .product(_, let conditions): return conditions
}
}

/// Returns the direct dependencies of the underlying dependency, accross the package graph.
public var dependencies: [ResolvedTarget.Dependency] {
switch self {
case .target(let target, _):
return target.dependencies
case .product(let product, _):
return product.targets.map { .target($0, conditions: []) }
}
}

/// Returns the direct dependencies of the underlying dependency, limited to the target's package.
public var packageDependencies: [ResolvedTarget.Dependency] {
switch self {
case .target(let target, _):
return target.dependencies
case .product:
return []
}
}

public func satisfies(_ environment: BuildEnvironment) -> Bool {
conditions.allSatisfy { $0.satisfies(environment) }
}
}

/// The underlying target represented in this resolved target.
public let underlyingTarget: Target

/// The name of this target.
public var name: String {
return underlyingTarget.name
}

/// The dependencies of this target.
public let dependencies: [Dependency]

/// Returns dependencies which satisfy the input build environment, based on their conditions.
/// - Parameters:
/// - environment: The build environment to use to filter dependencies on.
public func dependencies(satisfying environment: BuildEnvironment) -> [Dependency] {
return dependencies.filter { $0.satisfies(environment) }
}

/// Returns the recursive dependencies, accross the whole package-graph.
public func recursiveDependencies() -> [Dependency] {
return try! topologicalSort(self.dependencies) { $0.dependencies }
}

/// Returns the recursive target dependencies, accross the whole package-graph.
public func recursiveTargetDependencies() -> [ResolvedTarget] {
return try! topologicalSort(self.dependencies) { $0.dependencies }.compactMap { $0.target }
}

/// Returns the recursive dependencies, accross the whole package-graph, which satisfy the input build environment,
/// based on their conditions.
/// - Parameters:
/// - environment: The build environment to use to filter dependencies on.
public func recursiveDependencies(satisfying environment: BuildEnvironment) -> [Dependency] {
return try! topologicalSort(dependencies(satisfying: environment)) { dependency in
return dependency.dependencies.filter { $0.satisfies(environment) }
}
}

/// The language-level target name.
public var c99name: String {
return underlyingTarget.c99name
}

/// The "type" of target.
public var type: Target.Kind {
return underlyingTarget.type
}

/// The sources for the target.
public var sources: Sources {
return underlyingTarget.sources
}

/// Create a target instance.
public init(target: Target, dependencies: [Dependency]) {
self.underlyingTarget = target
self.dependencies = dependencies
}
}

extension ResolvedTarget: CustomStringConvertible {
public var description: String {
return "<ResolvedTarget: \(name)>"
}
}

extension ResolvedTarget.Dependency: Equatable {
public static func == (lhs: ResolvedTarget.Dependency, rhs: ResolvedTarget.Dependency) -> Bool {
switch (lhs, rhs) {
case (.target(let lhsTarget, _), .target(let rhsTarget, _)):
return lhsTarget == rhsTarget
case (.product(let lhsProduct, _), .product(let rhsProduct, _)):
return lhsProduct == rhsProduct
case (.product, .target), (.target, .product):
return false
}
}
}

extension ResolvedTarget.Dependency: Hashable {
public func hash(into hasher: inout Hasher) {
switch self {
case .target(let target, _):
hasher.combine(target)
case .product(let product, _):
hasher.combine(product)
}
}
}

extension ResolvedTarget.Dependency: CustomStringConvertible {
public var description: String {
var str = "<ResolvedTarget.Dependency: "
switch self {
case .product(let p, _):
str += p.description
case .target(let t, _):
str += t.description
}
str += ">"
return str
}
}
1 change: 1 addition & 0 deletions Sources/PackageLoading/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ add_library(PackageLoading
ModuleMapGenerator.swift
PackageBuilder.swift
PackageDescription4Loader.swift
PlatformRegistry.swift
Target+PkgConfig.swift
TargetSourcesBuilder.swift
ToolsVersionLoader.swift
Expand Down
36 changes: 36 additions & 0 deletions Sources/PackageLoading/PlatformRegistry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2018 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 Swift project authors
*/

import PackageModel

/// A registry for available platforms.
public final class PlatformRegistry {

/// The current registery is hardcoded and static so we can just use
/// a singleton for now.
public static let `default`: PlatformRegistry = .init()

/// The list of known platforms.
public let knownPlatforms: [Platform]

/// The mapping of platforms to their name.
public let platformByName: [String: Platform]

/// Create a registry with the given list of platforms.
init(platforms: [Platform] = PlatformRegistry._knownPlatforms) {
self.knownPlatforms = platforms
self.platformByName = Dictionary(uniqueKeysWithValues: knownPlatforms.map({ ($0.name, $0) }))
}

/// The static list of known platforms.
private static var _knownPlatforms: [Platform] {
return [.macOS, .iOS, .tvOS, .watchOS, .linux, .windows, .android, .wasi]
}
}
Loading