Skip to content

Commit 64546fb

Browse files
authored
Add .snippet target to @main heuristics for including -parse-as-library (#5704)
The heuristics for deciding whether to include the `-parse-as-library` flag were recently improved in #5687 (rdar://97297732). This change allows `.snippet` target types to benefit from those improved heuristics. According to the same rules, snippets with `@main` should get `-parse-as-library`, while those assumed to have top-level code should not. Testing: Changed the walk when searching for snippets to explicitly use the `PackageBuilder.fileSystem`; the default argument uses the local filesystem, which won't work for in-memory filesystems used in tests. Testing: Added additional snippet files, one with `@main` and one without, to `BuildPlanTests.testParseAsLibraryFlagForExe`. rdar://97802934
1 parent 97503a1 commit 64546fb

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

Sources/Build/BuildPlan.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ public final class SwiftTargetBuildDescription {
640640
switch self.target.type {
641641
case .library, .test:
642642
return true
643-
case .executable:
643+
case .executable, .snippet:
644644
// This deactivates heuristics in the Swift compiler that treats single-file modules and source files
645645
// named "main.swift" specially w.r.t. whether they can have an entry point.
646646
//

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,7 +1395,7 @@ extension PackageBuilder {
13951395
return []
13961396
}
13971397

1398-
return try walk(snippetsDirectory)
1398+
return try walk(snippetsDirectory, fileSystem: self.fileSystem)
13991399
.filter { fileSystem.isFile($0) && $0.extension == "swift" }
14001400
.map { sourceFile in
14011401
let name = sourceFile.basenameWithoutExt

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,11 @@ final class BuildPlanTests: XCTestCase {
12321232
"/Pkg/Sources/exe12/comments.swift",
12331233
// executable has multiple source files.
12341234
"/Pkg/Sources/exe13/bar.swift",
1235-
"/Pkg/Sources/exe13/main.swift"
1235+
"/Pkg/Sources/exe13/main.swift",
1236+
// Snippet with top-level code
1237+
"/Pkg/Snippets/TopLevelCodeSnippet.swift",
1238+
// Snippet with @main
1239+
"/Pkg/Snippets/AtMainSnippet.swift"
12361240
)
12371241

12381242
try fs.writeFileContents(AbsolutePath("/Pkg/Sources/exe3/foo.swift")) {
@@ -1347,6 +1351,28 @@ final class BuildPlanTests: XCTestCase {
13471351
"""
13481352
}
13491353

1354+
try fs.writeFileContents(AbsolutePath("/Pkg/Snippets/TopLevelCodeSnippet.swift")) {
1355+
"""
1356+
struct Foo {
1357+
init() {}
1358+
func foo() {}
1359+
}
1360+
let foo = Foo()
1361+
foo.foo()
1362+
"""
1363+
}
1364+
1365+
try fs.writeFileContents(AbsolutePath("/Pkg/Snippets/AtMainSnippet.swift")) {
1366+
"""
1367+
@main
1368+
struct Runner {
1369+
static func main() {
1370+
print("hello world")
1371+
}
1372+
}
1373+
"""
1374+
}
1375+
13501376
let observability = ObservabilitySystem.makeForTesting()
13511377
let graph = try loadPackageGraph(
13521378
fileSystem: fs,
@@ -1382,8 +1408,8 @@ final class BuildPlanTests: XCTestCase {
13821408
observabilityScope: observability.topScope
13831409
))
13841410

1385-
result.checkProductsCount(13)
1386-
result.checkTargetsCount(13)
1411+
result.checkProductsCount(15)
1412+
result.checkTargetsCount(15)
13871413

13881414
XCTAssertNoDiagnostics(observability.diagnostics)
13891415

@@ -1438,6 +1464,14 @@ final class BuildPlanTests: XCTestCase {
14381464
// multiple source files should not have -parse-as-library.
14391465
let exe13 = try result.target(for: "exe13").swiftTarget().emitCommandLine()
14401466
XCTAssertNoMatch(exe13, ["-parse-as-library"])
1467+
1468+
// A snippet with top-level code should not have -parse-as-library.
1469+
let topLevelCodeSnippet = try result.target(for: "TopLevelCodeSnippet").swiftTarget().emitCommandLine()
1470+
XCTAssertNoMatch(topLevelCodeSnippet, ["-parse-as-library"])
1471+
1472+
// A snippet with @main should have -parse-as-library
1473+
let atMainSnippet = try result.target(for: "AtMainSnippet").swiftTarget().emitCommandLine()
1474+
XCTAssertMatch(atMainSnippet, ["-parse-as-library"])
14411475
}
14421476

14431477
func testCModule() throws {

0 commit comments

Comments
 (0)