From 17cd8e2c6add346dfb6f9f20c64e8cbb5a5d4929 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Fri, 17 Oct 2025 16:38:27 -0400 Subject: [PATCH 1/4] Fix crash in macros caused by mixing prebuilts and source. There is an issue when a macro that uses prebuilts uses a library that also depends on the swift-syntax library. This is commonly used to share utility code between macros. However, we currently can't tell whether the library will only be built for the host so it can not take advantage of the prebuilts. When a macro which is using prebuilts uses that library, we are seeing crashes in the macro caused when the library and the swift-syntax it uses is built for debug which is then linked with the macro which uses the swift-syntas prebuilts which are built for release. For now, this change turns off the prebuilts for macros that use such a library to avoid the crash. We'll investigate making the use of prebuilts conditional on the build settings in a future release. To be able to implement this change, we need to be able to detect the downstream swift-syntax dependency. We move the insertion of the settings for the prebuilts from Module creation time until after the ResolvedModuleBuilder is created so that we can make the changes there before the final ResolvedModules are created. --- .../PackageGraph/ModulesGraph+Loading.swift | 130 ++++++++++++++---- Sources/PackageLoading/PackageBuilder.swift | 83 ----------- Sources/PackageModel/Module/Module.swift | 38 ++++- .../PackageModel/Module/PrebuiltLibrary.swift | 51 +++++++ Sources/Workspace/Workspace.swift | 2 - Tests/WorkspaceTests/PrebuiltsTests.swift | 89 +++++++++++- 6 files changed, 283 insertions(+), 110 deletions(-) create mode 100644 Sources/PackageModel/Module/PrebuiltLibrary.swift diff --git a/Sources/PackageGraph/ModulesGraph+Loading.swift b/Sources/PackageGraph/ModulesGraph+Loading.swift index 2ea14951129..9855d16c7ea 100644 --- a/Sources/PackageGraph/ModulesGraph+Loading.swift +++ b/Sources/PackageGraph/ModulesGraph+Loading.swift @@ -19,6 +19,7 @@ import Foundation import func TSCBasic.bestMatch import func TSCBasic.findCycle import struct TSCBasic.KeyedPair +import func TSCBasic.topologicalSort extension ModulesGraph { /// Load the package graph for the given package path. @@ -30,7 +31,7 @@ extension ModulesGraph { requiredDependencies: [PackageReference] = [], unsafeAllowedPackages: Set = [], binaryArtifacts: [PackageIdentity: [String: BinaryArtifact]], - prebuilts: [PackageIdentity: [String: PrebuiltLibrary]], // Product name to library mapping + prebuilts: [PackageIdentity: [String: PrebuiltLibrary]], // Package -> Product name -> library shouldCreateMultipleTestProducts: Bool = false, createREPLProduct: Bool = false, customPlatformsRegistry: PlatformRegistry? = .none, @@ -167,7 +168,6 @@ extension ModulesGraph { path: packagePath, additionalFileRules: additionalFileRules, binaryArtifacts: binaryArtifacts[node.identity] ?? [:], - prebuilts: prebuilts, shouldCreateMultipleTestProducts: shouldCreateMultipleTestProducts, testEntryPointPath: testEntryPointPath, createREPLProduct: manifest.packageKind.isRoot ? createREPLProduct : false, @@ -214,7 +214,7 @@ extension ModulesGraph { let rootPackages = resolvedPackages.filter { root.manifests.values.contains($0.manifest) } checkAllDependenciesAreUsed( packages: resolvedPackages, - rootPackages, + rootPackages: rootPackages, prebuilts: prebuilts, observabilityScope: observabilityScope ) @@ -231,7 +231,7 @@ extension ModulesGraph { private func checkAllDependenciesAreUsed( packages: IdentifiableSet, - _ rootPackages: [ResolvedPackage], + rootPackages: [ResolvedPackage], prebuilts: [PackageIdentity: [String: PrebuiltLibrary]], observabilityScope: ObservabilityScope ) { @@ -311,7 +311,7 @@ private func checkAllDependenciesAreUsed( // We check if any of the products of this dependency is guarded by a trait. let traitGuarded = traitGuardedProductDependencies.contains(product.name) // Consider prebuilts as used - let prebuilt = prebuilts[dependency.identity]?.keys.contains(product.name) ?? false + let prebuilt = prebuilts[dependency.identity]?[product.name] != nil return usedByPackage || traitGuarded || prebuilt } @@ -729,24 +729,6 @@ private func createResolvedPackages( // Establish product dependencies. for case .product(let productRef, let conditions) in moduleBuilder.module.dependencies { - if let package = productRef.package, prebuilts[.plain(package)]?[productRef.name] != nil { - // See if we're using a prebuilt instead - if moduleBuilder.module.type == .macro { - continue - } else if moduleBuilder.module.type == .test { - // use prebuilt if this is a test that depends a macro target - // these are guaranteed built for host - if moduleBuilder.module.dependencies.contains(where: { dep in - guard let module = dep.module else { - return false - } - return module.type == .macro - }) { - continue - } - } - } - // Find the product in this package's dependency products. // Look it up by ID if module aliasing is used, otherwise by name. let product = lookupByProductIDs ? productDependencyMap[productRef.identity] : @@ -800,6 +782,91 @@ private func createResolvedPackages( } } + // Prebuilts + for packageBuilder in packageBuilders { + for moduleBuilder in packageBuilder.modules { + // Currently we only support prebuilts for macros and their tests + switch moduleBuilder.module.type { + case .macro: + // Skip if the module has a dependency that depends on a prebuilt + // This is causing a mix of release and debug modes which is causing + // macros to crash. + // TODO: Find a way to build those dependencies with the prebuilts on host + if moduleBuilder.dependencies.contains(where: { + switch $0 { + case .module(let moduleBuilder, conditions: _): + return moduleBuilder.recursiveDependenciesContains(where: { + switch $0 { + case .product(let productBuilder, conditions: _): + return prebuilts[productBuilder.packageBuilder.package.identity]?[productBuilder.product.name] != nil + case .module: + return false + } + }) + case .product(let productBuilder, conditions: _): + return productBuilder.moduleBuilders.contains(where: { + $0.recursiveDependenciesContains(where: { + switch $0 { + case .product(let productBuilder, conditions: _): + return prebuilts[productBuilder.packageBuilder.package.identity]?[productBuilder.product.name] != nil + case .module: + return false + } + }) + }) + } + }) { + // Skip + continue + } + case .test: + // Check for macro tests + if !moduleBuilder.dependencies.contains(where: { + switch $0 { + case .module(let depModuleBuilder, conditions: _): + return depModuleBuilder.module.type == .macro + case .product: + return false + } + }) { + // Skip + continue + } + default: + // Skip + continue + } + + var prebuiltLibraries: [PrebuiltLibrary] = [] + for dep in moduleBuilder.dependencies { + switch dep { + case .product(let productBuilder, conditions: _): + if let prebuilt = prebuilts[productBuilder.packageBuilder.package.identity]?[productBuilder.product.name] { + // Use the prebuilt + if !prebuiltLibraries.contains(where: { $0.libraryName == prebuilt.libraryName }) { + prebuiltLibraries.append(prebuilt) + } + } + case .module: + break + } + } + + for prebuiltLibrary in prebuiltLibraries { + moduleBuilder.module.use(prebuiltLibrary: prebuiltLibrary) + + moduleBuilder.dependencies = moduleBuilder.dependencies.filter({ + switch $0 { + case .product(let productBuilder, conditions: _): + return prebuilts[productBuilder.packageBuilder.package.identity]?[productBuilder.product.name] == nil + case .module: + return true + } + }) + } + } + } + // If a module with similar name was encountered before, we emit a diagnostic. if foundDuplicateModule { var duplicateModules = [String: [Package]]() @@ -1337,6 +1404,23 @@ private final class ResolvedModuleBuilder: ResolvedBuilder { /// The module dependencies of this module. var dependencies: [Dependency] = [] + func recursiveDependenciesContains(where check: (Dependency) -> Bool) -> Bool { + dependencies.contains(where: { + if check($0) { + return true + } else { + switch $0 { + case .module(let moduleBuilder, conditions: _): + return moduleBuilder.recursiveDependenciesContains(where: check) + case .product(let productBuilder, conditions: _): + return productBuilder.moduleBuilders.contains(where: { + $0.recursiveDependenciesContains(where: check) + }) + } + } + }) + } + /// The defaultLocalization for this package var defaultLocalization: String? = nil diff --git a/Sources/PackageLoading/PackageBuilder.swift b/Sources/PackageLoading/PackageBuilder.swift index 08535c82807..a1e055508b0 100644 --- a/Sources/PackageLoading/PackageBuilder.swift +++ b/Sources/PackageLoading/PackageBuilder.swift @@ -279,48 +279,6 @@ public struct BinaryArtifact { } } -/// A structure representing a prebuilt library to be used instead of a source dependency -public struct PrebuiltLibrary { - /// The package identity. - public let identity: PackageIdentity - - /// The name of the binary target the artifact corresponds to. - public let libraryName: String - - /// The path to the extracted prebuilt artifacts - public let path: AbsolutePath - - /// The path to the checked out source - public let checkoutPath: AbsolutePath? - - /// The products in the library - public let products: [String] - - /// The include path relative to the checkouts dir - public let includePath: [RelativePath]? - - /// The C modules that need their includes directory added to the include path - public let cModules: [String] - - public init( - identity: PackageIdentity, - libraryName: String, - path: AbsolutePath, - checkoutPath: AbsolutePath?, - products: [String], - includePath: [RelativePath]? = nil, - cModules: [String] = [] - ) { - self.identity = identity - self.libraryName = libraryName - self.path = path - self.checkoutPath = checkoutPath - self.products = products - self.includePath = includePath - self.cModules = cModules - } -} - /// Helper for constructing a package following the convention system. /// /// The 'builder' here refers to the builder pattern and not any build system @@ -348,9 +306,6 @@ public final class PackageBuilder { /// Information concerning the different downloaded or local (archived) binary target artifacts. private let binaryArtifacts: [String: BinaryArtifact] - /// Prebuilts that may referenced from this package's targets - private let prebuilts: [PackageIdentity: [Product.ID: PrebuiltLibrary]] - /// Create multiple test products. /// /// If set to true, one test product will be created for each test target. @@ -407,7 +362,6 @@ public final class PackageBuilder { path: AbsolutePath, additionalFileRules: [FileRuleDescription], binaryArtifacts: [String: BinaryArtifact], - prebuilts: [PackageIdentity: [String: PrebuiltLibrary]], shouldCreateMultipleTestProducts: Bool = false, testEntryPointPath: AbsolutePath? = nil, warnAboutImplicitExecutableTargets: Bool = true, @@ -422,7 +376,6 @@ public final class PackageBuilder { self.packagePath = path self.additionalFileRules = additionalFileRules self.binaryArtifacts = binaryArtifacts - self.prebuilts = prebuilts self.shouldCreateMultipleTestProducts = shouldCreateMultipleTestProducts self.testEntryPointPath = testEntryPointPath self.createREPLProduct = createREPLProduct @@ -1407,42 +1360,6 @@ public final class PackageBuilder { table.add(assignment, for: .SWIFT_ACTIVE_COMPILATION_CONDITIONS) } - // Add in flags for prebuilts if the target is a macro or a macro test. - // Currently we only support prebuilts for macros. - if target.type == .macro || target.isMacroTest(in: manifest) { - let prebuiltLibraries: [String: PrebuiltLibrary] = target.dependencies.reduce(into: .init()) { - guard case let .product(name: name, package: package, moduleAliases: _, condition: _) = $1, - let package = package, - let prebuilt = prebuilts[.plain(package)]?[name] - else { - return - } - - $0[prebuilt.libraryName] = prebuilt - } - - for prebuilt in prebuiltLibraries.values { - let lib = prebuilt.path.appending(components: ["lib", "lib\(prebuilt.libraryName).a"]).pathString - var ldFlagsAssignment = BuildSettings.Assignment() - ldFlagsAssignment.values = [lib] - table.add(ldFlagsAssignment, for: .OTHER_LDFLAGS) - - var includeDirs: [AbsolutePath] = [prebuilt.path.appending(component: "Modules")] - if let checkoutPath = prebuilt.checkoutPath, let includePath = prebuilt.includePath { - for includeDir in includePath { - includeDirs.append(checkoutPath.appending(includeDir)) - } - } else { - for cModule in prebuilt.cModules { - includeDirs.append(prebuilt.path.appending(components: "include", cModule)) - } - } - var includeAssignment = BuildSettings.Assignment() - includeAssignment.values = includeDirs.map({ "-I\($0.pathString)" }) - table.add(includeAssignment, for: .OTHER_SWIFT_FLAGS) - } - } - return table } diff --git a/Sources/PackageModel/Module/Module.swift b/Sources/PackageModel/Module/Module.swift index 34d6f72c8f8..0d4c7194cbd 100644 --- a/Sources/PackageModel/Module/Module.swift +++ b/Sources/PackageModel/Module/Module.swift @@ -194,8 +194,44 @@ public class Module { return false } + public func use(prebuiltLibrary: PrebuiltLibrary) { + dependencies = dependencies.filter({ + switch $0 { + case .product(let product, conditions: _): + if let packageName = product.package, + prebuiltLibrary.identity == .plain(packageName) && prebuiltLibrary.products.contains(product.name) { + return false + } else { + return true + } + case .module: + return true + } + }) + + // Add build settings to use the prebuilts + let lib = prebuiltLibrary.path.appending(components: ["lib", "lib\(prebuiltLibrary.libraryName).a"]).pathString + var ldFlagsAssignment = BuildSettings.Assignment() + ldFlagsAssignment.values = [lib] + buildSettings.add(ldFlagsAssignment, for: .OTHER_LDFLAGS) + + var includeDirs: [AbsolutePath] = [prebuiltLibrary.path.appending(component: "Modules")] + if let checkoutPath = prebuiltLibrary.checkoutPath, let includePath = prebuiltLibrary.includePath { + for includeDir in includePath { + includeDirs.append(checkoutPath.appending(includeDir)) + } + } else { + for cModule in prebuiltLibrary.cModules { + includeDirs.append(prebuiltLibrary.path.appending(components: "include", cModule)) + } + } + var includeAssignment = BuildSettings.Assignment() + includeAssignment.values = includeDirs.map({ "-I\($0.pathString)" }) + buildSettings.add(includeAssignment, for: .OTHER_SWIFT_FLAGS) + } + /// The dependencies of this module. - public let dependencies: [Dependency] + public private(set) var dependencies: [Dependency] /// The language-level module name. public private(set) var c99name: String diff --git a/Sources/PackageModel/Module/PrebuiltLibrary.swift b/Sources/PackageModel/Module/PrebuiltLibrary.swift new file mode 100644 index 00000000000..efc2d3a95a0 --- /dev/null +++ b/Sources/PackageModel/Module/PrebuiltLibrary.swift @@ -0,0 +1,51 @@ +// +// PrebuiltLibrary.swift +// SwiftPM +// +// Created by Doug Schaefer on 2025-10-16. +// + +import Basics + +/// A structure representing a prebuilt library to be used instead of a source dependency +public struct PrebuiltLibrary { + /// The package identity. + public let identity: PackageIdentity + + /// The name of the binary target the artifact corresponds to. + public let libraryName: String + + /// The path to the extracted prebuilt artifacts + public let path: AbsolutePath + + /// The path to the checked out source + public let checkoutPath: AbsolutePath? + + /// The products in the library + public let products: [String] + + /// The include path relative to the checkouts dir + public let includePath: [RelativePath]? + + /// The C modules that need their includes directory added to the include path + public let cModules: [String] + + public init( + identity: PackageIdentity, + libraryName: String, + path: AbsolutePath, + checkoutPath: AbsolutePath?, + products: [String], + includePath: [RelativePath]? = nil, + cModules: [String] = [] + ) { + self.identity = identity + self.libraryName = libraryName + self.path = path + self.checkoutPath = checkoutPath + self.products = products + self.includePath = includePath + self.cModules = cModules + } +} + diff --git a/Sources/Workspace/Workspace.swift b/Sources/Workspace/Workspace.swift index 2eb9bd1affd..aa6d413b12f 100644 --- a/Sources/Workspace/Workspace.swift +++ b/Sources/Workspace/Workspace.swift @@ -1252,7 +1252,6 @@ extension Workspace { path: path, additionalFileRules: [], binaryArtifacts: binaryArtifacts, - prebuilts: [:], fileSystem: self.fileSystem, observabilityScope: observabilityScope, enabledTraits: try manifest.enabledTraits(using: .default) @@ -1317,7 +1316,6 @@ extension Workspace { path: previousPackage.path, additionalFileRules: self.configuration.additionalFileRules, binaryArtifacts: packageGraph.binaryArtifacts[identity] ?? [:], - prebuilts: [:], shouldCreateMultipleTestProducts: self.configuration.shouldCreateMultipleTestProducts, createREPLProduct: self.configuration.createREPLProduct, fileSystem: self.fileSystem, diff --git a/Tests/WorkspaceTests/PrebuiltsTests.swift b/Tests/WorkspaceTests/PrebuiltsTests.swift index 8725d6c2d66..691d1f81370 100644 --- a/Tests/WorkspaceTests/PrebuiltsTests.swift +++ b/Tests/WorkspaceTests/PrebuiltsTests.swift @@ -32,6 +32,7 @@ final class PrebuiltsTests: XCTestCase { artifact: Data, swiftSyntaxVersion: String, swiftSyntaxURL: String? = nil, + additionalTargets: [MockTarget] = [], run: (Workspace.SignedPrebuiltsManifest, AbsolutePath, MockPackage, MockPackage) async throws -> () ) async throws { try await fixture(name: "Signing") { fixturePath in @@ -121,7 +122,7 @@ final class PrebuiltsTests: XCTestCase { ], type: .test ), - ], + ] + additionalTargets, dependencies: [ .sourceControl( url: swiftSyntaxURL, @@ -963,6 +964,92 @@ final class PrebuiltsTests: XCTestCase { } } } + + func testPrebuiltsInDeps() async throws { + // This is the case where macros that depend on libraries that also depend on swift-syntax. + // Currently we disable the use of prebuilts in the macros since the libraries are + // not able to take advantage of the prebuilts at this time and macros crash when they mix. + let sandbox = AbsolutePath("/tmp/ws") + let fs = InMemoryFileSystem() + let artifact = Data() + + let extraTargets: [MockTarget] = [ + try MockTarget( + name: "ExtraLibrary", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + ], + type: .regular + ), + try MockTarget( + name: "ExtraMacros", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + .target(name: "ExtraLibrary") + ], + type: .macro + ), + ] + + try await with(fileSystem: fs, artifact: artifact, swiftSyntaxVersion: "600.0.1", additionalTargets: extraTargets) + { manifest, rootCertPath, rootPackage, swiftSyntax in + let manifestData = try JSONEncoder().encode(manifest) + + let httpClient = HTTPClient { request, progressHandler in + guard case .download(let fileSystem, let destination) = request.kind else { + throw StringError("invalid request \(request.kind)") + } + + if request.url == "https://download.swift.org/prebuilts/swift-syntax/600.0.1/\(self.swiftVersion)-manifest.json" { + try fileSystem.writeFileContents(destination, data: manifestData) + return .okay() + } else if request.url == "https://download.swift.org/prebuilts/swift-syntax/600.0.1/\(self.swiftVersion)-MacroSupport-macos_aarch64.zip" { + try fileSystem.writeFileContents(destination, data: artifact) + return .okay() + } else { + XCTFail("Unexpected URL \(request.url)") + return .notFound() + } + } + + let archiver = MockArchiver(handler: { _, archivePath, destination, completion in + XCTAssertEqual(archivePath, sandbox.appending(components: ".build", "prebuilts", "swift-syntax", "600.0.1", "\(self.swiftVersion)-MacroSupport-macos_aarch64.zip")) + XCTAssertEqual(destination, sandbox.appending(components: ".build", "prebuilts", "swift-syntax", "600.0.1", "\(self.swiftVersion)-MacroSupport-macos_aarch64")) + completion(.success(())) + }) + + let workspace = try await MockWorkspace( + sandbox: sandbox, + fileSystem: fs, + roots: [ + rootPackage + ], + packages: [ + swiftSyntax + ], + prebuiltsManager: .init( + swiftVersion: swiftVersion, + httpClient: httpClient, + archiver: archiver, + hostPlatform: .macos_aarch64, + rootCertPath: rootCertPath + ), + ) + + try await workspace.checkPackageGraph(roots: ["Foo"]) { modulesGraph, diagnostics in + XCTAssertTrue(diagnostics.filter({ $0.severity == .error || $0.severity == .warning }).isEmpty) + let rootPackage = try XCTUnwrap(modulesGraph.rootPackages.first) + try checkSettings(rootPackage, "FooMacros", usePrebuilt: true) + try checkSettings(rootPackage, "FooTests", usePrebuilt: true) + try checkSettings(rootPackage, "Foo", usePrebuilt: false) + try checkSettings(rootPackage, "FooClient", usePrebuilt: false) + try checkSettings(rootPackage, "ExtraLibrary", usePrebuilt: false) + try checkSettings(rootPackage, "ExtraMacros", usePrebuilt: false) + } + } + + } } extension String { From 96cf63a72df9043c34df1aefd04b2ed76ebdd565 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Fri, 17 Oct 2025 16:55:11 -0400 Subject: [PATCH 2/4] Fix CMakeLists.txt file after moving PrebuiltLibrary to PackageModel --- Sources/PackageGraph/ModulesGraph+Loading.swift | 1 - Sources/PackageModel/CMakeLists.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PackageGraph/ModulesGraph+Loading.swift b/Sources/PackageGraph/ModulesGraph+Loading.swift index 9855d16c7ea..a269cd0e478 100644 --- a/Sources/PackageGraph/ModulesGraph+Loading.swift +++ b/Sources/PackageGraph/ModulesGraph+Loading.swift @@ -19,7 +19,6 @@ import Foundation import func TSCBasic.bestMatch import func TSCBasic.findCycle import struct TSCBasic.KeyedPair -import func TSCBasic.topologicalSort extension ModulesGraph { /// Load the package graph for the given package path. diff --git a/Sources/PackageModel/CMakeLists.txt b/Sources/PackageModel/CMakeLists.txt index aa8848b4155..5d2ffa9d7f2 100644 --- a/Sources/PackageModel/CMakeLists.txt +++ b/Sources/PackageModel/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(PackageModel Module/BinaryModule.swift Module/ClangModule.swift Module/PluginModule.swift + Module/PrebuiltLibrary.swift Module/SwiftModule.swift Module/SystemLibraryModule.swift Module/Module.swift From 72d13856934150464a51177b7025941c298e93a6 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Sun, 19 Oct 2025 12:46:42 -0400 Subject: [PATCH 3/4] Fix build of PackageBuilderTests --- Tests/PackageLoadingTests/PackageBuilderTests.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tests/PackageLoadingTests/PackageBuilderTests.swift b/Tests/PackageLoadingTests/PackageBuilderTests.swift index a00ad7eeeb2..3f8ef326b51 100644 --- a/Tests/PackageLoadingTests/PackageBuilderTests.swift +++ b/Tests/PackageLoadingTests/PackageBuilderTests.swift @@ -3502,7 +3502,6 @@ final class PackageBuilderTester { _ manifest: Manifest, path: AbsolutePath = .root, binaryArtifacts: [String: BinaryArtifact] = [:], - prebuilts: [PackageIdentity: [String: PrebuiltLibrary]] = [:], shouldCreateMultipleTestProducts: Bool = false, createREPLProduct: Bool = false, supportXCBuildTypes: Bool = false, @@ -3522,7 +3521,6 @@ final class PackageBuilderTester { path: path, additionalFileRules: supportXCBuildTypes ? FileRuleDescription.xcbuildFileTypes : FileRuleDescription.swiftpmFileTypes, binaryArtifacts: binaryArtifacts, - prebuilts: prebuilts, shouldCreateMultipleTestProducts: shouldCreateMultipleTestProducts, warnAboutImplicitExecutableTargets: true, createREPLProduct: createREPLProduct, From 0145f2306f8aa0f1c71def0e1653b9e043be26a1 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Mon, 20 Oct 2025 09:42:50 -0400 Subject: [PATCH 4/4] Fix BuildPlanTests so it works with new loading --- Tests/BuildTests/BuildPlanTests.swift | 83 ++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index d8ba95b7710..9adf87b46bf 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -4657,16 +4657,48 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { emptyFiles: [ "/MyPackage/Sources/MyMacroMacros/MyMacroMacros.swift", "/MyPackage/Sources/MyMacros/MyMacros.swift", - "/MyPackage/Sources/MyMacroTests/MyMacroTests.swift" + "/MyPackage/Sources/MyMacroTests/MyMacroTests.swift", + "/swift-syntax/Sources/SwiftSyntaxMacrosTestSupport/SwiftSyntaxMacrosTestSupport.swift", + "/swift-syntax/Sources/SwiftSyntaxMacros/SwiftSyntaxMacros.swift", + "/swift-syntax/Sources/SwiftCompilerPlugin/SwiftCompilerPlugin.swift", ] ) let graph = try loadModulesGraph( fileSystem: fs, manifests: [ + Manifest.createRemoteSourceControlManifest( + displayName: "swift-syntax", + url: "https://github.com/swiftlang/swift-syntax", + path: "/swift-syntax", + products: [ + .init( + name: "SwiftSyntaxMacrosTestSupport", + type: .library(.automatic), + targets: ["SwiftSyntaxMacrosTestSupport"] + ), + .init( + name: "SwiftSyntaxMacros", + type: .library(.automatic), + targets: ["SwiftSyntaxMacros"] + ), + .init( + name: "SwiftCompilerPlugin", + type: .library(.automatic), + targets: ["SwiftCompilerPlugin"]) + ], + targets: [ + .init(name: "SwiftSyntaxMacrosTestSupport"), + .init(name: "SwiftSyntaxMacros"), + .init(name: "SwiftCompilerPlugin"), + ] + ), Manifest.createRootManifest( displayName: "MyPackage", path: "/MyPackage", + dependencies: [ + .remoteSourceControl(url: "https://github.com/swiftlang/swift-syntax", requirement: .exact("600.0.1")), + ], targets: [ TargetDescription( name: "MyMacroMacros", @@ -4763,27 +4795,60 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { "/MyPackage/Sources/MyMacroLibrary/MyMacroLibrary.swift", "/MyPackage/Sources/MyMacroMacros/MyMacroMacros.swift", "/MyPackage/Sources/MyMacros/MyMacros.swift", - "/MyPackage/Sources/MyMacroTests/MyMacroTests.swift" + "/MyPackage/Sources/MyMacroTests/MyMacroTests.swift", + "/swift-syntax/Sources/SwiftSyntaxMacrosTestSupport/SwiftSyntaxMacrosTestSupport.swift", + "/swift-syntax/Sources/SwiftSyntaxMacros/SwiftSyntaxMacros.swift", + "/swift-syntax/Sources/SwiftCompilerPlugin/SwiftCompilerPlugin.swift", + "/swift-syntax/Sources/SwiftSyntax/SwiftSyntax.swift" ] ) let graph = try loadModulesGraph( fileSystem: fs, manifests: [ + Manifest.createRemoteSourceControlManifest( + displayName: "swift-syntax", + url: "https://github.com/swiftlang/swift-syntax", + path: "/swift-syntax", + products: [ + .init( + name: "SwiftSyntaxMacrosTestSupport", + type: .library(.automatic), + targets: ["SwiftSyntaxMacrosTestSupport"] + ), + .init( + name: "SwiftSyntaxMacros", + type: .library(.automatic), + targets: ["SwiftSyntaxMacros"] + ), + .init( + name: "SwiftCompilerPlugin", + type: .library(.automatic), + targets: ["SwiftCompilerPlugin"] + ), + .init( + name: "SwiftSyntax", + type: .library(.automatic), + targets: ["SwiftSyntax"] + ), + ], + targets: [ + .init(name: "SwiftSyntaxMacrosTestSupport"), + .init(name: "SwiftSyntaxMacros"), + .init(name: "SwiftCompilerPlugin"), + .init(name: "SwiftSyntax"), + ] + ), Manifest.createRootManifest( displayName: "MyPackage", path: "/MyPackage", + dependencies: [ + .remoteSourceControl(url: "https://github.com/swiftlang/swift-syntax", requirement: .exact("600.0.1")), + ], targets: [ - TargetDescription( - name: "MyMacroLibrary", - dependencies: [ - .product(name: "SwiftSyntax", package: "swift-syntax"), - ] - ), TargetDescription( name: "MyMacroMacros", dependencies: [ - "MyMacroLibrary", .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), ],