Skip to content

Commit 0392765

Browse files
committed
Implement --enable-parseable-module-interfaces for swift-build buildsystem
- this also fixes -enable-library-evolution when used as a unsafeFlags Closes: 8337
1 parent 2dc064d commit 0392765

File tree

2 files changed

+86
-62
lines changed

2 files changed

+86
-62
lines changed

Sources/SwiftBuildSupport/SwiftBuildSystem.swift

+5
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
470470
settings["ARCHS"] = architectures.joined(separator: " ")
471471
}
472472

473+
// support for --enable-parseable-module-interfaces
474+
if buildParameters.driverParameters.enableParseableModuleInterfaces {
475+
settings["SWIFT_EMIT_MODULE_INTERFACE"] = "YES"
476+
}
477+
473478
// Generate the build parameters.
474479
var params = SwiftBuild.SWBBuildParameters()
475480
params.configurationName = buildParameters.configuration.swiftbuildName

Tests/CommandsTests/BuildCommandTests.swift

+81-62
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase {
3838
}
3939

4040
@discardableResult
41-
private func execute(
41+
func execute(
4242
_ args: [String] = [],
4343
environment: Environment? = nil,
4444
packagePath: AbsolutePath? = nil
@@ -70,7 +70,19 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase {
7070
// is what `binContents` is meant to represent.
7171
return contents != ["output-file-map.json"]
7272
}
73-
let moduleContents = (try? localFileSystem.getDirectoryContents(binPath.appending(component: "Modules"))) ?? []
73+
var moduleContents: [String] = []
74+
if buildSystemProvider == .native {
75+
moduleContents = (try? localFileSystem.getDirectoryContents(binPath.appending(component: "Modules"))) ?? []
76+
} else {
77+
let moduleDirs = (try? localFileSystem.getDirectoryContents(binPath).filter {
78+
$0.hasSuffix(".swiftmodule")
79+
}) ?? []
80+
for dir: String in moduleDirs {
81+
moduleContents +=
82+
(try? localFileSystem.getDirectoryContents(binPath.appending(component: dir)).map { "\(dir)/\($0)" }) ?? []
83+
}
84+
}
85+
7486

7587
if cleanAfterward {
7688
try! await executeSwiftPackage(
@@ -190,48 +202,6 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase {
190202
}
191203
}
192204

193-
func testBinSymlink() async throws {
194-
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
195-
let fullPath = try resolveSymlinks(fixturePath)
196-
let targetPath = try fullPath.appending(
197-
components: ".build",
198-
UserToolchain.default.targetTriple.platformBuildPathComponent
199-
)
200-
let xcbuildTargetPath = fullPath.appending(components: ".build", "apple")
201-
try await XCTAssertAsyncEqual(
202-
try await self.execute(["--show-bin-path"], packagePath: fullPath).stdout,
203-
"\(targetPath.appending("debug").pathString)\n"
204-
)
205-
try await XCTAssertAsyncEqual(
206-
try await self.execute(["-c", "release", "--show-bin-path"], packagePath: fullPath).stdout,
207-
"\(targetPath.appending("release").pathString)\n"
208-
)
209-
210-
guard buildSystemProvider == .xcode || buildSystemProvider == .swiftbuild else {
211-
// The remainder of this test only applies to XCBuild or Swift Build
212-
return
213-
}
214-
215-
// Print correct path when building with XCBuild or Swift Build
216-
let xcodeDebugOutput = try await execute(
217-
["-c", "debug", "--show-bin-path"],
218-
packagePath: fullPath)
219-
.stdout
220-
let xcodeReleaseOutput = try await execute(
221-
["-c", "release", "--show-bin-path"],
222-
packagePath: fullPath
223-
).stdout
224-
XCTAssertEqual(
225-
xcodeDebugOutput,
226-
"\(xcbuildTargetPath.appending(components: "Products", "Debug").pathString)\n"
227-
)
228-
XCTAssertEqual(
229-
xcodeReleaseOutput,
230-
"\(xcbuildTargetPath.appending(components: "Products", "Release").pathString)\n"
231-
)
232-
}
233-
}
234-
235205
func testSymlink() async throws {
236206
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
237207
let fullPath = try resolveSymlinks(fixturePath)
@@ -792,6 +762,25 @@ class BuildCommandNativeTests: BuildCommandTestCases {
792762
override func testUsage() async throws {
793763
try await super.testUsage()
794764
}
765+
766+
func testBinSymlink() async throws {
767+
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
768+
let fullPath = try resolveSymlinks(fixturePath)
769+
let targetPath = try fullPath.appending(
770+
components: ".build",
771+
UserToolchain.default.targetTriple.platformBuildPathComponent
772+
)
773+
try await XCTAssertAsyncEqual(
774+
try await self.execute(["--show-bin-path"], packagePath: fullPath).stdout,
775+
"\(targetPath.appending("debug").pathString)\n"
776+
)
777+
try await XCTAssertAsyncEqual(
778+
try await self.execute(["-c", "release", "--show-bin-path"], packagePath: fullPath)
779+
.stdout,
780+
"\(targetPath.appending("release").pathString)\n"
781+
)
782+
}
783+
}
795784
}
796785

797786
#if os(macOS)
@@ -806,47 +795,47 @@ class BuildCommandXcodeTests: BuildCommandTestCases {
806795
}
807796

808797
override func testAutomaticParseableInterfacesWithLibraryEvolution() async throws {
809-
try XCTSkip("Test not implemented for xcode build system.")
798+
throw XCTSkip("Test not implemented for xcode build system.")
810799
}
811800

812801
override func testNonReachableProductsAndTargetsFunctional() async throws {
813-
try XCTSkip("Test not implemented for xcode build system.")
802+
throw XCTSkip("Test not implemented for xcode build system.")
814803
}
815804

816805
override func testCodeCoverage() async throws {
817-
try XCTSkip("Test not implemented for xcode build system.")
806+
throw XCTSkip("Test not implemented for xcode build system.")
818807
}
819808

820809
override func testBuildStartMessage() async throws {
821-
try XCTSkip("Test not implemented for xcode build system.")
810+
throw XCTSkip("Test not implemented for xcode build system.")
822811
}
823812

824-
override func testBinSymlink() async throws {
825-
try XCTSkip("Test not implemented for xcode build system.")
813+
func testBinSymlink() async throws {
814+
throw XCTSkip("Test not implemented for xcode build system.")
826815
}
827816

828817
override func testSymlink() async throws {
829-
try XCTSkip("Test not implemented for xcode build system.")
818+
throw XCTSkip("Test not implemented for xcode build system.")
830819
}
831820

832821
override func testSwiftGetVersion() async throws {
833-
try XCTSkip("Test not implemented for xcode build system.")
822+
throw XCTSkip("Test not implemented for xcode build system.")
834823
}
835824

836825
override func testParseableInterfaces() async throws {
837-
try XCTSkip("Test not implemented for xcode build system.")
826+
throw XCTSkip("Test not implemented for xcode build system.")
838827
}
839828

840829
override func testProductAndTarget() async throws {
841-
try XCTSkip("Test not implemented for xcode build system.")
830+
throw XCTSkip("Test not implemented for xcode build system.")
842831
}
843832

844833
override func testImportOfMissedDepWarning() async throws {
845-
try XCTSkip("Test not implemented for xcode build system.")
834+
throw XCTSkip("Test not implemented for xcode build system.")
846835
}
847836

848837
override func testGetTaskAllowEntitlement() async throws {
849-
try XCTSkip("Test not implemented for xcode build system.")
838+
throw XCTSkip("Test not implemented for xcode build system.")
850839
}
851840

852841
override func testBuildCompleteMessage() async throws {
@@ -866,9 +855,36 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases {
866855
}
867856

868857
override func testParseableInterfaces() async throws {
869-
throw XCTSkip("SWBINTTODO: Test failed with swiftbuild engine because the --enable-parseable-module-interfaces flag doesn't yet produce .swiftinterface files. This needs to be investigated")
858+
try await fixture(name: "Miscellaneous/ParseableInterfaces") { fixturePath in
859+
do {
860+
let result = try await build(["--enable-parseable-module-interfaces"], packagePath: fixturePath)
861+
XCTAssertMatch(result.moduleContents, [.regex(#"A\.swiftmodule\/.*\.swiftinterface"#)])
862+
XCTAssertMatch(result.moduleContents, [.regex(#"B\.swiftmodule\/.*\.swiftmodule"#)])
863+
} catch SwiftPMError.executionFailure(_, _, let stderr) {
864+
XCTFail(stderr)
865+
}
866+
}
870867
}
871868

869+
func testBinSymlink() async throws {
870+
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
871+
let fullPath = try resolveSymlinks(fixturePath)
872+
let targetPath = try fullPath.appending(
873+
components: ".build",
874+
UserToolchain.default.targetTriple.platformBuildPathComponent
875+
)
876+
try await XCTAssertAsyncEqual(
877+
try await self.execute(["--show-bin-path"], packagePath: fullPath).stdout,
878+
"\(targetPath.appending(components: "Products", "Debug").pathString)\n"
879+
)
880+
try await XCTAssertAsyncEqual(
881+
try await self.execute(["-c", "release", "--show-bin-path"], packagePath: fullPath)
882+
.stdout,
883+
"\(targetPath.appending(components: "Products", "Release").pathString)\n"
884+
)
885+
}
886+
}
887+
872888
override func testGetTaskAllowEntitlement() async throws {
873889
throw XCTSkip("SWBINTTODO: Test failed because swiftbuild doesn't output precis codesign commands. Once swift run works with swiftbuild the test can be investigated.")
874890
}
@@ -886,7 +902,14 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases {
886902
}
887903

888904
override func testAutomaticParseableInterfacesWithLibraryEvolution() async throws {
889-
throw XCTSkip("SWBINTTODO: The test fails because when the unsafe flag for a target is set to '-enable-library-evolution' it is not producing the correct .swiftinterface files. This needs to be investigated")
905+
try await fixture(name: "Miscellaneous/LibraryEvolution") { fixturePath in
906+
do {
907+
let result = try await build([], packagePath: fixturePath)
908+
XCTAssertMatch(
909+
result.moduleContents, [.regex(#"A\.swiftmodule\/.*\.swiftinterface"#)])
910+
XCTAssertMatch(result.moduleContents, [.regex(#"B\.swiftmodule\/.*\.swiftmodule"#)])
911+
}
912+
}
890913
}
891914

892915
override func testImportOfMissedDepWarning() async throws {
@@ -901,10 +924,6 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases {
901924
throw XCTSkip("SWBINTTODO: Test fails because the dummy-swiftc used in the test isn't accepted by swift-build. This needs to be investigated")
902925
}
903926

904-
override func testBinSymlink() async throws {
905-
throw XCTSkip("SWBINTTODO: Test fails because of a difference in the build layout. This needs to be updated to the expected path")
906-
}
907-
908927
override func testSymlink() async throws {
909928
throw XCTSkip("SWBINTTODO: Test fails because of a difference in the build layout. This needs to be updated to the expected path")
910929
}

0 commit comments

Comments
 (0)