diff --git a/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift b/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift index 6b74a890067..2352ae9e5d0 100644 --- a/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift +++ b/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift @@ -138,7 +138,7 @@ public class LLBuildManifestBuilder { case .swift(let desc): try self.createSwiftCompileCommand(desc) case .clang(let desc): - if desc.target.buildTriple == .tools { + if desc.destination == .host { // Need the clang modules for tools try self.createClangCompileCommand(desc) } else { diff --git a/Sources/Build/BuildOperation.swift b/Sources/Build/BuildOperation.swift index 688722aede9..2efa0111c9a 100644 --- a/Sources/Build/BuildOperation.swift +++ b/Sources/Build/BuildOperation.swift @@ -573,6 +573,19 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS /// Compute the llbuild target name using the given subset. func computeLLBuildTargetName(for subset: BuildSubset) async throws -> String { + func inferTestDestination( + testModule: ResolvedModule, + graph: ModulesGraph + ) throws -> BuildParameters.Destination { + for product in graph.allProducts where product.type == .test { + if product.modules.contains(where: { $0.id == testModule.id }) { + return product.hasDirectMacroDependencies ? .host : .target + } + } + + throw InternalError("Could not find a product for test module: \(testModule)") + } + switch subset { case .allExcludingTests: return LLBuildManifestBuilder.TargetKind.main.targetName @@ -582,25 +595,22 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS // FIXME: This is super unfortunate that we might need to load the package graph. let graph = try await getPackageGraph() - let buildTriple: BuildTriple? = if let destination { - destination == .host ? .tools : .destination - } else { - nil - } - - let product = graph.product( - for: productName, - destination: buildTriple - ) + let product = graph.product(for: productName) guard let product else { observabilityScope.emit(error: "no product named '\(productName)'") throw Diagnostics.fatalError } - let buildParameters = config.buildParameters( - for: product.buildTriple == .tools ? .host : .target - ) + let buildParameters = if let destination { + config.buildParameters(for: destination) + } else if product.type == .macro || product.type == .plugin { + config.buildParameters(for: .host) + } else if product.type == .test { + config.buildParameters(for: product.hasDirectMacroDependencies ? .host : .target) + } else { + config.buildParameters(for: .target) + } // If the product is automatic, we build the main target because automatic products // do not produce a binary right now. @@ -616,27 +626,24 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS // FIXME: This is super unfortunate that we might need to load the package graph. let graph = try await getPackageGraph() - let buildTriple: BuildTriple? = if let destination { - destination == .host ? .tools : .destination - } else { - nil - } + let module = graph.module(for: targetName) - let target = graph.module( - for: targetName, - destination: buildTriple - ) - - guard let target else { + guard let module else { observabilityScope.emit(error: "no target named '\(targetName)'") throw Diagnostics.fatalError } - let buildParameters = config.buildParameters( - for: target.buildTriple == .tools ? .host : .target - ) + let buildParameters = if let destination { + config.buildParameters(for: destination) + } else if module.type == .macro || module.type == .plugin { + config.buildParameters(for: .host) + } else if module.type == .test { + try config.buildParameters(for: inferTestDestination(testModule: module, graph: graph)) + } else { + config.buildParameters(for: .target) + } - return target.getLLBuildTargetName(buildParameters: buildParameters) + return module.getLLBuildTargetName(buildParameters: buildParameters) } } @@ -1008,32 +1015,14 @@ extension BuildSubset { return Array(graph.reachableModules) case .allExcludingTests: return graph.reachableModules.filter { $0.type != .test } - case .product(let productName, let destination): - let buildTriple: BuildTriple? = if let destination { - destination == .host ? .tools : .destination - } else { - nil - } - - guard let product = graph.product( - for: productName, - destination: buildTriple - ) else { + case .product(let productName, _): + guard let product = graph.product(for: productName) else { observabilityScope.emit(error: "no product named '\(productName)'") return nil } return try product.recursiveModuleDependencies() - case .target(let targetName, let destination): - let buildTriple: BuildTriple? = if let destination { - destination == .host ? .tools : .destination - } else { - nil - } - - guard let target = graph.module( - for: targetName, - destination: buildTriple - ) else { + case .target(let targetName, _): + guard let target = graph.module(for: targetName) else { observabilityScope.emit(error: "no target named '\(targetName)'") return nil } diff --git a/Sources/Build/BuildPlan/BuildPlan+Test.swift b/Sources/Build/BuildPlan/BuildPlan+Test.swift index 94a14db29ff..7613b6e1b7b 100644 --- a/Sources/Build/BuildPlan/BuildPlan+Test.swift +++ b/Sources/Build/BuildPlan/BuildPlan+Test.swift @@ -92,7 +92,7 @@ extension BuildPlan { packageAccess: true, // test target is allowed access to package decls by default testDiscoverySrc: Sources(paths: discoveryPaths, root: discoveryDerivedDir) ) - var discoveryResolvedModule = ResolvedModule( + let discoveryResolvedModule = ResolvedModule( packageIdentity: testProduct.packageIdentity, underlying: discoveryTarget, dependencies: testProduct.modules.map { .module($0, conditions: []) }, @@ -100,7 +100,6 @@ extension BuildPlan { supportedPlatforms: testProduct.supportedPlatforms, platformVersionProvider: testProduct.platformVersionProvider ) - discoveryResolvedModule.buildTriple = testProduct.buildTriple let discoveryTargetBuildDescription = try SwiftModuleBuildDescription( package: package, @@ -135,7 +134,7 @@ extension BuildPlan { packageAccess: true, // test target is allowed access to package decls testEntryPointSources: entryPointSources ) - var entryPointResolvedTarget = ResolvedModule( + let entryPointResolvedTarget = ResolvedModule( packageIdentity: testProduct.packageIdentity, underlying: entryPointTarget, dependencies: testProduct.modules.map { .module($0, conditions: []) } + resolvedTargetDependencies, @@ -143,7 +142,6 @@ extension BuildPlan { supportedPlatforms: testProduct.supportedPlatforms, platformVersionProvider: testProduct.platformVersionProvider ) - entryPointResolvedTarget.buildTriple = testProduct.buildTriple return try SwiftModuleBuildDescription( package: package, diff --git a/Sources/Build/BuildPlan/BuildPlan.swift b/Sources/Build/BuildPlan/BuildPlan.swift index 9e2ea7836ca..f53bca3b8ce 100644 --- a/Sources/Build/BuildPlan/BuildPlan.swift +++ b/Sources/Build/BuildPlan/BuildPlan.swift @@ -419,10 +419,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan { switch $0 { case .module(let moduleDependency, _): if moduleDependency.type == .executable { - return graph.product( - for: moduleDependency.name, - destination: .tools - ) + return graph.product(for: moduleDependency.name) } return nil default: @@ -613,7 +610,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan { arguments.append("-l" + replProductName) // The graph should have the REPL product. - assert(self.graph.product(for: replProductName, destination: .destination) != nil) + assert(self.graph.product(for: replProductName) != nil) // Add the search path to the directory containing the modulemap file. for target in self.targets { @@ -958,7 +955,7 @@ extension BuildPlan { case .macro, .plugin: self = .product(product, .host) case .test: - self = .product(product, product.modules.contains(where: Self.hasMacroDependency) ? .host : destination) + self = .product(product, product.hasDirectMacroDependencies ? .host : destination) default: self = .product(product, destination) } @@ -973,7 +970,7 @@ extension BuildPlan { // Macros and plugins are ways built for host self = .module(module, .host) case .test: - self = .module(module, Self.hasMacroDependency(module: module) ? .host : destination) + self = .module(module, module.hasDirectMacroDependencies ? .host : destination) default: // By default assume the destination of the context. // This means that i.e. test products that reference macros @@ -981,17 +978,6 @@ extension BuildPlan { self = .module(module, destination) } } - - static func hasMacroDependency(module: ResolvedModule) -> Bool { - module.dependencies.contains(where: { - switch $0 { - case .product(let productDependency, _): - productDependency.type == .macro - case .module(let moduleDependency, _): - moduleDependency.type == .macro - } - }) - } } /// Traverse the modules graph and find a destination for every product and module. diff --git a/Sources/Commands/Snippets/Cards/SnippetCard.swift b/Sources/Commands/Snippets/Cards/SnippetCard.swift index 6a90da250a5..09d82750837 100644 --- a/Sources/Commands/Snippets/Cards/SnippetCard.swift +++ b/Sources/Commands/Snippets/Cards/SnippetCard.swift @@ -96,7 +96,7 @@ struct SnippetCard: Card { let buildSystem = try await swiftCommandState.createBuildSystem(explicitProduct: snippet.name, traitConfiguration: .init()) try await buildSystem.build(subset: .product(snippet.name)) let executablePath = try swiftCommandState.productsBuildParameters.buildPath.appending(component: snippet.name) - if let exampleTarget = try await buildSystem.getPackageGraph().module(for: snippet.name, destination: .destination) { + if let exampleTarget = try await buildSystem.getPackageGraph().module(for: snippet.name) { try ProcessEnv.chdir(exampleTarget.sources.paths[0].parentDirectory) } try exec(path: executablePath.pathString, args: []) diff --git a/Sources/Commands/SwiftRunCommand.swift b/Sources/Commands/SwiftRunCommand.swift index 602f5b45c6b..39e97a09499 100644 --- a/Sources/Commands/SwiftRunCommand.swift +++ b/Sources/Commands/SwiftRunCommand.swift @@ -231,7 +231,7 @@ public struct SwiftRunCommand: AsyncSwiftCommand { if let executable = options.executable { // There should be only one product with the given name in the graph // and it should be executable or snippet. - guard let product = graph.product(for: executable, destination: .destination), + guard let product = graph.product(for: executable), product.type == .executable || product.type == .snippet else { throw RunError.executableNotFound(executable) diff --git a/Sources/PackageGraph/BuildTriple.swift b/Sources/PackageGraph/BuildTriple.swift deleted file mode 100644 index 359628abaeb..00000000000 --- a/Sources/PackageGraph/BuildTriple.swift +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -import class PackageModel.Module -import class PackageModel.Product - -/// Triple for which code should be compiled for. -/// > Note: We're not using "host" and "target" triple terminology in this enum, as that clashes with build -/// > system "targets" and can lead to confusion in this context. -public enum BuildTriple: String { - /// Triple for which build tools are compiled (the host triple). - case tools = "tools" - - /// Triple of the destination platform for which end products are compiled (the target triple). - case destination = "destination" -} - -extension Module { - var buildTriple: BuildTriple { - if self.type == .macro || self.type == .plugin { - .tools - } else { - .destination - } - } -} - -extension Product { - var buildTriple: BuildTriple { - if self.type == .macro || self.type == .plugin { - .tools - } else { - .destination - } - } -} diff --git a/Sources/PackageGraph/CMakeLists.txt b/Sources/PackageGraph/CMakeLists.txt index e4466f3151b..9ce1edd89c6 100644 --- a/Sources/PackageGraph/CMakeLists.txt +++ b/Sources/PackageGraph/CMakeLists.txt @@ -8,7 +8,6 @@ add_library(PackageGraph BoundVersion.swift - BuildTriple.swift DependencyMirrors.swift Diagnostics.swift GraphLoadingNode.swift diff --git a/Sources/PackageGraph/ModulesGraph.swift b/Sources/PackageGraph/ModulesGraph.swift index 836fdbaecf7..8cfac5a1933 100644 --- a/Sources/PackageGraph/ModulesGraph.swift +++ b/Sources/PackageGraph/ModulesGraph.swift @@ -166,65 +166,19 @@ public struct ModulesGraph { /// Find a product given a name and an optional destination. If a destination is not specified /// this method uses `.destination` and falls back to `.tools` for macros, plugins, and tests. - public func product(for name: String, destination: BuildTriple? = .none) -> ResolvedProduct? { - func findProduct(name: String, destination: BuildTriple) -> ResolvedProduct? { - self.allProducts.first { $0.name == name && $0.buildTriple == destination } - } - - if let destination { - return findProduct(name: name, destination: destination) - } - - if let product = findProduct(name: name, destination: .destination) { - return product - } - - // It's possible to request a build of a macro, a plugin, or a test via `swift build` - // which won't have the right destination set because it's impossible to indicate it. - // - // Same happens with `--test-product` - if one of the test modules directly references - // a macro then all if its modules and the product itself become `host`. - if let toolsProduct = findProduct(name: name, destination: .tools), - toolsProduct.type == .macro || toolsProduct.type == .plugin || toolsProduct.type == .test - { - return toolsProduct - } - - return nil + public func product(for name: String) -> ResolvedProduct? { + self.allProducts.first { $0.name == name } } - @available(*, deprecated, renamed: "module(for:destination:)") - public func target(for name: String, destination: BuildTriple? = .none) -> ResolvedModule? { - self.module(for: name, destination: destination) + @available(*, deprecated, renamed: "module(for:)") + public func target(for name: String) -> ResolvedModule? { + self.module(for: name) } /// Find a module given a name and an optional destination. If a destination is not specified /// this method uses `.destination` and falls back to `.tools` for macros, plugins, and tests. - public func module(for name: String, destination: BuildTriple? = .none) -> ResolvedModule? { - func findModule(name: String, destination: BuildTriple) -> ResolvedModule? { - self.allModules.first { $0.name == name && $0.buildTriple == destination } - } - - if let destination { - return findModule(name: name, destination: destination) - } - - if let module = findModule(name: name, destination: .destination) { - return module - } - - // It's possible to request a build of a macro, a plugin or a test via `swift build` - // which won't have the right destination set because it's impossible to indicate it. - // - // Same happens with `--test-product` - if one of the test modules directly references - // a macro then all if its modules and the product itself become `host`. - if let toolsModule = findModule(name: name, destination: .tools), - toolsModule.type == .macro || toolsModule.type == .plugin || toolsModule.type == .test - { - return toolsModule - } - - return nil + public func module(for name: String) -> ResolvedModule? { + self.allModules.first { $0.name == name } } /// All root and root dependency packages provided as input to the graph. @@ -250,61 +204,16 @@ public struct ModulesGraph { var allModules = IdentifiableSet() var allProducts = IdentifiableSet() for package in self.packages { - let modulesToInclude: [ResolvedModule] - if rootPackages.contains(id: package.id) { - modulesToInclude = Array(package.modules) + let modulesToInclude = if rootPackages.contains(id: package.id) { + Array(package.modules) } else { // Don't include tests modules from non-root packages so swift-test doesn't // try to run them. - modulesToInclude = package.modules.filter { $0.type != .test } + package.modules.filter { $0.type != .test } } for module in modulesToInclude { allModules.insert(module) - - // Explicitly include dependencies of host tools in the maps of all modules or all products - if module.buildTriple == .tools { - for dependency in try module.recursiveDependencies() { - switch dependency { - case .module(let moduleDependency, _): - allModules.insert(moduleDependency) - case .product(let productDependency, _): - allProducts.insert(productDependency) - } - } - } - - // Create a new executable product if plugin depends on an executable module. - // This is necessary, even though PackageBuilder creates one already, because - // that product is going to be built for `destination`, and this one has to - // be built for `tools`. - if module.underlying is PluginModule { - for dependency in module.dependencies { - switch dependency { - case .product(_, conditions: _): - break - - case .module(let module, conditions: _): - if module.type != .executable { - continue - } - - var product = try ResolvedProduct( - packageIdentity: module.packageIdentity, - product: .init( - package: module.packageIdentity, - name: module.name, - type: .executable, - modules: [module.underlying] - ), - modules: IdentifiableSet([module]) - ) - product.buildTriple = .tools - - allProducts.insert(product) - } - } - } } if rootPackages.contains(id: package.id) { diff --git a/Sources/PackageGraph/Resolution/ResolvedModule.swift b/Sources/PackageGraph/Resolution/ResolvedModule.swift index fd205f6a4f0..c7b535bcf49 100644 --- a/Sources/PackageGraph/Resolution/ResolvedModule.swift +++ b/Sources/PackageGraph/Resolution/ResolvedModule.swift @@ -168,11 +168,15 @@ public struct ResolvedModule { @_spi(SwiftPMInternal) public let platformVersionProvider: PlatformVersionProvider - /// Triple for which this resolved module should be compiled for. - public package(set) var buildTriple: BuildTriple { - didSet { - self.updateBuildTriplesOfDependencies() - } + package var hasDirectMacroDependencies: Bool { + self.dependencies.contains(where: { + switch $0 { + case .product(let productDependency, _): + productDependency.type == .macro + case .module(let moduleDependency, _): + moduleDependency.type == .macro + } + }) } /// Create a resolved module instance. @@ -190,50 +194,6 @@ public struct ResolvedModule { self.defaultLocalization = defaultLocalization self.supportedPlatforms = supportedPlatforms self.platformVersionProvider = platformVersionProvider - - if underlying.type == .test { - // Make sure that test products are built for the tools triple if it has tools as direct dependencies. - // Without this workaround, `assertMacroExpansion` in tests can't be built, as it requires macros - // and SwiftSyntax to be built for the same triple as the tests. - // See https://github.com/swiftlang/swift-package-manager/pull/7349 for more context. - var inferredBuildTriple = BuildTriple.destination - loop: for dependency in dependencies { - switch dependency { - case .module(let moduleDependency, _): - if moduleDependency.type == .macro { - inferredBuildTriple = .tools - break loop - } - case .product(let productDependency, _): - if productDependency.type == .macro { - inferredBuildTriple = .tools - break loop - } - } - } - self.buildTriple = inferredBuildTriple - } else { - self.buildTriple = underlying.buildTriple - } - self.updateBuildTriplesOfDependencies() - } - - mutating func updateBuildTriplesOfDependencies() { - if self.buildTriple == .tools { - for (i, dependency) in dependencies.enumerated() { - let updatedDependency: Dependency - switch dependency { - case .module(var module, let conditions): - module.buildTriple = self.buildTriple - updatedDependency = .module(module, conditions: conditions) - case .product(var product, let conditions): - product.buildTriple = self.buildTriple - updatedDependency = .product(product, conditions: conditions) - } - - dependencies[i] = updatedDependency - } - } } public func getSupportedPlatform(for platform: Platform, usingXCTest: Bool) -> SupportedPlatform { @@ -247,7 +207,7 @@ public struct ResolvedModule { extension ResolvedModule: CustomStringConvertible { public var description: String { - return "" + return "" } } @@ -322,11 +282,10 @@ extension ResolvedModule: Identifiable { public let moduleName: String let packageIdentity: PackageIdentity - public var buildTriple: BuildTriple } public var id: ID { - ID(moduleName: self.name, packageIdentity: self.packageIdentity, buildTriple: self.buildTriple) + ID(moduleName: self.name, packageIdentity: self.packageIdentity) } } diff --git a/Sources/PackageGraph/Resolution/ResolvedProduct.swift b/Sources/PackageGraph/Resolution/ResolvedProduct.swift index 99aa2448506..c6cbbe3bf1d 100644 --- a/Sources/PackageGraph/Resolution/ResolvedProduct.swift +++ b/Sources/PackageGraph/Resolution/ResolvedProduct.swift @@ -50,13 +50,6 @@ public struct ResolvedProduct { @_spi(SwiftPMInternal) public let platformVersionProvider: PlatformVersionProvider - /// Triple for which this resolved product should be compiled for. - public internal(set) var buildTriple: BuildTriple { - didSet { - self.updateBuildTriplesOfDependencies() - } - } - @available(*, deprecated, renamed: "executableModule") public var executableTarget: ResolvedModule { get throws { try self.executableModule } } @@ -77,6 +70,10 @@ public struct ResolvedProduct { } } + package var hasDirectMacroDependencies: Bool { + self.modules.contains(where: \.hasDirectMacroDependencies) + } + @available(*, deprecated, renamed: "init(packageIdentity:product:modules:)") public init( packageIdentity: PackageIdentity, @@ -123,42 +120,6 @@ public struct ResolvedProduct { platformVersionProvider: platformVersionProvider ) } - - if product.type == .test { - // Make sure that test products are built for the tools triple if it has tools as direct dependencies. - // Without this workaround, `assertMacroExpansion` in tests can't be built, as it requires macros - // and SwiftSyntax to be built for the same triple as the tests. - // See https://github.com/swiftlang/swift-package-manager/pull/7349 for more context. - var inferredBuildTriple = BuildTriple.destination - modulesLoop: for module in modules { - for dependency in module.dependencies { - switch dependency { - case .module(let moduleDependency, _): - if moduleDependency.type == .macro { - inferredBuildTriple = .tools - break modulesLoop - } - case .product(let productDependency, _): - if productDependency.type == .macro { - inferredBuildTriple = .tools - break modulesLoop - } - } - } - } - self.buildTriple = inferredBuildTriple - } else { - self.buildTriple = product.buildTriple - } - self.updateBuildTriplesOfDependencies() - } - - mutating func updateBuildTriplesOfDependencies() { - self.modules = IdentifiableSet(self.modules.map { - var module = $0 - module.buildTriple = self.buildTriple - return module - }) } @available(*, deprecated, renamed: "containsSwiftModules") @@ -218,7 +179,7 @@ public struct ResolvedProduct { extension ResolvedProduct: CustomStringConvertible { public var description: String { - "" + "" } } @@ -235,11 +196,10 @@ extension ResolvedProduct: Identifiable { public struct ID: Hashable { public let productName: String let packageIdentity: PackageIdentity - public var buildTriple: BuildTriple } public var id: ID { - ID(productName: self.name, packageIdentity: self.packageIdentity, buildTriple: self.buildTriple) + ID(productName: self.name, packageIdentity: self.packageIdentity) } } diff --git a/Sources/_InternalTestSupport/MockBuildTestHelper.swift b/Sources/_InternalTestSupport/MockBuildTestHelper.swift index 30a68afc3a1..ef9bdf7ce55 100644 --- a/Sources/_InternalTestSupport/MockBuildTestHelper.swift +++ b/Sources/_InternalTestSupport/MockBuildTestHelper.swift @@ -285,54 +285,50 @@ enum BuildError: Swift.Error { public struct BuildPlanResult { public let plan: Build.BuildPlan - public let targetMap: [ResolvedModule.ID: Build.ModuleBuildDescription] - public let productMap: [ResolvedProduct.ID: Build.ProductBuildDescription] + + public var productMap: IdentifiableSet { + self.plan.productMap + } + + public var targetMap: IdentifiableSet { + self.plan.targetMap + } public init(plan: Build.BuildPlan) throws { self.plan = plan - self.productMap = try Dictionary( - throwingUniqueKeysWithValues: plan.buildProducts - .compactMap { $0 as? Build.ProductBuildDescription } - .map { ($0.product.id, $0) } - ) - self.targetMap = try Dictionary( - throwingUniqueKeysWithValues: plan.targetMap.compactMap { - ($0.module.id, $0) - } - ) } public func checkTargetsCount(_ count: Int, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(self.plan.targetMap.count, count, file: file, line: line) + XCTAssertEqual(self.targetMap.count, count, file: file, line: line) } public func checkProductsCount(_ count: Int, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(self.plan.productMap.count, count, file: file, line: line) + XCTAssertEqual(self.productMap.count, count, file: file, line: line) } public func moduleBuildDescription(for name: String) throws -> Build.ModuleBuildDescription { - let matchingIDs = targetMap.keys.filter({ $0.moduleName == name }) - guard matchingIDs.count == 1, let target = targetMap[matchingIDs[0]] else { - if matchingIDs.isEmpty { + let matches = self.targetMap.filter({ $0.module.name == name }) + guard matches.count == 1 else { + if matches.isEmpty { throw BuildError.error("Target \(name) not found.") } else { throw BuildError.error("More than one target \(name) found.") } } - return target + return matches.first! } public func buildProduct(for name: String) throws -> Build.ProductBuildDescription { - let matchingIDs = productMap.keys.filter({ $0.productName == name }) - guard matchingIDs.count == 1, let product = productMap[matchingIDs[0]] else { - if matchingIDs.isEmpty { + let matches = self.productMap.filter({ $0.product.name == name }) + guard matches.count == 1 else { + if matches.isEmpty { // Display the thrown error on macOS throw BuildError.error("Product \(name) not found.") } else { throw BuildError.error("More than one target \(name) found.") } } - return product + return matches.first! } } diff --git a/Sources/_InternalTestSupport/MockPackageGraphs.swift b/Sources/_InternalTestSupport/MockPackageGraphs.swift index 6d5a92a2f1e..8903a461f24 100644 --- a/Sources/_InternalTestSupport/MockPackageGraphs.swift +++ b/Sources/_InternalTestSupport/MockPackageGraphs.swift @@ -212,7 +212,7 @@ package func macrosTestsPackageGraph() throws -> MockPackageGraph { ) ] ), - Manifest.createFileSystemManifest( + Manifest.createRootManifest( displayName: "swift-syntax", path: "/swift-syntax", products: [ diff --git a/Sources/_InternalTestSupport/PackageGraphTester.swift b/Sources/_InternalTestSupport/PackageGraphTester.swift index e7691e8db9d..896845cbe15 100644 --- a/Sources/_InternalTestSupport/PackageGraphTester.swift +++ b/Sources/_InternalTestSupport/PackageGraphTester.swift @@ -88,12 +88,11 @@ public final class PackageGraphResult { public func checkTarget( _ name: String, - destination: BuildTriple? = .none, file: StaticString = #file, line: UInt = #line, body: (ResolvedTargetResult) -> Void ) { - let target = graph.module(for: name, destination: destination) + let target = graph.module(for: name) guard let target else { return XCTFail("Target \(name) not found", file: file, line: line) @@ -113,12 +112,11 @@ public final class PackageGraphResult { public func checkProduct( _ name: String, - destination: BuildTriple? = .none, file: StaticString = #file, line: UInt = #line, body: (ResolvedProductResult) -> Void ) { - let product = graph.product(for: name, destination: destination) + let product = graph.product(for: name) guard let product else { return XCTFail("Product \(name) not found", file: file, line: line) @@ -242,9 +240,6 @@ public final class ResolvedTargetResult { line: line ) } - public func check(buildTriple: BuildTriple, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(self.target.buildTriple, buildTriple, file: file, line: line) - } } public final class ResolvedTargetDependencyResult { @@ -323,10 +318,6 @@ public final class ResolvedProductResult { XCTAssertEqual(platform.options, options, file: file, line: line) } - public func check(buildTriple: BuildTriple, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(self.product.buildTriple, buildTriple, file: file, line: line) - } - public func checkTarget( _ name: String, file: StaticString = #file, diff --git a/Tests/BuildTests/BuildOperationTests.swift b/Tests/BuildTests/BuildOperationTests.swift index c538e31e255..858e67e075f 100644 --- a/Tests/BuildTests/BuildOperationTests.swift +++ b/Tests/BuildTests/BuildOperationTests.swift @@ -137,19 +137,37 @@ final class BuildOperationTests: XCTestCase { func testHostProductsAndTargetsWithoutExplicitDestination() async throws { let mock = try macrosTestsPackageGraph() + let hostParameters = mockBuildParameters(destination: .host) + let targetParameters = mockBuildParameters(destination: .target) let op = mockBuildOperation( - productsBuildParameters: mockBuildParameters(destination: .target), - toolsBuildParameters: mockBuildParameters(destination: .host), + productsBuildParameters: targetParameters, + toolsBuildParameters: hostParameters, packageGraphLoader: { mock.graph }, scratchDirectory: AbsolutePath("/.build/\(hostTriple)"), fs: mock.fileSystem, observabilityScope: mock.observabilityScope ) - let result = try await op.computeLLBuildTargetName(for: .product("MMIOMacros")) + let mmioMacrosProductName = try await op.computeLLBuildTargetName(for: .product("MMIOMacros")) XCTAssertEqual( "MMIOMacros-\(hostTriple)-debug-tool.exe", - result + mmioMacrosProductName + ) + + let mmioTestsProductName = try await op.computeLLBuildTargetName( + for: .product("swift-mmioPackageTests") + ) + XCTAssertEqual( + "swift-mmioPackageTests-\(hostTriple)-debug-tool.test", + mmioTestsProductName + ) + + let swiftSyntaxTestsProductName = try await op.computeLLBuildTargetName( + for: .product("swift-syntaxPackageTests") + ) + XCTAssertEqual( + "swift-syntaxPackageTests-\(targetParameters.triple)-debug.test", + swiftSyntaxTestsProductName ) for target in ["MMIOMacros", "MMIOPlugin", "MMIOMacrosTests", "MMIOMacro+PluginTests"] { @@ -160,6 +178,14 @@ final class BuildOperationTests: XCTestCase { ) } + let swiftSyntaxTestsTarget = try await op.computeLLBuildTargetName( + for: .target("SwiftSyntaxTests") + ) + XCTAssertEqual( + "SwiftSyntaxTests-\(targetParameters.triple)-debug.module", + swiftSyntaxTestsTarget + ) + let dependencies = try BuildSubset.target("MMIOMacro+PluginTests").recursiveDependencies( for: mock.graph, observabilityScope: mock.observabilityScope @@ -167,9 +193,5 @@ final class BuildOperationTests: XCTestCase { XCTAssertNotNil(dependencies) XCTAssertTrue(dependencies!.count > 0) - - for dependency in dependencies! { - XCTAssertEqual(dependency.buildTriple, .tools) - } } } diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index 394574dbea5..a13b32855b2 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -1145,7 +1145,7 @@ final class BuildPlanTests: XCTestCase { observabilityScope: observability.topScope )) - XCTAssertEqual(Set(result.productMap.keys.map(\.productName)), ["APackageTests"]) + XCTAssertEqual(Set(result.productMap.map(\.product.name)), ["APackageTests"]) var expectedTargets: Set = [ "APackageTests", "ATarget", @@ -1155,7 +1155,7 @@ final class BuildPlanTests: XCTestCase { #if !os(macOS) expectedTargets.insert("APackageDiscoveredTests") #endif - XCTAssertEqual(Set(result.targetMap.keys.map(\.moduleName)), expectedTargets) + XCTAssertEqual(Set(result.targetMap.map(\.module.name)), expectedTargets) } func testBasicReleasePackage() async throws { @@ -1503,9 +1503,8 @@ final class BuildPlanTests: XCTestCase { let buildProduct = try XCTUnwrap( result.productMap[.init( - productName: "exe", - packageIdentity: "Pkg", - buildTriple: .destination + productID: .init(productName: "exe", packageIdentity: "Pkg"), + destination: .target )] ) XCTAssertEqual(Array(buildProduct.objects), [ @@ -6273,10 +6272,9 @@ final class BuildPlanTests: XCTestCase { )) switch try XCTUnwrap( - result.targetMap[.init( - moduleName: "ExtLib", - packageIdentity: "ExtPkg", - buildTriple: .destination + result.plan.targetMap[.init( + moduleID: .init(moduleName: "ExtLib", packageIdentity: "ExtPkg"), + destination: .target )] ) { case .swift(let swiftTarget): @@ -6441,10 +6439,9 @@ final class BuildPlanTests: XCTestCase { XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "FooLogging" }) XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "BarLogging" }) let buildProduct = try XCTUnwrap( - result.productMap[.init( - productName: "exe", - packageIdentity: "thisPkg", - buildTriple: .destination + result.plan.productMap[.init( + productID: .init(productName: "exe", packageIdentity: "thisPkg"), + destination: .target )] ) let dylibs = Array(buildProduct.dylibs.map({$0.product.name})).sorted() diff --git a/Tests/BuildTests/CrossCompilationBuildPlanTests.swift b/Tests/BuildTests/CrossCompilationBuildPlanTests.swift index 607d1c8767e..76e37ccc907 100644 --- a/Tests/BuildTests/CrossCompilationBuildPlanTests.swift +++ b/Tests/BuildTests/CrossCompilationBuildPlanTests.swift @@ -15,10 +15,9 @@ import class Basics.InMemoryFileSystem import class Basics.ObservabilitySystem import class Build.BuildPlan import class Build.ProductBuildDescription -import enum Build.ModuleBuildDescription +@testable import enum Build.ModuleBuildDescription import class Build.SwiftModuleBuildDescription import struct Basics.Triple -import enum PackageGraph.BuildTriple import class PackageModel.Manifest import struct PackageModel.TargetDescription import enum PackageModel.ProductType @@ -162,7 +161,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase { let lib = try XCTUnwrap( result.allTargets(named: "lib") .map { try $0.clang() } - .first { $0.target.buildTriple == .destination } + .first { $0.destination == .target } ) XCTAssertEqual(try lib.basicArguments(isCXX: false), [ @@ -249,11 +248,11 @@ final class CrossCompilationBuildPlanTests: XCTestCase { XCTAssertTrue(try result.allTargets(named: "SwiftSyntax") .map { try $0.swift() } - .contains { $0.target.buildTriple == .tools }) - try result.check(buildTriple: .tools, triple: toolsTriple, for: "MMIOMacros") - try result.check(buildTriple: .destination, triple: destinationTriple, for: "MMIO") - try result.check(buildTriple: .destination, triple: destinationTriple, for: "Core") - try result.check(buildTriple: .destination, triple: destinationTriple, for: "HAL") + .contains { $0.destination == .host }) + try result.check(destination: .host, triple: toolsTriple, for: "MMIOMacros") + try result.check(destination: .target, triple: destinationTriple, for: "MMIO") + try result.check(destination: .target, triple: destinationTriple, for: "Core") + try result.check(destination: .target, triple: destinationTriple, for: "HAL") let macroProducts = result.allProducts(named: "MMIOMacros") XCTAssertEqual(macroProducts.count, 1) @@ -296,24 +295,28 @@ final class CrossCompilationBuildPlanTests: XCTestCase { observabilityScope: scope ) - // Make sure that build plan doesn't have any "target" tests. + // Make sure that build plan doesn't have any "target" tests except SwiftSyntax ones. for description in plan.targetMap where description.module.underlying.type == .test { - XCTAssertEqual(description.buildParameters.destination, .host) + XCTAssertEqual( + description.buildParameters.destination, + description.module.name == "SwiftSyntaxTests" ? .target : .host + ) } let result = try BuildPlanResult(plan: plan) - result.checkProductsCount(2) - result.checkTargetsCount(17) + result.checkProductsCount(3) + result.checkTargetsCount(20) XCTAssertTrue(try result.allTargets(named: "SwiftSyntax") .map { try $0.swift() } - .contains { $0.target.buildTriple == .tools }) + .contains { $0.destination == .host }) - try result.check(buildTriple: .tools, triple: toolsTriple, for: "swift-mmioPackageTests") - try result.check(buildTriple: .tools, triple: toolsTriple, for: "swift-mmioPackageDiscoveredTests") - try result.check(buildTriple: .tools, triple: toolsTriple, for: "MMIOMacros") - try result.check(buildTriple: .destination, triple: destinationTriple, for: "MMIO") - try result.check(buildTriple: .tools, triple: toolsTriple, for: "MMIOMacrosTests") + try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageTests") + try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageDiscoveredTests") + try result.check(destination: .host, triple: toolsTriple, for: "MMIOMacros") + try result.check(destination: .target, triple: destinationTriple, for: "MMIO") + try result.check(destination: .host, triple: toolsTriple, for: "MMIOMacrosTests") + try result.check(destination: .target, triple: destinationTriple, for: "swift-syntaxPackageTests") let macroProducts = result.allProducts(named: "MMIOMacros") XCTAssertEqual(macroProducts.count, 1) @@ -362,12 +365,12 @@ final class CrossCompilationBuildPlanTests: XCTestCase { XCTAssertTrue(try result.allTargets(named: "SwiftSyntax") .map { try $0.swift() } - .contains { $0.target.buildTriple == .tools }) + .contains { $0.destination == .host }) - try result.check(buildTriple: .tools, triple: toolsTriple, for: "swift-mmioPackageTests") - try result.check(buildTriple: .tools, triple: toolsTriple, for: "swift-mmioPackageDiscoveredTests") - try result.check(buildTriple: .tools, triple: toolsTriple, for: "MMIOMacros") - try result.check(buildTriple: .tools, triple: toolsTriple, for: "MMIOMacrosTests") + try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageTests") + try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageDiscoveredTests") + try result.check(destination: .host, triple: toolsTriple, for: "MMIOMacros") + try result.check(destination: .host, triple: toolsTriple, for: "MMIOMacrosTests") let macroProducts = result.allProducts(named: "MMIOMacros") XCTAssertEqual(macroProducts.count, 1) @@ -376,7 +379,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase { let swiftSyntaxProducts = result.allProducts(named: "SwiftSyntax") XCTAssertEqual(swiftSyntaxProducts.count, 2) - let swiftSyntaxToolsProduct = try XCTUnwrap(swiftSyntaxProducts.first { $0.product.buildTriple == .tools }) + let swiftSyntaxToolsProduct = try XCTUnwrap(swiftSyntaxProducts.first { $0.destination == .host }) let archiveArguments = try swiftSyntaxToolsProduct.archiveArguments() // Verify that produced library file has a correct name @@ -388,30 +391,28 @@ final class CrossCompilationBuildPlanTests: XCTestCase { extension BuildPlanResult { func allTargets(named name: String) throws -> some Collection { self.targetMap - .filter { $0.0.moduleName == name } - .values + .filter { $0.module.name == name } } func allProducts(named name: String) -> some Collection { self.productMap - .filter { $0.0.productName == name } - .values + .filter { $0.product.name == name } } func check( - buildTriple: BuildTriple, + destination: BuildParameters.Destination, triple: Triple, for target: String, file: StaticString = #file, line: UInt = #line ) throws { let targets = self.targetMap.filter { - $0.key.moduleName == target && $0.key.buildTriple == buildTriple + $0.module.name == target && $0.destination == destination } XCTAssertEqual(targets.count, 1, file: file, line: line) let target = try XCTUnwrap( - targets.first?.value, + targets.first, file: file, line: line ).swift() diff --git a/Tests/BuildTests/PrepareForIndexTests.swift b/Tests/BuildTests/PrepareForIndexTests.swift index 2004d11d207..c283b360391 100644 --- a/Tests/BuildTests/PrepareForIndexTests.swift +++ b/Tests/BuildTests/PrepareForIndexTests.swift @@ -87,7 +87,7 @@ class PrepareForIndexTests: XCTestCase { let manifest = try builder.generatePrepareManifest(at: "/manifest") // Ensure our C module is here. - let lib = try XCTUnwrap(graph.module(for: "lib", destination: .destination)) + let lib = try XCTUnwrap(graph.module(for: "lib")) let name = lib.getLLBuildTargetName(buildParameters: plan.destinationBuildParameters) XCTAssertTrue(manifest.targets.keys.contains(name)) } diff --git a/Tests/BuildTests/ProductBuildDescriptionTests.swift b/Tests/BuildTests/ProductBuildDescriptionTests.swift index ffbefbcf3aa..5674142e10d 100644 --- a/Tests/BuildTests/ProductBuildDescriptionTests.swift +++ b/Tests/BuildTests/ProductBuildDescriptionTests.swift @@ -55,7 +55,7 @@ final class ProductBuildDescriptionTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let id = ResolvedProduct.ID(productName: "exe", packageIdentity: .plain("pkg"), buildTriple: .destination) + let id = ResolvedProduct.ID(productName: "exe", packageIdentity: .plain("pkg")) let package = try XCTUnwrap(graph.rootPackages.first) let product = try XCTUnwrap(graph.allProducts[id]) diff --git a/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift b/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift index 790c62e114a..5e7119d5b45 100644 --- a/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift +++ b/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift @@ -22,21 +22,18 @@ import XCTest final class CrossCompilationPackageGraphTests: XCTestCase { func testTrivialPackage() throws { let graph = try trivialPackageGraph().graph - try PackageGraphTester(graph) { result in + PackageGraphTester(graph) { result in result.check(packages: "Pkg") // "SwiftSyntax" is included for both host and target triples and is not pruned on this level result.check(modules: "app", "lib") result.check(testModules: "test") result.checkTarget("app") { result in - result.check(buildTriple: .destination) result.check(dependencies: "lib") } - try result.checkTargets("lib") { results in - let result = try XCTUnwrap(results.first { $0.target.buildTriple == .destination }) + result.checkTarget("lib") { result in result.check(dependencies: []) } result.checkTarget("test") { result in - result.check(buildTriple: .destination) result.check(dependencies: "lib") } } @@ -44,54 +41,36 @@ final class CrossCompilationPackageGraphTests: XCTestCase { func testMacros() throws { let graph = try macrosPackageGraph().graph - try PackageGraphTester(graph) { result in + PackageGraphTester(graph) { result in result.check(packages: "swift-firmware", "swift-mmio", "swift-syntax") - // "SwiftSyntax" is included for both host and target triples and is not pruned on this level result.check( modules: "Core", "HAL", "MMIO", "MMIOMacros", - "SwiftSyntax", "SwiftSyntax" ) result.check(testModules: "CoreTests", "HALTests") - try result.checkTargets("Core") { results in - let result = try XCTUnwrap(results.first { $0.target.buildTriple == .destination }) + result.checkTarget("Core") { result in result.check(dependencies: "HAL") } - try result.checkTargets("HAL") { results in - let result = try XCTUnwrap(results.first { $0.target.buildTriple == .destination }) - result.check(buildTriple: .destination) + result.checkTarget("HAL") { result in result.check(dependencies: "MMIO") } - try result.checkTargets("MMIO") { results in - let result = try XCTUnwrap(results.first { $0.target.buildTriple == .destination }) - result.check(buildTriple: .destination) + result.checkTarget("MMIO") { result in result.check(dependencies: "MMIOMacros") } - try result.checkTargets("MMIOMacros") { results in - let result = try XCTUnwrap(results.first(where: { $0.target.buildTriple == .tools })) - result.check(buildTriple: .tools) + result.checkTarget("MMIOMacros") { result in result.checkDependency("SwiftSyntax") { result in result.checkProduct { result in - result.check(buildTriple: .tools) - result.checkTarget("SwiftSyntax") { result in - result.check(buildTriple: .tools) + result.checkTarget("SwiftSyntax") { _ in } } } } - result.checkProduct("MMIOMacros") { result in - result.check(buildTriple: .tools) - } - result.checkTargets("SwiftSyntax") { results in - XCTAssertEqual(results.count, 2) - - XCTAssertEqual(results.filter({ $0.target.buildTriple == .tools }).count, 1) - XCTAssertEqual(results.filter({ $0.target.buildTriple == .destination }).count, 1) + XCTAssertEqual(results.count, 1) } } } @@ -106,47 +85,32 @@ final class CrossCompilationPackageGraphTests: XCTestCase { "MMIOMacros", "MMIOPlugin", "SwiftCompilerPlugin", - "SwiftCompilerPlugin", - "SwiftCompilerPluginMessageHandling", "SwiftCompilerPluginMessageHandling", "SwiftSyntax", - "SwiftSyntax", "SwiftSyntaxMacros", - "SwiftSyntaxMacros", - "SwiftSyntaxMacrosTestSupport", "SwiftSyntaxMacrosTestSupport" ) - // TODO: NOOPTests are mentioned twice because in the graph they appear - // as if they target both "tools" and "destination", see the test below. - // Once the `buildTriple` is gone, there is going to be only one mention - // left. - result.check(testModules: "MMIOMacrosTests", "MMIOMacro+PluginTests", "NOOPTests", "NOOPTests") + + result.check(testModules: "MMIOMacrosTests", "MMIOMacro+PluginTests", "NOOPTests", "SwiftSyntaxTests") result.checkTarget("MMIO") { result in - result.check(buildTriple: .destination) result.check(dependencies: "MMIOMacros") } result.checkTargets("MMIOMacros") { results in XCTAssertEqual(results.count, 1) } - result.checkTarget("MMIOMacrosTests", destination: .tools) { result in - result.check(buildTriple: .tools) + result.checkTarget("MMIOMacrosTests") { result in result.checkDependency("MMIOMacros") { result in result.checkTarget { result in - result.check(buildTriple: .tools) result.checkDependency("SwiftSyntaxMacros") { result in - result.checkProduct { result in - result.check(buildTriple: .tools) + result.checkProduct { _ in } } result.checkDependency("SwiftCompilerPlugin") { result in result.checkProduct { result in - result.check(buildTriple: .tools) result.checkTarget("SwiftCompilerPlugin") { result in - result.check(buildTriple: .tools) result.checkDependency("SwiftCompilerPluginMessageHandling") { result in - result.checkTarget { result in - result.check(buildTriple: .tools) + result.checkTarget { _ in } } } @@ -156,19 +120,14 @@ final class CrossCompilationPackageGraphTests: XCTestCase { } } - result.checkTarget("MMIOMacros") { result in - result.check(buildTriple: .tools) + result.checkTarget("MMIOMacros") { _ in } - result.checkTarget("MMIOMacrosTests") { result in - result.check(buildTriple: .tools) + result.checkTarget("MMIOMacrosTests") { _ in } result.checkTargets("SwiftSyntax") { results in - XCTAssertEqual(results.count, 2) - - XCTAssertEqual(results.filter({ $0.target.buildTriple == .tools }).count, 1) - XCTAssertEqual(results.filter({ $0.target.buildTriple == .destination }).count, 1) + XCTAssertEqual(results.count, 1) for result in results { XCTAssertEqual(result.target.packageIdentity, .plain("swift-syntax")) @@ -177,7 +136,7 @@ final class CrossCompilationPackageGraphTests: XCTestCase { } result.checkTargets("SwiftCompilerPlugin") { results in - XCTAssertEqual(results.count, 2) + XCTAssertEqual(results.count, 1) for result in results { XCTAssertEqual(result.target.packageIdentity, .plain("swift-syntax")) @@ -186,41 +145,7 @@ final class CrossCompilationPackageGraphTests: XCTestCase { } result.checkTargets("NOOPTests") { results in - XCTAssertEqual(results.count, 2) - - XCTAssertEqual(results.filter({ $0.target.buildTriple == .tools }).count, 1) - XCTAssertEqual(results.filter({ $0.target.buildTriple == .destination }).count, 1) - } - } - } - - func testPlugins() throws { - let graph = try macrosTestsPackageGraph().graph - PackageGraphTester(graph) { result in - result.checkProduct("MMIOPlugin", destination: .tools) { result in - result.check(buildTriple: .tools) - } - - result.checkProduct("MMIOPlugin") { result in - result.check(buildTriple: .tools) - } - - result.checkTarget("MMIOPlugin", destination: .tools) { result in - result.check(buildTriple: .tools) - } - - result.checkTarget("MMIOPlugin") { result in - result.check(buildTriple: .tools) - } - - result.checkTarget("MMIOMacro+PluginTests", destination: .tools) { result in - result.check(buildTriple: .tools) - result.check(dependencies: "MMIOPlugin", "MMIOMacros") - } - - result.checkTarget("MMIOMacro+PluginTests") { result in - result.check(buildTriple: .tools) - result.check(dependencies: "MMIOPlugin", "MMIOMacros") + XCTAssertEqual(results.count, 1) } } } diff --git a/Tests/PackageGraphTests/ModulesGraphTests.swift b/Tests/PackageGraphTests/ModulesGraphTests.swift index da138f690fc..11ce25959ef 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests.swift @@ -83,12 +83,12 @@ final class ModulesGraphTests: XCTestCase { } let fooPackage = try XCTUnwrap(g.package(for: .plain("Foo"))) - let fooTarget = try XCTUnwrap(g.module(for: "Foo", destination: .destination)) - let fooDepTarget = try XCTUnwrap(g.module(for: "FooDep", destination: .destination)) + let fooTarget = try XCTUnwrap(g.module(for: "Foo")) + let fooDepTarget = try XCTUnwrap(g.module(for: "FooDep")) XCTAssertEqual(g.package(for: fooTarget)?.id, fooPackage.id) XCTAssertEqual(g.package(for: fooDepTarget)?.id, fooPackage.id) let barPackage = try XCTUnwrap(g.package(for: .plain("Bar"))) - let barTarget = try XCTUnwrap(g.module(for: "Bar", destination: .destination)) + let barTarget = try XCTUnwrap(g.module(for: "Bar")) XCTAssertEqual(g.package(for: barTarget)?.id, barPackage.id) } diff --git a/Tests/SPMBuildCoreTests/PluginInvocationTests.swift b/Tests/SPMBuildCoreTests/PluginInvocationTests.swift index 4fc9ce4c761..e46e7de9190 100644 --- a/Tests/SPMBuildCoreTests/PluginInvocationTests.swift +++ b/Tests/SPMBuildCoreTests/PluginInvocationTests.swift @@ -87,28 +87,45 @@ final class PluginInvocationTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) PackageGraphTester(graph) { graph in graph.check(packages: "Foo") - // "FooTool{Lib}" duplicated as it's present for both build tools and end products triples. - graph.check(modules: "Foo", "FooPlugin", "FooTool", "FooTool", "FooToolLib", "FooToolLib") + graph.check(modules: "Foo", "FooPlugin", "FooTool", "FooToolLib") graph.checkTarget("Foo") { target in target.check(dependencies: "FooPlugin") } - graph.checkTarget("FooPlugin", destination: .tools) { target in + graph.checkTarget("FooPlugin") { target in target.check(type: .plugin) target.check(dependencies: "FooTool") } - for destination: BuildTriple in [.tools, .destination] { - graph.checkTarget("FooTool", destination: destination) { target in - target.check(type: .executable) - target.check(buildTriple: destination) - target.checkDependency("FooToolLib") { dependency in - dependency.checkTarget { - $0.check(buildTriple: destination) - } + graph.checkTarget("FooTool") { target in + target.check(type: .executable) + target.checkDependency("FooToolLib") { dependency in + dependency.checkTarget { _ in } } } } + // "FooTool{Lib}" duplicated as it's present for both build host and end target. + do { + let buildPlanResult = try await BuildPlanResult(plan: mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fileSystem, + observabilityScope: observability.topScope + )) + buildPlanResult.checkProductsCount(3) + buildPlanResult.checkTargetsCount(5) // Note: plugins are not included here. + + buildPlanResult.check(destination: .target, for: "Foo") + + buildPlanResult.check(destination: .host, for: "FooTool") + buildPlanResult.check(destination: .target, for: "FooTool") + + buildPlanResult.check(destination: .host, for: "FooToolLib") + buildPlanResult.check(destination: .target, for: "FooToolLib") + } + // A fake PluginScriptRunner that just checks the input conditions and returns canned output. struct MockPluginScriptRunner: PluginScriptRunner { var hostTriple: Triple { @@ -1378,3 +1395,17 @@ final class PluginInvocationTests: XCTestCase { return pluginInvocationResults } } + +extension BuildPlanResult { + func check( + destination: BuildParameters.Destination, + for target: String, + file: StaticString = #file, + line: UInt = #line + ) { + let targets = self.targetMap.filter { + $0.module.name == target && $0.destination == destination + } + XCTAssertEqual(targets.count, 1, file: file, line: line) + } +}