Skip to content

Commit 11c1cdf

Browse files
authored
Provide library paths to plugin tools when run as custom tasks (#8767)
Linux build tool plugins won't work because they require a library path to the Swift standard libraries. Add the toolchain's library path to the environment for the custom task. Enable the tests that cover this area for non-macOS platforms.
1 parent 77a52fe commit 11c1cdf

File tree

7 files changed

+61
-23
lines changed

7 files changed

+61
-23
lines changed

Sources/Basics/Environment/EnvironmentKey.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ public struct EnvironmentKey {
2424
extension EnvironmentKey {
2525
package static let path: Self = "PATH"
2626

27+
package static var libraryPath: Self {
28+
#if os(Windows)
29+
path
30+
#elseif canImport(Darwin)
31+
"DYLD_LIBRARY_PATH"
32+
#else
33+
"LD_LIBRARY_PATH"
34+
#endif
35+
}
36+
2737
/// A set of known keys which should not be included in cache keys.
2838
package static let nonCachable: Set<Self> = [
2939
"TERM",

Sources/PackageModel/Toolchain.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public protocol Toolchain {
3535
/// An array of paths to search for libraries at link time.
3636
var librarySearchPaths: [AbsolutePath] { get }
3737

38+
/// An array of paths to use with binaries produced by this toolchain at run time.
39+
var runtimeLibraryPaths: [AbsolutePath] { get }
40+
3841
/// Configuration from the used toolchain.
3942
var installedSwiftPMConfiguration: InstalledSwiftPMConfiguration { get }
4043

Sources/PackageModel/UserToolchain.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public final class UserToolchain: Toolchain {
4242
/// An array of paths to search for libraries at link time.
4343
public let librarySearchPaths: [AbsolutePath]
4444

45+
/// An array of paths to use with binaries produced by this toolchain at run time.
46+
public let runtimeLibraryPaths: [AbsolutePath]
47+
4548
/// Path containing Swift resources for dynamic linking.
4649
public var swiftResourcesPath: AbsolutePath? {
4750
swiftSDK.pathsConfiguration.swiftResourcesPath
@@ -206,6 +209,24 @@ public final class UserToolchain: Toolchain {
206209
}
207210
}
208211

212+
private static func computeRuntimeLibraryPaths(targetInfo: JSON) throws -> [AbsolutePath] {
213+
var libraryPaths: [AbsolutePath] = []
214+
215+
for runtimeLibPath in (try? (try? targetInfo.get("paths"))?.getArray("runtimeLibraryPaths")) ?? [] {
216+
guard case .string(let value) = runtimeLibPath else {
217+
continue
218+
}
219+
220+
guard let path = try? AbsolutePath(validating: value) else {
221+
continue
222+
}
223+
224+
libraryPaths.append(path)
225+
}
226+
227+
return libraryPaths
228+
}
229+
209230
private static func computeSwiftCompilerVersion(targetInfo: JSON) -> String? {
210231
// Get the compiler version from the target info
211232
let compilerVersion: String
@@ -701,6 +722,9 @@ public final class UserToolchain: Toolchain {
701722
// Get compiler version information from target info
702723
self.swiftCompilerVersion = Self.computeSwiftCompilerVersion(targetInfo: targetInfo)
703724

725+
// Get the list of runtime libraries from the target info
726+
self.runtimeLibraryPaths = try Self.computeRuntimeLibraryPaths(targetInfo: targetInfo)
727+
704728
// Use the triple from Swift SDK or compute the host triple from the target info
705729
var triple = try swiftSDK.targetTriple ?? Self.getHostTriple(targetInfo: targetInfo)
706730

Sources/SwiftBuildSupport/PIFBuilder.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
import Basics
13+
@_spi(SwiftPMInternal) import Basics
1414
import Foundation
1515
import PackageGraph
1616
import PackageLoading
@@ -357,9 +357,12 @@ public final class PIFBuilder {
357357
let result2 = PackagePIFBuilder.BuildToolPluginInvocationResult(
358358
prebuildCommandOutputPaths: result.prebuildCommands.map( { $0.outputFilesDirectory } ),
359359
buildCommands: result.buildCommands.map( { buildCommand in
360-
var env: [String: String] = [:]
361-
for (key, value) in buildCommand.configuration.environment {
362-
env[key.rawValue] = value
360+
var newEnv: Environment = buildCommand.configuration.environment
361+
362+
if let runtimeLibPaths = try? buildParameters.toolchain.runtimeLibraryPaths {
363+
for libPath in runtimeLibPaths {
364+
newEnv.appendPath(key: .libraryPath, value: libPath.pathString)
365+
}
363366
}
364367

365368
let workingDir = buildCommand.configuration.workingDirectory
@@ -370,7 +373,7 @@ public final class PIFBuilder {
370373
displayName: buildCommand.configuration.displayName,
371374
executable: buildCommand.configuration.executable.pathString,
372375
arguments: buildCommand.configuration.arguments,
373-
environment: env,
376+
environment: .init(newEnv),
374377
workingDir: workingDir,
375378
inputPaths: buildCommand.inputFiles,
376379
outputPaths: buildCommand.outputFiles.map(\.pathString),

Sources/_InternalTestSupport/MockBuildTestHelper.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public struct MockToolchain: PackageModel.Toolchain {
3131
public let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc")
3232
public let includeSearchPaths = [AbsolutePath]()
3333
public let librarySearchPaths = [AbsolutePath]()
34+
public let runtimeLibraryPaths: [AbsolutePath] = [AbsolutePath]()
3435
public let swiftResourcesPath: AbsolutePath?
3536
public let swiftStaticResourcesPath: AbsolutePath? = nil
3637
public let sdkRootPath: AbsolutePath? = nil

Tests/CommandsTests/SwiftSDKCommandTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ final class SwiftSDKCommandTests: CommandsTestCase {
6666

6767
// We only expect tool's output on the stdout stream.
6868
XCTAssertMatch(
69-
stdout,
69+
stdout + "\nstderr:\n" + stderr,
7070
.contains("\(bundle)` successfully installed as test-sdk.artifactbundle.")
7171
)
7272

Tests/FunctionalTests/PluginTests.swift

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ final class PluginTests: XCTestCase {
7070
XCTAssert(stdout.contains("Build of product 'MyTool' complete!"), "stdout:\n\(stdout)")
7171
}
7272

73-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
73+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
7474
// Try again with the Swift Build build system
7575
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
7676
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyTool"])
@@ -92,7 +92,7 @@ final class PluginTests: XCTestCase {
9292
XCTAssert(stdout.contains("Build of product 'MyOtherLocalTool' complete!"), "stdout:\n\(stdout)")
9393
}
9494

95-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
95+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
9696
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
9797
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyOtherLocalTool"])
9898
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
@@ -115,7 +115,7 @@ final class PluginTests: XCTestCase {
115115
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
116116
}
117117

118-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
118+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
119119
// Try again with the Swift Build build system
120120
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
121121
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ClientOfPluginWithInternalExecutable"), extraArgs: ["--build-system", "swiftbuild"])
@@ -136,13 +136,11 @@ final class PluginTests: XCTestCase {
136136
}
137137
}
138138

139-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
140139
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
141140
await XCTAssertThrowsCommandExecutionError(try await executeSwiftBuild(fixturePath.appending("InvalidUseOfInternalPluginExecutable")), "Illegally used internal executable"
142141
) { error in
143142
}
144143
}
145-
#endif
146144
}
147145

148146
func testLocalBuildToolPluginUsingRemoteExecutable() async throws {
@@ -159,7 +157,7 @@ final class PluginTests: XCTestCase {
159157
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
160158
}
161159

162-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
160+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
163161
// Try again with the Swift Build build system
164162
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
165163
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("LibraryWithLocalBuildToolPluginUsingRemoteTool"), extraArgs: ["--build-system", "swiftbuild"])
@@ -182,7 +180,7 @@ final class PluginTests: XCTestCase {
182180
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
183181
}
184182

185-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
183+
#if os(macOS)
186184
// Try again with the Swift Build build system
187185
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
188186
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MyBuildToolPluginDependencies"), extraArgs: ["--build-system", "swiftbuild"])
@@ -204,7 +202,7 @@ final class PluginTests: XCTestCase {
204202
XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)")
205203
}
206204

207-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
205+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
208206
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
209207
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool", "--disable-sandbox"])
210208
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
@@ -1158,7 +1156,7 @@ final class PluginTests: XCTestCase {
11581156
XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)")
11591157
}
11601158

1161-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1159+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
11621160
// Try again with the Swift Build build system
11631161
try await fixture(name: "Miscellaneous/Plugins") { path in
11641162
let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "do-something"])
@@ -1175,7 +1173,7 @@ final class PluginTests: XCTestCase {
11751173
XCTAssert(stdout.contains("Build complete!"), "output:\n\(stderr)\n\(stdout)")
11761174
}
11771175

1178-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1176+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
11791177
// Try again with the Swift Build build system
11801178
try await fixture(name: "Miscellaneous/Plugins") { path in
11811179
let (stdout, stderr) = try await executeSwiftBuild(path.appending("IncorrectDependencies"), extraArgs: ["--build-system", "swiftbuild", "--build-tests"])
@@ -1219,7 +1217,7 @@ final class PluginTests: XCTestCase {
12191217
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
12201218
}
12211219

1222-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1220+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
12231221
// Try again with Swift Build build system
12241222
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
12251223
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("TransitivePluginOnlyDependency"), extraArgs: ["--build-system", "swiftbuild"])
@@ -1240,7 +1238,7 @@ final class PluginTests: XCTestCase {
12401238
}
12411239
}
12421240

1243-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1241+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
12441242
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
12451243
do {
12461244
try await executeSwiftBuild(fixturePath.appending("MissingPlugin"), extraArgs: ["--build-system", "swiftbuild"])
@@ -1262,7 +1260,7 @@ final class PluginTests: XCTestCase {
12621260
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
12631261
}
12641262

1265-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1263+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
12661264
// Try again with the Swift Build build system
12671265
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
12681266
let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("PluginCanBeReferencedByProductName"), extraArgs: ["--build-system", "swiftbuild"])
@@ -1292,7 +1290,7 @@ final class PluginTests: XCTestCase {
12921290
XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)")
12931291
}
12941292

1295-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1293+
#if os(macOS)
12961294
try await fixture(name: "Miscellaneous/Plugins") { fixturePath in
12971295
let (stdout, stderr) = try await executeSwiftBuild(
12981296
fixturePath.appending(component: "MySourceGenPlugin"),
@@ -1315,8 +1313,7 @@ final class PluginTests: XCTestCase {
13151313
let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .Debug)
13161314
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
13171315
}
1318-
1319-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1316+
#if os(macOS)
13201317
// Try again with the Swift Build build system
13211318
try await fixture(name: "Miscellaneous/Plugins/MySourceGenPluginUsingURLBasedAPI") { fixturePath in
13221319
let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .Debug, extraArgs: ["--build-system", "swiftbuild"])
@@ -1333,7 +1330,7 @@ final class PluginTests: XCTestCase {
13331330
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
13341331
}
13351332

1336-
#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux
1333+
#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774
13371334
try await fixture(name: "Miscellaneous/Plugins/DependentPlugins") { fixturePath in
13381335
let (stdout, _) = try await executeSwiftBuild(fixturePath, extraArgs: ["--build-system", "swiftbuild"])
13391336
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")

0 commit comments

Comments
 (0)