Skip to content

Commit 207a053

Browse files
committed
Move .swiftmodule output directory
While working on #7090, we noticed that any builds of Swift sources will currently find lots of unrelated module maps because of the structure of the build arena. We pass a `-I` to the top-level of the arena which leads to *everything* being recursively searched for modules, so the compiler will find module maps that aren't intended to be included at all. Changing this so that the search paths won't include random module maps should actually solve various issues around seeing incomplete module maps, such as ones referring to ObjC compatibility headers that haven't been written, yet. rdar://89082987
1 parent 7411a19 commit 207a053

File tree

9 files changed

+58
-42
lines changed

9 files changed

+58
-42
lines changed

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

+7-4
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,16 @@ public final class SwiftTargetBuildDescription {
103103
}
104104
}
105105

106+
var modulesPath: AbsolutePath {
107+
return self.buildParameters.buildPath.appending(component: "Modules")
108+
}
109+
106110
/// The path to the swiftmodule file after compilation.
107111
var moduleOutputPath: AbsolutePath {
108112
// If we're an executable and we're not allowing test targets to link against us, we hide the module.
109113
let allowLinkingAgainstExecutables = (buildParameters.targetTriple.isDarwin() || self.buildParameters.targetTriple
110114
.isLinux() || self.buildParameters.targetTriple.isWindows()) && self.toolsVersion >= .v5_5
111-
let dirPath = (target.type == .executable && !allowLinkingAgainstExecutables) ? self.tempsPath : self
112-
.buildParameters.buildPath
115+
let dirPath = (target.type == .executable && !allowLinkingAgainstExecutables) ? self.tempsPath : self.modulesPath
113116
return dirPath.appending(component: self.target.c99name + ".swiftmodule")
114117
}
115118

@@ -122,7 +125,7 @@ public final class SwiftTargetBuildDescription {
122125

123126
/// The path to the swifinterface file after compilation.
124127
var parseableModuleInterfaceOutputPath: AbsolutePath {
125-
self.buildParameters.buildPath.appending(component: self.target.c99name + ".swiftinterface")
128+
self.modulesPath.appending(component: self.target.c99name + ".swiftinterface")
126129
}
127130

128131
/// Path to the resource Info.plist file, if generated.
@@ -638,7 +641,7 @@ public final class SwiftTargetBuildDescription {
638641
result.append(contentsOf: self.sources.map(\.pathString))
639642

640643
result.append("-I")
641-
result.append(self.buildParameters.buildPath.pathString)
644+
result.append(self.modulesPath.pathString)
642645

643646
result += try self.compileArguments()
644647
return result

Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ extension LLBuildManifestBuilder {
380380
moduleName: target.target.c99name,
381381
moduleAliases: target.target.moduleAliases,
382382
moduleOutputPath: target.moduleOutputPath,
383-
importPath: target.buildParameters.buildPath,
383+
importPath: target.modulesPath,
384384
tempsPath: target.tempsPath,
385385
objects: try target.objects,
386386
otherArguments: try target.compileArguments(),

Sources/Build/BuildPlan/BuildPlan.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,11 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
467467
}
468468
arguments += extraSwiftCFlags
469469

470-
// Add the search path to the directory containing the modulemap file.
470+
// Add search paths to the directories containing module maps and Swift modules.
471471
for target in targets {
472472
switch target {
473-
case .swift: break
473+
case .swift(let targetDescription):
474+
arguments += ["-I", targetDescription.moduleOutputPath.pathString]
474475
case .clang(let targetDescription):
475476
if let includeDir = targetDescription.moduleMap?.parentDirectory {
476477
arguments += ["-I", includeDir.pathString]

Tests/BuildTests/BuildPlanTests.swift

+12-12
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,8 @@ final class BuildPlanTests: XCTestCase {
645645
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
646646
"-Xlinker", "-rpath", "-Xlinker", "/fake/path/lib/swift-5.5/macosx",
647647
"-target", defaultTargetTriple,
648+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Modules", "lib.swiftmodule").pathString,
648649
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "exe.build", "exe.swiftmodule").pathString,
649-
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "lib.swiftmodule").pathString,
650650
"-g",
651651
]
652652
#elseif os(Windows)
@@ -869,7 +869,7 @@ final class BuildPlanTests: XCTestCase {
869869
let contents: String = try fs.readFileContents(yaml)
870870
let swiftGetVersionFilePath = try XCTUnwrap(llbuild.swiftGetVersionFiles.first?.value)
871871
XCTAssertMatch(contents, .contains("""
872-
inputs: ["\(Pkg.appending(components: "Sources", "exe", "main.swift").escapedPathString)","\(swiftGetVersionFilePath.escapedPathString)","\(buildPath.appending(components: "PkgLib.swiftmodule").escapedPathString)","\(buildPath.appending(components: "exe.build", "sources").escapedPathString)"]
872+
inputs: ["\(Pkg.appending(components: "Sources", "exe", "main.swift").escapedPathString)","\(swiftGetVersionFilePath.escapedPathString)","\(buildPath.appending(components: "Modules", "PkgLib.swiftmodule").escapedPathString)","\(buildPath.appending(components: "exe.build", "sources").escapedPathString)"]
873873
"""))
874874

875875
}
@@ -1736,8 +1736,8 @@ final class BuildPlanTests: XCTestCase {
17361736
"@\(buildPath.appending(components: "PkgPackageTests.product", "Objects.LinkFileList"))"] +
17371737
rpathsForBackdeployment +
17381738
["-target", "\(hostTriple.tripleString(forPlatformVersion: version))",
1739-
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Foo.swiftmodule").pathString,
1740-
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "FooTests.swiftmodule").pathString,
1739+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Modules", "Foo.swiftmodule").pathString,
1740+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Modules", "FooTests.swiftmodule").pathString,
17411741
"-g",
17421742
])
17431743
#elseif os(Windows)
@@ -2313,7 +2313,7 @@ final class BuildPlanTests: XCTestCase {
23132313
"@\(buildPath.appending(components: "Bar-Baz.product", "Objects.LinkFileList"))",
23142314
"-Xlinker", "-rpath", "-Xlinker", "/fake/path/lib/swift-5.5/macosx",
23152315
"-target", defaultTargetTriple,
2316-
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Bar.swiftmodule").pathString,
2316+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Modules", "Bar.swiftmodule").pathString,
23172317
"-g",
23182318
])
23192319
#elseif os(Windows)
@@ -2432,7 +2432,7 @@ final class BuildPlanTests: XCTestCase {
24322432
"@\(buildPath.appending(components: "lib.product", "Objects.LinkFileList"))",
24332433
"-Xlinker", "-rpath", "-Xlinker", "/fake/path/lib/swift-5.5/macosx",
24342434
"-target", defaultTargetTriple,
2435-
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "lib.swiftmodule").pathString,
2435+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Modules", "lib.swiftmodule").pathString,
24362436
"-g",
24372437
]
24382438
#elseif os(Windows)
@@ -4110,7 +4110,7 @@ final class BuildPlanTests: XCTestCase {
41104110
XCTAssertMatch(contents, .contains("""
41114111
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
41124112
tool: clang
4113-
inputs: ["\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
4113+
inputs: ["\(buildPath.appending(components: "Modules", "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
41144114
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
41154115
description: "Compiling Bar main.m"
41164116
"""))
@@ -4184,7 +4184,7 @@ final class BuildPlanTests: XCTestCase {
41844184
XCTAssertMatch(contents, .contains("""
41854185
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
41864186
tool: clang
4187-
inputs: ["\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
4187+
inputs: ["\(buildPath.appending(components: "Modules", "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
41884188
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
41894189
description: "Compiling Bar main.m"
41904190
"""))
@@ -4322,10 +4322,10 @@ final class BuildPlanTests: XCTestCase {
43224322
XCTAssertMatch(contents, .contains("""
43234323
"\(buildPath.appending(components: "lib.build", "lib.swiftmodule.o").escapedPathString)":
43244324
tool: shell
4325-
inputs: ["\(buildPath.appending(components: "lib.swiftmodule").escapedPathString)"]
4325+
inputs: ["\(buildPath.appending(components: "Modules", "lib.swiftmodule").escapedPathString)"]
43264326
outputs: ["\(buildPath.appending(components: "lib.build", "lib.swiftmodule.o").escapedPathString)"]
43274327
description: "Wrapping AST for lib for debugging"
4328-
args: ["\(result.plan.buildParameters.toolchain.swiftCompilerPath.escapedPathString)","-modulewrap","\(buildPath.appending(components: "lib.swiftmodule").escapedPathString)","-o","\(buildPath.appending(components: "lib.build", "lib.swiftmodule.o").escapedPathString)","-target","x86_64-unknown-linux-gnu"]
4328+
args: ["\(result.plan.buildParameters.toolchain.swiftCompilerPath.escapedPathString)","-modulewrap","\(buildPath.appending(components: "Modules", "lib.swiftmodule").escapedPathString)","-o","\(buildPath.appending(components: "lib.build", "lib.swiftmodule.o").escapedPathString)","-target","x86_64-unknown-linux-gnu"]
43294329
"""))
43304330
}
43314331

@@ -4958,7 +4958,7 @@ final class BuildPlanTests: XCTestCase {
49584958

49594959
let yamlContents: String = try fs.readFileContents(yaml)
49604960
let inputs: SerializedJSON = """
4961-
inputs: ["\(AbsolutePath("/Pkg/Snippets/ASnippet.swift"))","\(swiftGetVersionFilePath)","\(AbsolutePath("/Pkg/.build/debug/Lib.swiftmodule"))"
4961+
inputs: ["\(AbsolutePath("/Pkg/Snippets/ASnippet.swift"))","\(swiftGetVersionFilePath)","\(AbsolutePath("/Pkg/.build/debug/Modules/Lib.swiftmodule"))"
49624962
"""
49634963
XCTAssertMatch(yamlContents, .contains(inputs.underlying))
49644964
}
@@ -5173,8 +5173,8 @@ final class BuildPlanTests: XCTestCase {
51735173
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
51745174
"-Xlinker", "-rpath", "-Xlinker", "/fake/path/lib/swift-5.5/macosx",
51755175
"-target", defaultTargetTriple,
5176+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "Modules", "lib.swiftmodule").pathString,
51765177
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "exe.build", "exe.swiftmodule").pathString,
5177-
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "lib.swiftmodule").pathString,
51785178
"-g",
51795179
]
51805180
#elseif os(Windows)

Tests/CommandsTests/BuildToolTests.swift

+16-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct BuildResult {
2626
let stdout: String
2727
let stderr: String
2828
let binContents: [String]
29+
let moduleContents: [String]
2930
}
3031

3132
final class BuildToolTests: CommandsTestCase {
@@ -55,7 +56,14 @@ final class BuildToolTests: CommandsTestCase {
5556
// is what `binContents` is meant to represent.
5657
return contents != ["output-file-map.json"]
5758
}
58-
return BuildResult(binPath: binPath, stdout: stdout, stderr: stderr, binContents: binContents)
59+
let moduleContents = (try? localFileSystem.getDirectoryContents(binPath.appending(component: "Modules"))) ?? []
60+
return BuildResult(
61+
binPath: binPath,
62+
stdout: stdout,
63+
stderr: stderr,
64+
binContents: binContents,
65+
moduleContents: moduleContents
66+
)
5967
}
6068

6169
func testUsage() throws {
@@ -325,9 +333,9 @@ final class BuildToolTests: CommandsTestCase {
325333
// Also make sure we didn't emit parseable module interfaces
326334
// (do this here to avoid doing a second build in
327335
// testParseableInterfaces().
328-
XCTAssertNoMatch(result.binContents, ["ATarget.swiftinterface"])
329-
XCTAssertNoMatch(result.binContents, ["BTarget.swiftinterface"])
330-
XCTAssertNoMatch(result.binContents, ["CTarget.swiftinterface"])
336+
XCTAssertNoMatch(result.moduleContents, ["ATarget.swiftinterface"])
337+
XCTAssertNoMatch(result.moduleContents, ["BTarget.swiftinterface"])
338+
XCTAssertNoMatch(result.moduleContents, ["CTarget.swiftinterface"])
331339
}
332340
}
333341
}
@@ -336,8 +344,8 @@ final class BuildToolTests: CommandsTestCase {
336344
try fixture(name: "Miscellaneous/ParseableInterfaces") { fixturePath in
337345
do {
338346
let result = try build(["--enable-parseable-module-interfaces"], packagePath: fixturePath)
339-
XCTAssertMatch(result.binContents, ["A.swiftinterface"])
340-
XCTAssertMatch(result.binContents, ["B.swiftinterface"])
347+
XCTAssertMatch(result.moduleContents, ["A.swiftinterface"])
348+
XCTAssertMatch(result.moduleContents, ["B.swiftinterface"])
341349
} catch SwiftPMError.executionFailure(_, _, let stderr) {
342350
XCTFail(stderr)
343351
}
@@ -348,8 +356,8 @@ final class BuildToolTests: CommandsTestCase {
348356
try fixture(name: "Miscellaneous/LibraryEvolution") { fixturePath in
349357
do {
350358
let result = try build([], packagePath: fixturePath)
351-
XCTAssertMatch(result.binContents, ["A.swiftinterface"])
352-
XCTAssertMatch(result.binContents, ["B.swiftinterface"])
359+
XCTAssertMatch(result.moduleContents, ["A.swiftinterface"])
360+
XCTAssertMatch(result.moduleContents, ["B.swiftinterface"])
353361
}
354362
}
355363
}

Tests/FunctionalTests/MiscellaneousTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ class MiscellaneousTestCase: XCTestCase {
5454
XCTAssertBuilds(fixturePath.appending("app"))
5555
let buildDir = fixturePath.appending(components: "app", ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug")
5656
XCTAssertFileExists(buildDir.appending("FooExec"))
57-
XCTAssertFileExists(buildDir.appending("FooLib1.swiftmodule"))
58-
XCTAssertFileExists(buildDir.appending("FooLib2.swiftmodule"))
57+
XCTAssertFileExists(buildDir.appending(components: "Modules", "FooLib1.swiftmodule"))
58+
XCTAssertFileExists(buildDir.appending(components: "Modules", "FooLib2.swiftmodule"))
5959
}
6060
}
6161

Tests/FunctionalTests/ModuleAliasingFixtureTests.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ class ModuleAliasingFixtureTests: XCTestCase {
2525
let buildPath = pkgPath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug")
2626
XCTAssertBuilds(pkgPath, extraArgs: ["--vv"])
2727
XCTAssertFileExists(buildPath.appending(components: "App"))
28-
XCTAssertFileExists(buildPath.appending(components: "GameUtils.swiftmodule"))
29-
XCTAssertFileExists(buildPath.appending(components: "Utils.swiftmodule"))
28+
XCTAssertFileExists(buildPath.appending(components: "Modules", "GameUtils.swiftmodule"))
29+
XCTAssertFileExists(buildPath.appending(components: "Modules", "Utils.swiftmodule"))
3030
_ = try SwiftPM.Build.execute(packagePath: pkgPath)
3131
}
3232
}
@@ -37,8 +37,8 @@ class ModuleAliasingFixtureTests: XCTestCase {
3737
let buildPath = pkgPath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug")
3838
XCTAssertBuilds(pkgPath, extraArgs: ["--vv"])
3939
XCTAssertFileExists(buildPath.appending(components: "App"))
40-
XCTAssertFileExists(buildPath.appending(components: "AUtils.swiftmodule"))
41-
XCTAssertFileExists(buildPath.appending(components: "BUtils.swiftmodule"))
40+
XCTAssertFileExists(buildPath.appending(components: "Modules", "AUtils.swiftmodule"))
41+
XCTAssertFileExists(buildPath.appending(components: "Modules", "BUtils.swiftmodule"))
4242
_ = try SwiftPM.Build.execute(packagePath: pkgPath)
4343
}
4444
}

Tests/WorkspaceTests/InitTests.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class InitTests: XCTestCase {
9494
#else
9595
XCTAssertFileExists(binPath.appending("Foo"))
9696
#endif
97-
XCTAssertFileExists(binPath.appending(components: "Foo.swiftmodule"))
97+
XCTAssertFileExists(binPath.appending(components: "Modules", "Foo.swiftmodule"))
9898
}
9999
}
100100

@@ -145,7 +145,7 @@ class InitTests: XCTestCase {
145145
// Try building it
146146
XCTAssertBuilds(path)
147147
let triple = try UserToolchain.default.targetTriple
148-
XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Foo.swiftmodule"))
148+
XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule"))
149149
}
150150
}
151151

@@ -243,7 +243,7 @@ class InitTests: XCTestCase {
243243
// Try building it.
244244
XCTAssertBuilds(packageRoot)
245245
let triple = try UserToolchain.default.targetTriple
246-
XCTAssertFileExists(packageRoot.appending(components: ".build", triple.platformBuildPathComponent, "debug", "some_package.swiftmodule"))
246+
XCTAssertFileExists(packageRoot.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "some_package.swiftmodule"))
247247
}
248248
}
249249

Utilities/bootstrap

+10-6
Original file line numberDiff line numberDiff line change
@@ -450,19 +450,23 @@ def install_dylib(args, library_name, install_dir, module_names):
450450
for module in module_names:
451451
# If we're cross-compiling, we expect the .swiftmodule to be a directory that contains everything.
452452
if args.cross_compile_hosts:
453-
install_binary(args, module + ".swiftmodule", install_dir, ['Project', '*.swiftmodule'])
453+
install_binary(args, module + ".swiftmodule", install_dir, ['Project', '*.swiftmodule'], subpath="Modules")
454454
else:
455455
# Otherwise we have either a .swiftinterface or a .swiftmodule, plus a .swiftdoc.
456456
if os.path.exists(os.path.join(args.bin_dir, module + ".swiftinterface")):
457-
install_binary(args, module + ".swiftinterface", install_dir)
457+
install_binary(args, module + ".swiftinterface", install_dir, subpath="Modules")
458458
else:
459-
install_binary(args, module + ".swiftmodule", install_dir)
460-
install_binary(args, module + ".swiftdoc", install_dir)
459+
install_binary(args, module + ".swiftmodule", install_dir, subpath="Modules")
460+
install_binary(args, module + ".swiftdoc", install_dir, subpath="Modules")
461461

462462

463463
# Helper function that installs a single built artifact to a particular directory. The source may be either a file or a directory.
464-
def install_binary(args, binary, destination, destination_is_directory=True, ignored_patterns=[]):
465-
src = os.path.join(args.bin_dir, binary)
464+
def install_binary(args, binary, destination, destination_is_directory=True, ignored_patterns=[], subpath=None):
465+
if subpath:
466+
basepath = os.path.join(args.bin_dir, subpath)
467+
else:
468+
basepath = args.bin_dir
469+
src = os.path.join(basepath, binary)
466470
install_file(args, src, destination, destination_is_directory=destination_is_directory, ignored_patterns=ignored_patterns)
467471

468472
def install_file(args, src, destination, destination_is_directory=True, ignored_patterns=[]):

0 commit comments

Comments
 (0)