Skip to content

Commit fba40af

Browse files
authored
Revert "improve heuristics for @main support (#5678) (#5680)" (#5684)
1 parent ad90c17 commit fba40af

File tree

2 files changed

+23
-64
lines changed

2 files changed

+23
-64
lines changed

Sources/Build/BuildPlan.swift

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -626,26 +626,21 @@ public final class SwiftTargetBuildDescription {
626626
public let isTestDiscoveryTarget: Bool
627627

628628
/// True if this module needs to be parsed as a library based on the target type and the configuration
629-
/// of the source code
629+
/// of the source code (for example because it has a single source file whose name isn't "main.swift").
630+
/// This deactivates heuristics in the Swift compiler that treats single-file modules and source files
631+
/// named "main.swift" specially w.r.t. whether they can have an entry point.
632+
///
633+
/// See https://bugs.swift.org/browse/SR-14488 for discussion about improvements so that SwiftPM can
634+
/// convey the intent to build an executable module to the compiler regardless of the number of files
635+
/// in the module or their names.
630636
var needsToBeParsedAsLibrary: Bool {
631-
switch self.target.type {
637+
switch target.type {
632638
case .library, .test:
633639
return true
634640
case .executable:
635-
// This deactivates heuristics in the Swift compiler that treats single-file modules and source files
636-
// named "main.swift" specially w.r.t. whether they can have an entry point.
637-
//
638-
// See https://bugs.swift.org/browse/SR-14488 for discussion about improvements so that SwiftPM can
639-
// convey the intent to build an executable module to the compiler regardless of the number of files
640-
// in the module or their names.
641-
if self.toolsVersion < .v5_5 || self.sources.count != 1 {
642-
return false
643-
}
644-
// looking into the file content to see if it is using the @main annotation which requires parse-as-library
645-
// this is not bullet-proof since theoretically the file can contain the @main string for other reasons
646-
// but it is the closest to accurate we can do at this point
647-
let content: String = self.sources.first.flatMap({ try? self.fileSystem.readFileContents($0) }) ?? ""
648-
return content.contains("@main")
641+
guard toolsVersion >= .v5_5 else { return false }
642+
let sources = self.sources
643+
return sources.count == 1 && sources.first?.basename != "main.swift"
649644
default:
650645
return false
651646
}

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,41 +1014,15 @@ final class BuildPlanTests: XCTestCase {
10141014

10151015
func testParseAsLibraryFlagForExe() throws {
10161016
let fs = InMemoryFileSystem(emptyFiles:
1017-
// executable has a single source file not named `main.swift`, without @main.
1017+
// First executable has a single source file not named `main.swift`.
10181018
"/Pkg/Sources/exe1/foo.swift",
1019-
// executable has a single source file named `main.swift`, without @main.
1019+
// Second executable has a single source file named `main.swift`.
10201020
"/Pkg/Sources/exe2/main.swift",
1021-
// executable has a single source file not named `main.swift`, with @main.
1022-
"/Pkg/Sources/exe3/foo.swift",
1023-
// executable has a single source file named `main.swift`, with @main
1024-
"/Pkg/Sources/exe4/main.swift",
1025-
// executable has multiple source files.
1026-
"/Pkg/Sources/exe5/bar.swift",
1027-
"/Pkg/Sources/exe5/main.swift"
1021+
// Third executable has multiple source files.
1022+
"/Pkg/Sources/exe3/bar.swift",
1023+
"/Pkg/Sources/exe3/main.swift"
10281024
)
10291025

1030-
try fs.writeFileContents(AbsolutePath("/Pkg/Sources/exe3/foo.swift")) {
1031-
"""
1032-
@main
1033-
struct Runner {
1034-
static func main() {
1035-
print("hello world")
1036-
}
1037-
}
1038-
"""
1039-
}
1040-
1041-
try fs.writeFileContents(AbsolutePath("/Pkg/Sources/exe4/main.swift")) {
1042-
"""
1043-
@main
1044-
struct Runner {
1045-
static func main() {
1046-
print("hello world")
1047-
}
1048-
}
1049-
"""
1050-
}
1051-
10521026
let observability = ObservabilitySystem.makeForTesting()
10531027
let graph = try loadPackageGraph(
10541028
fileSystem: fs,
@@ -1061,8 +1035,6 @@ final class BuildPlanTests: XCTestCase {
10611035
TargetDescription(name: "exe1", type: .executable),
10621036
TargetDescription(name: "exe2", type: .executable),
10631037
TargetDescription(name: "exe3", type: .executable),
1064-
TargetDescription(name: "exe4", type: .executable),
1065-
TargetDescription(name: "exe5", type: .executable),
10661038
]),
10671039
],
10681040
observabilityScope: observability.topScope
@@ -1076,30 +1048,22 @@ final class BuildPlanTests: XCTestCase {
10761048
observabilityScope: observability.topScope
10771049
))
10781050

1079-
result.checkProductsCount(5)
1080-
result.checkTargetsCount(5)
1051+
result.checkProductsCount(3)
1052+
result.checkTargetsCount(3)
10811053

10821054
XCTAssertNoDiagnostics(observability.diagnostics)
10831055

1084-
// single source file not named main, and without @main should not have -parse-as-library.
1056+
// Check that the first target (single source file not named main) has -parse-as-library.
10851057
let exe1 = try result.target(for: "exe1").swiftTarget().emitCommandLine()
1086-
XCTAssertNoMatch(exe1, ["-parse-as-library"])
1058+
XCTAssertMatch(exe1, ["-parse-as-library"])
10871059

1088-
// single source file named main, and without @main should not have -parse-as-library.
1060+
// Check that the second target (single source file named main) does not have -parse-as-library.
10891061
let exe2 = try result.target(for: "exe2").swiftTarget().emitCommandLine()
10901062
XCTAssertNoMatch(exe2, ["-parse-as-library"])
10911063

1092-
// single source file not named main, with @main should have -parse-as-library.
1064+
// Check that the third target (multiple source files) does not have -parse-as-library.
10931065
let exe3 = try result.target(for: "exe3").swiftTarget().emitCommandLine()
1094-
XCTAssertMatch(exe3, ["-parse-as-library"])
1095-
1096-
// single source file named main, with @main should have -parse-as-library.
1097-
let exe4 = try result.target(for: "exe4").swiftTarget().emitCommandLine()
1098-
XCTAssertMatch(exe4, ["-parse-as-library"])
1099-
1100-
// multiple source files should not have -parse-as-library.
1101-
let exe5 = try result.target(for: "exe5").swiftTarget().emitCommandLine()
1102-
XCTAssertNoMatch(exe5, ["-parse-as-library"])
1066+
XCTAssertNoMatch(exe3, ["-parse-as-library"])
11031067
}
11041068

11051069
func testCModule() throws {

0 commit comments

Comments
 (0)