Skip to content

Commit 6cd80ed

Browse files
committed
Implementation of the conditional target dependency proposal
1 parent d1e519f commit 6cd80ed

34 files changed

+1317
-402
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

@@ -155,6 +155,10 @@ public final class ClangTargetBuildDescription {
155155
/// The build parameters.
156156
let buildParameters: BuildParameters
157157

158+
var buildEnvironment: BuildEnvironment {
159+
buildParameters.buildEnvironment
160+
}
161+
158162
/// Path to the bundle generated for this module (if any).
159163
var bundlePath: AbsolutePath? {
160164
buildParameters.bundlePath(for: target)
@@ -1132,6 +1136,10 @@ public class BuildPlan {
11321136
/// The build parameters.
11331137
public let buildParameters: BuildParameters
11341138

1139+
private var buildEnvironment: BuildEnvironment {
1140+
buildParameters.buildEnvironment
1141+
}
1142+
11351143
/// The package graph.
11361144
public let graph: PackageGraph
11371145

@@ -1200,10 +1208,10 @@ public class BuildPlan {
12001208
let swiftTarget = SwiftTarget(
12011209
testDiscoverySrc: src,
12021210
name: testProduct.name,
1203-
dependencies: testProduct.underlyingProduct.targets)
1211+
dependencies: testProduct.underlyingProduct.targets.map({ .target($0, conditions: []) }))
12041212
let linuxMainTarget = ResolvedTarget(
12051213
target: swiftTarget,
1206-
dependencies: testProduct.targets.map(ResolvedTarget.Dependency.target)
1214+
dependencies: testProduct.targets.map({ .target($0, conditions: []) })
12071215
)
12081216

12091217
let target = try SwiftTargetBuildDescription(
@@ -1238,7 +1246,7 @@ public class BuildPlan {
12381246
for dependency in target.dependencies {
12391247
switch dependency {
12401248
case .target: break
1241-
case .product(let product):
1249+
case .product(let product, _):
12421250
if buildParameters.triple.isDarwin() {
12431251
BuildPlan.validateDeploymentVersionOfProductDependency(
12441252
product, forTarget: target, diagnostics: diagnostics)
@@ -1426,19 +1434,19 @@ public class BuildPlan {
14261434
) {
14271435

14281436
// Sort the product targets in topological order.
1429-
let nodes = product.targets.map(ResolvedTarget.Dependency.target)
1437+
let nodes: [ResolvedTarget.Dependency] = product.targets.map({ .target($0, conditions: []) })
14301438
let allTargets = try! topologicalSort(nodes, successors: { dependency in
14311439
switch dependency {
14321440
// Include all the depenencies of a target.
1433-
case .target(let target):
1434-
return target.dependencies
1441+
case .target(let target, _):
1442+
return target.dependencies.filter({ $0.satisfies(self.buildEnvironment) })
14351443

14361444
// For a product dependency, we only include its content only if we
14371445
// need to statically link it.
1438-
case .product(let product):
1446+
case .product(let product, _):
14391447
switch product.type {
14401448
case .library(.automatic), .library(.static):
1441-
return product.targets.map(ResolvedTarget.Dependency.target)
1449+
return product.targets.map({ .target($0, conditions: []) })
14421450
case .library(.dynamic), .test, .executable:
14431451
return []
14441452
}
@@ -1453,7 +1461,7 @@ public class BuildPlan {
14531461

14541462
for dependency in allTargets {
14551463
switch dependency {
1456-
case .target(let target):
1464+
case .target(let target, _):
14571465
switch target.type {
14581466
// Include executable and tests only if they're top level contents
14591467
// of the product. Otherwise they are just build time dependency.
@@ -1477,7 +1485,7 @@ public class BuildPlan {
14771485
}
14781486
}
14791487

1480-
case .product(let product):
1488+
case .product(let product, _):
14811489
// Add the dynamic products to array of libraries to link.
14821490
if product.type == .library(.dynamic) {
14831491
linkLibraries.append(product)
@@ -1496,10 +1504,11 @@ public class BuildPlan {
14961504

14971505
/// Plan a Clang target.
14981506
private func plan(clangTarget: ClangTargetBuildDescription) {
1499-
for dependency in clangTarget.target.recursiveDependencies() {
1500-
switch dependency.underlyingTarget {
1507+
let recursiveBuildTargets = clangTarget.target.recursiveBuildTargetDependencies(in: buildEnvironment)
1508+
for targetDependency in recursiveBuildTargets {
1509+
switch targetDependency.underlyingTarget {
15011510
case is SwiftTarget:
1502-
if case let .swift(dependencyTargetDescription)? = targetMap[dependency] {
1511+
if case let .swift(dependencyTargetDescription)? = targetMap[targetDependency] {
15031512
if let moduleMap = dependencyTargetDescription.moduleMap {
15041513
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
15051514
}
@@ -1510,7 +1519,7 @@ public class BuildPlan {
15101519
clangTarget.additionalFlags += ["-I", target.includeDir.pathString]
15111520

15121521
// Add the modulemap of the dependency if it has one.
1513-
if case let .clang(dependencyTargetDescription)? = targetMap[dependency] {
1522+
if case let .clang(dependencyTargetDescription)? = targetMap[targetDependency] {
15141523
if let moduleMap = dependencyTargetDescription.moduleMap {
15151524
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
15161525
}
@@ -1534,10 +1543,13 @@ public class BuildPlan {
15341543
private func plan(swiftTarget: SwiftTargetBuildDescription) throws {
15351544
// We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target
15361545
// depends on.
1537-
for dependency in swiftTarget.target.recursiveDependencies() {
1538-
switch dependency.underlyingTarget {
1546+
let recursiveBuildTargets = swiftTarget.target
1547+
.recursiveBuildDependencies(in: buildEnvironment)
1548+
.compactMap({ $0.target })
1549+
for targetDependency in recursiveBuildTargets {
1550+
switch targetDependency.underlyingTarget {
15391551
case let underlyingTarget as ClangTarget where underlyingTarget.type == .library:
1540-
guard case let .clang(target)? = targetMap[dependency] else {
1552+
guard case let .clang(target)? = targetMap[targetDependency] else {
15411553
fatalError("unexpected clang target \(underlyingTarget)")
15421554
}
15431555
// 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) {
@@ -268,12 +269,12 @@ extension LLBuildManifestBuilder {
268269
}
269270
}
270271

271-
for dependency in target.target.dependencies {
272+
for dependency in target.target.buildDependencies(in: buildEnvironment) {
272273
switch dependency {
273-
case .target(let target):
274+
case .target(let target, _):
274275
addStaticTargetInputs(target)
275276

276-
case .product(let product):
277+
case .product(let product, _):
277278
switch product.type {
278279
case .executable, .library(.dynamic):
279280
// Establish a dependency on binary of the product.
@@ -368,12 +369,12 @@ extension LLBuildManifestBuilder {
368369
}
369370
}
370371

371-
for dependency in target.target.dependencies {
372+
for dependency in target.target.buildDependencies(in: buildEnvironment) {
372373
switch dependency {
373-
case .target(let target):
374+
case .target(let target, _):
374375
addStaticTargetInputs(target)
375376

376-
case .product(let product):
377+
case .product(let product, _):
377378
switch product.type {
378379
case .executable, .library(.dynamic):
379380
// 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
@@ -37,9 +37,9 @@ public final class Target {
3737
case productItem(name: String, package: String?)
3838
case byNameItem(name: String)
3939
#else
40-
case _targetItem(name: String)
41-
case _productItem(name: String, package: String?)
42-
case _byNameItem(name: String)
40+
case _targetItem(name: String, condition: BuildSettingCondition?)
41+
case _productItem(name: String, package: String?, condition: BuildSettingCondition?)
42+
case _byNameItem(name: String, condition: BuildSettingCondition?)
4343
#endif
4444
}
4545

@@ -603,7 +603,7 @@ extension Target.Dependency {
603603
#if PACKAGE_DESCRIPTION_4
604604
return .targetItem(name: name)
605605
#else
606-
return ._targetItem(name: name)
606+
return ._targetItem(name: name, condition: nil)
607607
#endif
608608
}
609609

@@ -617,36 +617,69 @@ extension Target.Dependency {
617617
#if PACKAGE_DESCRIPTION_4
618618
return .productItem(name: name, package: package)
619619
#else
620-
return ._productItem(name: name, package: package)
620+
return ._productItem(name: name, package: package, condition: nil)
621621
#endif
622622
}
623623

624-
/// Creates a dependency on a product from a package dependency.
624+
/// Creates a by-name dependency that resolves to either a target or a product but
625+
/// after the package graph has been loaded.
625626
///
626627
/// - parameters:
627-
/// - name: The name of the product.
628-
/// - package: The name of the package.
629-
@available(_PackageDescription, introduced: 5.2)
630-
public static func product(name: String, package: String) -> Target.Dependency {
628+
/// - name: The name of the dependency, either a target or a product.
629+
public static func byName(name: String) -> Target.Dependency {
631630
#if PACKAGE_DESCRIPTION_4
632-
return .productItem(name: name, package: package)
631+
return .byNameItem(name: name)
633632
#else
634-
return ._productItem(name: name, package: package)
633+
return ._byNameItem(name: name, condition: nil)
635634
#endif
636635
}
637636

637+
#if !PACKAGE_DESCRIPTION_4
638+
/// Creates a dependency on a product from a package dependency.
639+
///
640+
/// - parameters:
641+
/// - name: The name of the product.
642+
/// - package: The name of the package.
643+
public static func product(
644+
name: String,
645+
package: String
646+
) -> Target.Dependency {
647+
return ._productItem(name: name, package: package, condition: nil)
648+
}
649+
650+
/// Creates a dependency on a target in the same package.
651+
///
652+
/// - parameters:
653+
/// - name: The name of the target.
654+
/// - condition: The condition under which the dependency is exercised.
655+
public static func _target(name: String, condition: BuildSettingCondition? = nil) -> Target.Dependency {
656+
return ._targetItem(name: name, condition: condition)
657+
}
658+
659+
/// Creates a dependency on a product from a package dependency.
660+
///
661+
/// - parameters:
662+
/// - name: The name of the product.
663+
/// - package: The name of the package.
664+
/// - condition: The condition under which the dependency is exercised.
665+
public static func _product(
666+
name: String,
667+
package: String,
668+
condition: BuildSettingCondition? = nil
669+
) -> Target.Dependency {
670+
return ._productItem(name: name, package: package, condition: condition)
671+
}
672+
638673
/// Creates a by-name dependency that resolves to either a target or a product but
639674
/// after the package graph has been loaded.
640675
///
641676
/// - parameters:
642677
/// - name: The name of the dependency, either a target or a product.
643-
public static func byName(name: String) -> Target.Dependency {
644-
#if PACKAGE_DESCRIPTION_4
645-
return .byNameItem(name: name)
646-
#else
647-
return ._byNameItem(name: name)
648-
#endif
678+
/// - condition: The condition under which the dependency is exercised.
679+
public static func _byName(name: String, condition: BuildSettingCondition? = nil) -> Target.Dependency {
680+
return ._byNameItem(name: name, condition: condition)
649681
}
682+
#endif
650683
}
651684

652685
// MARK: ExpressibleByStringLiteral
@@ -661,7 +694,7 @@ extension Target.Dependency: ExpressibleByStringLiteral {
661694
#if PACKAGE_DESCRIPTION_4
662695
self = .byNameItem(name: value)
663696
#else
664-
self = ._byNameItem(name: value)
697+
self = ._byNameItem(name: value, condition: nil)
665698
#endif
666699
}
667700
}

0 commit comments

Comments
 (0)