Skip to content

Commit 8162869

Browse files
committed
Move resolved models to PackageGraph module
Extract ResolvedPackage into separate file Extract ResolvedProduct into separate file Extract ResolvedTarget into separate file Reorganize protocol conformance
1 parent 3045cba commit 8162869

File tree

12 files changed

+354
-314
lines changed

12 files changed

+354
-314
lines changed

Sources/Commands/show-dependencies.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import TSCBasic
1212
import PackageModel
13+
import PackageGraph
1314

1415
public func dumpDependenciesOf(rootPackage: ResolvedPackage, mode: ShowDependenciesMode, on stream: OutputByteStream = stdoutStream) {
1516
let dumper: DependenciesDumper

Sources/PackageGraph/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ add_library(PackageGraph
1515
PinsStore.swift
1616
Pubgrub.swift
1717
RawPackageConstraints.swift
18+
ResolvedPackage.swift
19+
ResolvedProduct.swift
20+
ResolvedTarget.swift
1821
RepositoryPackageContainerProvider.swift
1922
VersionSetSpecifier.swift)
2023
target_link_libraries(PackageGraph PUBLIC
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import TSCBasic
12+
import PackageModel
13+
14+
/// A fully resolved package. Contains resolved targets, products and dependencies of the package.
15+
public final class ResolvedPackage: ObjectIdentifierProtocol {
16+
17+
/// The underlying package reference.
18+
public let underlyingPackage: Package
19+
20+
/// The manifest describing the package.
21+
public var manifest: Manifest {
22+
return underlyingPackage.manifest
23+
}
24+
25+
/// The name of the package.
26+
public var name: String {
27+
return underlyingPackage.name
28+
}
29+
30+
/// The local path of the package.
31+
public var path: AbsolutePath {
32+
return underlyingPackage.path
33+
}
34+
35+
/// The targets contained in the package.
36+
public let targets: [ResolvedTarget]
37+
38+
/// The products produced by the package.
39+
public let products: [ResolvedProduct]
40+
41+
/// The dependencies of the package.
42+
public let dependencies: [ResolvedPackage]
43+
44+
public init(
45+
package: Package,
46+
dependencies: [ResolvedPackage],
47+
targets: [ResolvedTarget],
48+
products: [ResolvedProduct]
49+
) {
50+
self.underlyingPackage = package
51+
self.dependencies = dependencies
52+
self.targets = targets
53+
self.products = products
54+
}
55+
}
56+
57+
extension ResolvedPackage: CustomStringConvertible {
58+
public var description: String {
59+
return "<ResolvedPackage: \(name)>"
60+
}
61+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import TSCBasic
12+
import PackageModel
13+
14+
public final class ResolvedProduct: ObjectIdentifierProtocol {
15+
16+
/// The underlying product.
17+
public let underlyingProduct: Product
18+
19+
/// The name of this product.
20+
public var name: String {
21+
return underlyingProduct.name
22+
}
23+
24+
/// The top level targets contained in this product.
25+
public let targets: [ResolvedTarget]
26+
27+
/// The type of this product.
28+
public var type: ProductType {
29+
return underlyingProduct.type
30+
}
31+
32+
/// Executable target for linux main test manifest file.
33+
public let linuxMainTarget: ResolvedTarget?
34+
35+
/// The main executable target of product.
36+
///
37+
/// Note: This property is only valid for executable products.
38+
public var executableModule: ResolvedTarget {
39+
precondition(type == .executable, "This property should only be called for executable targets")
40+
return targets.first(where: { $0.type == .executable })!
41+
}
42+
43+
public init(product: Product, targets: [ResolvedTarget]) {
44+
assert(product.targets.count == targets.count && product.targets.map({ $0.name }) == targets.map({ $0.name }))
45+
self.underlyingProduct = product
46+
self.targets = targets
47+
48+
self.linuxMainTarget = underlyingProduct.linuxMain.map({ linuxMain in
49+
// Create an executable resolved target with the linux main, adding product's targets as dependencies.
50+
let dependencies: [Target.Dependency] = product.targets.map { .target($0, conditions: []) }
51+
let swiftTarget = SwiftTarget(linuxMain: linuxMain, name: product.name, dependencies: dependencies)
52+
return ResolvedTarget(target: swiftTarget, dependencies: targets.map { .target($0, conditions: []) })
53+
})
54+
}
55+
56+
/// True if this product contains Swift targets.
57+
public var containsSwiftTargets: Bool {
58+
// C targets can't import Swift targets in SwiftPM (at least not right
59+
// now), so we can just look at the top-level targets.
60+
//
61+
// If that ever changes, we'll need to do something more complex here,
62+
// recursively checking dependencies for SwiftTargets, and considering
63+
// dynamic library targets to be Swift targets (since the dylib could
64+
// contain Swift code we don't know about as part of this build).
65+
return targets.contains { $0.underlyingTarget is SwiftTarget }
66+
}
67+
68+
/// Returns the recursive target dependencies.
69+
public func recursiveTargetDependencies() -> [ResolvedTarget] {
70+
let recursiveDependencies = targets.lazy.flatMap { $0.recursiveTargetDependencies() }
71+
return Array(Set(targets).union(recursiveDependencies))
72+
}
73+
}
74+
75+
extension ResolvedProduct: CustomStringConvertible {
76+
public var description: String {
77+
return "<ResolvedProduct: \(name)>"
78+
}
79+
}
80+
81+
fileprivate extension SwiftTarget {
82+
/// Create an executable Swift target from linux main test manifest file.
83+
convenience init(linuxMain: AbsolutePath, name: String, dependencies: [Target.Dependency]) {
84+
// Look for the first swift test target and use the same swift version
85+
// for linux main target. This will need to change if we move to a model
86+
// where we allow per target swift language version build settings.
87+
let swiftTestTarget = dependencies.first {
88+
guard case .target(let target as SwiftTarget, _) = $0 else { return false }
89+
return target.type == .test
90+
}.flatMap { $0.target as? SwiftTarget }
91+
92+
// FIXME: This is not very correct but doesn't matter much in practice.
93+
// We need to select the latest Swift language version that can
94+
// satisfy the current tools version but there is not a good way to
95+
// do that currently.
96+
let sources = Sources(paths: [linuxMain], root: linuxMain.parentDirectory)
97+
98+
let platforms: [SupportedPlatform] = swiftTestTarget?.platforms ?? []
99+
100+
let swiftVersion = swiftTestTarget?.swiftVersion ?? SwiftLanguageVersion(string: String(ToolsVersion.currentToolsVersion.major)) ?? .v4
101+
102+
self.init(
103+
name: name,
104+
defaultLocalization: nil,
105+
platforms: platforms,
106+
sources: sources,
107+
dependencies: dependencies,
108+
swiftVersion: swiftVersion,
109+
buildSettings: .init()
110+
)
111+
}
112+
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import TSCBasic
12+
import PackageModel
13+
14+
/// Represents a fully resolved target. All the dependencies for the target are resolved.
15+
public final class ResolvedTarget: ObjectIdentifierProtocol {
16+
17+
/// Represents dependency of a resolved target.
18+
public enum Dependency {
19+
/// Direct dependency of the target. This target is in the same package and should be statically linked.
20+
case target(_ target: ResolvedTarget, conditions: [PackageConditionProtocol])
21+
22+
/// The target depends on this product.
23+
case product(_ product: ResolvedProduct, conditions: [PackageConditionProtocol])
24+
25+
public var target: ResolvedTarget? {
26+
switch self {
27+
case .target(let target, _): return target
28+
case .product: return nil
29+
}
30+
}
31+
32+
public var product: ResolvedProduct? {
33+
switch self {
34+
case .target: return nil
35+
case .product(let product, _): return product
36+
}
37+
}
38+
39+
public var conditions: [PackageConditionProtocol] {
40+
switch self {
41+
case .target(_, let conditions): return conditions
42+
case .product(_, let conditions): return conditions
43+
}
44+
}
45+
46+
/// Returns the direct dependencies of the underlying dependency, accross the package graph.
47+
public var dependencies: [ResolvedTarget.Dependency] {
48+
switch self {
49+
case .target(let target, _):
50+
return target.dependencies
51+
case .product(let product, _):
52+
return product.targets.map { .target($0, conditions: []) }
53+
}
54+
}
55+
56+
/// Returns the direct dependencies of the underlying dependency, limited to the target's package.
57+
public var packageDependencies: [ResolvedTarget.Dependency] {
58+
switch self {
59+
case .target(let target, _):
60+
return target.dependencies
61+
case .product:
62+
return []
63+
}
64+
}
65+
66+
public func satisfies(_ environment: BuildEnvironment) -> Bool {
67+
conditions.allSatisfy { $0.satisfies(environment) }
68+
}
69+
}
70+
71+
/// The underlying target represented in this resolved target.
72+
public let underlyingTarget: Target
73+
74+
/// The name of this target.
75+
public var name: String {
76+
return underlyingTarget.name
77+
}
78+
79+
/// The dependencies of this target.
80+
public let dependencies: [Dependency]
81+
82+
/// Returns dependencies which satisfy the input build environment, based on their conditions.
83+
/// - Parameters:
84+
/// - environment: The build environment to use to filter dependencies on.
85+
public func dependencies(satisfying environment: BuildEnvironment) -> [Dependency] {
86+
return dependencies.filter { $0.satisfies(environment) }
87+
}
88+
89+
/// Returns the recursive dependencies, accross the whole package-graph.
90+
public func recursiveDependencies() -> [Dependency] {
91+
return try! topologicalSort(self.dependencies) { $0.dependencies }
92+
}
93+
94+
/// Returns the recursive target dependencies, accross the whole package-graph.
95+
public func recursiveTargetDependencies() -> [ResolvedTarget] {
96+
return try! topologicalSort(self.dependencies) { $0.dependencies }.compactMap { $0.target }
97+
}
98+
99+
/// Returns the recursive dependencies, accross the whole package-graph, which satisfy the input build environment,
100+
/// based on their conditions.
101+
/// - Parameters:
102+
/// - environment: The build environment to use to filter dependencies on.
103+
public func recursiveDependencies(satisfying environment: BuildEnvironment) -> [Dependency] {
104+
return try! topologicalSort(dependencies(satisfying: environment)) { dependency in
105+
return dependency.dependencies.filter { $0.satisfies(environment) }
106+
}
107+
}
108+
109+
/// The language-level target name.
110+
public var c99name: String {
111+
return underlyingTarget.c99name
112+
}
113+
114+
/// The "type" of target.
115+
public var type: Target.Kind {
116+
return underlyingTarget.type
117+
}
118+
119+
/// The sources for the target.
120+
public var sources: Sources {
121+
return underlyingTarget.sources
122+
}
123+
124+
/// Create a target instance.
125+
public init(target: Target, dependencies: [Dependency]) {
126+
self.underlyingTarget = target
127+
self.dependencies = dependencies
128+
}
129+
}
130+
131+
extension ResolvedTarget: CustomStringConvertible {
132+
public var description: String {
133+
return "<ResolvedTarget: \(name)>"
134+
}
135+
}
136+
137+
extension ResolvedTarget.Dependency: Equatable {
138+
public static func == (lhs: ResolvedTarget.Dependency, rhs: ResolvedTarget.Dependency) -> Bool {
139+
switch (lhs, rhs) {
140+
case (.target(let lhsTarget, _), .target(let rhsTarget, _)):
141+
return lhsTarget == rhsTarget
142+
case (.product(let lhsProduct, _), .product(let rhsProduct, _)):
143+
return lhsProduct == rhsProduct
144+
case (.product, .target), (.target, .product):
145+
return false
146+
}
147+
}
148+
}
149+
150+
extension ResolvedTarget.Dependency: Hashable {
151+
public func hash(into hasher: inout Hasher) {
152+
switch self {
153+
case .target(let target, _):
154+
hasher.combine(target)
155+
case .product(let product, _):
156+
hasher.combine(product)
157+
}
158+
}
159+
}
160+
161+
extension ResolvedTarget.Dependency: CustomStringConvertible {
162+
public var description: String {
163+
var str = "<ResolvedTarget.Dependency: "
164+
switch self {
165+
case .product(let p, _):
166+
str += p.description
167+
case .target(let t, _):
168+
str += t.description
169+
}
170+
str += ">"
171+
return str
172+
}
173+
}

Sources/PackageModel/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ add_library(PackageModel
1313
Package.swift
1414
Platform.swift
1515
Product.swift
16-
ResolvedModels.swift
1716
Resource.swift
1817
Sources.swift
1918
Target.swift

0 commit comments

Comments
 (0)