diff --git a/Documentation/Configuration File.md b/Documentation/Configuration File.md index 6fd133ff..d19dcca0 100644 --- a/Documentation/Configuration File.md +++ b/Documentation/Configuration File.md @@ -15,7 +15,7 @@ The structure of the file is currently not guaranteed to be stable. Options may - `swiftPM`: Dictionary with the following keys, defining options for SwiftPM workspaces - `configuration: "debug"|"release"`: The configuration to build the project for during background indexing and the configuration whose build folder should be used for Swift modules if background indexing is disabled. Equivalent to SwiftPM's `--configuration` option. - - `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value. Equivalent to SwiftPM's `--scratch-path` option. + - `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value. This path can be specified as a relative path, which will be interpreted relative to the project root. Equivalent to SwiftPM's `--scratch-path` option. - `swiftSDKsDirectory: string`: Equivalent to SwiftPM's `--swift-sdks-path` option - `swiftSDK: string`: Equivalent to SwiftPM's `--swift-sdk` option - `triple: string`: Equivalent to SwiftPM's `--triple` option diff --git a/Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift b/Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift index 6f58cdfc..69c993fa 100644 --- a/Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift +++ b/Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift @@ -324,7 +324,7 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem { if options.backgroundIndexingOrDefault { location.scratchDirectory = AbsolutePath(projectRoot.appending(components: ".build", "index-build")) } else if let scratchDirectory = options.swiftPMOrDefault.scratchPath, - let scratchDirectoryPath = try? AbsolutePath(validating: scratchDirectory) + let scratchDirectoryPath = try? AbsolutePath(validating: scratchDirectory, relativeTo: AbsolutePath(projectRoot)) { location.scratchDirectory = scratchDirectoryPath } diff --git a/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift b/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift index 4764d84f..fa4efb0f 100644 --- a/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift +++ b/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift @@ -90,6 +90,43 @@ final class SwiftPMBuildSystemTests: XCTestCase { } } + func testRelativeScratchPath() async throws { + try await withTestScratchDir { tempDir in + try localFileSystem.createFiles( + root: tempDir, + files: [ + "pkg/Sources/lib/a.swift": "", + "pkg/Package.swift": """ + // swift-tools-version:4.2 + import PackageDescription + let package = Package( + name: "a", + targets: [.target(name: "lib")] + ) + """, + ] + ) + let packageRoot = tempDir.appending(component: "pkg") + let options = SourceKitLSPOptions( + swiftPM: .init( + scratchPath: "non_default_relative_build_path" + ), + backgroundIndexing: false + ) + let swiftpmBuildSystem = try await SwiftPMBuildSystem( + projectRoot: packageRoot, + toolchainRegistry: .forTesting, + options: options, + connectionToSourceKitLSP: LocalConnection(receiverName: "dummy"), + testHooks: SwiftPMTestHooks() + ) + + let dataPath = await swiftpmBuildSystem.destinationBuildParameters.dataPath + let expectedScratchPath = packageRoot.appending(component: try XCTUnwrap(options.swiftPMOrDefault.scratchPath)) + XCTAssertTrue(AbsolutePath(dataPath).isDescendant(of: expectedScratchPath)) + } + } + func testBasicSwiftArgs() async throws { try await SkipUnless.swiftpmStoresModulesInSubdirectory() try await withTestScratchDir { tempDir in