Skip to content

Commit 40aefdc

Browse files
committed
Implementation of the conditional target dependency proposal
1 parent 9cea0db commit 40aefdc

34 files changed

+1316
-401
lines changed

Sources/Build/BuildParameters.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ public struct BuildParameters: Encodable {
8686
/// module to finish building.
8787
public var emitSwiftModuleSeparately: Bool
8888

89+
/// The current build environment.
90+
public var buildEnvironment: BuildEnvironment {
91+
BuildEnvironment(platform: currentPlatform, configuration: configuration)
92+
}
93+
8994
public init(
9095
dataPath: AbsolutePath,
9196
configuration: BuildConfiguration,

Sources/Build/BuildPlan.swift

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ extension BuildParameters {
7676
}
7777

7878
/// The current platform we're building for.
79-
fileprivate var currentPlatform: PackageModel.Platform {
79+
var currentPlatform: PackageModel.Platform {
8080
if self.triple.isDarwin() {
8181
return .macOS
8282
} else if self.triple.isAndroid() {
@@ -88,7 +88,7 @@ extension BuildParameters {
8888

8989
/// Returns the scoped view of build settings for a given target.
9090
fileprivate func createScope(for target: ResolvedTarget) -> BuildSettings.Scope {
91-
return BuildSettings.Scope(target.underlyingTarget.buildSettings, boundCondition: (currentPlatform, configuration))
91+
return BuildSettings.Scope(target.underlyingTarget.buildSettings, environment: buildEnvironment)
9292
}
9393
}
9494

@@ -145,6 +145,10 @@ public final class ClangTargetBuildDescription {
145145
/// The build parameters.
146146
let buildParameters: BuildParameters
147147

148+
var buildEnvironment: BuildEnvironment {
149+
buildParameters.buildEnvironment
150+
}
151+
148152
/// Path to the bundle generated for this module (if any).
149153
var bundlePath: AbsolutePath? {
150154
buildParameters.bundlePath(for: target)
@@ -1036,6 +1040,10 @@ public class BuildPlan {
10361040
/// The build parameters.
10371041
public let buildParameters: BuildParameters
10381042

1043+
private var buildEnvironment: BuildEnvironment {
1044+
buildParameters.buildEnvironment
1045+
}
1046+
10391047
/// The package graph.
10401048
public let graph: PackageGraph
10411049

@@ -1104,10 +1112,10 @@ public class BuildPlan {
11041112
let swiftTarget = SwiftTarget(
11051113
testDiscoverySrc: src,
11061114
name: testProduct.name,
1107-
dependencies: testProduct.underlyingProduct.targets)
1115+
dependencies: testProduct.underlyingProduct.targets.map({ .target($0, conditions: []) }))
11081116
let linuxMainTarget = ResolvedTarget(
11091117
target: swiftTarget,
1110-
dependencies: testProduct.targets.map(ResolvedTarget.Dependency.target)
1118+
dependencies: testProduct.targets.map({ .target($0, conditions: []) })
11111119
)
11121120

11131121
let target = try SwiftTargetBuildDescription(
@@ -1142,7 +1150,7 @@ public class BuildPlan {
11421150
for dependency in target.dependencies {
11431151
switch dependency {
11441152
case .target: break
1145-
case .product(let product):
1153+
case .product(let product, _):
11461154
if buildParameters.triple.isDarwin() {
11471155
BuildPlan.validateDeploymentVersionOfProductDependency(
11481156
product, forTarget: target, diagnostics: diagnostics)
@@ -1317,19 +1325,19 @@ public class BuildPlan {
13171325
) {
13181326

13191327
// Sort the product targets in topological order.
1320-
let nodes = product.targets.map(ResolvedTarget.Dependency.target)
1328+
let nodes: [ResolvedTarget.Dependency] = product.targets.map({ .target($0, conditions: []) })
13211329
let allTargets = try! topologicalSort(nodes, successors: { dependency in
13221330
switch dependency {
13231331
// Include all the depenencies of a target.
1324-
case .target(let target):
1325-
return target.dependencies
1332+
case .target(let target, _):
1333+
return target.dependencies.filter({ $0.satisfies(self.buildEnvironment) })
13261334

13271335
// For a product dependency, we only include its content only if we
13281336
// need to statically link it.
1329-
case .product(let product):
1337+
case .product(let product, _):
13301338
switch product.type {
13311339
case .library(.automatic), .library(.static):
1332-
return product.targets.map(ResolvedTarget.Dependency.target)
1340+
return product.targets.map({ .target($0, conditions: []) })
13331341
case .library(.dynamic), .test, .executable:
13341342
return []
13351343
}
@@ -1343,7 +1351,7 @@ public class BuildPlan {
13431351

13441352
for dependency in allTargets {
13451353
switch dependency {
1346-
case .target(let target):
1354+
case .target(let target, _):
13471355
switch target.type {
13481356
// Include executable and tests only if they're top level contents
13491357
// of the product. Otherwise they are just build time dependency.
@@ -1359,7 +1367,7 @@ public class BuildPlan {
13591367
systemModules.append(target)
13601368
}
13611369

1362-
case .product(let product):
1370+
case .product(let product, _):
13631371
// Add the dynamic products to array of libraries to link.
13641372
if product.type == .library(.dynamic) {
13651373
linkLibraries.append(product)
@@ -1378,10 +1386,11 @@ public class BuildPlan {
13781386

13791387
/// Plan a Clang target.
13801388
private func plan(clangTarget: ClangTargetBuildDescription) {
1381-
for dependency in clangTarget.target.recursiveDependencies() {
1382-
switch dependency.underlyingTarget {
1389+
let recursiveBuildTargets = clangTarget.target.recursiveBuildTargetDependencies(in: buildEnvironment)
1390+
for targetDependency in recursiveBuildTargets {
1391+
switch targetDependency.underlyingTarget {
13831392
case is SwiftTarget:
1384-
if case let .swift(dependencyTargetDescription)? = targetMap[dependency] {
1393+
if case let .swift(dependencyTargetDescription)? = targetMap[targetDependency] {
13851394
if let moduleMap = dependencyTargetDescription.moduleMap {
13861395
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
13871396
}
@@ -1392,7 +1401,7 @@ public class BuildPlan {
13921401
clangTarget.additionalFlags += ["-I", target.includeDir.pathString]
13931402

13941403
// Add the modulemap of the dependency if it has one.
1395-
if case let .clang(dependencyTargetDescription)? = targetMap[dependency] {
1404+
if case let .clang(dependencyTargetDescription)? = targetMap[targetDependency] {
13961405
if let moduleMap = dependencyTargetDescription.moduleMap {
13971406
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
13981407
}
@@ -1409,10 +1418,13 @@ public class BuildPlan {
14091418
private func plan(swiftTarget: SwiftTargetBuildDescription) throws {
14101419
// We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target
14111420
// depends on.
1412-
for dependency in swiftTarget.target.recursiveDependencies() {
1413-
switch dependency.underlyingTarget {
1421+
let recursiveBuildTargets = swiftTarget.target
1422+
.recursiveBuildDependencies(in: buildEnvironment)
1423+
.compactMap({ $0.target })
1424+
for targetDependency in recursiveBuildTargets {
1425+
switch targetDependency.underlyingTarget {
14141426
case let underlyingTarget as ClangTarget where underlyingTarget.type == .library:
1415-
guard case let .clang(target)? = targetMap[dependency] else {
1427+
guard case let .clang(target)? = targetMap[targetDependency] else {
14161428
fatalError("unexpected clang target \(underlyingTarget)")
14171429
}
14181430
// Add the path to modulemap of the dependency. Currently we require that all Clang targets have a

Sources/Build/ManifestBuilder.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class LLBuildManifestBuilder {
3636

3737
var buildConfig: String { buildParameters.configuration.dirname }
3838
var buildParameters: BuildParameters { plan.buildParameters }
39+
var buildEnvironment: BuildEnvironment { buildParameters.buildEnvironment }
3940

4041
/// Create a new builder with a build plan.
4142
public init(_ plan: BuildPlan) {
@@ -259,12 +260,12 @@ extension LLBuildManifestBuilder {
259260
}
260261
}
261262

262-
for dependency in target.target.dependencies {
263+
for dependency in target.target.buildDependencies(in: buildEnvironment) {
263264
switch dependency {
264-
case .target(let target):
265+
case .target(let target, _):
265266
addStaticTargetInputs(target)
266267

267-
case .product(let product):
268+
case .product(let product, _):
268269
switch product.type {
269270
case .executable, .library(.dynamic):
270271
// Establish a dependency on binary of the product.
@@ -350,12 +351,12 @@ extension LLBuildManifestBuilder {
350351
}
351352
}
352353

353-
for dependency in target.target.dependencies {
354+
for dependency in target.target.buildDependencies(in: buildEnvironment) {
354355
switch dependency {
355-
case .target(let target):
356+
case .target(let target, _):
356357
addStaticTargetInputs(target)
357358

358-
case .product(let product):
359+
case .product(let product, _):
359360
switch product.type {
360361
case .executable, .library(.dynamic):
361362
// Establish a dependency on binary of the product.

Sources/PackageDescription/BuildSettings.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public struct BuildConfiguration: Encodable {
4545
/// .define("ENABLE_SOMETHING", .when(configuration: .release)),
4646
/// ],
4747
/// linkerSettings: [
48-
/// .linkLibrary("openssl", .when(platforms: [.linux])),
48+
/// .linkedLibrary("openssl", .when(platforms: [.linux])),
4949
/// ]
5050
/// ),
5151
public struct BuildSettingCondition: Encodable {
@@ -228,7 +228,7 @@ public struct SwiftSetting: Encodable {
228228
/// Use compilation conditions to only compile statements if a certain condition is true.
229229
/// For example, the Swift compiler will only compile the
230230
/// statements inside the `#if` block when `ENABLE_SOMETHING` is defined:
231-
///
231+
///
232232
/// #if ENABLE_SOMETHING
233233
/// ...
234234
/// #endif

Sources/PackageDescription/Package.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ extension Target.Dependency: Encodable {
452452
case type
453453
case name
454454
case package
455+
case condition
455456
}
456457

457458
private enum Kind: String, Codable {
@@ -477,16 +478,19 @@ extension Target.Dependency: Encodable {
477478
}
478479
#else
479480
switch self {
480-
case ._targetItem(let name):
481+
case ._targetItem(let name, let condition):
481482
try container.encode(Kind.target, forKey: .type)
482483
try container.encode(name, forKey: .name)
483-
case ._productItem(let name, let package):
484+
try container.encode(condition, forKey: .condition)
485+
case ._productItem(let name, let package, let condition):
484486
try container.encode(Kind.product, forKey: .type)
485487
try container.encode(name, forKey: .name)
486488
try container.encode(package, forKey: .package)
487-
case ._byNameItem(let name):
489+
try container.encode(condition, forKey: .condition)
490+
case ._byNameItem(let name, let condition):
488491
try container.encode(Kind.byName, forKey: .type)
489492
try container.encode(name, forKey: .name)
493+
try container.encode(condition, forKey: .condition)
490494
}
491495
#endif
492496
}

Sources/PackageDescription/Target.swift

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public final class Target {
3333
case productItem(name: String, package: String?)
3434
case byNameItem(name: String)
3535
#else
36-
case _targetItem(name: String)
37-
case _productItem(name: String, package: String?)
38-
case _byNameItem(name: String)
36+
case _targetItem(name: String, condition: BuildSettingCondition?)
37+
case _productItem(name: String, package: String?, condition: BuildSettingCondition?)
38+
case _byNameItem(name: String, condition: BuildSettingCondition?)
3939
#endif
4040
}
4141

@@ -494,7 +494,7 @@ extension Target.Dependency {
494494
#if PACKAGE_DESCRIPTION_4
495495
return .targetItem(name: name)
496496
#else
497-
return ._targetItem(name: name)
497+
return ._targetItem(name: name, condition: nil)
498498
#endif
499499
}
500500

@@ -508,36 +508,69 @@ extension Target.Dependency {
508508
#if PACKAGE_DESCRIPTION_4
509509
return .productItem(name: name, package: package)
510510
#else
511-
return ._productItem(name: name, package: package)
511+
return ._productItem(name: name, package: package, condition: nil)
512512
#endif
513513
}
514514

515-
/// Creates a dependency on a product from a package dependency.
515+
/// Creates a by-name dependency that resolves to either a target or a product but
516+
/// after the package graph has been loaded.
516517
///
517518
/// - parameters:
518-
/// - name: The name of the product.
519-
/// - package: The name of the package.
520-
@available(_PackageDescription, introduced: 5.2)
521-
public static func product(name: String, package: String) -> Target.Dependency {
519+
/// - name: The name of the dependency, either a target or a product.
520+
public static func byName(name: String) -> Target.Dependency {
522521
#if PACKAGE_DESCRIPTION_4
523-
return .productItem(name: name, package: package)
522+
return .byNameItem(name: name)
524523
#else
525-
return ._productItem(name: name, package: package)
524+
return ._byNameItem(name: name, condition: nil)
526525
#endif
527526
}
528527

528+
#if !PACKAGE_DESCRIPTION_4
529+
/// Creates a dependency on a product from a package dependency.
530+
///
531+
/// - parameters:
532+
/// - name: The name of the product.
533+
/// - package: The name of the package.
534+
public static func product(
535+
name: String,
536+
package: String
537+
) -> Target.Dependency {
538+
return ._productItem(name: name, package: package, condition: nil)
539+
}
540+
541+
/// Creates a dependency on a target in the same package.
542+
///
543+
/// - parameters:
544+
/// - name: The name of the target.
545+
/// - condition: The condition under which the dependency is exercised.
546+
public static func _target(name: String, condition: BuildSettingCondition? = nil) -> Target.Dependency {
547+
return ._targetItem(name: name, condition: condition)
548+
}
549+
550+
/// Creates a dependency on a product from a package dependency.
551+
///
552+
/// - parameters:
553+
/// - name: The name of the product.
554+
/// - package: The name of the package.
555+
/// - condition: The condition under which the dependency is exercised.
556+
public static func _product(
557+
name: String,
558+
package: String,
559+
condition: BuildSettingCondition? = nil
560+
) -> Target.Dependency {
561+
return ._productItem(name: name, package: package, condition: condition)
562+
}
563+
529564
/// Creates a by-name dependency that resolves to either a target or a product but
530565
/// after the package graph has been loaded.
531566
///
532567
/// - parameters:
533568
/// - name: The name of the dependency, either a target or a product.
534-
public static func byName(name: String) -> Target.Dependency {
535-
#if PACKAGE_DESCRIPTION_4
536-
return .byNameItem(name: name)
537-
#else
538-
return ._byNameItem(name: name)
539-
#endif
569+
/// - condition: The condition under which the dependency is exercised.
570+
public static func _byName(name: String, condition: BuildSettingCondition? = nil) -> Target.Dependency {
571+
return ._byNameItem(name: name, condition: condition)
540572
}
573+
#endif
541574
}
542575

543576
// MARK: ExpressibleByStringLiteral
@@ -552,7 +585,7 @@ extension Target.Dependency: ExpressibleByStringLiteral {
552585
#if PACKAGE_DESCRIPTION_4
553586
self = .byNameItem(name: value)
554587
#else
555-
self = ._byNameItem(name: value)
588+
self = ._byNameItem(name: value, condition: nil)
556589
#endif
557590
}
558591
}

0 commit comments

Comments
 (0)