Skip to content

Commit f76c789

Browse files
committed
Implementation of the conditional target dependency proposal
1 parent fba8a19 commit f76c789

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)
@@ -1097,6 +1101,10 @@ public class BuildPlan {
10971101
/// The build parameters.
10981102
public let buildParameters: BuildParameters
10991103

1104+
private var buildEnvironment: BuildEnvironment {
1105+
buildParameters.buildEnvironment
1106+
}
1107+
11001108
/// The package graph.
11011109
public let graph: PackageGraph
11021110

@@ -1165,10 +1173,10 @@ public class BuildPlan {
11651173
let swiftTarget = SwiftTarget(
11661174
testDiscoverySrc: src,
11671175
name: testProduct.name,
1168-
dependencies: testProduct.underlyingProduct.targets)
1176+
dependencies: testProduct.underlyingProduct.targets.map({ .target($0, conditions: []) }))
11691177
let linuxMainTarget = ResolvedTarget(
11701178
target: swiftTarget,
1171-
dependencies: testProduct.targets.map(ResolvedTarget.Dependency.target)
1179+
dependencies: testProduct.targets.map({ .target($0, conditions: []) })
11721180
)
11731181

11741182
let target = try SwiftTargetBuildDescription(
@@ -1203,7 +1211,7 @@ public class BuildPlan {
12031211
for dependency in target.dependencies {
12041212
switch dependency {
12051213
case .target: break
1206-
case .product(let product):
1214+
case .product(let product, _):
12071215
if buildParameters.triple.isDarwin() {
12081216
BuildPlan.validateDeploymentVersionOfProductDependency(
12091217
product, forTarget: target, diagnostics: diagnostics)
@@ -1378,19 +1386,19 @@ public class BuildPlan {
13781386
) {
13791387

13801388
// Sort the product targets in topological order.
1381-
let nodes = product.targets.map(ResolvedTarget.Dependency.target)
1389+
let nodes: [ResolvedTarget.Dependency] = product.targets.map({ .target($0, conditions: []) })
13821390
let allTargets = try! topologicalSort(nodes, successors: { dependency in
13831391
switch dependency {
13841392
// Include all the depenencies of a target.
1385-
case .target(let target):
1386-
return target.dependencies
1393+
case .target(let target, _):
1394+
return target.dependencies.filter({ $0.satisfies(self.buildEnvironment) })
13871395

13881396
// For a product dependency, we only include its content only if we
13891397
// need to statically link it.
1390-
case .product(let product):
1398+
case .product(let product, _):
13911399
switch product.type {
13921400
case .library(.automatic), .library(.static):
1393-
return product.targets.map(ResolvedTarget.Dependency.target)
1401+
return product.targets.map({ .target($0, conditions: []) })
13941402
case .library(.dynamic), .test, .executable:
13951403
return []
13961404
}
@@ -1404,7 +1412,7 @@ public class BuildPlan {
14041412

14051413
for dependency in allTargets {
14061414
switch dependency {
1407-
case .target(let target):
1415+
case .target(let target, _):
14081416
switch target.type {
14091417
// Include executable and tests only if they're top level contents
14101418
// of the product. Otherwise they are just build time dependency.
@@ -1423,7 +1431,7 @@ public class BuildPlan {
14231431
break
14241432
}
14251433

1426-
case .product(let product):
1434+
case .product(let product, _):
14271435
// Add the dynamic products to array of libraries to link.
14281436
if product.type == .library(.dynamic) {
14291437
linkLibraries.append(product)
@@ -1442,10 +1450,11 @@ public class BuildPlan {
14421450

14431451
/// Plan a Clang target.
14441452
private func plan(clangTarget: ClangTargetBuildDescription) {
1445-
for dependency in clangTarget.target.recursiveDependencies() {
1446-
switch dependency.underlyingTarget {
1453+
let recursiveBuildTargets = clangTarget.target.recursiveBuildTargetDependencies(in: buildEnvironment)
1454+
for targetDependency in recursiveBuildTargets {
1455+
switch targetDependency.underlyingTarget {
14471456
case is SwiftTarget:
1448-
if case let .swift(dependencyTargetDescription)? = targetMap[dependency] {
1457+
if case let .swift(dependencyTargetDescription)? = targetMap[targetDependency] {
14491458
if let moduleMap = dependencyTargetDescription.moduleMap {
14501459
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
14511460
}
@@ -1456,7 +1465,7 @@ public class BuildPlan {
14561465
clangTarget.additionalFlags += ["-I", target.includeDir.pathString]
14571466

14581467
// Add the modulemap of the dependency if it has one.
1459-
if case let .clang(dependencyTargetDescription)? = targetMap[dependency] {
1468+
if case let .clang(dependencyTargetDescription)? = targetMap[targetDependency] {
14601469
if let moduleMap = dependencyTargetDescription.moduleMap {
14611470
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
14621471
}
@@ -1473,10 +1482,13 @@ public class BuildPlan {
14731482
private func plan(swiftTarget: SwiftTargetBuildDescription) throws {
14741483
// We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target
14751484
// depends on.
1476-
for dependency in swiftTarget.target.recursiveDependencies() {
1477-
switch dependency.underlyingTarget {
1485+
let recursiveBuildTargets = swiftTarget.target
1486+
.recursiveBuildDependencies(in: buildEnvironment)
1487+
.compactMap({ $0.target })
1488+
for targetDependency in recursiveBuildTargets {
1489+
switch targetDependency.underlyingTarget {
14781490
case let underlyingTarget as ClangTarget where underlyingTarget.type == .library:
1479-
guard case let .clang(target)? = targetMap[dependency] else {
1491+
guard case let .clang(target)? = targetMap[targetDependency] else {
14801492
fatalError("unexpected clang target \(underlyingTarget)")
14811493
}
14821494
// 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
@@ -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)