Skip to content

[Package/Build] Remove SwiftTarget.toolsSwiftVersion in favor of a build setting #7557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,6 @@ package final class SwiftTargetBuildDescription {
/// Any addition flags to be added. These flags are expected to be computed during build planning.
var additionalFlags: [String] = []

/// The swift language version that is computed for this target based on tools version of the manifest.
var toolsSwiftVersion: SwiftLanguageVersion {
self.swiftTarget.toolSwiftVersion
}

/// Describes the purpose of a test target, including any special roles such as containing a list of discovered
/// tests or serving as the manifest target which contains the main entry point.
package enum TestTargetRole {
Expand Down Expand Up @@ -580,11 +575,6 @@ package final class SwiftTargetBuildDescription {
// Add arguments from declared build settings.
args += try self.buildSettingsFlags()

// Fallback to package wide setting if there is no target specific version.
if args.firstIndex(of: "-swift-version") == nil {
args += ["-swift-version", self.toolsSwiftVersion.rawValue]
}

// Add the output for the `.swiftinterface`, if requested or if library evolution has been enabled some other
// way.
if self.defaultBuildParameters.driverParameters.enableParseableModuleInterfaces || args.contains("-enable-library-evolution") {
Expand Down
1 change: 0 additions & 1 deletion Sources/Build/BuildPlan/BuildPlan+Test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ private extension PackageModel.SwiftTarget {
sources: sources,
dependencies: dependencies,
packageAccess: packageAccess,
toolsSwiftVersion: .v5,
usesUnsafeFlags: false
)
}
Expand Down
19 changes: 13 additions & 6 deletions Sources/PackageLoading/PackageBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,8 @@ public final class PackageBuilder {
let buildSettings = try self.buildSettings(
for: manifestTarget,
targetRoot: potentialModule.path,
cxxLanguageStandard: self.manifest.cxxLanguageStandard
cxxLanguageStandard: self.manifest.cxxLanguageStandard,
toolsSwiftVersion: self.toolsSwiftVersion()
)

// Compute the path to public headers directory.
Expand Down Expand Up @@ -997,7 +998,6 @@ public final class PackageBuilder {
others: others,
dependencies: dependencies,
packageAccess: potentialModule.packageAccess,
toolsSwiftVersion: self.toolsSwiftVersion(),
declaredSwiftVersions: self.declaredSwiftVersions(),
buildSettings: buildSettings,
buildSettingsDescription: manifestTarget.settings,
Expand Down Expand Up @@ -1055,11 +1055,18 @@ public final class PackageBuilder {
func buildSettings(
for target: TargetDescription?,
targetRoot: AbsolutePath,
cxxLanguageStandard: String? = nil
cxxLanguageStandard: String? = nil,
toolsSwiftVersion: SwiftLanguageVersion
) throws -> BuildSettings.AssignmentTable {
var table = BuildSettings.AssignmentTable()
guard let target else { return table }

// First let's add a default assignments for tools swift version.
var versionAssignment = BuildSettings.Assignment(default: true)
versionAssignment.values = [toolsSwiftVersion.rawValue]

table.add(versionAssignment, for: .SWIFT_VERSION)

// Process each setting.
for setting in target.settings {
let decl: BuildSettings.Declaration
Expand Down Expand Up @@ -1728,17 +1735,17 @@ extension PackageBuilder {
)
buildSettings = try self.buildSettings(
for: targetDescription,
targetRoot: sourceFile.parentDirectory
targetRoot: sourceFile.parentDirectory,
toolsSwiftVersion: self.toolsSwiftVersion()
)

return try SwiftTarget(
return SwiftTarget(
name: name,
type: .snippet,
path: .root,
sources: sources,
dependencies: dependencies,
packageAccess: false,
toolsSwiftVersion: self.toolsSwiftVersion(),
buildSettings: buildSettings,
buildSettingsDescription: targetDescription.settings,
usesUnsafeFlags: false
Expand Down
33 changes: 22 additions & 11 deletions Sources/PackageModel/BuildSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

/// Namespace for build settings.
public enum BuildSettings {

/// Build settings declarations.
public struct Declaration: Hashable, Codable {
// Swift.
public static let SWIFT_ACTIVE_COMPILATION_CONDITIONS: Declaration = .init("SWIFT_ACTIVE_COMPILATION_CONDITIONS")
public static let SWIFT_ACTIVE_COMPILATION_CONDITIONS: Declaration =
.init("SWIFT_ACTIVE_COMPILATION_CONDITIONS")
public static let OTHER_SWIFT_FLAGS: Declaration = .init("OTHER_SWIFT_FLAGS")
public static let SWIFT_VERSION: Declaration = .init("SWIFT_VERSION")

Expand Down Expand Up @@ -48,18 +48,23 @@ public enum BuildSettings {
/// The condition associated with this assignment.
public var conditions: [PackageCondition] {
get {
return _conditions.map { $0.underlying }
self._conditions.map(\.underlying)
}
set {
_conditions = newValue.map { PackageConditionWrapper($0) }
self._conditions = newValue.map { PackageConditionWrapper($0) }
}
}

private var _conditions: [PackageConditionWrapper]

public init() {
/// Indicates whether this assignment represents a default
/// that should be used only if no other assignments match.
public let `default`: Bool

public init(default: Bool = false) {
self._conditions = []
self.values = []
self.default = `default`
}
}

Expand All @@ -68,13 +73,13 @@ public enum BuildSettings {
public private(set) var assignments: [Declaration: [Assignment]]

public init() {
assignments = [:]
self.assignments = [:]
}

/// Add the given assignment to the table.
mutating public func add(_ assignment: Assignment, for decl: Declaration) {
public mutating func add(_ assignment: Assignment, for decl: Declaration) {
// FIXME: We should check for duplicate assignments.
assignments[decl, default: []].append(assignment)
self.assignments[decl, default: []].append(assignment)
}
}

Expand All @@ -101,12 +106,18 @@ public enum BuildSettings {
}

// Add values from each assignment if it satisfies the build environment.
let values = assignments
let allViableAssignments = assignments
.lazy
.filter { $0.conditions.allSatisfy { $0.satisfies(self.environment) } }
.flatMap { $0.values }

return Array(values)
let nonDefaultAssignments = allViableAssignments.filter { !$0.default }

// If there are no non-default assignments, let's fallback to defaults.
if nonDefaultAssignments.isEmpty {
return allViableAssignments.filter(\.default).flatMap(\.values)
}

return nonDefaultAssignments.flatMap(\.values)
}
}
}
27 changes: 14 additions & 13 deletions Sources/PackageModel/Target/SwiftTarget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public final class SwiftTarget: Target {
}

public init(name: String, dependencies: [Target.Dependency], packageAccess: Bool, testDiscoverySrc: Sources) {
self.toolSwiftVersion = .v5
self.declaredSwiftVersions = []

super.init(
Expand All @@ -40,9 +39,6 @@ public final class SwiftTarget: Target {
)
}

/// The swift language version that is computed for this target based on tools version of the manifest.
public let toolSwiftVersion: SwiftLanguageVersion

/// The list of swift versions declared by the manifest.
public let declaredSwiftVersions: [SwiftLanguageVersion]

Expand All @@ -57,14 +53,12 @@ public final class SwiftTarget: Target {
others: [AbsolutePath] = [],
dependencies: [Target.Dependency] = [],
packageAccess: Bool,
toolsSwiftVersion: SwiftLanguageVersion,
declaredSwiftVersions: [SwiftLanguageVersion] = [],
buildSettings: BuildSettings.AssignmentTable = .init(),
buildSettingsDescription: [TargetBuildSettingDescription.Setting] = [],
pluginUsages: [PluginUsage] = [],
usesUnsafeFlags: Bool
) {
self.toolSwiftVersion = toolsSwiftVersion
self.declaredSwiftVersions = declaredSwiftVersions
super.init(
name: name,
Expand Down Expand Up @@ -99,12 +93,22 @@ public final class SwiftTarget: Target {
return target.type == .test
}.flatMap { $0.target as? SwiftTarget }

// FIXME: This is not very correct but doesn't matter much in practice.
// We need to select the latest Swift language version that can
// satisfy the current tools version but there is not a good way to
// do that currently.
self.toolSwiftVersion = swiftTestTarget?
.toolSwiftVersion ?? SwiftLanguageVersion(string: String(SwiftVersion.current.major)) ?? .v4
var buildSettings: BuildSettings.AssignmentTable = .init()
do {
let toolsSwiftVersion = swiftTestTarget?.buildSettings.assignments[.SWIFT_VERSION]?
.filter(\.default)
.filter(\.conditions.isEmpty)
.flatMap(\.values)

var versionAssignment = BuildSettings.Assignment()
versionAssignment.values = toolsSwiftVersion ?? [String(SwiftVersion.current.major)]

buildSettings.add(versionAssignment, for: .SWIFT_VERSION)
}

self.declaredSwiftVersions = []
let sources = Sources(paths: [testEntryPointPath], root: testEntryPointPath.parentDirectory)

Expand All @@ -115,28 +119,25 @@ public final class SwiftTarget: Target {
sources: sources,
dependencies: dependencies,
packageAccess: packageAccess,
buildSettings: .init(),
buildSettings: buildSettings,
buildSettingsDescription: [],
pluginUsages: [],
usesUnsafeFlags: false
)
}

private enum CodingKeys: String, CodingKey {
case swiftVersion
case declaredSwiftVersions
}

override public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.toolSwiftVersion, forKey: .swiftVersion)
try container.encode(self.declaredSwiftVersions, forKey: .declaredSwiftVersions)
try super.encode(to: encoder)
}

public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.toolSwiftVersion = try container.decode(SwiftLanguageVersion.self, forKey: .swiftVersion)
self.declaredSwiftVersions = try container.decode([SwiftLanguageVersion].self, forKey: .declaredSwiftVersions)
try super.init(from: decoder)
}
Expand Down
1 change: 0 additions & 1 deletion Sources/SPMTestSupport/ResolvedTarget+Mock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ extension ResolvedModule {
sources: Sources(paths: [], root: "/"),
dependencies: [],
packageAccess: false,
toolsSwiftVersion: .v4,
usesUnsafeFlags: false
),
dependencies: deps.map { .target($0, conditions: conditions) },
Expand Down
Loading