Skip to content

Commit 7327c09

Browse files
committed
In macro tests, only link against files listed in Objects.LinkFileList
Otherwise we can get a situation where a `.swift` file is removed from swift-syntax, its `.o` file is still in the build directory because the build folder wasn't cleaned and thus we would link against the stale `.o` file. rdar://142666044
1 parent 194d340 commit 7327c09

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

Sources/SKTestSupport/SwiftPMTestProject.swift

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ import ToolchainRegistry
3030
import XCTest
3131
#endif
3232

33-
private struct SwiftSyntaxCShimsModulemapNotFoundError: Error {}
34-
3533
package class SwiftPMTestProject: MultiFileTestProject {
3634
enum Error: Swift.Error {
3735
/// The `swift` executable could not be found.
@@ -85,9 +83,36 @@ package class SwiftPMTestProject: MultiFileTestProject {
8583
.first { FileManager.default.fileExists(at: $0) }
8684

8785
guard let swiftSyntaxCShimsModulemap else {
86+
struct SwiftSyntaxCShimsModulemapNotFoundError: Swift.Error {}
8887
throw SwiftSyntaxCShimsModulemapNotFoundError()
8988
}
9089

90+
// Only link against object files that are listed in the `Objects.LinkFileList`. Otherwise we can get a situation
91+
// where a `.swift` file is removed from swift-syntax, its `.o` file is still in the build directory because the
92+
// build folder wasn't cleaned and thus we would link against the stale `.o` file.
93+
let linkFileListURL =
94+
productsDirectory
95+
.appendingPathComponent("SourceKitLSPPackageTests.product")
96+
.appendingPathComponent("Objects.LinkFileList")
97+
let linkFileListContents = try? String(contentsOf: linkFileListURL, encoding: .utf8)
98+
guard let linkFileListContents else {
99+
struct LinkFileListNotFoundError: Swift.Error {
100+
let url: URL
101+
}
102+
throw LinkFileListNotFoundError(url: linkFileListURL)
103+
}
104+
let linkFileList =
105+
linkFileListContents
106+
.split(separator: "\n")
107+
.map {
108+
// Files are wrapped in single quotes if the path contains spaces. Drop the quotes.
109+
if $0.hasPrefix("'") && $0.hasSuffix("'") {
110+
return String($0.dropFirst().dropLast())
111+
} else {
112+
return String($0)
113+
}
114+
}
115+
91116
let swiftSyntaxModulesToLink = [
92117
"SwiftBasicFormat",
93118
"SwiftCompilerPlugin",
@@ -108,7 +133,7 @@ package class SwiftPMTestProject: MultiFileTestProject {
108133
let dir = productsDirectory.appendingPathComponent("\(moduleName).build")
109134
let enumerator = FileManager.default.enumerator(at: dir, includingPropertiesForKeys: nil)
110135
while let file = enumerator?.nextObject() as? URL {
111-
if file.pathExtension == "o" {
136+
if linkFileList.contains(try file.filePath) {
112137
objectFiles.append(try file.filePath)
113138
}
114139
}

0 commit comments

Comments
 (0)