Skip to content

Commit 16c2d07

Browse files
authored
Merge pull request #2428 from hartbit/conditional-target-dependencies-impl
Conditional target dependencies proposal implementation
2 parents e705518 + 85a38c1 commit 16c2d07

36 files changed

+1380
-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: 34 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,11 @@ public final class ClangTargetBuildDescription {
155155
/// The build parameters.
156156
let buildParameters: BuildParameters
157157

158+
/// The build environment.
159+
var buildEnvironment: BuildEnvironment {
160+
buildParameters.buildEnvironment
161+
}
162+
158163
/// Path to the bundle generated for this module (if any).
159164
var bundlePath: AbsolutePath? {
160165
buildParameters.bundlePath(for: target)
@@ -1132,6 +1137,11 @@ public class BuildPlan {
11321137
/// The build parameters.
11331138
public let buildParameters: BuildParameters
11341139

1140+
/// The build environment.
1141+
private var buildEnvironment: BuildEnvironment {
1142+
buildParameters.buildEnvironment
1143+
}
1144+
11351145
/// The package graph.
11361146
public let graph: PackageGraph
11371147

@@ -1200,10 +1210,11 @@ public class BuildPlan {
12001210
let swiftTarget = SwiftTarget(
12011211
testDiscoverySrc: src,
12021212
name: testProduct.name,
1203-
dependencies: testProduct.underlyingProduct.targets)
1213+
dependencies: testProduct.underlyingProduct.targets.map { .target($0, conditions: []) }
1214+
)
12041215
let linuxMainTarget = ResolvedTarget(
12051216
target: swiftTarget,
1206-
dependencies: testProduct.targets.map(ResolvedTarget.Dependency.target)
1217+
dependencies: testProduct.targets.map { .target($0, conditions: []) }
12071218
)
12081219

12091220
let target = try SwiftTargetBuildDescription(
@@ -1238,7 +1249,7 @@ public class BuildPlan {
12381249
for dependency in target.dependencies {
12391250
switch dependency {
12401251
case .target: break
1241-
case .product(let product):
1252+
case .product(let product, _):
12421253
if buildParameters.triple.isDarwin() {
12431254
BuildPlan.validateDeploymentVersionOfProductDependency(
12441255
product, forTarget: target, diagnostics: diagnostics)
@@ -1426,19 +1437,19 @@ public class BuildPlan {
14261437
) {
14271438

14281439
// Sort the product targets in topological order.
1429-
let nodes = product.targets.map(ResolvedTarget.Dependency.target)
1440+
let nodes: [ResolvedTarget.Dependency] = product.targets.map { .target($0, conditions: []) }
14301441
let allTargets = try! topologicalSort(nodes, successors: { dependency in
14311442
switch dependency {
14321443
// Include all the depenencies of a target.
1433-
case .target(let target):
1434-
return target.dependencies
1444+
case .target(let target, _):
1445+
return target.dependencies.filter { $0.satisfies(self.buildEnvironment) }
14351446

14361447
// For a product dependency, we only include its content only if we
14371448
// need to statically link it.
1438-
case .product(let product):
1449+
case .product(let product, _):
14391450
switch product.type {
14401451
case .library(.automatic), .library(.static):
1441-
return product.targets.map(ResolvedTarget.Dependency.target)
1452+
return product.targets.map { .target($0, conditions: []) }
14421453
case .library(.dynamic), .test, .executable:
14431454
return []
14441455
}
@@ -1453,7 +1464,7 @@ public class BuildPlan {
14531464

14541465
for dependency in allTargets {
14551466
switch dependency {
1456-
case .target(let target):
1467+
case .target(let target, _):
14571468
switch target.type {
14581469
// Include executable and tests only if they're top level contents
14591470
// of the product. Otherwise they are just build time dependency.
@@ -1477,7 +1488,7 @@ public class BuildPlan {
14771488
}
14781489
}
14791490

1480-
case .product(let product):
1491+
case .product(let product, _):
14811492
// Add the dynamic products to array of libraries to link.
14821493
if product.type == .library(.dynamic) {
14831494
linkLibraries.append(product)
@@ -1496,10 +1507,11 @@ public class BuildPlan {
14961507

14971508
/// Plan a Clang target.
14981509
private func plan(clangTarget: ClangTargetBuildDescription) {
1499-
for dependency in clangTarget.target.recursiveDependencies() {
1500-
switch dependency.underlyingTarget {
1510+
let recursiveBuildTargets = clangTarget.target.recursiveBuildTargetDependencies(in: buildEnvironment)
1511+
for targetDependency in recursiveBuildTargets {
1512+
switch targetDependency.underlyingTarget {
15011513
case is SwiftTarget:
1502-
if case let .swift(dependencyTargetDescription)? = targetMap[dependency] {
1514+
if case let .swift(dependencyTargetDescription)? = targetMap[targetDependency] {
15031515
if let moduleMap = dependencyTargetDescription.moduleMap {
15041516
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
15051517
}
@@ -1510,7 +1522,7 @@ public class BuildPlan {
15101522
clangTarget.additionalFlags += ["-I", target.includeDir.pathString]
15111523

15121524
// Add the modulemap of the dependency if it has one.
1513-
if case let .clang(dependencyTargetDescription)? = targetMap[dependency] {
1525+
if case let .clang(dependencyTargetDescription)? = targetMap[targetDependency] {
15141526
if let moduleMap = dependencyTargetDescription.moduleMap {
15151527
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
15161528
}
@@ -1534,10 +1546,13 @@ public class BuildPlan {
15341546
private func plan(swiftTarget: SwiftTargetBuildDescription) throws {
15351547
// We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target
15361548
// depends on.
1537-
for dependency in swiftTarget.target.recursiveDependencies() {
1538-
switch dependency.underlyingTarget {
1549+
let recursiveBuildTargets = swiftTarget.target
1550+
.recursiveBuildDependencies(in: buildEnvironment)
1551+
.compactMap { $0.target }
1552+
for targetDependency in recursiveBuildTargets {
1553+
switch targetDependency.underlyingTarget {
15391554
case let underlyingTarget as ClangTarget where underlyingTarget.type == .library:
1540-
guard case let .clang(target)? = targetMap[dependency] else {
1555+
guard case let .clang(target)? = targetMap[targetDependency] else {
15411556
fatalError("unexpected clang target \(underlyingTarget)")
15421557
}
15431558
// 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: 58 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

@@ -599,11 +599,12 @@ extension Target.Dependency {
599599
///
600600
/// - parameters:
601601
/// - name: The name of the target.
602+
@available(_PackageDescription, obsoleted: 999)
602603
public static func target(name: String) -> Target.Dependency {
603604
#if PACKAGE_DESCRIPTION_4
604605
return .targetItem(name: name)
605606
#else
606-
return ._targetItem(name: name)
607+
return ._targetItem(name: name, condition: nil)
607608
#endif
608609
}
609610

@@ -617,36 +618,74 @@ extension Target.Dependency {
617618
#if PACKAGE_DESCRIPTION_4
618619
return .productItem(name: name, package: package)
619620
#else
620-
return ._productItem(name: name, package: package)
621+
return ._productItem(name: name, package: package, condition: nil)
621622
#endif
622623
}
623624

624-
/// Creates a dependency on a product from a package dependency.
625+
/// Creates a by-name dependency that resolves to either a target or a product but
626+
/// after the package graph has been loaded.
625627
///
626628
/// - 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 {
629+
/// - name: The name of the dependency, either a target or a product.
630+
@available(_PackageDescription, obsoleted: 999)
631+
public static func byName(name: String) -> Target.Dependency {
631632
#if PACKAGE_DESCRIPTION_4
632-
return .productItem(name: name, package: package)
633+
return .byNameItem(name: name)
633634
#else
634-
return ._productItem(name: name, package: package)
635+
return ._byNameItem(name: name, condition: nil)
635636
#endif
636637
}
637638

639+
#if !PACKAGE_DESCRIPTION_4
640+
/// Creates a dependency on a product from a package dependency.
641+
///
642+
/// - parameters:
643+
/// - name: The name of the product.
644+
/// - package: The name of the package.
645+
@available(_PackageDescription, introduced: 5.2, obsoleted: 999)
646+
public static func product(
647+
name: String,
648+
package: String
649+
) -> Target.Dependency {
650+
return ._productItem(name: name, package: package, condition: nil)
651+
}
652+
653+
/// Creates a dependency on a target in the same package.
654+
///
655+
/// - parameters:
656+
/// - name: The name of the target.
657+
/// - condition: The condition under which the dependency is exercised.
658+
@available(_PackageDescription, introduced: 999)
659+
public static func target(name: String, condition: BuildSettingCondition? = nil) -> Target.Dependency {
660+
return ._targetItem(name: name, condition: condition)
661+
}
662+
663+
/// Creates a dependency on a product from a package dependency.
664+
///
665+
/// - parameters:
666+
/// - name: The name of the product.
667+
/// - package: The name of the package.
668+
/// - condition: The condition under which the dependency is exercised.
669+
@available(_PackageDescription, introduced: 999)
670+
public static func product(
671+
name: String,
672+
package: String,
673+
condition: BuildSettingCondition? = nil
674+
) -> Target.Dependency {
675+
return ._productItem(name: name, package: package, condition: condition)
676+
}
677+
638678
/// Creates a by-name dependency that resolves to either a target or a product but
639679
/// after the package graph has been loaded.
640680
///
641681
/// - parameters:
642682
/// - 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
683+
/// - condition: The condition under which the dependency is exercised.
684+
@available(_PackageDescription, introduced: 999)
685+
public static func byName(name: String, condition: BuildSettingCondition? = nil) -> Target.Dependency {
686+
return ._byNameItem(name: name, condition: condition)
649687
}
688+
#endif
650689
}
651690

652691
// MARK: ExpressibleByStringLiteral
@@ -661,7 +700,7 @@ extension Target.Dependency: ExpressibleByStringLiteral {
661700
#if PACKAGE_DESCRIPTION_4
662701
self = .byNameItem(name: value)
663702
#else
664-
self = ._byNameItem(name: value)
703+
self = ._byNameItem(name: value, condition: nil)
665704
#endif
666705
}
667706
}

0 commit comments

Comments
 (0)