diff --git a/Package.swift b/Package.swift index 99730240..9e498086 100644 --- a/Package.swift +++ b/Package.swift @@ -209,7 +209,7 @@ let package = Package( .product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .openbsd, .android, .windows, .custom("freebsd")])), ], exclude: ["CMakeLists.txt"], - swiftSettings: swiftSettings(languageMode: .v5)), + swiftSettings: swiftSettings(languageMode: .v6)), .target( name: "SWBCAS", dependencies: ["SWBUtil", "SWBCSupport"], diff --git a/Sources/SWBAndroidPlatform/Plugin.swift b/Sources/SWBAndroidPlatform/Plugin.swift index 0f1efa1c..54c65090 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { let plugin = AndroidPlugin() manager.register(AndroidPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(AndroidEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self) diff --git a/Sources/SWBAndroidPlatformPlugin/PluginMain.swift b/Sources/SWBAndroidPlatformPlugin/PluginMain.swift index b6ae6c3b..935214bd 100644 --- a/Sources/SWBAndroidPlatformPlugin/PluginMain.swift +++ b/Sources/SWBAndroidPlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBAndroidPlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Sources/SWBApplePlatform/Plugin.swift b/Sources/SWBApplePlatform/Plugin.swift index ae11f5c7..06476374 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { manager.register(AppleDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(ApplePlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(ActoolInputFileGroupingStrategyExtension(), type: InputFileGroupingStrategyExtensionPoint.self) diff --git a/Sources/SWBApplePlatformPlugin/PluginMain.swift b/Sources/SWBApplePlatformPlugin/PluginMain.swift index 0cd92ef6..095e34cb 100644 --- a/Sources/SWBApplePlatformPlugin/PluginMain.swift +++ b/Sources/SWBApplePlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBApplePlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Sources/SWBBuildService/BuildServiceEntryPoint.swift b/Sources/SWBBuildService/BuildServiceEntryPoint.swift index 6614cf42..ee0c10c3 100644 --- a/Sources/SWBBuildService/BuildServiceEntryPoint.swift +++ b/Sources/SWBBuildService/BuildServiceEntryPoint.swift @@ -97,7 +97,7 @@ extension BuildService { fileprivate static func run(inputFD: FileDescriptor, outputFD: FileDescriptor, connectionMode: ServiceHostConnectionMode, pluginsDirectory: URL?, arguments: [String], pluginLoadingFinished: () throws -> Void) async throws { let pluginManager = try await { @PluginExtensionSystemActor () async throws in // Create the plugin manager and load plugins. - let pluginManager = PluginManager(skipLoadingPluginIdentifiers: []) + let pluginManager = MutablePluginManager(skipLoadingPluginIdentifiers: []) // Register plugin extension points. pluginManager.registerExtensionPoint(ServiceExtensionPoint()) diff --git a/Sources/SWBBuildSystem/BuildOperationExtension.swift b/Sources/SWBBuildSystem/BuildOperationExtension.swift index 4753e1b6..9bca060d 100644 --- a/Sources/SWBBuildSystem/BuildOperationExtension.swift +++ b/Sources/SWBBuildSystem/BuildOperationExtension.swift @@ -23,7 +23,7 @@ package struct BuildOperationExtensionPoint: ExtensionPoint { // MARK: - actual extension point - package static func additionalEnvironmentVariables(pluginManager: PluginManager, fromEnvironment: @autoclosure () -> [String: String], parameters: @autoclosure () -> BuildParameters) throws -> [String: String] { + package static func additionalEnvironmentVariables(pluginManager: any PluginManager, fromEnvironment: @autoclosure () -> [String: String], parameters: @autoclosure () -> BuildParameters) throws -> [String: String] { let (fromEnvironment, parameters) = (fromEnvironment(), parameters()) return try pluginManager.extensions(of: Self.self).reduce([:], { environment, ext in try environment.addingContents(of: ext.additionalEnvironmentVariables(fromEnvironment: fromEnvironment, parameters: parameters)) diff --git a/Sources/SWBCLibc/include/SWBCLibc.h b/Sources/SWBCLibc/include/SWBCLibc.h index 5d58842f..acb0031b 100644 --- a/Sources/SWBCLibc/include/SWBCLibc.h +++ b/Sources/SWBCLibc/include/SWBCLibc.h @@ -10,6 +10,11 @@ // //===----------------------------------------------------------------------===// +#include + +extern FILE * const swb_stdout(); +extern FILE * const swb_stderr(); + #if defined(__linux__) && !defined(__ANDROID__) #include #include diff --git a/Sources/SWBCLibc/libc.c b/Sources/SWBCLibc/libc.c index c1b0d3a8..8ffe85f4 100644 --- a/Sources/SWBCLibc/libc.c +++ b/Sources/SWBCLibc/libc.c @@ -18,3 +18,16 @@ int swb_clibc_anchor(void); int swb_clibc_anchor(void) { return 0; } + +#include + +extern FILE * const swb_stdout(); +extern FILE * const swb_stderr(); + +FILE * const swb_stdout() { + return stdout; +} + +FILE * const swb_stderr() { + return stderr; +} diff --git a/Sources/SWBCore/Core.swift b/Sources/SWBCore/Core.swift index 1f61258e..352ac806 100644 --- a/Sources/SWBCore/Core.swift +++ b/Sources/SWBCore/Core.swift @@ -40,9 +40,9 @@ public final class Core: Sendable { /// Get a configured instance of the core. /// /// - returns: An initialized Core instance on which all discovery and loading will have been completed. If there are errors during that process, they will be logged to `stderr` and no instance will be returned. Otherwise, the initialized object is returned. - public static func getInitializedCore(_ delegate: any CoreDelegate, pluginManager: PluginManager, developerPath: DeveloperPath? = nil, resourceSearchPaths: [Path] = [], inferiorProductsPath: Path? = nil, extraPluginRegistration: @PluginExtensionSystemActor (_ pluginPaths: [Path]) -> Void = { _ in }, additionalContentPaths: [Path] = [], environment: [String:String] = [:], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async -> Core? { + public static func getInitializedCore(_ delegate: any CoreDelegate, pluginManager: MutablePluginManager, developerPath: DeveloperPath? = nil, resourceSearchPaths: [Path] = [], inferiorProductsPath: Path? = nil, extraPluginRegistration: @PluginExtensionSystemActor (_ pluginManager: MutablePluginManager, _ pluginPaths: [Path]) -> Void = { _, _ in }, additionalContentPaths: [Path] = [], environment: [String:String] = [:], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async -> Core? { // Enable macro expression interning during loading. - return await MacroNamespace.withExpressionInterningEnabled { + return await MacroNamespace.withExpressionInterningEnabled { () -> Core? in let hostOperatingSystem: OperatingSystem do { hostOperatingSystem = try ProcessInfo.processInfo.hostOperatingSystem() @@ -56,7 +56,7 @@ public final class Core: Sendable { // 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([]) + await extraPluginRegistration(pluginManager, []) #endif let resolvedDeveloperPath: DeveloperPath @@ -83,20 +83,20 @@ public final class Core: Sendable { let core: Core do { - core = try await Core(delegate: delegate, hostOperatingSystem: hostOperatingSystem, pluginManager: pluginManager, developerPath: resolvedDeveloperPath, resourceSearchPaths: resourceSearchPaths, inferiorProductsPath: inferiorProductsPath, additionalContentPaths: additionalContentPaths, environment: environment, buildServiceModTime: buildServiceModTime, connectionMode: connectionMode) + 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) } catch { delegate.error("\(error)") return nil } if UserDefaults.enablePluginManagerLogging { - let plugins = await core.pluginManager.pluginsByIdentifier + let plugins = core.pluginManager.pluginsByIdentifier delegate.emit(Diagnostic(behavior: .note, location: .unknown, data: DiagnosticData("Loaded \(plugins.count) plugins"), childDiagnostics: plugins.sorted(byKey: <).map { (identifier, plugin) in Diagnostic(behavior: .note, location: .path(plugin.path), data: DiagnosticData("Loaded plugin: \(identifier) from \(plugin.path.str)")) })) } - for diagnostic in await core.pluginManager.loadingDiagnostics { + for diagnostic in core.pluginManager.loadingDiagnostics { // Only emit "severe" diagnostics (warning, error) from the plugin manager if the logging dwrite isn't set. if UserDefaults.enablePluginManagerLogging || [.error, .warning].contains(diagnostic.behavior) { delegate.emit(diagnostic) @@ -106,7 +106,7 @@ 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.pluginPaths) + await extraPluginRegistration(core.pluginManager, core.pluginPaths) #endif await core.initializeSpecRegistry() @@ -167,7 +167,7 @@ public final class Core: Sendable { /// The host operating system. public let hostOperatingSystem: OperatingSystem - public let pluginManager: PluginManager + public let pluginManager: any PluginManager public enum DeveloperPath: Sendable, Hashable { // A path to an Xcode install's "/Contents/Developer" directory @@ -220,7 +220,7 @@ public final class Core: Sendable { public let connectionMode: ServiceHostConnectionMode - @_spi(Testing) public init(delegate: any CoreDelegate, hostOperatingSystem: OperatingSystem, pluginManager: PluginManager, developerPath: DeveloperPath, resourceSearchPaths: [Path], inferiorProductsPath: Path?, additionalContentPaths: [Path], environment: [String:String], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async throws { + @_spi(Testing) public init(delegate: any CoreDelegate, hostOperatingSystem: OperatingSystem, pluginManager: any PluginManager, developerPath: DeveloperPath, resourceSearchPaths: [Path], inferiorProductsPath: Path?, additionalContentPaths: [Path], environment: [String:String], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async throws { self.delegate = delegate self.hostOperatingSystem = hostOperatingSystem self.pluginManager = pluginManager @@ -739,7 +739,7 @@ struct CoreRegistryDelegate : PlatformRegistryDelegate, SDKRegistryDelegate, Spe return specRegistry.internalMacroNamespace } - var pluginManager: PluginManager { + var pluginManager: any PluginManager { core.pluginManager } diff --git a/Sources/SWBCore/DependencyResolution.swift b/Sources/SWBCore/DependencyResolution.swift index ccad7d11..fbbcdf96 100644 --- a/Sources/SWBCore/DependencyResolution.swift +++ b/Sources/SWBCore/DependencyResolution.swift @@ -96,10 +96,7 @@ struct SpecializationParameters: Hashable, CustomStringConvertible { BuiltinMacros.TOOLCHAINS.name, BuiltinMacros.SWIFT_ENABLE_COMPILE_CACHE.name, ] - @preconcurrency @PluginExtensionSystemActor func sdkVariantInfoExtensions() -> [any SDKVariantInfoExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) - } - for sdkVariantInfoExtension in sdkVariantInfoExtensions() { + for sdkVariantInfoExtension in core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) { macros.formUnion(sdkVariantInfoExtension.supportsMacCatalystMacroNames) } return macros diff --git a/Sources/SWBCore/Extensions/EnvironmentExtension.swift b/Sources/SWBCore/Extensions/EnvironmentExtension.swift index 99ba0da3..db2b2054 100644 --- a/Sources/SWBCore/Extensions/EnvironmentExtension.swift +++ b/Sources/SWBCore/Extensions/EnvironmentExtension.swift @@ -22,7 +22,7 @@ public struct EnvironmentExtensionPoint: ExtensionPoint { // MARK: - actual extension point - public static func additionalEnvironmentVariables(pluginManager: PluginManager, context: any EnvironmentExtensionAdditionalEnvironmentVariablesContext) async throws -> [String: String] { + public static func additionalEnvironmentVariables(pluginManager: any PluginManager, context: any EnvironmentExtensionAdditionalEnvironmentVariablesContext) async throws -> [String: String] { var env: [String: String] = [:] for ext in pluginManager.extensions(of: Self.self) { try await env.merge(ext.additionalEnvironmentVariables(context: context), uniquingKeysWith: { _, new in new }) diff --git a/Sources/SWBCore/Extensions/SpecificationsExtension.swift b/Sources/SWBCore/Extensions/SpecificationsExtension.swift index 827da3d6..55ec3ff8 100644 --- a/Sources/SWBCore/Extensions/SpecificationsExtension.swift +++ b/Sources/SWBCore/Extensions/SpecificationsExtension.swift @@ -23,25 +23,25 @@ public struct SpecificationsExtensionPoint: ExtensionPoint { // MARK: - actual extension point - public static func specificationTypes(pluginManager: PluginManager) -> [any SpecType.Type] { + public static func specificationTypes(pluginManager: any PluginManager) -> [any SpecType.Type] { return pluginManager.extensions(of: Self.self).reduce([]) { specs, ext in specs.appending(contentsOf: ext.specificationTypes()) } } - public static func specificationClasses(pluginManager: PluginManager) -> [any SpecIdentifierType.Type] { + public static func specificationClasses(pluginManager: any PluginManager) -> [any SpecIdentifierType.Type] { return pluginManager.extensions(of: Self.self).reduce([]) { specs, ext in specs.appending(contentsOf: ext.specificationClasses()) } } - public static func specificationClassesClassic(pluginManager: PluginManager) -> [any SpecClassType.Type] { + public static func specificationClassesClassic(pluginManager: any PluginManager) -> [any SpecClassType.Type] { return pluginManager.extensions(of: Self.self).reduce([]) { specs, ext in specs.appending(contentsOf: ext.specificationClassesClassic()) } } - public static func specificationImplementations(pluginManager: PluginManager) -> [any SpecImplementationType.Type] { + public static func specificationImplementations(pluginManager: any PluginManager) -> [any SpecImplementationType.Type] { return pluginManager.extensions(of: Self.self).reduce([]) { specs, ext in specs.appending(contentsOf: ext.specificationImplementations()) } diff --git a/Sources/SWBCore/PlatformRegistry.swift b/Sources/SWBCore/PlatformRegistry.swift index 9aefcffa..d2b6a792 100644 --- a/Sources/SWBCore/PlatformRegistry.swift +++ b/Sources/SWBCore/PlatformRegistry.swift @@ -19,7 +19,7 @@ public import SWBMacro /// Delegate protocol used to access external information (such as specifications) and to report diagnostics. @_spi(Testing) public protocol PlatformRegistryDelegate: DiagnosticProducingDelegate, SpecRegistryProvider { - var pluginManager: PluginManager { get } + var pluginManager: any PluginManager { get } var developerPath: Core.DeveloperPath { get } } @@ -359,7 +359,7 @@ public final class PlatformRegistry { await registerPlatformsInDirectory(path, fs) } - @preconcurrency @PluginExtensionSystemActor func platformInfoExtensions() async -> [any PlatformInfoExtensionPoint.ExtensionProtocol] { + @PluginExtensionSystemActor func platformInfoExtensions() async -> [any PlatformInfoExtensionPoint.ExtensionProtocol] { return delegate.pluginManager.extensions(of: PlatformInfoExtensionPoint.self) } @@ -562,7 +562,7 @@ public final class PlatformRegistry { return values.only }() - @preconcurrency @PluginExtensionSystemActor func platformInfoExtensions() -> [any PlatformInfoExtensionPoint.ExtensionProtocol] { + @PluginExtensionSystemActor func platformInfoExtensions() -> [any PlatformInfoExtensionPoint.ExtensionProtocol] { delegate.pluginManager.extensions(of: PlatformInfoExtensionPoint.self) } diff --git a/Sources/SWBCore/SDKRegistry.swift b/Sources/SWBCore/SDKRegistry.swift index 67cb0898..399d0fc5 100644 --- a/Sources/SWBCore/SDKRegistry.swift +++ b/Sources/SWBCore/SDKRegistry.swift @@ -20,7 +20,7 @@ public import SWBMacro /// The namespace to parse macros into. var namespace: MacroNamespace { get } - var pluginManager: PluginManager { get } + var pluginManager: any PluginManager { get } var platformRegistry: PlatformRegistry? { get } } @@ -32,23 +32,20 @@ public final class SDK: Sendable { public let suffix: String? } - private static func supportedSDKCanonicalNameSuffixes(pluginManager: PluginManager) -> Set { - @preconcurrency @PluginExtensionSystemActor func extensions() -> [any SDKRegistryExtensionPoint.ExtensionProtocol] { - pluginManager.extensions(of: SDKRegistryExtensionPoint.self) - } + private static func supportedSDKCanonicalNameSuffixes(registry: SDKRegistry) -> Set { var suffixes: Set = [] - for `extension` in extensions() { + for `extension` in registry.extensions { suffixes.formUnion(`extension`.supportedSDKCanonicalNameSuffixes) } return suffixes } /// Returns the component pieces of a given `canonicalName` for an SDK. Returns `nil` if the string is does not match the canonical name format. - @_spi(Testing) public static func parseSDKName(_ sdkCanonicalName: String, pluginManager: PluginManager) throws -> CanonicalNameComponents { + @_spi(Testing) public static func parseSDKName(_ sdkCanonicalName: String, registry: SDKRegistry) throws -> CanonicalNameComponents { // Remove the suffix, if there is one. var baseAndVersion = sdkCanonicalName var suffix: String? = nil - for supportedSuffix in Self.supportedSDKCanonicalNameSuffixes(pluginManager: pluginManager).sorted() { + for supportedSuffix in Self.supportedSDKCanonicalNameSuffixes(registry: registry).sorted() { // Some SDKs use the dot for suffixes and some do not, so both are supported. if sdkCanonicalName.hasSuffix(".\(supportedSuffix)") { baseAndVersion = sdkCanonicalName.withoutSuffix(".\(supportedSuffix)") @@ -591,10 +588,12 @@ public final class SDKRegistry: SDKRegistryLookup, CustomStringConvertible, Send private func parseSDKName(_ canonicalName: String) throws -> SDK.CanonicalNameComponents { try parsedSDKNames.getOrInsert(canonicalName) { - Result { try SDK.parseSDKName(canonicalName, pluginManager: delegate.pluginManager) } + Result { try SDK.parseSDKName(canonicalName, registry: self) } }.get() } + public let extensions: [any SDKRegistryExtension] + /// The boot system SDK. // // FIXME: This doesn't belong here. @@ -607,6 +606,8 @@ public final class SDKRegistry: SDKRegistryLookup, CustomStringConvertible, Send self.type = type self.hostOperatingSystem = hostOperatingSystem + extensions = delegate.pluginManager.extensions(of: SDKRegistryExtensionPoint.self) + for (path, platform) in searchPaths { registerSDKsInDirectory(path, platform) } @@ -989,10 +990,6 @@ public final class SDKRegistry: SDKRegistryLookup, CustomStringConvertible, Send return nil } - @preconcurrency @PluginExtensionSystemActor func extensions() -> [any SDKRegistryExtensionPoint.ExtensionProtocol] { - delegate.pluginManager.extensions(of: SDKRegistryExtensionPoint.self) - } - // Construct the SDK and add it to the registry. let sdk = SDK(canonicalName, canonicalNameComponents: try? parseSDKName(canonicalName), aliases, cohortPlatforms, displayName, path, version, productBuildVersion, defaultSettings, overrideSettings, variants, defaultDeploymentTarget, defaultVariant, (headerSearchPaths, frameworkSearchPaths, librarySearchPaths), directoryMacros.elements, isBaseSDK, fallbackSettingConditionValues, toolchains, versionMap, maximumDeploymentTarget) if let duplicate = sdksByCanonicalName[canonicalName] { @@ -1237,11 +1234,8 @@ public final class SDKRegistry: SDKRegistryLookup, CustomStringConvertible, Send } func supportedSDKCanonicalNameSuffixes() -> Set { - @preconcurrency @PluginExtensionSystemActor func extensions() -> [any SDKRegistryExtensionPoint.ExtensionProtocol] { - delegate.pluginManager.extensions(of: SDKRegistryExtensionPoint.self) - } var suffixes: Set = [] - for `extension` in extensions() { + for `extension` in extensions { suffixes.formUnion(`extension`.supportedSDKCanonicalNameSuffixes) } return suffixes diff --git a/Sources/SWBCore/Settings/Settings.swift b/Sources/SWBCore/Settings/Settings.swift index 609412f1..f8b784a8 100644 --- a/Sources/SWBCore/Settings/Settings.swift +++ b/Sources/SWBCore/Settings/Settings.swift @@ -356,14 +356,10 @@ fileprivate struct PreOverridesSettings { } } - @preconcurrency @PluginExtensionSystemActor func searchPaths() -> [Path] { - core.pluginManager.extensions(of: SpecificationsExtensionPoint.self).flatMap { ext in - ext.specificationSearchPaths(resourceSearchPaths: core.resourceSearchPaths).compactMap { try? $0.filePath } - }.sorted() - } - // Add rules from the Resources directories of the loaded plugins. We sort the paths to ensure deterministic loading. - for searchPath in searchPaths() { + for searchPath in core.pluginManager.extensions(of: SpecificationsExtensionPoint.self).flatMap({ ext in + ext.specificationSearchPaths(resourceSearchPaths: core.resourceSearchPaths).compactMap { try? $0.filePath } + }).sorted() { findAndLoadBuildRules(resourcesPath: searchPath) } @@ -759,11 +755,8 @@ public final class Settings: PlatformBuildContext, Sendable { public let headerDependencies: [HeaderDependency] public static func supportsMacCatalyst(scope: MacroEvaluationScope, core: Core) -> Bool { - @preconcurrency @PluginExtensionSystemActor func sdkVariantInfoExtensions() -> [any SDKVariantInfoExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) - } var supportsMacCatalystMacros: Set = [] - for sdkVariantInfoExtension in sdkVariantInfoExtensions() { + for sdkVariantInfoExtension in core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) { supportsMacCatalystMacros.formUnion(sdkVariantInfoExtension.supportsMacCatalystMacroNames) } @@ -1003,14 +996,10 @@ extension WorkspaceContext { } } - @preconcurrency @PluginExtensionSystemActor func searchPaths() -> [Path] { - core.pluginManager.extensions(of: SpecificationsExtensionPoint.self).flatMap { ext in - ext.specificationSearchPaths(resourceSearchPaths: core.resourceSearchPaths).compactMap { try? $0.filePath } - }.sorted() - } - // Add the search paths from each loaded plugin. - paths.append(contentsOf: searchPaths()) + paths.append(contentsOf: core.pluginManager.extensions(of: SpecificationsExtensionPoint.self).flatMap { ext in + ext.specificationSearchPaths(resourceSearchPaths: core.resourceSearchPaths).compactMap { try? $0.filePath } + }.sorted()) // Add the binary paths for each toolchain. for toolchain in toolchains { @@ -1508,10 +1497,7 @@ private class SettingsBuilder { addSDKOverridingSettings(sdk, boundProperties.sdkVariant) - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { do { let overridingSettings = try settingsExtension.addSDKOverridingSettings(sdk, boundProperties.sdkVariant, boundProperties.sparseSDKs, specLookupContext: specLookupContext) pushTable(.exported) { @@ -2036,11 +2022,7 @@ private class SettingsBuilder { errors.append("Unable to determine host platform: \(error)") } - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { let baseEnvironment = workspaceContext.userInfo?.buildSystemEnvironment ?? [:] do { @@ -2633,10 +2615,7 @@ private class SettingsBuilder { } } - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { do { let additionalSettings = try settingsExtension.addSDKSettings(sdk, variant, sparseSDKs) sdkTable.pushContentsOf(createTableFromUserSettings(additionalSettings)) @@ -2657,9 +2636,7 @@ private class SettingsBuilder { table.push(BuiltinMacros.STRIP_BITCODE_FROM_COPIED_FILES, literal: true) } - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } + let settingsExtensions = core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) func shouldPopulateValidArchs(platform: Platform, sdk: SDK?) -> Bool { // For now, we only do this for some platforms to avoid behavior changes. @@ -2672,7 +2649,7 @@ private class SettingsBuilder { "xros": return false default: - for settingsExtension in settingsExtensions() { + for settingsExtension in settingsExtensions { if settingsExtension.shouldSkipPopulatingValidArchs(platform: platform, sdk: sdk) { return false } @@ -2686,7 +2663,7 @@ private class SettingsBuilder { table.push(BuiltinMacros.VALID_ARCHS, literal: archs) } - for settingsExtension in settingsExtensions() { + for settingsExtension in settingsExtensions { table.pushContentsOf(createTableFromUserSettings(settingsExtension.addPlatformSDKSettings(platform, sdk, sdkVariant))) } } @@ -2706,11 +2683,8 @@ private class SettingsBuilder { } let scope = createScope(sdkToUse: sdk) - @preconcurrency @PluginExtensionSystemActor func sdkVariantInfoExtensions() -> [any SDKVariantInfoExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) - } var macCatalystDeriveBundleIDMacros: Set = [] - for sdkVariantInfoExtension in sdkVariantInfoExtensions() { + for sdkVariantInfoExtension in core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) { macCatalystDeriveBundleIDMacros.formUnion(sdkVariantInfoExtension.macCatalystDeriveBundleIDMacroNames) } let wantsDerivedMacCatalystBundleId = macCatalystDeriveBundleIDMacros.contains { scope.evaluate(scope.namespace.parseString("$(\($0)")).boolValue } @@ -2865,11 +2839,8 @@ private class SettingsBuilder { func validateSDK(_ sdk: SDK, sdkVariant: SDKVariant?, scope: MacroEvaluationScope) { if sdkVariant?.isMacCatalyst ?? false { - @preconcurrency @PluginExtensionSystemActor func sdkVariantInfoExtensions() -> [any SDKVariantInfoExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) - } var disallowedMacCatalystMacros: Set = [] - for sdkVariantInfoExtension in sdkVariantInfoExtensions() { + for sdkVariantInfoExtension in core.pluginManager.extensions(of: SDKVariantInfoExtensionPoint.self) { disallowedMacCatalystMacros.formUnion(sdkVariantInfoExtension.disallowedMacCatalystMacroNames) } @@ -3003,11 +2974,7 @@ private class SettingsBuilder { push(productType.buildSettings, .exportedForNative) - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { push(createTableFromUserSettings(settingsExtension.addProductTypeDefaults(productType: productType)), .exportedForNative) } @@ -3089,7 +3056,7 @@ private class SettingsBuilder { if Settings.targetPlatformSpecializationEnabled(scope: scope) { // The SDK might not be known yet during the push of the target settings (especially true for top-level targets), but the usage of a suffixed SDK might be known from the macro scope. This is a side-effect of the multiple calls to `addTargetSettings()` we make during settings construction... // The `SPECIALIZATION_SDK_OPTIONS` needs to be set here, primarily so that top-level targets are handled correctly when they are specialized. Otherwise, the original intent of the SDK choice can be lost due to how the `SDKROOT` is imposed. - if let suffix = sdk?.canonicalNameSuffix?.nilIfEmpty ?? (try? SDK.parseSDKName(scope.evaluate(BuiltinMacros.SDKROOT).str, pluginManager: core.pluginManager).suffix) { + if let suffix = sdk?.canonicalNameSuffix?.nilIfEmpty ?? (try? SDK.parseSDKName(scope.evaluate(BuiltinMacros.SDKROOT).str, registry: core.sdkRegistry).suffix) { table.push(BuiltinMacros.SPECIALIZATION_SDK_OPTIONS, literal: [suffix]) } } @@ -3117,12 +3084,7 @@ private class SettingsBuilder { push(createTableFromUserSettings(parameters.commandLineOverrides), .exported) // Add in command line build settings from extensions - - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { // FIXME: We should do something better here if the environment cannot be retrieved let baseEnvironment = workspaceContext.userInfo?.buildSystemEnvironment ?? [:] @@ -3349,11 +3311,7 @@ private class SettingsBuilder { return false } - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { if settingsExtension.shouldDisableXOJITPreviews(platformName: platformName, sdk: sdk) { return false } @@ -4298,10 +4256,7 @@ private class SettingsBuilder { private func getTargetTestingSwiftPluginFlags(_ scope: MacroEvaluationScope) -> [String] { // First, query settings extensions to see if they provide their own Swift testing flags. var flags: [String] = [] - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { flags.append(contentsOf: settingsExtension.getTargetTestingSwiftPluginFlags(scope, toolchainRegistry: core.toolchainRegistry, sdkRegistry: core.sdkRegistry, activeRunDestination: parameters.activeRunDestination, project: project)) } guard flags.isEmpty else { @@ -4484,10 +4439,7 @@ private class SettingsBuilder { warnings.append(contentsOf: overrides.warnings) errors.append(contentsOf: overrides.errors) - @preconcurrency @PluginExtensionSystemActor func settingsExtensions() -> [any SettingsBuilderExtensionPoint.ExtensionProtocol] { - core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) - } - for settingsExtension in settingsExtensions() { + for settingsExtension in core.pluginManager.extensions(of: SettingsBuilderExtensionPoint.self) { let overrides = settingsExtension.overridingBuildSettings(createScope(sdkToUse: baseSDK), platform: specLookupContext.platform, productType: productType) pushTable(.exported) { $0.pushContentsOf(createTableFromUserSettings(overrides)) diff --git a/Sources/SWBCore/SpecImplementations/SpecRegistry.swift b/Sources/SWBCore/SpecImplementations/SpecRegistry.swift index c02d6f9a..b6e0164b 100644 --- a/Sources/SWBCore/SpecImplementations/SpecRegistry.swift +++ b/Sources/SWBCore/SpecImplementations/SpecRegistry.swift @@ -369,7 +369,7 @@ public final class SpecRegistry: Sendable { /// - parameter delegate: The delegate used to report diagnostics about spec loading. /// - parameter searchPaths: The list of (path, defaultDomain) tuples to search for specs. The path may be either a directory (which will be scanned for specs), or the path directly to an ".xcspec" which will be registered. In both cases, the defaultDomain specifies which domain to register the found specs in if the spec itself does not specify the domain. /// - parameter domainIncludes: The mapping of which domains include other ones. - @_spi(Testing) public init(_ pluginManager: PluginManager, _ delegate: any SpecRegistryDelegate, _ searchPaths: [(Path, String)], _ domainInclusions: [String: [String]] = [:], _ domainRemaps: [String: [String]] = [:], loadBuiltinImplementations: Bool = true) async { + @_spi(Testing) public init(_ pluginManager: any PluginManager, _ delegate: any SpecRegistryDelegate, _ searchPaths: [(Path, String)], _ domainInclusions: [String: [String]] = [:], _ domainRemaps: [String: [String]] = [:], loadBuiltinImplementations: Bool = true) async { self.delegate = delegate self.domainInclusions = domainInclusions self.domainRemaps = domainRemaps diff --git a/Sources/SWBCore/ToolchainRegistry.swift b/Sources/SWBCore/ToolchainRegistry.swift index 2515b184..b701b11e 100644 --- a/Sources/SWBCore/ToolchainRegistry.swift +++ b/Sources/SWBCore/ToolchainRegistry.swift @@ -18,7 +18,7 @@ import SWBMacro /// Delegate protocol used to report diagnostics. @_spi(Testing) public protocol ToolchainRegistryDelegate: DiagnosticProducingDelegate { - var pluginManager: PluginManager { get } + var pluginManager: any PluginManager { get } var platformRegistry: PlatformRegistry? { get } } @@ -105,7 +105,7 @@ public final class Toolchain: Hashable, Sendable { self.testingLibraryPlatformNames = testingLibraryPlatformNames } - convenience init(path: Path, operatingSystem: OperatingSystem, fs: any FSProxy, pluginManager: PluginManager, platformRegistry: PlatformRegistry?) async throws { + convenience init(path: Path, operatingSystem: OperatingSystem, fs: any FSProxy, pluginManager: any PluginManager, platformRegistry: PlatformRegistry?) async throws { let data: PropertyListItem do { diff --git a/Sources/SWBGenericUnixPlatform/Plugin.swift b/Sources/SWBGenericUnixPlatform/Plugin.swift index 632a4cae..6b85d398 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { let plugin = GenericUnixPlugin() manager.register(GenericUnixDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(GenericUnixPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) diff --git a/Sources/SWBGenericUnixPlatformPlugin/PluginMain.swift b/Sources/SWBGenericUnixPlatformPlugin/PluginMain.swift index 43d119d0..211fae22 100644 --- a/Sources/SWBGenericUnixPlatformPlugin/PluginMain.swift +++ b/Sources/SWBGenericUnixPlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBGenericUnixPlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Sources/SWBQNXPlatform/Plugin.swift b/Sources/SWBQNXPlatform/Plugin.swift index 6e46d66b..6e279cf7 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { let plugin = QNXPlugin() manager.register(QNXPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(QNXEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self) diff --git a/Sources/SWBQNXPlatformPlugin/PluginMain.swift b/Sources/SWBQNXPlatformPlugin/PluginMain.swift index 02a95dd0..f18294dd 100644 --- a/Sources/SWBQNXPlatformPlugin/PluginMain.swift +++ b/Sources/SWBQNXPlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBQNXPlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Sources/SWBServiceCore/Service.swift b/Sources/SWBServiceCore/Service.swift index 4718a558..4dce3f68 100644 --- a/Sources/SWBServiceCore/Service.swift +++ b/Sources/SWBServiceCore/Service.swift @@ -48,7 +48,7 @@ open class Service: @unchecked Sendable { public let connectionMode: ServiceHostConnectionMode - public let pluginManager: PluginManager + public let pluginManager: MutablePluginManager /// The message handlers, operating on (channel, message) pairs. /// @@ -64,7 +64,7 @@ open class Service: @unchecked Sendable { /// - outputFD: The output file descriptor for outgoing messages. /// - connectionMode: Whether the build service is being run in-process or out-of-process. /// - tracer: The tracing support service, if enabled. - public init(inputFD: FileDescriptor, outputFD: FileDescriptor, connectionMode: ServiceHostConnectionMode, pluginManager: PluginManager) async { + public init(inputFD: FileDescriptor, outputFD: FileDescriptor, connectionMode: ServiceHostConnectionMode, pluginManager: MutablePluginManager) async { self.connectionMode = connectionMode self.pluginManager = pluginManager diff --git a/Sources/SWBTaskExecution/BuildDescription.swift b/Sources/SWBTaskExecution/BuildDescription.swift index 53aae732..460e79c4 100644 --- a/Sources/SWBTaskExecution/BuildDescription.swift +++ b/Sources/SWBTaskExecution/BuildDescription.swift @@ -1394,7 +1394,7 @@ extension BuildDescription { package final class TaskActionRegistry: Sendable { private let implementations: [SerializableTypeCode: any PolymorphicSerializable.Type] - @PluginExtensionSystemActor @_spi(Testing) public init(pluginManager: PluginManager) throws { + @PluginExtensionSystemActor @_spi(Testing) public init(pluginManager: any PluginManager) throws { implementations = try TaskActionExtensionPoint.taskActionImplementations(pluginManager: pluginManager) } diff --git a/Sources/SWBTaskExecution/TaskActionExtensionPoint.swift b/Sources/SWBTaskExecution/TaskActionExtensionPoint.swift index 2b86ed75..04e3ca33 100644 --- a/Sources/SWBTaskExecution/TaskActionExtensionPoint.swift +++ b/Sources/SWBTaskExecution/TaskActionExtensionPoint.swift @@ -21,7 +21,7 @@ public struct TaskActionExtensionPoint: ExtensionPoint { // MARK: - actual extension point - package static func taskActionImplementations(pluginManager: PluginManager) throws -> [SerializableTypeCode: any PolymorphicSerializable.Type] { + package static func taskActionImplementations(pluginManager: any PluginManager) throws -> [SerializableTypeCode: any PolymorphicSerializable.Type] { return try pluginManager.extensions(of: Self.self).reduce([:], { implementations, ext in for (code, _) in ext.taskActionImplementations where implementations[code] != nil { throw StubError.error("Multiple implementations for task action implementation type code: \(code)") diff --git a/Sources/SWBTestSupport/CoreBasedTests.swift b/Sources/SWBTestSupport/CoreBasedTests.swift index 3a175a85..67255a67 100644 --- a/Sources/SWBTestSupport/CoreBasedTests.swift +++ b/Sources/SWBTestSupport/CoreBasedTests.swift @@ -24,7 +24,7 @@ package protocol CoreBasedTests { extension CoreBasedTests { /// This will create a customized `Core` object using the specified parameters, providing a test with detailed control over the contents of the `Core` it uses. - package static func makeCore(skipLoadingPluginsNamed: Set = [], registerExtraPlugins: @PluginExtensionSystemActor (PluginManager) -> Void = { _ in }, simulatedInferiorProductsPath: Path? = nil, environment: [String: String] = [:], _ delegate: TestingCoreDelegate? = nil, configurationDelegate: TestingCoreConfigurationDelegate? = nil, sourceLocation: SourceLocation = #_sourceLocation) async throws -> Core { + package static func makeCore(skipLoadingPluginsNamed: Set = [], registerExtraPlugins: @PluginExtensionSystemActor (MutablePluginManager) -> Void = { _ in }, simulatedInferiorProductsPath: Path? = nil, environment: [String: String] = [:], _ delegate: TestingCoreDelegate? = nil, configurationDelegate: TestingCoreConfigurationDelegate? = nil, sourceLocation: SourceLocation = #_sourceLocation) async throws -> Core { let core: Result do { let theCore = try await Core.createInitializedTestingCore(skipLoadingPluginsNamed: skipLoadingPluginsNamed, registerExtraPlugins: registerExtraPlugins, simulatedInferiorProductsPath: simulatedInferiorProductsPath, environment: environment, delegate: delegate, configurationDelegate: configurationDelegate) diff --git a/Sources/SWBTestSupport/CoreTestSupport.swift b/Sources/SWBTestSupport/CoreTestSupport.swift index a424a3d6..bf0301fc 100644 --- a/Sources/SWBTestSupport/CoreTestSupport.swift +++ b/Sources/SWBTestSupport/CoreTestSupport.swift @@ -41,13 +41,13 @@ extension Core { developerPath = .swiftToolchain(.root, xcodeDeveloperPath: nil) } let delegate = TestingCoreDelegate() - return await (try Core(delegate: delegate, hostOperatingSystem: hostOperatingSystem, pluginManager: PluginManager(skipLoadingPluginIdentifiers: []), developerPath: developerPath, resourceSearchPaths: [], inferiorProductsPath: nil, additionalContentPaths: [], environment: [:], buildServiceModTime: Date(), connectionMode: .inProcess), delegate.diagnostics) + return await (try Core(delegate: delegate, hostOperatingSystem: hostOperatingSystem, pluginManager: MutablePluginManager(skipLoadingPluginIdentifiers: []).finalize(), developerPath: developerPath, resourceSearchPaths: [], inferiorProductsPath: nil, additionalContentPaths: [], environment: [:], buildServiceModTime: Date(), connectionMode: .inProcess), delegate.diagnostics) } /// Get an initialized Core suitable for testing. /// /// This function requires there to be no errors during loading the core. - package static func createInitializedTestingCore(skipLoadingPluginsNamed: Set, registerExtraPlugins: @PluginExtensionSystemActor (PluginManager) -> Void, simulatedInferiorProductsPath: Path? = nil, environment: [String:String] = [:], delegate: TestingCoreDelegate? = nil, configurationDelegate: TestingCoreConfigurationDelegate? = nil) async throws -> Core { + package static func createInitializedTestingCore(skipLoadingPluginsNamed: Set, registerExtraPlugins: @PluginExtensionSystemActor (MutablePluginManager) -> Void, simulatedInferiorProductsPath: Path? = nil, environment: [String:String] = [:], delegate: TestingCoreDelegate? = nil, configurationDelegate: TestingCoreConfigurationDelegate? = nil) async throws -> Core { // When this code is being loaded directly via unit tests, find the running Xcode path. // // This is a "well known" launch parameter set in Xcode's schemes. @@ -115,9 +115,9 @@ extension Core { additionalContentPaths.append(simulatedInferiorProductsPath) } - let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: skipLoadingPluginsNamed) + let pluginManager = await MutablePluginManager(skipLoadingPluginIdentifiers: skipLoadingPluginsNamed) - @PluginExtensionSystemActor func extraPluginRegistration(pluginPaths: [Path]) { + @PluginExtensionSystemActor func extraPluginRegistration(pluginManager: MutablePluginManager, pluginPaths: [Path]) { pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) pluginManager.registerExtensionPoint(SettingsBuilderExtensionPoint()) pluginManager.registerExtensionPoint(SDKRegistryExtensionPoint()) diff --git a/Sources/SWBUniversalPlatform/Plugin.swift b/Sources/SWBUniversalPlatform/Plugin.swift index 4fffa083..abf9dd3c 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { manager.register(UniversalPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(UniversalPlatformTaskProducerExtension(), type: TaskProducerExtensionPoint.self) manager.register(UniversalPlatformTaskActionExtension(), type: TaskActionExtensionPoint.self) diff --git a/Sources/SWBUniversalPlatformPlugin/PluginMain.swift b/Sources/SWBUniversalPlatformPlugin/PluginMain.swift index 012feb71..372dd8e1 100644 --- a/Sources/SWBUniversalPlatformPlugin/PluginMain.swift +++ b/Sources/SWBUniversalPlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBUniversalPlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Sources/SWBUtil/FSProxy.swift b/Sources/SWBUtil/FSProxy.swift index d6a6ee71..943f3ab2 100644 --- a/Sources/SWBUtil/FSProxy.swift +++ b/Sources/SWBUtil/FSProxy.swift @@ -1446,3 +1446,10 @@ extension FileDescriptor { return result } } + +extension FileManager { + fileprivate func attributesOfItem(atPath path: String) throws -> [FileAttributeKey: any Sendable] { + let attributes: [FileAttributeKey: Any] = try attributesOfItem(atPath: path) + return (attributes as NSDictionary) as! [FileAttributeKey: any Sendable] + } +} diff --git a/Sources/SWBUtil/HeavyCache.swift b/Sources/SWBUtil/HeavyCache.swift index 25cbd479..e829ee6e 100644 --- a/Sources/SWBUtil/HeavyCache.swift +++ b/Sources/SWBUtil/HeavyCache.swift @@ -62,7 +62,7 @@ public func withHeavyCacheGlobalState(isolated: Bool = true, _ body: () throw /// A cache designed for holding few, relatively heavy-weight objects. /// /// This cache is specifically designed for holding a limited number of objects (usually less than 100) which are expensive enough to merit particular attention in terms of being purgeable under memory pressure, evictable in-mass, or cached with more complex parameters like time-to-live (TTL). -public final class HeavyCache: _HeavyCacheBase, KeyValueStorage, @unchecked Sendable { +public final class HeavyCache: _HeavyCacheBase, KeyValueStorage, @unchecked Sendable { public typealias HeavyCacheClock = SuspendingClock /// Controls the non-deterministic eviction policy of the cache. Note that this is distinct from deterministic _pruning_ (due to TTL or size limits). @@ -74,21 +74,32 @@ public final class HeavyCache: _HeavyCacheBase, case `default`(totalCostLimit: Int?, willEvictCallback: (@Sendable (Value) -> Void)? = nil) } - fileprivate final class Entry { + fileprivate final class Entry: Sendable { + /// Empty helper type to prove exclusive access to `accessTime` without storing a mutex for each instance. + struct Witness: ~Copyable { } + /// The actual value. let value: Value /// The last access timestamp. - var accessTime: HeavyCacheClock.Instant + private nonisolated(unsafe) var accessTime: HeavyCacheClock.Instant init(_ value: Value, _ accessTime: HeavyCacheClock.Instant) { self.value = value self.accessTime = accessTime } + + func accessTime(_ Witness: borrowing Witness) -> HeavyCacheClock.Instant { + self.accessTime + } + + func updateAccessTime(_ accessTime: HeavyCacheClock.Instant, _ Witness: borrowing Witness) { + self.accessTime = accessTime + } } /// The lock to protect shared instance state. - private let stateLock = SWBMutex(()) + private let stateLock = SWBMutex(Entry.Witness()) /// The underlying cache. private let _cache: any HeavyCacheImpl @@ -132,7 +143,7 @@ public final class HeavyCache: _HeavyCacheBase, deinit { _timer?.cancel() - stateLock.withLock { + stateLock.withLock { _ in for waiter in _expirationWaiters { waiter.resume() } @@ -146,12 +157,12 @@ public final class HeavyCache: _HeavyCacheBase, /// /// Due to the implementation details, this may overestimate the number of active items, if some items have been recently evicted. public var count: Int { - return stateLock.withLock { _keys.count } + return stateLock.withLock { _ in _keys.count } } /// Clear all items in the cache. public func removeAll() { - stateLock.withLock { + stateLock.withLock { _ in _cache.removeAll() _keys.removeAll() } @@ -161,13 +172,13 @@ public final class HeavyCache: _HeavyCacheBase, /// /// This function is thread-safe, but may allow computing the value multiple times in case of a race. public func getOrInsert(_ key: Key, _ body: () throws -> Value) rethrows -> Value { - return try stateLock.withLock { + return try stateLock.withLock { witness in let entry = try _cache.getOrInsert(key) { return Entry(try body(), currentTime()) } _keys.insert(key) - entry.accessTime = currentTime() - _pruneCache() + entry.updateAccessTime(currentTime(), witness) + _pruneCache(witness) return entry.value } } @@ -175,21 +186,21 @@ public final class HeavyCache: _HeavyCacheBase, /// Subscript access to the cache. public subscript(_ key: Key) -> Value? { get { - return stateLock.withLock { + return stateLock.withLock { witness in if let entry = _cache[key] { - entry.accessTime = currentTime() + entry.updateAccessTime(currentTime(), witness) return entry.value } return nil } } set { - stateLock.withLock { + stateLock.withLock { witness in if let newValue { let entry = Entry(newValue, currentTime()) _cache[key] = entry _keys.insert(key) - _pruneCache() + _pruneCache(witness) } else { _cache.remove(key) _keys.remove(key) @@ -206,7 +217,7 @@ public final class HeavyCache: _HeavyCacheBase, /// Prune the cache following an insert. /// /// This method is expected to be called on `queue`. - private func _pruneCache() { + private func _pruneCache(_ witness: borrowing Entry.Witness) { // Enforce the cache maximum size. guard let max = maximumSize else { return } @@ -223,7 +234,7 @@ public final class HeavyCache: _HeavyCacheBase, _cache.remove(key) continue whileLoop } - if oldest == nil || oldest!.entry.accessTime > entry.accessTime { + if oldest == nil || oldest!.entry.accessTime(witness) > entry.accessTime(witness) { oldest = (key, entry) } } @@ -237,7 +248,7 @@ public final class HeavyCache: _HeavyCacheBase, /// Prune the cache based on the TTL value. /// /// This method is expected to be called on `queue`. - private func _pruneForTTL() { + private func _pruneForTTL(_ witness: borrowing Entry.Witness) { guard let ttl = _timeToLive else { return } let time = currentTime() @@ -247,7 +258,7 @@ public final class HeavyCache: _HeavyCacheBase, keysToRemove.append(key) continue } - if time - entry.accessTime > ttl { + if time - entry.accessTime(witness) > ttl { keysToRemove.append(key) } } @@ -272,9 +283,9 @@ public final class HeavyCache: _HeavyCacheBase, return _maximumSize } set { - stateLock.withLock { + stateLock.withLock { witness in _maximumSize = newValue - _pruneCache() + _pruneCache(witness) } } } @@ -287,7 +298,7 @@ public final class HeavyCache: _HeavyCacheBase, return _timeToLive } set { - stateLock.withLock { + stateLock.withLock { _ in _timeToLive = newValue // Install the TTL timer. @@ -298,8 +309,8 @@ public final class HeavyCache: _HeavyCacheBase, while !Task.isCancelled { if let self = self { self.preventExpiration { - self.stateLock.withLock { - self._pruneForTTL() + self.stateLock.withLock { witness in + self._pruneForTTL(witness) } } } @@ -326,7 +337,7 @@ public final class HeavyCache: _HeavyCacheBase, extension HeavyCache { /// Allows freezing the current time as seen by the object, for TTL pruning testing purposes. @_spi(Testing) @discardableResult public func setTime(instant: HeavyCacheClock.Instant?) -> HeavyCacheClock.Instant { - stateLock.withLock { + stateLock.withLock { _ in _currentTimeTestingOverride = instant return instant ?? .now } @@ -335,7 +346,7 @@ extension HeavyCache { /// Waits until the next time pruning for TTL occurs. @_spi(Testing) public func waitForExpiration() async { await withCheckedContinuation { continuation in - stateLock.withLock { + stateLock.withLock { _ in _expirationWaiters.append(continuation) } } diff --git a/Sources/SWBUtil/LazyCache.swift b/Sources/SWBUtil/LazyCache.swift index 292d38b4..12ea2a2d 100644 --- a/Sources/SWBUtil/LazyCache.swift +++ b/Sources/SWBUtil/LazyCache.swift @@ -65,7 +65,7 @@ public final class Lazy: Sendable { } /// Wrapper for thread-safe lazily computed values. -public final class LazyCache { +public final class LazyCache { private let body: @Sendable (Class) -> T private let cachedValue = LockedValue(nil) @@ -89,7 +89,7 @@ public final class LazyCache { extension LazyCache: Sendable where T: Sendable {} /// Wrapper for thread-safe lazily computed key-value pairs. -public final class LazyKeyValueCache { +public final class LazyKeyValueCache { private let body: @Sendable (Class, Key) -> Value private let cachedValues = LockedValue<[Key: Value]>([:]) diff --git a/Sources/SWBUtil/Misc.swift b/Sources/SWBUtil/Misc.swift index a3e6d880..b2eb169c 100644 --- a/Sources/SWBUtil/Misc.swift +++ b/Sources/SWBUtil/Misc.swift @@ -84,11 +84,11 @@ public struct FILETextOutputStream: TextOutputStream { } public static var stdout: Self { - .init(SWBLibc.stdout) + .init(SWBLibc.swb_stdout()) } public static var stderr: Self { - .init(SWBLibc.stderr) + .init(SWBLibc.swb_stderr()) } } diff --git a/Sources/SWBUtil/PluginManager.swift b/Sources/SWBUtil/PluginManager.swift index 3a638c86..af65a972 100644 --- a/Sources/SWBUtil/PluginManager.swift +++ b/Sources/SWBUtil/PluginManager.swift @@ -32,8 +32,8 @@ import SWBLibc /// This manager works by using a *very* minimal API between the service and the plugins, only the PluginManager itself is passed to the plugins (as an opaque pointer). All actual plugging then can happen using real Swift APIs between the plugin manager and the plugins. /// /// This mechanism is *NOT* intended to be used to build plugins which have a stable API -- all plugins must be built with exactly the Swift Build the are intended to plug in to. The only thing this allows is for dynamically loaded the plugin in order to manage distributing parts independently. -@PluginExtensionSystemActor public final class PluginManager: Sendable { - private struct Plugin: CommonPlugin { +@PluginExtensionSystemActor public final class MutablePluginManager: Sendable { + fileprivate struct Plugin: CommonPlugin { /// The identifier of the plugin. @_spi(Testing) public let identifier: String @@ -44,7 +44,7 @@ import SWBLibc /// The set of all plugins we've successfully loaded (CFBundleIdentifier for bundles if they have one, filenames otherwise), mapping to the paths to those plugins (for debugging convenience). /// /// This is primarily used to avoid loading the same plugin twice. - private var loadedPlugins = [String: Path]() + fileprivate var loadedPlugins = [String: Path]() /// Diagnostics produced during plugin loading. public private(set) var loadingDiagnostics: [Diagnostic] = [] @@ -52,7 +52,7 @@ import SWBLibc /// The set of registered extension points. private var extensionPoints: [String: any ExtensionPoint] = [:] - private var extensions: [Ref: [Any]] = [:] + fileprivate var extensions: [Ref: [any Sendable]] = [:] private let skipLoadingPluginIdentifiers: Set @@ -183,4 +183,41 @@ import SWBLibc return [] } } + + /// Finalizes the loading process by returning a read-only interface to the plugin manager which prevents further loading. + public consuming func finalize() -> any PluginManager { + ImmutablePluginManager(pluginManager: self) + } +} + +public protocol PluginManager: Sendable { + var pluginsByIdentifier: [String: any CommonPlugin] { get } + var loadingDiagnostics: [Diagnostic] { get } + + func extensions(of extensionPoint: T.Type) -> [T.ExtensionProtocol] +} + +private final class ImmutablePluginManager: Sendable, PluginManager { + private let loadedPlugins: [String: Path] + public let loadingDiagnostics: [Diagnostic] + private let extensions: [Ref: [any Sendable]] + + @PluginExtensionSystemActor public init(pluginManager: MutablePluginManager) { + self.loadedPlugins = pluginManager.loadedPlugins + self.loadingDiagnostics = pluginManager.loadingDiagnostics + self.extensions = pluginManager.extensions + } + + public var pluginsByIdentifier: [String: any CommonPlugin] { + Dictionary(uniqueKeysWithValues: loadedPlugins.map { ($0.key, MutablePluginManager.Plugin(identifier: $0.key, path: $0.value)) }) + } + + public func extensions(of extensionPoint: T.Type) -> [T.ExtensionProtocol] { + extensions.flatMap { key, value in + if type(of: key.instance) == extensionPoint { + return value as! [T.ExtensionProtocol] + } + return [] + } + } } diff --git a/Sources/SWBUtil/Process.swift b/Sources/SWBUtil/Process.swift index 75c27b81..6ddd690f 100644 --- a/Sources/SWBUtil/Process.swift +++ b/Sources/SWBUtil/Process.swift @@ -152,7 +152,7 @@ extension Process { } } - private static func _getOutput(url: URL, arguments: [String], currentDirectoryURL: URL?, environment: Environment?, interruptible: Bool, setup: (Process) -> T, collect: (T) async throws -> U) async throws -> (exitStatus: Processes.ExitStatus, output: U) { + private static func _getOutput(url: URL, arguments: [String], currentDirectoryURL: URL?, environment: Environment?, interruptible: Bool, setup: (Process) -> T, collect: @Sendable (T) async throws -> U) async throws -> (exitStatus: Processes.ExitStatus, output: U) { let executableFilePath = try url.standardizedFileURL.filePath let process = Process() diff --git a/Sources/SWBUtil/Registry.swift b/Sources/SWBUtil/Registry.swift index 88a42249..974917e7 100644 --- a/Sources/SWBUtil/Registry.swift +++ b/Sources/SWBUtil/Registry.swift @@ -11,15 +11,16 @@ //===----------------------------------------------------------------------===// import SWBLibc +import Synchronization /// A threadsafe mapping of hashable keys to values. Unlike a Dictionary, which has independent lookup and insertion operations, a registry has an atomic lookup-or-insert operation that takes a constructor block, which is called only if the key isn't already in the registry. The block is guaranteed to be called only once, even if multiple threads lookup-or-insert the same key at the same time (this allows it to have side effects without needing additional checking). Unlike a Cache, a Registry never discards entries based on memory pressure. Unlike a LazyCache, the value creation block is provided for each call and not just once per instance. // FIXME: We should consider whether we should combine Cache, LazyCache, and Registry, possibly with per-instance options for things like whether background deletion is allowed, whether a value creator block is guaranteed to run only once, etc. At the moment, the various clients in Swift Build depend on the semantics of the various utility types they use. -public final class Registry: KeyValueStorage { +public final class Registry: KeyValueStorage { public typealias Key = K public typealias Value = V /// Underlying dictionary, which is accessed only while holding the lock. - private let dict = LockedValue>([:]) + private let dict = SWBMutex>([:]) /// Public initializer of a new, empty registry. public init() { diff --git a/Sources/SWBWebAssemblyPlatform/Plugin.swift b/Sources/SWBWebAssemblyPlatform/Plugin.swift index c3c16659..287d54e9 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { manager.register(WebAssemblyPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(WebAssemblyPlatformExtension(), type: PlatformInfoExtensionPoint.self) manager.register(WebAssemblySDKRegistryExtension(), type: SDKRegistryExtensionPoint.self) diff --git a/Sources/SWBWebAssemblyPlatformPlugin/PluginMain.swift b/Sources/SWBWebAssemblyPlatformPlugin/PluginMain.swift index 68a3d4d2..a7d4c589 100644 --- a/Sources/SWBWebAssemblyPlatformPlugin/PluginMain.swift +++ b/Sources/SWBWebAssemblyPlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBWebAssemblyPlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Sources/SWBWindowsPlatform/Plugin.swift b/Sources/SWBWindowsPlatform/Plugin.swift index 9a2c7e40..d80b7fb1 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: PluginManager) { +@PluginExtensionSystemActor public func initializePlugin(_ manager: MutablePluginManager) { let plugin = WindowsPlugin() manager.register(WindowsDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(WindowsPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) diff --git a/Sources/SWBWindowsPlatformPlugin/PluginMain.swift b/Sources/SWBWindowsPlatformPlugin/PluginMain.swift index fdeb0c83..637453fe 100644 --- a/Sources/SWBWindowsPlatformPlugin/PluginMain.swift +++ b/Sources/SWBWindowsPlatformPlugin/PluginMain.swift @@ -16,5 +16,5 @@ import SWBWindowsPlatform @_cdecl("initializePlugin") @PluginExtensionSystemActor public func main(_ ptr: UnsafeRawPointer) { - initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) + initializePlugin(Unmanaged.fromOpaque(ptr).takeUnretainedValue()) } diff --git a/Tests/SWBCoreTests/CoreTests.swift b/Tests/SWBCoreTests/CoreTests.swift index 36fbd821..7cd8b525 100644 --- a/Tests/SWBCoreTests/CoreTests.swift +++ b/Tests/SWBCoreTests/CoreTests.swift @@ -332,7 +332,7 @@ import SWBServiceCore ])) let delegate = Delegate() - let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + let pluginManager = await MutablePluginManager(skipLoadingPluginIdentifiers: []) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.register(BuiltinSpecsExtension(), type: SpecificationsExtensionPoint.self) let core = await Core.getInitializedCore(delegate, pluginManager: pluginManager, developerPath: .swiftToolchain(tmpDirPath, xcodeDeveloperPath: nil), buildServiceModTime: Date(), connectionMode: .inProcess) @@ -383,7 +383,7 @@ import SWBServiceCore try await withTemporaryDirectory { tmpDir in try localFS.createDirectory(tmpDir.join("Toolchains")) let delegate = Delegate() - let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + let pluginManager = await MutablePluginManager(skipLoadingPluginIdentifiers: []) await pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.registerExtensionPoint(ToolchainRegistryExtensionPoint()) @@ -430,7 +430,7 @@ import SWBServiceCore func testExternalToolchainPath(toolchainPath: Path, environmentOverrides: [String:String], expecting expectedPathStrings: [String], _ originalToolchainCount: Int) async throws { let delegate = Delegate() - let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + let pluginManager = await MutablePluginManager(skipLoadingPluginIdentifiers: []) await pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.registerExtensionPoint(ToolchainRegistryExtensionPoint()) diff --git a/Tests/SWBCoreTests/PlatformRegistryTests.swift b/Tests/SWBCoreTests/PlatformRegistryTests.swift index ae74a237..72287e8e 100644 --- a/Tests/SWBCoreTests/PlatformRegistryTests.swift +++ b/Tests/SWBCoreTests/PlatformRegistryTests.swift @@ -29,10 +29,10 @@ import SWBMacro let specRegistry: SpecRegistry let _diagnosticsEngine = DiagnosticsEngine() - let pluginManager: PluginManager + let pluginManager: any PluginManager - init(pluginManager: PluginManager) async { - self.specRegistry = await SpecRegistry(PluginManager(skipLoadingPluginIdentifiers: []), MockSpecRegistryDelegate(_diagnosticsEngine), []) + init(pluginManager: any PluginManager) async { + self.specRegistry = await SpecRegistry(MutablePluginManager(skipLoadingPluginIdentifiers: []).finalize(), MockSpecRegistryDelegate(_diagnosticsEngine), []) self.pluginManager = pluginManager } @@ -69,7 +69,7 @@ import SWBMacro } } - let delegate = await TestDataDelegate(pluginManager: PluginManager(skipLoadingPluginIdentifiers: [])) + let delegate = await TestDataDelegate(pluginManager: MutablePluginManager(skipLoadingPluginIdentifiers: []).finalize()) let registry = await PlatformRegistry(delegate: delegate, searchPaths: [tmpDirPath], hostOperatingSystem: try ProcessInfo.processInfo.hostOperatingSystem(), fs: localFS) try await perform(registry, delegate) } diff --git a/Tests/SWBCoreTests/SDKRegistryTests.swift b/Tests/SWBCoreTests/SDKRegistryTests.swift index 8a57885b..368da32d 100644 --- a/Tests/SWBCoreTests/SDKRegistryTests.swift +++ b/Tests/SWBCoreTests/SDKRegistryTests.swift @@ -22,10 +22,10 @@ import SWBMacro /// Delegate for testing loading SDKs in a registry. final class TestDataDelegate : SDKRegistryDelegate { let namespace = MacroNamespace() - let pluginManager: PluginManager + let pluginManager: any PluginManager private let _diagnosticsEngine = DiagnosticsEngine() - init(pluginManager: PluginManager) { + init(pluginManager: any PluginManager) { self.pluginManager = pluginManager } @@ -81,7 +81,7 @@ import SWBMacro let components: SDK.CanonicalNameComponents? let errorString: String? do { - components = try SDK.parseSDKName(sdkName, pluginManager: try await getCore().pluginManager) + components = try SDK.parseSDKName(sdkName, registry: try await getCore().sdkRegistry) errorString = nil } catch { @@ -728,9 +728,9 @@ import SWBMacro let registry: SDKRegistry = try await { final class TestDataDelegate : SDKRegistryDelegate { let namespace = MacroNamespace() - let pluginManager: PluginManager + let pluginManager: any PluginManager - init(pluginManager: PluginManager) { + init(pluginManager: any PluginManager) { self.pluginManager = pluginManager } diff --git a/Tests/SWBCoreTests/SettingsTests.swift b/Tests/SWBCoreTests/SettingsTests.swift index 10f93489..d6d2dfe5 100644 --- a/Tests/SWBCoreTests/SettingsTests.swift +++ b/Tests/SWBCoreTests/SettingsTests.swift @@ -1005,9 +1005,9 @@ import SWBMacro final class TestDataDelegate : SDKRegistryDelegate { let namespace: MacroNamespace - let pluginManager: PluginManager + let pluginManager: any PluginManager private let _diagnosticsEngine = DiagnosticsEngine() - init(_ namespace: MacroNamespace, pluginManager: PluginManager) { + init(_ namespace: MacroNamespace, pluginManager: any PluginManager) { self.namespace = namespace self.pluginManager = pluginManager } @@ -2450,9 +2450,9 @@ import SWBMacro } final class TestDataDelegate : SDKRegistryDelegate { let namespace: MacroNamespace - let pluginManager: PluginManager + let pluginManager: any PluginManager private let _diagnosticsEngine = DiagnosticsEngine() - init(_ namespace: MacroNamespace, pluginManager: PluginManager) { + init(_ namespace: MacroNamespace, pluginManager: any PluginManager) { self.namespace = namespace self.pluginManager = pluginManager } diff --git a/Tests/SWBCoreTests/SpecLoadingTests.swift b/Tests/SWBCoreTests/SpecLoadingTests.swift index ded14676..c7bbc8ee 100644 --- a/Tests/SWBCoreTests/SpecLoadingTests.swift +++ b/Tests/SWBCoreTests/SpecLoadingTests.swift @@ -67,7 +67,7 @@ import SWBMacro init(namespace: MacroNamespace? = nil) async { self.internalMacroNamespace = namespace ?? MacroNamespace(parent: BuiltinMacros.namespace, debugDescription: "spec loading tests") - specRegistry = await SpecRegistry(PluginManager(skipLoadingPluginIdentifiers: []), MockSpecRegistryDelegate(_diagnosticsEngine), []) + specRegistry = await SpecRegistry(MutablePluginManager(skipLoadingPluginIdentifiers: []).finalize(), MockSpecRegistryDelegate(_diagnosticsEngine), []) } } diff --git a/Tests/SWBCoreTests/SpecParserTests.swift b/Tests/SWBCoreTests/SpecParserTests.swift index b1f7447b..ac14b6e9 100644 --- a/Tests/SWBCoreTests/SpecParserTests.swift +++ b/Tests/SWBCoreTests/SpecParserTests.swift @@ -73,7 +73,7 @@ fileprivate final class MockSpecType: SpecType { } init() async { - specRegistry = await SpecRegistry(PluginManager(skipLoadingPluginIdentifiers: []), MockSpecRegistryDelegate(_diagnosticsEngine), []) + specRegistry = await SpecRegistry(MutablePluginManager(skipLoadingPluginIdentifiers: []).finalize(), MockSpecRegistryDelegate(_diagnosticsEngine), []) } } diff --git a/Tests/SWBCoreTests/SpecRegistryTests.swift b/Tests/SWBCoreTests/SpecRegistryTests.swift index 5be07231..595e94c2 100644 --- a/Tests/SWBCoreTests/SpecRegistryTests.swift +++ b/Tests/SWBCoreTests/SpecRegistryTests.swift @@ -46,12 +46,12 @@ import SWBUtil } // Ensure spec types are loaded. - let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + let pluginManager = await MutablePluginManager(skipLoadingPluginIdentifiers: []) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.register(BuiltinSpecsExtension(), type: SpecificationsExtensionPoint.self) let delegate = TestDataDelegate() - let registry = await SpecRegistry(pluginManager, delegate, [(tmpDirPath, "")], loadBuiltinImplementations: false) + let registry = await SpecRegistry(pluginManager.finalize(), delegate, [(tmpDirPath, "")], loadBuiltinImplementations: false) try await perform(registry, delegate) } diff --git a/Tests/SWBCoreTests/ToolchainRegistryTests.swift b/Tests/SWBCoreTests/ToolchainRegistryTests.swift index 60510119..4a5a495d 100644 --- a/Tests/SWBCoreTests/ToolchainRegistryTests.swift +++ b/Tests/SWBCoreTests/ToolchainRegistryTests.swift @@ -50,7 +50,7 @@ import SWBServiceCore class TestDataDelegate : ToolchainRegistryDelegate { private let _diagnosticsEngine = DiagnosticsEngine() - init(pluginManager: PluginManager) { + init(pluginManager: any PluginManager) { self.pluginManager = pluginManager } @@ -66,14 +66,14 @@ import SWBServiceCore return _diagnosticsEngine.diagnostics.pathMessageTuples(.error) } - var pluginManager: PluginManager + var pluginManager: any PluginManager var platformRegistry: PlatformRegistry? { nil } } - let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + let pluginManager = await MutablePluginManager(skipLoadingPluginIdentifiers: []) await pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.registerExtensionPoint(ToolchainRegistryExtensionPoint())