@@ -37,7 +37,6 @@ extension ModulesGraph {
37
37
fileSystem: FileSystem ,
38
38
observabilityScope: ObservabilityScope
39
39
) throws -> ModulesGraph {
40
-
41
40
let observabilityScope = observabilityScope. makeChildScope ( description: " Loading Package Graph " )
42
41
43
42
// Create a map of the manifests, keyed by their identity.
@@ -51,43 +50,64 @@ extension ModulesGraph {
51
50
let rootDependencies = Set ( root. dependencies. compactMap {
52
51
manifestMap [ $0. identity] ? . manifest
53
52
} )
54
- let rootManifestNodes = root. packages. map { identity, package in
55
- GraphLoadingNode ( identity: identity, manifest: package . manifest, productFilter: . everything)
53
+
54
+ let rootManifestNodes = try root. packages. map { identity, package in
55
+ // We are going to enable all default traits of the root manifests.
56
+ // In a future PR we make this overridable by CLI options.
57
+ let enabledTraits = package . manifest. traits. lazy. filter { $0. isDefault } . map { $0. name }
58
+ return try GraphLoadingNode (
59
+ identity: identity,
60
+ manifest: package . manifest,
61
+ productFilter: . everything,
62
+ enabledTraits: Set ( enabledTraits)
63
+ )
56
64
}
57
- let rootDependencyNodes = root. dependencies. lazy. compactMap { dependency in
58
- manifestMap [ dependency. identity] . map {
59
- GraphLoadingNode (
65
+ let rootDependencyNodes = try root. dependencies. lazy. compactMap { dependency in
66
+ try manifestMap [ dependency. identity] . map {
67
+ try GraphLoadingNode (
60
68
identity: dependency. identity,
61
69
manifest: $0. manifest,
62
- productFilter: dependency. productFilter
70
+ productFilter: dependency. productFilter,
71
+ enabledTraits: Set ( dependency. traits. map { $0. name } )
63
72
)
64
73
}
65
74
}
66
75
let inputManifests = ( rootManifestNodes + rootDependencyNodes) . map {
67
- KeyedPair ( $0, key: $0. id )
76
+ KeyedPair ( $0, key: $0. identity )
68
77
}
69
78
70
79
// Collect the manifests for which we are going to build packages.
71
- var allNodes = [ GraphLoadingNode] ( )
80
+ var allNodes = OrderedDictionary < PackageIdentity , GraphLoadingNode > ( )
72
81
73
82
let nodeSuccessorProvider = { ( node: KeyedPair < GraphLoadingNode , PackageIdentity > ) in
74
- node. item. requiredDependencies. compactMap { dependency in
75
- manifestMap [ dependency. identity] . map { manifest, _ in
76
- KeyedPair (
77
- GraphLoadingNode (
78
- identity: dependency. identity,
79
- manifest: manifest,
80
- productFilter: dependency. productFilter
81
- ) ,
82
- key: dependency. identity
83
- )
83
+ return try node. item. requiredDependencies. compactMap { dependency in
84
+ return try manifestMap [ dependency. identity] . map { manifest, _ in
85
+ // We are going to check the conditionally enabled traits here and enable them if
86
+ // required. This checks the current node and then enables the conditional
87
+ // dependencies of the dependency node.
88
+ let enabledTraits = dependency. traits. filter {
89
+ guard let conditionTraits = $0. condition? . traits else {
90
+ return true
91
+ }
92
+ return !conditionTraits. intersection ( node. item. enabledTraits) . isEmpty
93
+ } . map { $0. name }
94
+
95
+ return try KeyedPair (
96
+ GraphLoadingNode (
97
+ identity: dependency. identity,
98
+ manifest: manifest,
99
+ productFilter: dependency. productFilter,
100
+ enabledTraits: Set ( enabledTraits)
101
+ ) ,
102
+ key: dependency. identity
103
+ )
84
104
}
85
105
}
86
106
}
87
107
88
108
// Package dependency cycles feature is gated on tools version 6.0.
89
109
if !root. manifests. allSatisfy ( { $1. toolsVersion >= . v6_0 } ) {
90
- if let cycle = findCycle ( inputManifests, successors: nodeSuccessorProvider) {
110
+ if let cycle = try findCycle ( inputManifests, successors: nodeSuccessorProvider) {
91
111
let path = ( cycle. path + cycle. cycle) . map ( \. item. manifest)
92
112
observabilityScope. emit ( PackageGraphError . dependencyCycleDetected (
93
113
path: path, cycle: cycle. cycle [ 0 ] . item. manifest
@@ -104,18 +124,20 @@ extension ModulesGraph {
104
124
}
105
125
106
126
// Cycles in dependencies don't matter as long as there are no target cycles between packages.
107
- depthFirstSearch (
127
+ try depthFirstSearch (
108
128
inputManifests,
109
129
successors: nodeSuccessorProvider
110
130
) {
111
- allNodes. append ( $0. item)
112
- } onDuplicate: { _, _ in
113
- // no de-duplication is required.
131
+ allNodes [ $0. key] = $0. item
132
+ } onDuplicate: { first, second in
133
+ // We are unifying the enabled traits on duplicate
134
+ print ( first. item. identity, first. item. enabledTraits, second. item. enabledTraits)
135
+ allNodes [ first. key] ? . enabledTraits. formUnion ( second. item. enabledTraits)
114
136
}
115
137
116
138
// Create the packages.
117
139
var manifestToPackage : [ Manifest : Package ] = [ : ]
118
- for node in allNodes {
140
+ for node in allNodes. values {
119
141
let nodeObservabilityScope = observabilityScope. makeChildScope (
120
142
description: " loading package \( node. identity) " ,
121
143
metadata: . packageMetadata( identity: node. identity, kind: node. manifest. packageKind)
@@ -139,7 +161,8 @@ extension ModulesGraph {
139
161
testEntryPointPath: testEntryPointPath,
140
162
createREPLProduct: manifest. packageKind. isRoot ? createREPLProduct : false ,
141
163
fileSystem: fileSystem,
142
- observabilityScope: nodeObservabilityScope
164
+ observabilityScope: nodeObservabilityScope,
165
+ enabledTraits: node. enabledTraits
143
166
)
144
167
let package = try builder. construct ( )
145
168
manifestToPackage [ manifest] = package
@@ -162,7 +185,7 @@ extension ModulesGraph {
162
185
163
186
// Resolve dependencies and create resolved packages.
164
187
let resolvedPackages = try createResolvedPackages (
165
- nodes: allNodes,
188
+ nodes: Array ( allNodes. values ) ,
166
189
identityResolver: identityResolver,
167
190
manifestToPackage: manifestToPackage,
168
191
rootManifests: root. manifests,
@@ -273,7 +296,7 @@ private func createResolvedPackages(
273
296
) throws -> IdentifiableSet < ResolvedPackage > {
274
297
275
298
// Create package builder objects from the input manifests.
276
- let packageBuilders : [ ResolvedPackageBuilder ] = nodes. compactMap { node in
299
+ let packageBuilders : [ ResolvedPackageBuilder ] = nodes. compactMap { node in
277
300
guard let package = manifestToPackage [ node. manifest] else {
278
301
return nil
279
302
}
@@ -283,6 +306,7 @@ private func createResolvedPackages(
283
306
return ResolvedPackageBuilder (
284
307
package ,
285
308
productFilter: node. productFilter,
309
+ enabledTraits: node. enabledTraits,
286
310
isAllowedToVendUnsafeProducts: isAllowedToVendUnsafeProducts,
287
311
allowedToOverride: allowedToOverride,
288
312
platformVersionProvider: platformVersionProvider
@@ -315,8 +339,9 @@ private func createResolvedPackages(
315
339
var dependenciesByNameForTargetDependencyResolution = [ String: ResolvedPackageBuilder] ( )
316
340
var dependencyNamesForTargetDependencyResolutionOnly = [ PackageIdentity: String] ( )
317
341
318
- // Establish the manifest-declared package dependencies.
319
- package . manifest. dependenciesRequired ( for: packageBuilder. productFilter) . forEach { dependency in
342
+ package . manifest. dependenciesRequired (
343
+ for: packageBuilder. productFilter
344
+ ) . forEach { dependency in
320
345
let dependencyPackageRef = dependency. packageRef
321
346
322
347
// Otherwise, look it up by its identity.
@@ -530,6 +555,13 @@ private func createResolvedPackages(
530
555
531
556
// Establish product dependencies.
532
557
for case . product( let productRef, let conditions) in targetBuilder. target. dependencies {
558
+ if let traitCondition = conditions. compactMap ( { $0. traitCondition } ) . first {
559
+ if packageBuilder. enabledTraits. intersection ( traitCondition. traits) . isEmpty {
560
+ /// If we land here non of the traits required to enable this depenendcy has been enabled.
561
+ continue
562
+ }
563
+ }
564
+
533
565
// Find the product in this package's dependency products.
534
566
// Look it up by ID if module aliasing is used, otherwise by name.
535
567
let product = lookupByProductIDs ? productDependencyMap [ productRef. identity] : productDependencyMap [ productRef. name]
@@ -1054,6 +1086,9 @@ private final class ResolvedPackageBuilder: ResolvedBuilder<ResolvedPackage> {
1054
1086
/// The products in this package.
1055
1087
var products : [ ResolvedProductBuilder ] = [ ]
1056
1088
1089
+ /// The enabled traits of this package.
1090
+ var enabledTraits : Set < String > = [ ]
1091
+
1057
1092
/// The dependencies of this package.
1058
1093
var dependencies : [ ResolvedPackageBuilder ] = [ ]
1059
1094
@@ -1074,12 +1109,14 @@ private final class ResolvedPackageBuilder: ResolvedBuilder<ResolvedPackage> {
1074
1109
init (
1075
1110
_ package : Package ,
1076
1111
productFilter: ProductFilter ,
1112
+ enabledTraits: Set < String > ,
1077
1113
isAllowedToVendUnsafeProducts: Bool ,
1078
1114
allowedToOverride: Bool ,
1079
1115
platformVersionProvider: PlatformVersionProvider
1080
1116
) {
1081
1117
self . package = package
1082
1118
self . productFilter = productFilter
1119
+ self . enabledTraits = enabledTraits
1083
1120
self . isAllowedToVendUnsafeProducts = isAllowedToVendUnsafeProducts
1084
1121
self . allowedToOverride = allowedToOverride
1085
1122
self . platformVersionProvider = platformVersionProvider
@@ -1095,6 +1132,7 @@ private final class ResolvedPackageBuilder: ResolvedBuilder<ResolvedPackage> {
1095
1132
defaultLocalization: self . defaultLocalization,
1096
1133
supportedPlatforms: self . supportedPlatforms,
1097
1134
dependencies: self . dependencies. map { $0. package . identity } ,
1135
+ enabledTraits: self . enabledTraits,
1098
1136
targets: targets,
1099
1137
products: products,
1100
1138
registryMetadata: self . registryMetadata,
0 commit comments