Skip to content

Commit 73bf53a

Browse files
authored
Merge pull request #1933 from ahoppen/split-compile-commands-build-systems
Split build systems for JSON compilation database and fixed compilation database
2 parents 8e9773a + 15b9670 commit 73bf53a

15 files changed

+332
-270
lines changed

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,22 @@ private extension BuildSystemSpec {
195195
}
196196
logger.log("Created external build server at \(projectRoot)")
197197
return .external(buildSystem)
198-
case .compilationDatabase:
198+
case .jsonCompilationDatabase:
199199
return await createBuiltInBuildSystemAdapter(
200200
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
201201
buildSystemHooks: buildSystemHooks
202202
) { connectionToSourceKitLSP in
203-
try CompilationDatabaseBuildSystem(
203+
try JSONCompilationDatabaseBuildSystem(
204+
configPath: configPath,
205+
connectionToSourceKitLSP: connectionToSourceKitLSP
206+
)
207+
}
208+
case .fixedCompilationDatabase:
209+
return await createBuiltInBuildSystemAdapter(
210+
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
211+
buildSystemHooks: buildSystemHooks
212+
) { connectionToSourceKitLSP in
213+
try FixedCompilationDatabaseBuildSystem(
204214
configPath: configPath,
205215
connectionToSourceKitLSP: connectionToSourceKitLSP
206216
)

Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import Foundation
2828
package struct BuildSystemSpec {
2929
package enum Kind {
3030
case buildServer
31-
case compilationDatabase
31+
case jsonCompilationDatabase
32+
case fixedCompilationDatabase
3233
case swiftPM
3334
case injected(BuildSystemInjector)
3435
}

Sources/BuildSystemIntegration/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ add_library(BuildSystemIntegration STATIC
99
BuiltInBuildSystem.swift
1010
BuiltInBuildSystemAdapter.swift
1111
CompilationDatabase.swift
12-
CompilationDatabaseBuildSystem.swift
1312
DetermineBuildSystem.swift
1413
ExternalBuildSystemAdapter.swift
1514
FallbackBuildSettings.swift
1615
FileBuildSettings.swift
16+
FixedCompilationDatabaseBuildSystem.swift
17+
JSONCompilationDatabaseBuildSystem.swift
1718
LegacyBuildServerBuildSystem.swift
1819
MainFilesProvider.swift
1920
PathPrefixMapping.swift

Sources/BuildSystemIntegration/CompilationDatabase.swift

Lines changed: 7 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import WinSDK
3636
///
3737
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html
3838
package struct CompilationDatabaseCompileCommand: Equatable, Codable {
39-
4039
/// The working directory for the compilation.
4140
package var directory: String
4241

@@ -103,84 +102,6 @@ package struct CompilationDatabaseCompileCommand: Equatable, Codable {
103102
}
104103
}
105104

106-
/// A clang-compatible compilation database.
107-
///
108-
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html
109-
package protocol CompilationDatabase {
110-
typealias Command = CompilationDatabaseCompileCommand
111-
subscript(_ uri: DocumentURI) -> [Command] { get }
112-
var sourceItems: [SourceItem] { get }
113-
}
114-
115-
/// Loads a compilation database from `file`.
116-
package func tryLoadCompilationDatabase(
117-
file: URL
118-
) -> CompilationDatabase? {
119-
orLog("Failed to load compilation database") { () -> CompilationDatabase? in
120-
switch file.lastPathComponent {
121-
case JSONCompilationDatabase.dbName:
122-
return try JSONCompilationDatabase(file: file)
123-
case FixedCompilationDatabase.dbName:
124-
return try FixedCompilationDatabase(file: file)
125-
default:
126-
return nil
127-
}
128-
}
129-
}
130-
131-
/// Fixed clang-compatible compilation database (compile_flags.txt).
132-
///
133-
/// Each line in the file becomes a command line argument. Example:
134-
/// ```
135-
/// -xc++
136-
/// -I
137-
/// libwidget/include/
138-
/// ```
139-
///
140-
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html under Alternatives
141-
package struct FixedCompilationDatabase: CompilationDatabase, Equatable {
142-
package static let dbName: String = "compile_flags.txt"
143-
144-
private let fixedArgs: [String]
145-
private let directory: String
146-
147-
package subscript(path: DocumentURI) -> [CompilationDatabaseCompileCommand] {
148-
[Command(directory: directory, filename: path.pseudoPath, commandLine: fixedArgs + [path.pseudoPath])]
149-
}
150-
151-
package var sourceItems: [SourceItem] {
152-
return [
153-
SourceItem(uri: URI(filePath: directory, isDirectory: true), kind: .directory, generated: false)
154-
]
155-
}
156-
157-
/// Loads the compilation database located in `directory`, if any.
158-
/// - Returns: `nil` if `compile_flags.txt` was not found
159-
package init?(directory: URL) throws {
160-
let path = directory.appendingPathComponent(Self.dbName)
161-
try self.init(file: path)
162-
}
163-
164-
/// Loads the compilation database from `file`
165-
/// - Returns: `nil` if the file does not exist
166-
package init?(file: URL) throws {
167-
self.directory = try file.deletingLastPathComponent().filePath
168-
169-
let fileContents: String
170-
do {
171-
fileContents = try String(contentsOf: file, encoding: .utf8)
172-
} catch {
173-
return nil
174-
}
175-
176-
var fixedArgs: [String] = ["clang"]
177-
fileContents.enumerateLines { line, _ in
178-
fixedArgs.append(line.trimmingCharacters(in: .whitespacesAndNewlines))
179-
}
180-
self.fixedArgs = fixedArgs
181-
}
182-
}
183-
184105
/// The JSON clang-compatible compilation database.
185106
///
186107
/// Example:
@@ -196,11 +117,9 @@ package struct FixedCompilationDatabase: CompilationDatabase, Equatable {
196117
/// ```
197118
///
198119
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html
199-
package struct JSONCompilationDatabase: CompilationDatabase, Equatable, Codable {
200-
package static let dbName: String = "compile_commands.json"
201-
120+
package struct JSONCompilationDatabase: Equatable, Codable {
202121
private var pathToCommands: [DocumentURI: [Int]] = [:]
203-
private var commands: [CompilationDatabaseCompileCommand] = []
122+
var commands: [CompilationDatabaseCompileCommand] = []
204123

205124
package init(_ commands: [CompilationDatabaseCompileCommand] = []) {
206125
for command in commands {
@@ -211,27 +130,22 @@ package struct JSONCompilationDatabase: CompilationDatabase, Equatable, Codable
211130
package init(from decoder: Decoder) throws {
212131
var container = try decoder.unkeyedContainer()
213132
while !container.isAtEnd {
214-
self.add(try container.decode(Command.self))
133+
self.add(try container.decode(CompilationDatabaseCompileCommand.self))
215134
}
216135
}
217136

218137
/// Loads the compilation database located in `directory`, if any.
219138
///
220139
/// - Returns: `nil` if `compile_commands.json` was not found
221-
package init?(directory: URL) throws {
222-
let path = directory.appendingPathComponent(Self.dbName)
140+
package init(directory: URL) throws {
141+
let path = directory.appendingPathComponent(JSONCompilationDatabaseBuildSystem.dbName)
223142
try self.init(file: path)
224143
}
225144

226145
/// Loads the compilation database from `file`
227146
/// - Returns: `nil` if the file does not exist
228-
package init?(file: URL) throws {
229-
let data: Data
230-
do {
231-
data = try Data(contentsOf: file)
232-
} catch {
233-
return nil
234-
}
147+
package init(file: URL) throws {
148+
let data = try Data(contentsOf: file)
235149
self = try JSONDecoder().decode(JSONCompilationDatabase.self, from: data)
236150
}
237151

Sources/BuildSystemIntegration/DetermineBuildSystem.swift

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,56 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import Foundation
14-
15-
#if compiler(>=6)
16-
package import LanguageServerProtocol
1714
import SKLogging
18-
package import SKOptions
1915
import SwiftExtensions
16+
import TSCExtensions
2017
import ToolchainRegistry
2118

2219
import struct TSCBasic.AbsolutePath
20+
import struct TSCBasic.RelativePath
21+
22+
#if compiler(>=6)
23+
package import LanguageServerProtocol
24+
package import SKOptions
2325
#else
2426
import LanguageServerProtocol
25-
import SKLogging
2627
import SKOptions
27-
import SwiftExtensions
28-
import ToolchainRegistry
29-
30-
import struct TSCBasic.AbsolutePath
3128
#endif
3229

30+
private func searchForCompilationDatabaseConfig(
31+
in workspaceFolder: URL,
32+
options: SourceKitLSPOptions
33+
) -> BuildSystemSpec? {
34+
let searchPaths =
35+
(options.compilationDatabaseOrDefault.searchPaths ?? []).compactMap {
36+
try? RelativePath(validating: $0)
37+
} + [
38+
// These default search paths match the behavior of `clangd`
39+
try! RelativePath(validating: "."),
40+
try! RelativePath(validating: "build"),
41+
]
42+
43+
return
44+
searchPaths
45+
.lazy
46+
.compactMap { searchPath in
47+
let path = workspaceFolder.appending(searchPath)
48+
49+
let jsonPath = path.appendingPathComponent(JSONCompilationDatabaseBuildSystem.dbName)
50+
if FileManager.default.isFile(at: jsonPath) {
51+
return BuildSystemSpec(kind: .jsonCompilationDatabase, projectRoot: workspaceFolder, configPath: jsonPath)
52+
}
53+
54+
let fixedPath = path.appendingPathComponent(FixedCompilationDatabaseBuildSystem.dbName)
55+
if FileManager.default.isFile(at: fixedPath) {
56+
return BuildSystemSpec(kind: .fixedCompilationDatabase, projectRoot: workspaceFolder, configPath: fixedPath)
57+
}
58+
59+
return nil
60+
}
61+
.first
62+
}
63+
3364
/// Determine which build system should be started to handle the given workspace folder and at which folder that build
3465
/// system's project root is (see `BuiltInBuildSystem.projectRoot(for:options:)`). `onlyConsiderRoot` controls whether
3566
/// paths outside the root should be considered (eg. configuration files in the user's home directory).
@@ -66,7 +97,7 @@ package func determineBuildSystem(
6697
options: options
6798
)
6899
case .compilationDatabase:
69-
spec = CompilationDatabaseBuildSystem.searchForConfig(in: workspaceFolderUrl, options: options)
100+
spec = searchForCompilationDatabaseConfig(in: workspaceFolderUrl, options: options)
70101
case .swiftPM:
71102
#if canImport(PackageModel)
72103
spec = SwiftPMBuildSystem.searchForConfig(in: workspaceFolderUrl, options: options)

0 commit comments

Comments
 (0)