Skip to content

Commit 3ab87e8

Browse files
Refactor the plugin loading a bit to minimize compile-time differences (#758)
This narrows what's guarded by USE_STATIC_PLUGIN_INITIALIZATION as tightly as possible, to avoid unintentional build breakages during refactoring, for clients where this flag is turned off. It also fixes an issue which resulted from this during Core initialization where the wrong type of plugin manager was being passed into the plugin initialization function.
1 parent aa76ff5 commit 3ab87e8

File tree

11 files changed

+86
-65
lines changed

11 files changed

+86
-65
lines changed

Sources/SWBAndroidPlatform/Plugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public import SWBCore
1515
import SWBMacro
1616
import Foundation
1717

18-
@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) {
18+
public let initializePlugin: PluginInitializationFunction = { manager in
1919
let plugin = AndroidPlugin()
2020
manager.register(AndroidPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
2121
manager.register(AndroidEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self)

Sources/SWBApplePlatform/Plugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import SWBProtocol
1717
import Foundation
1818
import SWBTaskConstruction
1919

20-
@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) {
20+
public let initializePlugin: PluginInitializationFunction = { manager in
2121
manager.register(AppleDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self)
2222
manager.register(ApplePlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
2323
manager.register(ActoolInputFileGroupingStrategyExtension(), type: InputFileGroupingStrategyExtensionPoint.self)

Sources/SWBBuildService/BuildServiceEntryPoint.swift

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,39 @@ extension BuildService {
127127

128128
pluginManager.register(BuiltinTaskActionsExtension(), type: TaskActionExtensionPoint.self)
129129

130+
let staticPluginInitializers: [PluginInitializationFunction]
131+
132+
// This MUST be a compile-time check because the module dependencies on the plugins are conditional.
133+
// Minimize the amount of code that is conditionally compiled to avoid breaking the build during refactoring.
130134
#if USE_STATIC_PLUGIN_INITIALIZATION
131-
// Statically initialize the plugins.
132-
SWBAndroidPlatform.initializePlugin(pluginManager)
133-
SWBApplePlatform.initializePlugin(pluginManager)
134-
SWBGenericUnixPlatform.initializePlugin(pluginManager)
135-
SWBQNXPlatform.initializePlugin(pluginManager)
136-
SWBUniversalPlatform.initializePlugin(pluginManager)
137-
SWBWebAssemblyPlatform.initializePlugin(pluginManager)
138-
SWBWindowsPlatform.initializePlugin(pluginManager)
135+
staticPluginInitializers = [
136+
SWBAndroidPlatform.initializePlugin,
137+
SWBApplePlatform.initializePlugin,
138+
SWBGenericUnixPlatform.initializePlugin,
139+
SWBQNXPlatform.initializePlugin,
140+
SWBUniversalPlatform.initializePlugin,
141+
SWBWebAssemblyPlatform.initializePlugin,
142+
SWBWindowsPlatform.initializePlugin,
143+
]
139144
#else
140-
// Otherwise, load the normal plugins.
141-
if let pluginsDirectory {
142-
let pluginsPath = try pluginsDirectory.filePath
143-
pluginManager.load(at: pluginsPath)
144-
for subpath in (try? localFS.listdir(pluginsPath).sorted().map({ pluginsPath.join($0) })) ?? [] {
145-
if localFS.isDirectory(subpath) {
146-
pluginManager.load(at: subpath)
145+
staticPluginInitializers = []
146+
#endif
147+
148+
if useStaticPluginInitialization {
149+
// Statically initialize the plugins.
150+
staticPluginInitializers.forEach { $0(pluginManager) }
151+
} else {
152+
// Otherwise, load the normal plugins.
153+
if let pluginsDirectory {
154+
let pluginsPath = try pluginsDirectory.filePath
155+
pluginManager.load(at: pluginsPath)
156+
for subpath in (try? localFS.listdir(pluginsPath).sorted().map({ pluginsPath.join($0) })) ?? [] {
157+
if localFS.isDirectory(subpath) {
158+
pluginManager.load(at: subpath)
159+
}
147160
}
148161
}
149162
}
150-
#endif
151163

152164
return pluginManager
153165
}()

Sources/SWBCore/Core.swift

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ public final class Core: Sendable {
5151
return nil
5252
}
5353

54-
#if USE_STATIC_PLUGIN_INITIALIZATION
55-
// In a package context, plugins are statically linked into the build system.
56-
// Load specs from service plugins if requested since we don't have a Service in certain tests
57-
// Here we don't have access to `core.pluginPaths` like we do in the call below,
58-
// but it doesn't matter because it will return an empty array when USE_STATIC_PLUGIN_INITIALIZATION is defined.
59-
await extraPluginRegistration(pluginManager, [])
60-
#endif
54+
if useStaticPluginInitialization {
55+
// In a package context, plugins are statically linked into the build system.
56+
// Load specs from service plugins if requested since we don't have a Service in certain tests
57+
// Here we don't have access to `core.pluginPaths` like we do in the call below,
58+
// but it doesn't matter because `core.pluginPaths` will return an empty array when USE_STATIC_PLUGIN_INITIALIZATION is defined.
59+
await extraPluginRegistration(pluginManager, [])
60+
}
6161

6262
let resolvedDeveloperPath: DeveloperPath
6363
do {
@@ -81,6 +81,12 @@ public final class Core: Sendable {
8181
return nil
8282
}
8383

84+
if !useStaticPluginInitialization {
85+
// In a package context, plugins are statically linked into the build system.
86+
// Load specs from service plugins if requested since we don't have a Service in certain tests.
87+
await extraPluginRegistration(pluginManager, Self.pluginPaths(inferiorProductsPath: inferiorProductsPath, developerPath: resolvedDeveloperPath))
88+
}
89+
8490
let core: Core
8591
do {
8692
core = try await Core(delegate: delegate, hostOperatingSystem: hostOperatingSystem, pluginManager: pluginManager.finalize(), developerPath: resolvedDeveloperPath, resourceSearchPaths: resourceSearchPaths, inferiorProductsPath: inferiorProductsPath, additionalContentPaths: additionalContentPaths, environment: environment, buildServiceModTime: buildServiceModTime, connectionMode: connectionMode)
@@ -103,12 +109,6 @@ public final class Core: Sendable {
103109
}
104110
}
105111

106-
#if !USE_STATIC_PLUGIN_INITIALIZATION
107-
// In a package context, plugins are statically linked into the build system.
108-
// Load specs from service plugins if requested since we don't have a Service in certain tests
109-
await extraPluginRegistration(core.pluginManager, core.pluginPaths)
110-
#endif
111-
112112
await core.initializeSpecRegistry()
113113

114114
await core.initializePlatformRegistry()
@@ -313,19 +313,19 @@ public final class Core: Sendable {
313313
}()
314314

315315
/// The list of plugin search paths.
316-
@_spi(Testing) public lazy var pluginPaths: [Path] = {
317-
#if USE_STATIC_PLUGIN_INITIALIZATION
318-
// In a package context, plugins are statically linked into the build system.
319-
return []
320-
#else
316+
private static func pluginPaths(inferiorProductsPath: Path?, developerPath: DeveloperPath) -> [Path] {
317+
if useStaticPluginInitialization {
318+
// In a package context, plugins are statically linked into the build system.
319+
return []
320+
}
321321

322322
var result = [Path]()
323323

324324
// If we are inferior, then search the built products directory first.
325325
//
326326
// FIXME: This is error prone, as it won't validate that any of these are installed in the expected location.
327327
// FIXME: If we remove, move or rename something in the built Xcode, then this will still find the old item in the installed Xcode.
328-
if let inferiorProductsPath = self.inferiorProductsPath {
328+
if let inferiorProductsPath {
329329
result.append(inferiorProductsPath)
330330
}
331331

@@ -359,8 +359,7 @@ public final class Core: Sendable {
359359
}
360360

361361
return result.map { $0.normalize() }
362-
#endif
363-
}()
362+
}
364363

365364
/// The list of SDK search paths.
366365
@_spi(Testing) public lazy var sdkPaths: [(Path, Platform?)] = {

Sources/SWBGenericUnixPlatform/Plugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public import SWBUtil
1414
import SWBCore
1515
import Foundation
1616

17-
@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) {
17+
public let initializePlugin: PluginInitializationFunction = { manager in
1818
let plugin = GenericUnixPlugin()
1919
manager.register(GenericUnixDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self)
2020
manager.register(GenericUnixPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)

Sources/SWBQNXPlatform/Plugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import SWBCore
1515
import SWBMacro
1616
import Foundation
1717

18-
@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) {
18+
public let initializePlugin: PluginInitializationFunction = { manager in
1919
let plugin = QNXPlugin()
2020
manager.register(QNXPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
2121
manager.register(QNXEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self)

Sources/SWBTestSupport/CoreTestSupport.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -140,30 +140,30 @@ extension Core {
140140
pluginManager.load(at: path)
141141
}
142142

143+
let staticPluginInitializers: [String: PluginInitializationFunction]
144+
145+
// This MUST be a compile-time check because the module dependencies on the plugins are conditional.
146+
// Minimize the amount of code that is conditionally compiled to avoid breaking the build during refactoring.
143147
#if USE_STATIC_PLUGIN_INITIALIZATION
144-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBAndroidPlatformPlugin") {
145-
SWBAndroidPlatform.initializePlugin(pluginManager)
146-
}
147-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBApplePlatformPlugin") {
148-
SWBApplePlatform.initializePlugin(pluginManager)
149-
}
150-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBGenericUnixPlatformPlugin") {
151-
SWBGenericUnixPlatform.initializePlugin(pluginManager)
152-
}
153-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBQNXPlatformPlugin") {
154-
SWBQNXPlatform.initializePlugin(pluginManager)
155-
}
156-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBUniversalPlatformPlugin") {
157-
SWBUniversalPlatform.initializePlugin(pluginManager)
158-
}
159-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBWebAssemblyPlatformPlugin") {
160-
SWBWebAssemblyPlatform.initializePlugin(pluginManager)
161-
}
162-
if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBWindowsPlatformPlugin") {
163-
SWBWindowsPlatform.initializePlugin(pluginManager)
164-
}
148+
staticPluginInitializers = [
149+
"Android": SWBAndroidPlatform.initializePlugin,
150+
"Apple": SWBApplePlatform.initializePlugin,
151+
"GenericUnix": SWBGenericUnixPlatform.initializePlugin,
152+
"QNX": SWBQNXPlatform.initializePlugin,
153+
"Universal": SWBUniversalPlatform.initializePlugin,
154+
"WebAssembly": SWBWebAssemblyPlatform.initializePlugin,
155+
"Windows": SWBWindowsPlatform.initializePlugin,
156+
]
157+
#else
158+
staticPluginInitializers = [:]
165159
#endif
166160

161+
if useStaticPluginInitialization {
162+
for (infix, initializer) in staticPluginInitializers where !skipLoadingPluginsNamed.contains("com.apple.dt.SWB\(infix)PlatformPlugin") {
163+
initializer(pluginManager)
164+
}
165+
}
166+
167167
registerExtraPlugins(pluginManager)
168168
}
169169

Sources/SWBUniversalPlatform/Plugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import Foundation
1616
import SWBTaskConstruction
1717
import SWBTaskExecution
1818

19-
@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) {
19+
public let initializePlugin: PluginInitializationFunction = { manager in
2020
manager.register(UniversalPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
2121
manager.register(UniversalPlatformTaskProducerExtension(), type: TaskProducerExtensionPoint.self)
2222
manager.register(UniversalPlatformTaskActionExtension(), type: TaskActionExtensionPoint.self)

Sources/SWBUtil/PluginManager.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,13 @@ private final class ImmutablePluginManager: Sendable, PluginManager {
221221
}
222222
}
223223
}
224+
225+
public typealias PluginInitializationFunction = @Sendable @PluginExtensionSystemActor (_ manager: MutablePluginManager) -> ()
226+
227+
public var useStaticPluginInitialization: Bool {
228+
#if USE_STATIC_PLUGIN_INITIALIZATION
229+
true
230+
#else
231+
false
232+
#endif
233+
}

Sources/SWBWebAssemblyPlatform/Plugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import SWBCore
1515
import SWBMacro
1616
import Foundation
1717

18-
@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) {
18+
public let initializePlugin: PluginInitializationFunction = { manager in
1919
manager.register(WebAssemblyPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
2020
manager.register(WebAssemblyPlatformExtension(), type: PlatformInfoExtensionPoint.self)
2121
manager.register(WebAssemblySDKRegistryExtension(), type: SDKRegistryExtensionPoint.self)

0 commit comments

Comments
 (0)