Skip to content
Draft
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
8 changes: 8 additions & 0 deletions Fixtures/PIFBuilder/Simple/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
26 changes: 26 additions & 0 deletions Fixtures/PIFBuilder/Simple/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Simple",
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "Simple",
targets: ["Simple"]
),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "Simple"
),
.testTarget(
name: "SimpleTests",
dependencies: ["Simple"]
),
]
)
25 changes: 25 additions & 0 deletions Fixtures/PIFBuilder/Simple/Sources/Simple/Simple.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book

public struct Person {
public let name: String

public init(name: String) {
self.name = name
}
}
extension Person: CustomStringConvertible {
public var description: String {
return name
}
}

public func greet(person: Person? = nil) -> String {
let name = if let person {
person.name
} else {
"World"
}

return "Hello, \(name)!"
}
36 changes: 36 additions & 0 deletions Fixtures/PIFBuilder/Simple/Tests/SimpleTests/SimpleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Testing
import XCTest

import Simple


final public class XCTesting: XCTestCase {
func testGreetWithEmptyArgument() {
let actual = greet()
XCTAssertEqual(actual, "Hello, World!")
}

func testGreetWithNonEmptyArgument() {
let name = "MyName"
let person = Person(name: name)
let actual = greet(person: person)
XCTAssertEqual(actual, "Hello, \(name)!")
}
}

@Suite
struct STTestTests {
@Test("STTest tests")
func testGreetWithEmptyArgument() {
let actual = greet()
#expect(actual == "Hello, World!")
}

@Test("STTest tests")
func testGreetWithNonEmptyArgument() {
let name = "MyName"
let person = Person(name: name)
let actual = greet(person: person)
#expect(actual == "Hello, \(name)!")
}
}
3 changes: 2 additions & 1 deletion Sources/PackageModel/SwiftSDKs/SwiftSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ public struct SwiftSDK: Equatable {
extraCCFlags += ["-fPIC"]
#endif

return SwiftSDK(
let returnValue = SwiftSDK(
toolset: .init(
knownTools: [
.cCompiler: .init(extraCLIOptions: extraCCFlags),
Expand All @@ -620,6 +620,7 @@ public struct SwiftSDK: Equatable {
pathsConfiguration: .init(sdkRootPath: sdkPath),
xctestSupport: xctestSupport
)
return returnValue
}

/// Auxiliary platform frameworks and libraries.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public struct BuildParameters: Encodable {
}

/// Mode for the indexing-while-building feature.
public enum IndexStoreMode: String, Encodable {
public enum IndexStoreMode: String, Encodable, CaseIterable {
/// Index store should be enabled.
case on
/// Index store should be disabled.
Expand Down
13 changes: 8 additions & 5 deletions Sources/SwiftBuildSupport/PackagePIFBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import struct PackageGraph.ModulesGraph
import struct PackageGraph.ResolvedModule
import struct PackageGraph.ResolvedPackage

import struct SPMBuildCore.BuildParameters

import enum SwiftBuild.ProjectModel

typealias GUID = SwiftBuild.ProjectModel.GUID
Expand Down Expand Up @@ -203,7 +205,7 @@ public final class PackagePIFBuilder {
addLocalRpaths: Bool = true,
packageDisplayVersion: String?,
fileSystem: FileSystem,
observabilityScope: ObservabilityScope
observabilityScope: ObservabilityScope,
) {
self.package = resolvedPackage
self.packageManifest = packageManifest
Expand All @@ -227,7 +229,7 @@ public final class PackagePIFBuilder {
addLocalRpaths: Bool = true,
packageDisplayVersion: String?,
fileSystem: FileSystem,
observabilityScope: ObservabilityScope
observabilityScope: ObservabilityScope,
) {
self.package = resolvedPackage
self.packageManifest = packageManifest
Expand Down Expand Up @@ -438,7 +440,7 @@ public final class PackagePIFBuilder {
//

self.log(.debug, "Processing \(package.products.count) products:")

// For each of the **products** in the package we create a corresponding `PIFTarget` of the appropriate type.
for product in self.package.products {
switch product.type {
Expand Down Expand Up @@ -561,8 +563,8 @@ public final class PackagePIFBuilder {
// We currently deliberately do not support Swift ObjC interface headers.
settings[.SWIFT_INSTALL_OBJC_HEADER] = "NO"
settings[.SWIFT_OBJC_INTERFACE_HEADER_NAME] = ""
// rdar://47937899 (Don't try to link frameworks to object files)

// rdar://47937899 (Don't try to link frameworks to object files)
// - looks like this defaults to OTHER_LDFLAGS (via xcspec) which can result in linking frameworks to mh_objects which is unwanted.
settings[.OTHER_LDRFLAGS] = []

Expand Down Expand Up @@ -622,6 +624,7 @@ public final class PackagePIFBuilder {
debugSettings[.ENABLE_TESTABILITY] = "YES"
debugSettings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS, default: []].append(contentsOf: ["DEBUG"])
debugSettings[.GCC_PREPROCESSOR_DEFINITIONS, default: ["$(inherited)"]].append(contentsOf: ["DEBUG=1"])
debugSettings[.SWIFT_INDEX_STORE_ENABLE] = "YES"
builder.project.addBuildConfig { id in BuildConfig(id: id, name: "Debug", settings: debugSettings) }

// Add the build settings that are specific to release builds, and set those as the "Release" configuration.
Expand Down
84 changes: 68 additions & 16 deletions Sources/SwiftBuildSupport/SwiftBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct SessionFailedError: Error {
var diagnostics: [SwiftBuild.SwiftBuildMessage.DiagnosticInfo]
}

func withService<T>(
package func withService<T>(
connectionMode: SWBBuildServiceConnectionMode = .default,
variant: SWBBuildServiceVariant = .default,
serviceBundleURL: URL? = nil,
Expand Down Expand Up @@ -860,7 +860,11 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
)
}

private func makeBuildParameters(session: SWBBuildServiceSession, symbolGraphOptions: BuildOutput.SymbolGraphOptions?) async throws -> SwiftBuild.SWBBuildParameters {
internal func makeBuildParameters(
session: SWBBuildServiceSession,
symbolGraphOptions: BuildOutput.SymbolGraphOptions?,
setToolchainSetting: Bool = true,
) async throws -> SwiftBuild.SWBBuildParameters {
// Generate the run destination parameters.
let runDestination = makeRunDestination()

Expand All @@ -872,17 +876,33 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
// Generate a table of any overriding build settings.
var settings: [String: String] = [:]

// If the SwiftPM toolchain corresponds to a toolchain registered with the lower level build system, add it to the toolchain stack.
// Otherwise, apply overrides for each component of the SwiftPM toolchain.
if let toolchainID = try await session.lookupToolchain(at: buildParameters.toolchain.toolchainDir.pathString) {
settings["TOOLCHAINS"] = "\(toolchainID.rawValue) $(inherited)"
} else {
// FIXME: This list of overrides is incomplete.
// An error with determining the override should not be fatal here.
settings["CC"] = try? buildParameters.toolchain.getClangCompiler().pathString
// Always specify the path of the effective Swift compiler, which was determined in the same way as for the
// native build system.
settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString
if setToolchainSetting {
// If the SwiftPM toolchain corresponds to a toolchain registered with the lower level build system, add it to the toolchain stack.
// Otherwise, apply overrides for each component of the SwiftPM toolchain.
if let toolchainID = try await session.lookupToolchain(at: buildParameters.toolchain.toolchainDir.pathString) {
settings["TOOLCHAINS"] = "\(toolchainID.rawValue) $(inherited)"
} else {
// FIXME: This list of overrides is incomplete.
// An error with determining the override should not be fatal here.
settings["CC"] = try? buildParameters.toolchain.getClangCompiler().pathString
// Always specify the path of the effective Swift compiler, which was determined in the same way as for the
// native build system.
settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString
}
}

for sanitizer in buildParameters.sanitizers.sanitizers {
self.observabilityScope.emit(debug:"Enabling \(sanitizer) sanitizer")
switch sanitizer {
case .address:
settings["ENABLE_ADDRESS_SANITIZER"] = "YES"
case .thread:
settings["ENABLE_THREAD_SANITIZER"] = "YES"
case .undefined:
settings["ENABLE_UNDEFINED_BEHAVIOR_SANITIZER"] = "YES"
case .fuzzer, .scudo:
throw StringError("\(sanitizer) is not currently supported with this build system.")
}
}

// FIXME: workaround for old Xcode installations such as what is in CI
Expand Down Expand Up @@ -985,6 +1005,38 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
settings["GENERATE_TEST_ENTRYPOINTS_FOR_BUNDLES"] = "YES"
}

// Set the value of the index store
struct IndexStoreSettings {
let enableVariableName: String
let pathVariable: String
}

let indexStoreSettingNames: [IndexStoreSettings] = [
IndexStoreSettings(
enableVariableName: "CLANG_INDEX_STORE_ENABLE",
pathVariable: "CLANG_INDEX_STORE_PATH",
),
IndexStoreSettings(
enableVariableName: "SWIFT_INDEX_STORE_ENABLE",
pathVariable: "SWIFT_INDEX_STORE_PATH",
),
]

switch self.buildParameters.indexStoreMode {
case .on:
for setting in indexStoreSettingNames {
settings[setting.enableVariableName] = "YES"
settings[setting.pathVariable] = self.buildParameters.indexStore.pathString
}
case .off:
for setting in indexStoreSettingNames {
settings[setting.enableVariableName] = "NO"
}
case .auto:
// The settings are handles in the PIF builder
break
}

func reportConflict(_ a: String, _ b: String) throws -> String {
throw StringError("Build parameters constructed conflicting settings overrides '\(a)' and '\(b)'")
}
Expand Down Expand Up @@ -1223,13 +1275,13 @@ fileprivate extension SwiftBuild.SwiftBuildMessage.DiagnosticInfo.Location {
case .none:
return path
}

case .buildSettings(let names):
return names.joined(separator: ", ")

case .buildFiles(let buildFiles, let targetGUID):
return "\(targetGUID): " + buildFiles.map { String(describing: $0) }.joined(separator: ", ")

case .unknown:
return nil
}
Expand Down
8 changes: 5 additions & 3 deletions Sources/_InternalTestSupport/MockBuildTestHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,13 @@ public func mockBuildParameters(
shouldDisableLocalRpath: Bool = false,
canRenameEntrypointFunctionName: Bool = false,
triple: Basics.Triple = hostTriple,
indexStoreMode: BuildParameters.IndexStoreMode = .off,
indexStoreMode: BuildParameters.IndexStoreMode = .auto,
linkerDeadStrip: Bool = true,
linkTimeOptimizationMode: BuildParameters.LinkTimeOptimizationMode? = nil,
omitFramePointers: Bool? = nil,
enableXCFrameworksOnLinux: Bool = false,
prepareForIndexing: BuildParameters.PrepareForIndexingMode = .off
prepareForIndexing: BuildParameters.PrepareForIndexingMode = .off,
sanitizers: [Sanitizer] = [],
) -> BuildParameters {
try! BuildParameters(
destination: destination,
Expand All @@ -104,6 +105,7 @@ public func mockBuildParameters(
buildSystemKind: buildSystemKind,
pkgConfigDirectories: [],
workers: 3,
sanitizers: EnabledSanitizers(Set(sanitizers)),
indexStoreMode: indexStoreMode,
prepareForIndexing: prepareForIndexing,
enableXCFrameworksOnLinux: enableXCFrameworksOnLinux,
Expand All @@ -120,7 +122,7 @@ public func mockBuildParameters(
linkTimeOptimizationMode: linkTimeOptimizationMode,
shouldDisableLocalRpath: shouldDisableLocalRpath,
shouldLinkStaticSwiftStdlib: shouldLinkStaticSwiftStdlib
)
),
)
}

Expand Down
7 changes: 7 additions & 0 deletions Sources/_InternalTestSupport/SwiftTesting+Tags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extension Tag {
public enum TestSize {}
public enum Feature {}
public enum Platform {}
public enum FunctionalArea {}
@Tag public static var UserWorkflow: Tag
}

Expand All @@ -27,6 +28,12 @@ extension Tag.Platform {
@Tag public static var FileSystem: Tag
}

extension Tag.FunctionalArea {
@Tag public static var PIF: Tag
@Tag public static var IndexMode: Tag
@Tag public static var Sanitizer: Tag
}

extension Tag.Feature {
public enum Command {}
public enum CommandLineArguments {}
Expand Down
4 changes: 3 additions & 1 deletion Sources/_InternalTestSupport/Toolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ extension SwiftSDK {
extension UserToolchain {
public static var `default`: Self {
get throws {
return try .init(swiftSDK: SwiftSDK.default, environment: .current, fileSystem: localFileSystem)
let value = try Self.init(swiftSDK: SwiftSDK.default, environment: .current, fileSystem: localFileSystem)
return value
// return .init(swiftSDK: SwiftSDK.default, environment: .current, fileSystem: localFileSystem)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Tests/CommandsTests/Sanitizer+ExtensionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import enum PackageModel.Sanitizer

@Suite(
.tags(
Tag.TestSize.small,
.TestSize.small,
.FunctionalArea.Sanitizer,
),
)
struct SanitizerExtensionTests {
Expand Down
Loading