From 37dc26d1f6532d81fb75bb56822b770d87afc322 Mon Sep 17 00:00:00 2001 From: ikesyo Date: Tue, 22 Oct 2024 15:48:13 +0900 Subject: [PATCH] Factor out DescriptionPackage's path-related functions to PackageLocator protocol This would make it easy for testing FrameworkComponentsCollector and FrameworkModuleMapGenerator. --- Sources/ScipioKit/DescriptionPackage.swift | 52 +--------------- Sources/ScipioKit/PackageLocator.swift | 60 +++++++++++++++++++ .../PIF/FrameworkComponentsCollector.swift | 12 ++-- .../Producer/PIF/ModuleMapGenerator.swift | 8 +-- .../ScipioKit/Producer/PIF/PIFCompiler.swift | 4 +- .../Producer/PIF/XCBuildClient.swift | 14 ++--- 6 files changed, 80 insertions(+), 70 deletions(-) create mode 100644 Sources/ScipioKit/PackageLocator.swift diff --git a/Sources/ScipioKit/DescriptionPackage.swift b/Sources/ScipioKit/DescriptionPackage.swift index 8cdae2b4..cd48d813 100644 --- a/Sources/ScipioKit/DescriptionPackage.swift +++ b/Sources/ScipioKit/DescriptionPackage.swift @@ -7,7 +7,7 @@ import PackageLoading @preconcurrency import PackageGraph import Basics -struct DescriptionPackage { +struct DescriptionPackage: PackageLocator { let mode: Runner.Mode let packageDirectory: ScipioAbsolutePath private let toolchain: UserToolchain @@ -35,60 +35,10 @@ struct DescriptionPackage { manifest.displayName } - var buildDirectory: ScipioAbsolutePath { - packageDirectory.appending(component: ".build") - } - - var workspaceDirectory: ScipioAbsolutePath { - buildDirectory.appending(component: "scipio") - } - var supportedSDKs: Set { Set(manifest.platforms.map(\.platformName).compactMap(SDK.init(platformName:))) } - var derivedDataPath: ScipioAbsolutePath { - workspaceDirectory.appending(component: "DerivedData") - } - - func generatedModuleMapPath(of target: ScipioResolvedModule, sdk: SDK) throws -> ScipioAbsolutePath { - let relativePath = try TSCBasic.RelativePath(validating: "ModuleMapsForFramework/\(sdk.settingValue)") - return workspaceDirectory - .appending(relativePath) - .appending(component: target.modulemapName) - } - - /// Returns an Products directory path - /// It should be the default setting of `TARGET_BUILD_DIR` - func productsDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> ScipioAbsolutePath { - let intermediateDirectoryName = productDirectoryName( - buildConfiguration: buildConfiguration, - sdk: sdk - ) - return derivedDataPath.appending(components: ["Products", intermediateDirectoryName]) - } - - /// Returns a directory path which contains assembled frameworks - var assembledFrameworksRootDirectory: ScipioAbsolutePath { - workspaceDirectory.appending(component: "AssembledFrameworks") - } - - /// Returns a directory path of the assembled frameworks path for the specific Configuration/Platform - func assembledFrameworksDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> ScipioAbsolutePath { - let intermediateDirName = productDirectoryName(buildConfiguration: buildConfiguration, sdk: sdk) - return assembledFrameworksRootDirectory - .appending(component: intermediateDirName) - } - - /// Returns an intermediate directory name in the Products dir. - /// e.g. `Debug` / `Debug-iphoneos` - private func productDirectoryName(buildConfiguration: BuildConfiguration, sdk: SDK) -> String { - if sdk == .macOS { - return buildConfiguration.settingsValue - } else { - return "\(buildConfiguration.settingsValue)-\(sdk.settingValue)" - } - } // MARK: Initializer diff --git a/Sources/ScipioKit/PackageLocator.swift b/Sources/ScipioKit/PackageLocator.swift new file mode 100644 index 00000000..41024d46 --- /dev/null +++ b/Sources/ScipioKit/PackageLocator.swift @@ -0,0 +1,60 @@ +import TSCBasic +import PackageModel + +/// Holds the packageDirectory Scipio works on, and defines some path-related functionalities. +protocol PackageLocator { + var packageDirectory: ScipioAbsolutePath { get } +} + +extension PackageLocator { + var buildDirectory: ScipioAbsolutePath { + packageDirectory.appending(component: ".build") + } + + var workspaceDirectory: ScipioAbsolutePath { + buildDirectory.appending(component: "scipio") + } + + var derivedDataPath: ScipioAbsolutePath { + workspaceDirectory.appending(component: "DerivedData") + } + + func generatedModuleMapPath(of target: ScipioResolvedModule, sdk: SDK) throws -> ScipioAbsolutePath { + let relativePath = try TSCBasic.RelativePath(validating: "ModuleMapsForFramework/\(sdk.settingValue)") + return workspaceDirectory + .appending(relativePath) + .appending(component: target.modulemapName) + } + + /// Returns an Products directory path + /// It should be the default setting of `TARGET_BUILD_DIR` + func productsDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> ScipioAbsolutePath { + let intermediateDirectoryName = productDirectoryName( + buildConfiguration: buildConfiguration, + sdk: sdk + ) + return derivedDataPath.appending(components: ["Products", intermediateDirectoryName]) + } + + /// Returns a directory path which contains assembled frameworks + var assembledFrameworksRootDirectory: ScipioAbsolutePath { + workspaceDirectory.appending(component: "AssembledFrameworks") + } + + /// Returns a directory path of the assembled frameworks path for the specific Configuration/Platform + func assembledFrameworksDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> ScipioAbsolutePath { + let intermediateDirName = productDirectoryName(buildConfiguration: buildConfiguration, sdk: sdk) + return assembledFrameworksRootDirectory + .appending(component: intermediateDirName) + } + + /// Returns an intermediate directory name in the Products dir. + /// e.g. `Debug` / `Debug-iphoneos` + private func productDirectoryName(buildConfiguration: BuildConfiguration, sdk: SDK) -> String { + if sdk == .macOS { + return buildConfiguration.settingsValue + } else { + return "\(buildConfiguration.settingsValue)-\(sdk.settingValue)" + } + } +} diff --git a/Sources/ScipioKit/Producer/PIF/FrameworkComponentsCollector.swift b/Sources/ScipioKit/Producer/PIF/FrameworkComponentsCollector.swift index f063b0b4..7fbe7e4d 100644 --- a/Sources/ScipioKit/Producer/PIF/FrameworkComponentsCollector.swift +++ b/Sources/ScipioKit/Producer/PIF/FrameworkComponentsCollector.swift @@ -27,23 +27,23 @@ struct FrameworkComponentsCollector { } } - private let descriptionPackage: DescriptionPackage private let buildProduct: BuildProduct private let sdk: SDK private let buildOptions: BuildOptions + private let packageLocator: any PackageLocator private let fileSystem: any FileSystem init( - descriptionPackage: DescriptionPackage, buildProduct: BuildProduct, sdk: SDK, buildOptions: BuildOptions, + packageLocator: some PackageLocator, fileSystem: any FileSystem ) { - self.descriptionPackage = descriptionPackage self.buildProduct = buildProduct self.sdk = sdk self.buildOptions = buildOptions + self.packageLocator = packageLocator self.fileSystem = fileSystem } @@ -95,7 +95,7 @@ struct FrameworkComponentsCollector { /// Copy content data to the build artifacts private func copyModuleMapContentsToBuildArtifacts(_ data: Data) throws -> ScipioAbsolutePath { - let generatedModuleMapPath = try descriptionPackage.generatedModuleMapPath(of: buildProduct.target, sdk: sdk) + let generatedModuleMapPath = try packageLocator.generatedModuleMapPath(of: buildProduct.target, sdk: sdk) try fileSystem.writeFileContents(generatedModuleMapPath.spmAbsolutePath, data: data) return generatedModuleMapPath @@ -103,7 +103,7 @@ struct FrameworkComponentsCollector { private func generateFrameworkModuleMap() throws -> AbsolutePath? { let modulemapGenerator = FrameworkModuleMapGenerator( - descriptionPackage: descriptionPackage, + packageLocator: packageLocator, fileSystem: fileSystem ) @@ -119,7 +119,7 @@ struct FrameworkComponentsCollector { } private func generatedFrameworkPath() -> AbsolutePath { - descriptionPackage.productsDirectory( + packageLocator.productsDirectory( buildConfiguration: buildOptions.buildConfiguration, sdk: sdk ) diff --git a/Sources/ScipioKit/Producer/PIF/ModuleMapGenerator.swift b/Sources/ScipioKit/Producer/PIF/ModuleMapGenerator.swift index 9c8fc949..23b91a62 100644 --- a/Sources/ScipioKit/Producer/PIF/ModuleMapGenerator.swift +++ b/Sources/ScipioKit/Producer/PIF/ModuleMapGenerator.swift @@ -11,7 +11,7 @@ struct FrameworkModuleMapGenerator { var configuration: BuildConfiguration } - private var descriptionPackage: DescriptionPackage + private var packageLocator: any PackageLocator private var fileSystem: any FileSystem enum Error: LocalizedError { @@ -25,8 +25,8 @@ struct FrameworkModuleMapGenerator { } } - init(descriptionPackage: DescriptionPackage, fileSystem: any FileSystem) { - self.descriptionPackage = descriptionPackage + init(packageLocator: some PackageLocator, fileSystem: some FileSystem) { + self.packageLocator = packageLocator self.fileSystem = fileSystem } @@ -118,7 +118,7 @@ struct FrameworkModuleMapGenerator { } private func constructGeneratedModuleMapPath(context: Context) throws -> AbsolutePath { - let generatedModuleMapPath = try descriptionPackage.generatedModuleMapPath(of: context.resolvedTarget, sdk: context.sdk) + let generatedModuleMapPath = try packageLocator.generatedModuleMapPath(of: context.resolvedTarget, sdk: context.sdk) return generatedModuleMapPath } diff --git a/Sources/ScipioKit/Producer/PIF/PIFCompiler.swift b/Sources/ScipioKit/Producer/PIF/PIFCompiler.swift index 7f832b08..1791c7cb 100644 --- a/Sources/ScipioKit/Producer/PIF/PIFCompiler.swift +++ b/Sources/ScipioKit/Producer/PIF/PIFCompiler.swift @@ -54,10 +54,10 @@ struct PIFCompiler: Compiler { logger.info("📦 Building \(target.name) for \(sdkNames)") let xcBuildClient: XCBuildClient = .init( - package: descriptionPackage, buildProduct: buildProduct, buildOptions: buildOptions, - configuration: buildOptions.buildConfiguration + configuration: buildOptions.buildConfiguration, + packageLocator: descriptionPackage ) for sdk in sdks { diff --git a/Sources/ScipioKit/Producer/PIF/XCBuildClient.swift b/Sources/ScipioKit/Producer/PIF/XCBuildClient.swift index cc2e6780..13cd973b 100644 --- a/Sources/ScipioKit/Producer/PIF/XCBuildClient.swift +++ b/Sources/ScipioKit/Producer/PIF/XCBuildClient.swift @@ -4,25 +4,25 @@ import PackageGraph import PackageModel struct XCBuildClient { - private let descriptionPackage: DescriptionPackage private let buildOptions: BuildOptions private let buildProduct: BuildProduct private let configuration: BuildConfiguration + private let packageLocator: any PackageLocator private let fileSystem: any FileSystem private let executor: any Executor init( - package: DescriptionPackage, buildProduct: BuildProduct, buildOptions: BuildOptions, configuration: BuildConfiguration, + packageLocator: some PackageLocator, fileSystem: any FileSystem = localFileSystem, executor: any Executor = ProcessExecutor(decoder: StandardOutputDecoder()) ) { - self.descriptionPackage = package self.buildProduct = buildProduct self.buildOptions = buildOptions self.configuration = configuration + self.packageLocator = packageLocator self.fileSystem = fileSystem self.executor = executor } @@ -58,7 +58,7 @@ struct XCBuildClient { try await executor.build( pifPath: pifPath, configuration: configuration, - derivedDataPath: descriptionPackage.derivedDataPath, + derivedDataPath: packageLocator.derivedDataPath, buildParametersPath: buildParametersPath, target: buildProduct.target ) @@ -74,16 +74,16 @@ struct XCBuildClient { private func assembleFramework(sdk: SDK) throws { let frameworkComponentsCollector = FrameworkComponentsCollector( - descriptionPackage: descriptionPackage, buildProduct: buildProduct, sdk: sdk, buildOptions: buildOptions, + packageLocator: packageLocator, fileSystem: fileSystem ) let components = try frameworkComponentsCollector.collectComponents(sdk: sdk) - let frameworkOutputDir = descriptionPackage.assembledFrameworksDirectory( + let frameworkOutputDir = packageLocator.assembledFrameworksDirectory( buildConfiguration: buildOptions.buildConfiguration, sdk: sdk ) @@ -98,7 +98,7 @@ struct XCBuildClient { } private func assembledFrameworkPath(target: ScipioResolvedModule, of sdk: SDK) throws -> AbsolutePath { - let assembledFrameworkDir = descriptionPackage.assembledFrameworksDirectory( + let assembledFrameworkDir = packageLocator.assembledFrameworksDirectory( buildConfiguration: buildOptions.buildConfiguration, sdk: sdk )