Skip to content

Commit

Permalink
Merge pull request swiftlang#2428 from hartbit/conditional-target-dep…
Browse files Browse the repository at this point in the history
…endencies-impl

Conditional target dependencies proposal implementation
  • Loading branch information
aciidgh committed Feb 4, 2020
2 parents e705518 + 85a38c1 commit 56a3382
Show file tree
Hide file tree
Showing 50 changed files with 1,469 additions and 491 deletions.
9 changes: 7 additions & 2 deletions Sources/Build/BuildParameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,16 @@ public struct BuildParameters: Encodable {
/// module to finish building.
public var emitSwiftModuleSeparately: Bool

/// The current build environment.
public var buildEnvironment: BuildEnvironment {
BuildEnvironment(platform: currentPlatform, configuration: configuration)
}

public init(
dataPath: AbsolutePath,
configuration: BuildConfiguration,
toolchain: Toolchain,
destinationTriple: Triple = Triple.hostTriple,
destinationTriple: Triple? = nil,
flags: BuildFlags,
toolsVersion: ToolsVersion = ToolsVersion.currentToolsVersion,
jobs: UInt32 = UInt32(ProcessInfo.processInfo.activeProcessorCount),
Expand All @@ -106,7 +111,7 @@ public struct BuildParameters: Encodable {
self.dataPath = dataPath
self.configuration = configuration
self._toolchain = _Toolchain(toolchain: toolchain)
self.triple = destinationTriple
self.triple = destinationTriple ?? .getHostTriple(usingSwiftCompiler: toolchain.swiftCompiler)
self.flags = flags
self.toolsVersion = toolsVersion
self.jobs = jobs
Expand Down
53 changes: 34 additions & 19 deletions Sources/Build/BuildPlan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ extension BuildParameters {
}

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

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

Expand Down Expand Up @@ -155,6 +155,11 @@ public final class ClangTargetBuildDescription {
/// The build parameters.
let buildParameters: BuildParameters

/// The build environment.
var buildEnvironment: BuildEnvironment {
buildParameters.buildEnvironment
}

/// Path to the bundle generated for this module (if any).
var bundlePath: AbsolutePath? {
buildParameters.bundlePath(for: target)
Expand Down Expand Up @@ -1132,6 +1137,11 @@ public class BuildPlan {
/// The build parameters.
public let buildParameters: BuildParameters

/// The build environment.
private var buildEnvironment: BuildEnvironment {
buildParameters.buildEnvironment
}

/// The package graph.
public let graph: PackageGraph

Expand Down Expand Up @@ -1200,10 +1210,11 @@ public class BuildPlan {
let swiftTarget = SwiftTarget(
testDiscoverySrc: src,
name: testProduct.name,
dependencies: testProduct.underlyingProduct.targets)
dependencies: testProduct.underlyingProduct.targets.map { .target($0, conditions: []) }
)
let linuxMainTarget = ResolvedTarget(
target: swiftTarget,
dependencies: testProduct.targets.map(ResolvedTarget.Dependency.target)
dependencies: testProduct.targets.map { .target($0, conditions: []) }
)

let target = try SwiftTargetBuildDescription(
Expand Down Expand Up @@ -1238,7 +1249,7 @@ public class BuildPlan {
for dependency in target.dependencies {
switch dependency {
case .target: break
case .product(let product):
case .product(let product, _):
if buildParameters.triple.isDarwin() {
BuildPlan.validateDeploymentVersionOfProductDependency(
product, forTarget: target, diagnostics: diagnostics)
Expand Down Expand Up @@ -1426,19 +1437,19 @@ public class BuildPlan {
) {

// Sort the product targets in topological order.
let nodes = product.targets.map(ResolvedTarget.Dependency.target)
let nodes: [ResolvedTarget.Dependency] = product.targets.map { .target($0, conditions: []) }
let allTargets = try! topologicalSort(nodes, successors: { dependency in
switch dependency {
// Include all the depenencies of a target.
case .target(let target):
return target.dependencies
case .target(let target, _):
return target.dependencies.filter { $0.satisfies(self.buildEnvironment) }

// For a product dependency, we only include its content only if we
// need to statically link it.
case .product(let product):
case .product(let product, _):
switch product.type {
case .library(.automatic), .library(.static):
return product.targets.map(ResolvedTarget.Dependency.target)
return product.targets.map { .target($0, conditions: []) }
case .library(.dynamic), .test, .executable:
return []
}
Expand All @@ -1453,7 +1464,7 @@ public class BuildPlan {

for dependency in allTargets {
switch dependency {
case .target(let target):
case .target(let target, _):
switch target.type {
// Include executable and tests only if they're top level contents
// of the product. Otherwise they are just build time dependency.
Expand All @@ -1477,7 +1488,7 @@ public class BuildPlan {
}
}

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

/// Plan a Clang target.
private func plan(clangTarget: ClangTargetBuildDescription) {
for dependency in clangTarget.target.recursiveDependencies() {
switch dependency.underlyingTarget {
let recursiveBuildTargets = clangTarget.target.recursiveBuildTargetDependencies(in: buildEnvironment)
for targetDependency in recursiveBuildTargets {
switch targetDependency.underlyingTarget {
case is SwiftTarget:
if case let .swift(dependencyTargetDescription)? = targetMap[dependency] {
if case let .swift(dependencyTargetDescription)? = targetMap[targetDependency] {
if let moduleMap = dependencyTargetDescription.moduleMap {
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
}
Expand All @@ -1510,7 +1522,7 @@ public class BuildPlan {
clangTarget.additionalFlags += ["-I", target.includeDir.pathString]

// Add the modulemap of the dependency if it has one.
if case let .clang(dependencyTargetDescription)? = targetMap[dependency] {
if case let .clang(dependencyTargetDescription)? = targetMap[targetDependency] {
if let moduleMap = dependencyTargetDescription.moduleMap {
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
}
Expand All @@ -1534,10 +1546,13 @@ public class BuildPlan {
private func plan(swiftTarget: SwiftTargetBuildDescription) throws {
// We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target
// depends on.
for dependency in swiftTarget.target.recursiveDependencies() {
switch dependency.underlyingTarget {
let recursiveBuildTargets = swiftTarget.target
.recursiveBuildDependencies(in: buildEnvironment)
.compactMap { $0.target }
for targetDependency in recursiveBuildTargets {
switch targetDependency.underlyingTarget {
case let underlyingTarget as ClangTarget where underlyingTarget.type == .library:
guard case let .clang(target)? = targetMap[dependency] else {
guard case let .clang(target)? = targetMap[targetDependency] else {
fatalError("unexpected clang target \(underlyingTarget)")
}
// Add the path to modulemap of the dependency. Currently we require that all Clang targets have a
Expand Down
13 changes: 7 additions & 6 deletions Sources/Build/ManifestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class LLBuildManifestBuilder {

var buildConfig: String { buildParameters.configuration.dirname }
var buildParameters: BuildParameters { plan.buildParameters }
var buildEnvironment: BuildEnvironment { buildParameters.buildEnvironment }

/// Create a new builder with a build plan.
public init(_ plan: BuildPlan) {
Expand Down Expand Up @@ -268,12 +269,12 @@ extension LLBuildManifestBuilder {
}
}

for dependency in target.target.dependencies {
for dependency in target.target.buildDependencies(in: buildEnvironment) {
switch dependency {
case .target(let target):
case .target(let target, _):
addStaticTargetInputs(target)

case .product(let product):
case .product(let product, _):
switch product.type {
case .executable, .library(.dynamic):
// Establish a dependency on binary of the product.
Expand Down Expand Up @@ -368,12 +369,12 @@ extension LLBuildManifestBuilder {
}
}

for dependency in target.target.dependencies {
for dependency in target.target.buildDependencies(in: buildEnvironment) {
switch dependency {
case .target(let target):
case .target(let target, _):
addStaticTargetInputs(target)

case .product(let product):
case .product(let product, _):
switch product.type {
case .executable, .library(.dynamic):
// Establish a dependency on binary of the product.
Expand Down
62 changes: 21 additions & 41 deletions Sources/Build/Triple.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import TSCBasic

/// Triple - Helper class for working with Destination.target values
///
/// Used for parsing values such as x86_64-apple-macosx10.10 into
Expand Down Expand Up @@ -132,47 +134,25 @@ public struct Triple: Encodable {
}

public static let macOS = try! Triple("x86_64-apple-macosx")
public static let x86_64Linux = try! Triple("x86_64-unknown-linux-gnu")
public static let i686Linux = try! Triple("i686-unknown-linux")
public static let ppc64leLinux = try! Triple("powerpc64le-unknown-linux")
public static let s390xLinux = try! Triple("s390x-unknown-linux")
public static let arm64Linux = try! Triple("aarch64-unknown-linux-gnu")
public static let armLinux = try! Triple("armv7-unknown-linux-gnueabihf")
public static let armAndroid = try! Triple("armv7a-unknown-linux-androideabi")
public static let arm64Android = try! Triple("aarch64-unknown-linux-android")
public static let x86_64Android = try! Triple("x86_64-unknown-linux-android")
public static let i686Android = try! Triple("i686-unknown-linux-android")
public static let windows = try! Triple("x86_64-unknown-windows-msvc")

#if os(macOS)
public static let hostTriple: Triple = .macOS
#elseif os(Windows)
public static let hostTriple: Triple = .windows
#elseif os(Linux)
#if arch(x86_64)
public static let hostTriple: Triple = .x86_64Linux
#elseif arch(i386)
public static let hostTriple: Triple = .i686Linux
#elseif arch(powerpc64le)
public static let hostTriple: Triple = .ppc64leLinux
#elseif arch(s390x)
public static let hostTriple: Triple = .s390xLinux
#elseif arch(arm64)
public static let hostTriple: Triple = .arm64Linux
#elseif arch(arm)
public static let hostTriple: Triple = .armLinux
#endif
#elseif os(Android)
#if arch(arm)
public static let hostTriple: Triple = .armAndroid
#elseif arch(arm64)
public static let hostTriple: Triple = .arm64Android
#elseif arch(x86_64)
public static let hostTriple: Triple = .x86_64Android
#elseif arch(i386)
public static let hostTriple: Triple = .i686Android
#endif
#endif

/// Determine the host triple using the Swift compiler.
public static func getHostTriple(usingSwiftCompiler swiftCompiler: AbsolutePath) -> Triple {
do {
let result = try Process.popen(args: swiftCompiler.pathString, "-print-target-info")
let output = try result.utf8Output().spm_chomp()
let targetInfo = try JSON(string: output)
let tripleString: String = try targetInfo.get("target").get("unversionedTriple")
return try Triple(tripleString)
} catch {
// FIXME: Remove the macOS special-casing once the latest version of Xcode comes with
// a Swift compiler that supports -print-target-info.
#if os(macOS)
return .macOS
#else
fatalError("could not determine host triple: \(error)")
#endif
}
}
}

extension Triple {
Expand Down
4 changes: 2 additions & 2 deletions Sources/Commands/SwiftTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -722,10 +722,10 @@ public class SwiftTool<Options: ToolOptions> {
private lazy var _buildParameters: Result<BuildParameters, Swift.Error> = {
return Result(catching: {
let toolchain = try self.getToolchain()
let triple = toolchain.destination.target
let triple = toolchain.triple

return BuildParameters(
dataPath: buildPath.appending(component: toolchain.destination.target.tripleString),
dataPath: buildPath.appending(component: triple.tripleString),
configuration: options.configuration,
toolchain: toolchain,
destinationTriple: triple,
Expand Down
4 changes: 2 additions & 2 deletions Sources/PackageDescription/BuildSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public struct BuildConfiguration: Encodable {
/// .define("ENABLE_SOMETHING", .when(configuration: .release)),
/// ],
/// linkerSettings: [
/// .linkLibrary("openssl", .when(platforms: [.linux])),
/// .linkedLibrary("openssl", .when(platforms: [.linux])),
/// ]
/// ),
public struct BuildSettingCondition: Encodable {
Expand Down Expand Up @@ -228,7 +228,7 @@ public struct SwiftSetting: Encodable {
/// Use compilation conditions to only compile statements if a certain condition is true.
/// For example, the Swift compiler will only compile the
/// statements inside the `#if` block when `ENABLE_SOMETHING` is defined:
///
///
/// #if ENABLE_SOMETHING
/// ...
/// #endif
Expand Down
10 changes: 7 additions & 3 deletions Sources/PackageDescription/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ extension Target.Dependency: Encodable {
case type
case name
case package
case condition
}

private enum Kind: String, Codable {
Expand All @@ -477,16 +478,19 @@ extension Target.Dependency: Encodable {
}
#else
switch self {
case ._targetItem(let name):
case ._targetItem(let name, let condition):
try container.encode(Kind.target, forKey: .type)
try container.encode(name, forKey: .name)
case ._productItem(let name, let package):
try container.encode(condition, forKey: .condition)
case ._productItem(let name, let package, let condition):
try container.encode(Kind.product, forKey: .type)
try container.encode(name, forKey: .name)
try container.encode(package, forKey: .package)
case ._byNameItem(let name):
try container.encode(condition, forKey: .condition)
case ._byNameItem(let name, let condition):
try container.encode(Kind.byName, forKey: .type)
try container.encode(name, forKey: .name)
try container.encode(condition, forKey: .condition)
}
#endif
}
Expand Down
Loading

0 comments on commit 56a3382

Please sign in to comment.