1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Basics
import PackageGraph
import protocol TSCBasic.OutputByteStream
/// An enum representing what subset of the package to build.
public enum BuildSubset {
/// Represents the subset of all products and non-test targets.
case allExcludingTests
/// Represents the subset of all products and targets.
case allIncludingTests
/// Represents a specific product. Allows to set a specific
/// destination if it's known.
case product(String, for: BuildParameters.Destination? = .none)
/// Represents a specific target. Allows to set a specific
/// destination if it's known.
case target(String, for: BuildParameters.Destination? = .none)
}
/// A protocol that represents a build system used by SwiftPM for all build operations. This allows factoring out the
/// implementation details between SwiftPM's `BuildOperation` and the XCBuild backed `XCBuildSystem`.
public protocol BuildSystem: Cancellable {
/// The delegate used by the build system.
var delegate: BuildSystemDelegate? { get }
/// The test products that this build system will build.
var builtTestProducts: [BuiltTestProduct] { get }
/// Returns the package graph used by the build system.
func getPackageGraph() throws -> ModulesGraph
/// Builds a subset of the package graph.
/// - Parameters:
/// - subset: The subset of the package graph to build.
func build(subset: BuildSubset) throws
var buildPlan: BuildPlan { get throws }
}
extension BuildSystem {
/// Builds the default subset: all targets excluding tests.
public func build() throws {
try build(subset: .allExcludingTests)
}
}
public protocol ProductBuildDescription {
/// The reference to the product.
var package: ResolvedPackage { get }
/// The reference to the product.
var product: ResolvedProduct { get }
/// The build parameters.
var buildParameters: BuildParameters { get }
}
extension ProductBuildDescription {
/// The path to the product binary produced.
public var binaryPath: AbsolutePath {
get throws {
try self.buildParameters.binaryPath(for: product)
}
}
}
public protocol BuildPlan {
/// Parameters used when building end products for the destination platform.
var destinationBuildParameters: BuildParameters { get }
/// Parameters used when building tools (macros and plugins).
var toolsBuildParameters: BuildParameters { get }
var buildProducts: AnySequence<ProductBuildDescription> { get }
func createAPIToolCommonArgs(includeLibrarySearchPaths: Bool) throws -> [String]
func createREPLArguments() throws -> [String]
/// Determines the arguments needed to run `swift-symbolgraph-extract` for
/// a particular module.
func symbolGraphExtractArguments(for module: ResolvedModule) throws -> [String]
}
public protocol BuildSystemFactory {
func makeBuildSystem(
explicitProduct: String?,
cacheBuildManifest: Bool,
productsBuildParameters: BuildParameters?,
toolsBuildParameters: BuildParameters?,
packageGraphLoader: (() throws -> ModulesGraph)?,
outputStream: OutputByteStream?,
logLevel: Diagnostic.Severity?,
observabilityScope: ObservabilityScope?
) throws -> any BuildSystem
}
public struct BuildSystemProvider {
// TODO: In the future, we may want this to be about specific capabilities of a build system rather than choosing a concrete one.
public enum Kind: String, CaseIterable {
case native
case xcode
}
public let providers: [Kind: any BuildSystemFactory]
public init(providers: [Kind: any BuildSystemFactory]) {
self.providers = providers
}
public func createBuildSystem(
kind: Kind,
explicitProduct: String? = .none,
cacheBuildManifest: Bool = true,
productsBuildParameters: BuildParameters? = .none,
toolsBuildParameters: BuildParameters? = .none,
packageGraphLoader: (() throws -> ModulesGraph)? = .none,
outputStream: OutputByteStream? = .none,
logLevel: Diagnostic.Severity? = .none,
observabilityScope: ObservabilityScope? = .none
) throws -> any BuildSystem {
guard let buildSystemFactory = self.providers[kind] else {
throw Errors.buildSystemProviderNotRegistered(kind: kind)
}
return try buildSystemFactory.makeBuildSystem(
explicitProduct: explicitProduct,
cacheBuildManifest: cacheBuildManifest,
productsBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters,
packageGraphLoader: packageGraphLoader,
outputStream: outputStream,
logLevel: logLevel,
observabilityScope: observabilityScope
)
}
}
private enum Errors: Swift.Error {
case buildSystemProviderNotRegistered(kind: BuildSystemProvider.Kind)
}
public enum BuildSystemUtilities {
/// Returns the build path from the environment, if present.
public static func getEnvBuildPath(workingDir: AbsolutePath) throws -> AbsolutePath? {
// Don't rely on build path from env for SwiftPM's own tests.
guard Environment.current["SWIFTPM_TESTS_MODULECACHE"] == nil else { return nil }
guard let env = Environment.current["SWIFTPM_BUILD_DIR"] else { return nil }
return try AbsolutePath(validating: env, relativeTo: workingDir)
}
}
|