diff --git a/Sources/SWBAndroidPlatform/Plugin.swift b/Sources/SWBAndroidPlatform/Plugin.swift index 54c65090..87d0bee1 100644 --- a/Sources/SWBAndroidPlatform/Plugin.swift +++ b/Sources/SWBAndroidPlatform/Plugin.swift @@ -15,7 +15,7 @@ public import SWBCore import SWBMacro import Foundation -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in let plugin = AndroidPlugin() manager.register(AndroidPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(AndroidEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self) diff --git a/Sources/SWBApplePlatform/Plugin.swift b/Sources/SWBApplePlatform/Plugin.swift index 06476374..88527fec 100644 --- a/Sources/SWBApplePlatform/Plugin.swift +++ b/Sources/SWBApplePlatform/Plugin.swift @@ -17,7 +17,7 @@ import SWBProtocol import Foundation import SWBTaskConstruction -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in manager.register(AppleDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(ApplePlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(ActoolInputFileGroupingStrategyExtension(), type: InputFileGroupingStrategyExtensionPoint.self) diff --git a/Sources/SWBBuildService/BuildServiceEntryPoint.swift b/Sources/SWBBuildService/BuildServiceEntryPoint.swift index ee0c10c3..6c348dfa 100644 --- a/Sources/SWBBuildService/BuildServiceEntryPoint.swift +++ b/Sources/SWBBuildService/BuildServiceEntryPoint.swift @@ -127,27 +127,39 @@ extension BuildService { pluginManager.register(BuiltinTaskActionsExtension(), type: TaskActionExtensionPoint.self) + let staticPluginInitializers: [PluginInitializationFunction] + + // This MUST be a compile-time check because the module dependencies on the plugins are conditional. + // Minimize the amount of code that is conditionally compiled to avoid breaking the build during refactoring. #if USE_STATIC_PLUGIN_INITIALIZATION - // Statically initialize the plugins. - SWBAndroidPlatform.initializePlugin(pluginManager) - SWBApplePlatform.initializePlugin(pluginManager) - SWBGenericUnixPlatform.initializePlugin(pluginManager) - SWBQNXPlatform.initializePlugin(pluginManager) - SWBUniversalPlatform.initializePlugin(pluginManager) - SWBWebAssemblyPlatform.initializePlugin(pluginManager) - SWBWindowsPlatform.initializePlugin(pluginManager) + staticPluginInitializers = [ + SWBAndroidPlatform.initializePlugin, + SWBApplePlatform.initializePlugin, + SWBGenericUnixPlatform.initializePlugin, + SWBQNXPlatform.initializePlugin, + SWBUniversalPlatform.initializePlugin, + SWBWebAssemblyPlatform.initializePlugin, + SWBWindowsPlatform.initializePlugin, + ] #else - // Otherwise, load the normal plugins. - if let pluginsDirectory { - let pluginsPath = try pluginsDirectory.filePath - pluginManager.load(at: pluginsPath) - for subpath in (try? localFS.listdir(pluginsPath).sorted().map({ pluginsPath.join($0) })) ?? [] { - if localFS.isDirectory(subpath) { - pluginManager.load(at: subpath) + staticPluginInitializers = [] + #endif + + if useStaticPluginInitialization { + // Statically initialize the plugins. + staticPluginInitializers.forEach { $0(pluginManager) } + } else { + // Otherwise, load the normal plugins. + if let pluginsDirectory { + let pluginsPath = try pluginsDirectory.filePath + pluginManager.load(at: pluginsPath) + for subpath in (try? localFS.listdir(pluginsPath).sorted().map({ pluginsPath.join($0) })) ?? [] { + if localFS.isDirectory(subpath) { + pluginManager.load(at: subpath) + } } } } - #endif return pluginManager }() diff --git a/Sources/SWBCore/Core.swift b/Sources/SWBCore/Core.swift index 352ac806..4b6e59bb 100644 --- a/Sources/SWBCore/Core.swift +++ b/Sources/SWBCore/Core.swift @@ -51,13 +51,13 @@ public final class Core: Sendable { return nil } - #if USE_STATIC_PLUGIN_INITIALIZATION - // In a package context, plugins are statically linked into the build system. - // Load specs from service plugins if requested since we don't have a Service in certain tests - // Here we don't have access to `core.pluginPaths` like we do in the call below, - // but it doesn't matter because it will return an empty array when USE_STATIC_PLUGIN_INITIALIZATION is defined. - await extraPluginRegistration(pluginManager, []) - #endif + if useStaticPluginInitialization { + // In a package context, plugins are statically linked into the build system. + // Load specs from service plugins if requested since we don't have a Service in certain tests + // Here we don't have access to `core.pluginPaths` like we do in the call below, + // but it doesn't matter because `core.pluginPaths` will return an empty array when USE_STATIC_PLUGIN_INITIALIZATION is defined. + await extraPluginRegistration(pluginManager, []) + } let resolvedDeveloperPath: DeveloperPath do { @@ -81,6 +81,12 @@ public final class Core: Sendable { return nil } + if !useStaticPluginInitialization { + // In a package context, plugins are statically linked into the build system. + // Load specs from service plugins if requested since we don't have a Service in certain tests. + await extraPluginRegistration(pluginManager, Self.pluginPaths(inferiorProductsPath: inferiorProductsPath, developerPath: resolvedDeveloperPath)) + } + let core: Core do { 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 { } } - #if !USE_STATIC_PLUGIN_INITIALIZATION - // In a package context, plugins are statically linked into the build system. - // Load specs from service plugins if requested since we don't have a Service in certain tests - await extraPluginRegistration(core.pluginManager, core.pluginPaths) - #endif - await core.initializeSpecRegistry() await core.initializePlatformRegistry() @@ -313,11 +313,11 @@ public final class Core: Sendable { }() /// The list of plugin search paths. - @_spi(Testing) public lazy var pluginPaths: [Path] = { - #if USE_STATIC_PLUGIN_INITIALIZATION - // In a package context, plugins are statically linked into the build system. - return [] - #else + private static func pluginPaths(inferiorProductsPath: Path?, developerPath: DeveloperPath) -> [Path] { + if useStaticPluginInitialization { + // In a package context, plugins are statically linked into the build system. + return [] + } var result = [Path]() @@ -325,7 +325,7 @@ public final class Core: Sendable { // // FIXME: This is error prone, as it won't validate that any of these are installed in the expected location. // FIXME: If we remove, move or rename something in the built Xcode, then this will still find the old item in the installed Xcode. - if let inferiorProductsPath = self.inferiorProductsPath { + if let inferiorProductsPath { result.append(inferiorProductsPath) } @@ -359,8 +359,7 @@ public final class Core: Sendable { } return result.map { $0.normalize() } - #endif - }() + } /// The list of SDK search paths. @_spi(Testing) public lazy var sdkPaths: [(Path, Platform?)] = { diff --git a/Sources/SWBGenericUnixPlatform/Plugin.swift b/Sources/SWBGenericUnixPlatform/Plugin.swift index f674a4ef..04f5a458 100644 --- a/Sources/SWBGenericUnixPlatform/Plugin.swift +++ b/Sources/SWBGenericUnixPlatform/Plugin.swift @@ -14,7 +14,7 @@ public import SWBUtil import SWBCore import Foundation -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in let plugin = GenericUnixPlugin() manager.register(GenericUnixDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(GenericUnixPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) diff --git a/Sources/SWBQNXPlatform/Plugin.swift b/Sources/SWBQNXPlatform/Plugin.swift index 6e279cf7..dda0cc25 100644 --- a/Sources/SWBQNXPlatform/Plugin.swift +++ b/Sources/SWBQNXPlatform/Plugin.swift @@ -15,7 +15,7 @@ import SWBCore import SWBMacro import Foundation -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in let plugin = QNXPlugin() manager.register(QNXPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(QNXEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self) diff --git a/Sources/SWBTestSupport/CoreTestSupport.swift b/Sources/SWBTestSupport/CoreTestSupport.swift index bf0301fc..28576f3a 100644 --- a/Sources/SWBTestSupport/CoreTestSupport.swift +++ b/Sources/SWBTestSupport/CoreTestSupport.swift @@ -140,30 +140,30 @@ extension Core { pluginManager.load(at: path) } + let staticPluginInitializers: [String: PluginInitializationFunction] + + // This MUST be a compile-time check because the module dependencies on the plugins are conditional. + // Minimize the amount of code that is conditionally compiled to avoid breaking the build during refactoring. #if USE_STATIC_PLUGIN_INITIALIZATION - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBAndroidPlatformPlugin") { - SWBAndroidPlatform.initializePlugin(pluginManager) - } - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBApplePlatformPlugin") { - SWBApplePlatform.initializePlugin(pluginManager) - } - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBGenericUnixPlatformPlugin") { - SWBGenericUnixPlatform.initializePlugin(pluginManager) - } - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBQNXPlatformPlugin") { - SWBQNXPlatform.initializePlugin(pluginManager) - } - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBUniversalPlatformPlugin") { - SWBUniversalPlatform.initializePlugin(pluginManager) - } - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBWebAssemblyPlatformPlugin") { - SWBWebAssemblyPlatform.initializePlugin(pluginManager) - } - if !skipLoadingPluginsNamed.contains("com.apple.dt.SWBWindowsPlatformPlugin") { - SWBWindowsPlatform.initializePlugin(pluginManager) - } + staticPluginInitializers = [ + "Android": SWBAndroidPlatform.initializePlugin, + "Apple": SWBApplePlatform.initializePlugin, + "GenericUnix": SWBGenericUnixPlatform.initializePlugin, + "QNX": SWBQNXPlatform.initializePlugin, + "Universal": SWBUniversalPlatform.initializePlugin, + "WebAssembly": SWBWebAssemblyPlatform.initializePlugin, + "Windows": SWBWindowsPlatform.initializePlugin, + ] + #else + staticPluginInitializers = [:] #endif + if useStaticPluginInitialization { + for (infix, initializer) in staticPluginInitializers where !skipLoadingPluginsNamed.contains("com.apple.dt.SWB\(infix)PlatformPlugin") { + initializer(pluginManager) + } + } + registerExtraPlugins(pluginManager) } diff --git a/Sources/SWBUniversalPlatform/Plugin.swift b/Sources/SWBUniversalPlatform/Plugin.swift index abf9dd3c..66dce209 100644 --- a/Sources/SWBUniversalPlatform/Plugin.swift +++ b/Sources/SWBUniversalPlatform/Plugin.swift @@ -16,7 +16,7 @@ import Foundation import SWBTaskConstruction import SWBTaskExecution -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in manager.register(UniversalPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(UniversalPlatformTaskProducerExtension(), type: TaskProducerExtensionPoint.self) manager.register(UniversalPlatformTaskActionExtension(), type: TaskActionExtensionPoint.self) diff --git a/Sources/SWBUtil/PluginManager.swift b/Sources/SWBUtil/PluginManager.swift index af65a972..98e7d387 100644 --- a/Sources/SWBUtil/PluginManager.swift +++ b/Sources/SWBUtil/PluginManager.swift @@ -221,3 +221,13 @@ private final class ImmutablePluginManager: Sendable, PluginManager { } } } + +public typealias PluginInitializationFunction = @Sendable @PluginExtensionSystemActor (_ manager: MutablePluginManager) -> () + +public var useStaticPluginInitialization: Bool { + #if USE_STATIC_PLUGIN_INITIALIZATION + true + #else + false + #endif +} diff --git a/Sources/SWBWebAssemblyPlatform/Plugin.swift b/Sources/SWBWebAssemblyPlatform/Plugin.swift index 287d54e9..a68bc774 100644 --- a/Sources/SWBWebAssemblyPlatform/Plugin.swift +++ b/Sources/SWBWebAssemblyPlatform/Plugin.swift @@ -15,7 +15,7 @@ import SWBCore import SWBMacro import Foundation -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in manager.register(WebAssemblyPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(WebAssemblyPlatformExtension(), type: PlatformInfoExtensionPoint.self) manager.register(WebAssemblySDKRegistryExtension(), type: SDKRegistryExtensionPoint.self) diff --git a/Sources/SWBWindowsPlatform/Plugin.swift b/Sources/SWBWindowsPlatform/Plugin.swift index d80b7fb1..bb287a85 100644 --- a/Sources/SWBWindowsPlatform/Plugin.swift +++ b/Sources/SWBWindowsPlatform/Plugin.swift @@ -14,7 +14,7 @@ public import SWBUtil public import SWBCore import Foundation -@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { +public let initializePlugin: PluginInitializationFunction = { manager in let plugin = WindowsPlugin() manager.register(WindowsDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(WindowsPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)