Skip to content

Commit 38c5c05

Browse files
authored
Handle swift-sdk search paths (#6608)
- Fixes a bug where includeSearchPaths and librarySearchPaths defined in a swift-sdk.json file were not properly respected. Updates UserToolchain to support these by adding matching properties and updates SwiftTargetBuildDescription as well as ClangTargetBuildDescription to pass these toolchain search paths to the compilers and linkers as expected.
1 parent 948fc68 commit 38c5c05

File tree

7 files changed

+102
-4
lines changed

7 files changed

+102
-4
lines changed

Sources/Build/BuildDescription/ClangTargetBuildDescription.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ public final class ClangTargetBuildDescription {
304304
args += ["-flto=thin"]
305305
}
306306

307+
// Pass default include paths from the toolchain.
308+
for includeSearchPath in self.buildParameters.toolchain.includeSearchPaths {
309+
args += ["-I", includeSearchPath.pathString]
310+
}
311+
307312
return args
308313
}
309314

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
318318
// User arguments (from -Xlinker) should follow generated arguments to allow user overrides
319319
args += self.buildParameters.flags.linkerFlags.asSwiftcLinkerFlags()
320320

321+
// Pass default library paths from the toolchain.
322+
for librarySearchPath in self.buildParameters.toolchain.librarySearchPaths {
323+
args += ["-L", librarySearchPath.pathString]
324+
}
325+
321326
// Add toolchain's libdir at the very end (even after the user -Xlinker arguments).
322327
//
323328
// This will allow linking to libraries shipped in the toolchain.

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,11 @@ public final class SwiftTargetBuildDescription {
528528
args += ["-lto=llvm-thin"]
529529
}
530530

531+
// Pass default include paths from the toolchain.
532+
for includeSearchPath in self.buildParameters.toolchain.includeSearchPaths {
533+
args += ["-I", includeSearchPath.pathString]
534+
}
535+
531536
// suppress warnings if the package is remote
532537
if self.package.isRemote {
533538
args += ["-suppress-warnings"]
@@ -627,6 +632,11 @@ public final class SwiftTargetBuildDescription {
627632
result += try self.buildSettingsFlags()
628633
result += try self.macroArguments()
629634

635+
// Pass default include paths from the toolchain.
636+
for includeSearchPath in self.buildParameters.toolchain.includeSearchPaths {
637+
result += ["-I", includeSearchPath.pathString]
638+
}
639+
630640
return result
631641
}
632642

@@ -706,6 +716,11 @@ public final class SwiftTargetBuildDescription {
706716
result += ["-lto=llvm-thin"]
707717
}
708718

719+
// Pass default include paths from the toolchain.
720+
for includeSearchPath in self.buildParameters.toolchain.includeSearchPaths {
721+
result += ["-I", includeSearchPath.pathString]
722+
}
723+
709724
result += try self.macroArguments()
710725
return result
711726
}

Sources/PackageModel/Toolchain.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public protocol Toolchain {
2828
/// Path containing the macOS Swift stdlib.
2929
var macosSwiftStdlib: AbsolutePath { get throws }
3030

31+
/// An array of paths to search for headers and modules at compile time.
32+
var includeSearchPaths: [AbsolutePath] { get }
33+
34+
/// An array of paths to search for libraries at link time.
35+
var librarySearchPaths: [AbsolutePath] { get }
36+
3137
/// Path of the `clang` compiler.
3238
func getClangCompiler() throws -> AbsolutePath
3339

Sources/PackageModel/UserToolchain.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ public final class UserToolchain: Toolchain {
3434
/// Path of the `swiftc` compiler.
3535
public let swiftCompilerPath: AbsolutePath
3636

37+
/// An array of paths to search for headers and modules at compile time.
38+
public let includeSearchPaths: [AbsolutePath]
39+
40+
/// An array of paths to search for libraries at link time.
41+
public let librarySearchPaths: [AbsolutePath]
42+
3743
/// Additional flags to be passed to the build tools.
3844
public var extraFlags: BuildFlags
3945

@@ -482,6 +488,7 @@ public final class UserToolchain: Toolchain {
482488
}
483489

484490
self.triple = triple
491+
485492
self.extraFlags = BuildFlags(
486493
cCompilerFlags: destination.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [],
487494
cxxCompilerFlags: destination.toolset.knownTools[.cxxCompiler]?.extraCLIOptions ?? [],
@@ -492,6 +499,9 @@ public final class UserToolchain: Toolchain {
492499
linkerFlags: destination.toolset.knownTools[.linker]?.extraCLIOptions ?? [],
493500
xcbuildFlags: destination.toolset.knownTools[.xcbuild]?.extraCLIOptions ?? [])
494501

502+
self.includeSearchPaths = destination.pathsConfiguration.includeSearchPaths ?? []
503+
self.librarySearchPaths = destination.pathsConfiguration.includeSearchPaths ?? []
504+
495505
self.librarianPath = try UserToolchain.determineLibrarian(
496506
triple: triple,
497507
binDirectories: destination.toolset.rootPaths,

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,10 +3554,7 @@ final class BuildPlanTests: XCTestCase {
35543554
runTimeTriple: runtimeTriple,
35553555
properties: .init(
35563556
sdkRootPath: "/fake/sdk",
3557-
swiftStaticResourcesPath: "/usr/lib/swift_static/none",
3558-
includeSearchPaths: ["/usr/lib/swift_static/none"],
3559-
librarySearchPaths: ["/usr/lib/swift_static/none"],
3560-
toolsetPaths: []),
3557+
swiftStaticResourcesPath: "/usr/lib/swift_static/none"),
35613558
toolset: toolSet,
35623559
destinationDirectory: nil)
35633560
let toolchain = try UserToolchain(destination: destination)
@@ -3669,6 +3666,64 @@ final class BuildPlanTests: XCTestCase {
36693666
XCTAssertCount(1, exeLinkArguments, cliFlag(tool: .linker))
36703667
}
36713668

3669+
func testUserToolchainWithSDKSearchPaths() throws {
3670+
let fileSystem = InMemoryFileSystem(emptyFiles:
3671+
"/Pkg/Sources/exe/main.swift",
3672+
"/Pkg/Sources/cLib/cLib.c",
3673+
"/Pkg/Sources/cLib/include/cLib.h"
3674+
)
3675+
3676+
let observability = ObservabilitySystem.makeForTesting()
3677+
let graph = try loadPackageGraph(
3678+
fileSystem: fileSystem,
3679+
manifests: [
3680+
Manifest.createRootManifest(
3681+
displayName: "Pkg",
3682+
path: "/Pkg",
3683+
targets: [
3684+
TargetDescription(name: "exe", dependencies: ["cLib"]),
3685+
TargetDescription(name: "cLib", dependencies: []),
3686+
]),
3687+
],
3688+
observabilityScope: observability.topScope
3689+
)
3690+
XCTAssertNoDiagnostics(observability.diagnostics)
3691+
3692+
let runtimeTriple = try UserToolchain.default.triple
3693+
let sdkIncludeSearchPath = "/usr/lib/swift_static/none/include"
3694+
let sdkLibrarySearchPath = "/usr/lib/swift_static/none/lib"
3695+
let destination = try Destination(
3696+
runTimeTriple: runtimeTriple,
3697+
properties: .init(
3698+
sdkRootPath: "/fake/sdk",
3699+
includeSearchPaths: [sdkIncludeSearchPath],
3700+
librarySearchPaths: [sdkLibrarySearchPath]))
3701+
let toolchain = try UserToolchain(destination: destination)
3702+
let buildParameters = mockBuildParameters(toolchain: toolchain)
3703+
let result = try BuildPlanResult(plan: BuildPlan(
3704+
buildParameters: buildParameters,
3705+
graph: graph,
3706+
fileSystem: fileSystem,
3707+
observabilityScope: observability.topScope))
3708+
result.checkProductsCount(1)
3709+
result.checkTargetsCount(2)
3710+
3711+
// Compile C Target
3712+
let cLibCompileArguments = try result.target(for: "cLib").clangTarget().basicArguments(isCXX: false)
3713+
let cLibCompileArgumentsPattern: [StringPattern] = ["-I", "\(sdkIncludeSearchPath)"]
3714+
XCTAssertMatch(cLibCompileArguments, cLibCompileArgumentsPattern)
3715+
3716+
// Compile Swift Target
3717+
let exeCompileArguments = try result.target(for: "exe").swiftTarget().compileArguments()
3718+
let exeCompileArgumentsPattern: [StringPattern] = ["-I", "\(sdkIncludeSearchPath)"]
3719+
XCTAssertMatch(exeCompileArguments, exeCompileArgumentsPattern)
3720+
3721+
// Link Product
3722+
let exeLinkArguments = try result.buildProduct(for: "exe").linkArguments()
3723+
let exeLinkArgumentsPattern: [StringPattern] = ["-L", "\(sdkIncludeSearchPath)"]
3724+
XCTAssertMatch(exeLinkArguments, exeLinkArgumentsPattern)
3725+
}
3726+
36723727
func testExecBuildTimeDependency() throws {
36733728
let PkgA = AbsolutePath("/PkgA")
36743729

Tests/BuildTests/MockBuildTestHelper.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ struct MockToolchain: PackageModel.Toolchain {
2828
let librarianPath = AbsolutePath("/fake/path/to/ar")
2929
#endif
3030
let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc")
31+
let includeSearchPaths = [AbsolutePath]()
32+
let librarySearchPaths = [AbsolutePath]()
3133
let isSwiftDevelopmentToolchain = false
3234
let swiftPluginServerPath: AbsolutePath? = nil
3335
let extraFlags = PackageModel.BuildFlags()

0 commit comments

Comments
 (0)