From 36cda8e4dc6e5a152fb3f7300d334fa191832775 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Mon, 8 Dec 2025 14:23:28 -0800 Subject: [PATCH] Use the correct module name for executable targets combined with an executable product with a different name --- .../Package.swift | 20 +++++++++++++++ .../Sources/TestableExe/main.swift | 5 ++++ .../TestableExeTests/TestableExeTests.swift | 8 ++++++ .../PackagePIFProjectBuilder+Products.swift | 5 ++-- Tests/CommandsTests/TestCommandTests.swift | 25 +++++++++++++++++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Package.swift create mode 100644 Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Sources/TestableExe/main.swift create mode 100644 Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Tests/TestableExeTests/TestableExeTests.swift diff --git a/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Package.swift b/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Package.swift new file mode 100644 index 00000000000..5a2c88b9cef --- /dev/null +++ b/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Package.swift @@ -0,0 +1,20 @@ +// swift-tools-version: 5.5 +import PackageDescription + +let package = Package( + name: "TestableExe", + products: [ + .executable(name: "testable-exe", targets: ["TestableExe"]) + ], + targets: [ + .executableTarget( + name: "TestableExe" + ), + .testTarget( + name: "TestableExeTests", + dependencies: [ + "TestableExe", + ] + ), + ] +) diff --git a/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Sources/TestableExe/main.swift b/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Sources/TestableExe/main.swift new file mode 100644 index 00000000000..c10c21ba070 --- /dev/null +++ b/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Sources/TestableExe/main.swift @@ -0,0 +1,5 @@ +public func functionFromTestableExecutable() { + print("Hello, world") +} + +functionFromTestableExecutable() diff --git a/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Tests/TestableExeTests/TestableExeTests.swift b/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Tests/TestableExeTests/TestableExeTests.swift new file mode 100644 index 00000000000..3dcde32af9b --- /dev/null +++ b/Fixtures/Miscellaneous/TestableExeWithDifferentProductName/Tests/TestableExeTests/TestableExeTests.swift @@ -0,0 +1,8 @@ +import XCTest +@testable import TestableExe + +final class TestableExeTests: XCTestCase { + func testExample() throws { + functionFromTestableExecutable() + } +} diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift index e7c75b928d6..cb9978fd5ba 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift @@ -112,7 +112,8 @@ extension PackagePIFProjectBuilder { settings[.TARGET_NAME] = product.name settings[.PACKAGE_RESOURCE_TARGET_KIND] = "regular" settings[.PRODUCT_NAME] = "$(TARGET_NAME)" - settings[.PRODUCT_MODULE_NAME] = product.c99name + // We must use the main module name here instead of the product name, because they're not guranteed to be the same, and the users may have authored e.g. tests which rely on an executable's module name. + settings[.PRODUCT_MODULE_NAME] = mainModule.c99name settings[.PRODUCT_BUNDLE_IDENTIFIER] = "\(self.package.identity).\(product.name)" .spm_mangledToBundleIdentifier() settings[.SWIFT_PACKAGE_NAME] = mainModule.packageName @@ -415,7 +416,7 @@ extension PackagePIFProjectBuilder { case .executable, .snippet: // For executable targets, we depend on the *product* instead // (i.e., we infuse the product's main module target into the one for the product itself). - let productDependency = modulesGraph.allProducts.only { $0.name == moduleDependency.name } + let productDependency = modulesGraph.allProducts.only { $0.mainModule?.name == moduleDependency.name } if let productDependency { let productDependencyGUID = productDependency.pifTargetGUID self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( diff --git a/Tests/CommandsTests/TestCommandTests.swift b/Tests/CommandsTests/TestCommandTests.swift index 38961e48428..fc73f713412 100644 --- a/Tests/CommandsTests/TestCommandTests.swift +++ b/Tests/CommandsTests/TestCommandTests.swift @@ -317,6 +317,31 @@ struct TestCommandTests { } } + @Test( + .IssueWindowsLongPath, + .tags( + .Feature.TargetType.Executable, + ), + arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + ) + func testableExecutableWithDifferentlyNamedExecutableProduct( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration, + ) async throws { + try await withKnownIssue(isIntermittent: true) { + try await fixture(name: "Miscellaneous/TestableExeWithDifferentProductName") { fixturePath in + let result = try await execute( + ["--vv"], + packagePath: fixturePath, + configuration: configuration, + buildSystem: buildSystem, + ) + } + } when: { + .windows == ProcessInfo.hostOperatingSystem + } + } + @Test( .tags( .Feature.TargetType.Executable,