Skip to content

Commit 32b7a28

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 adc2535 commit 32b7a28

File tree

2 files changed

+88
-68
lines changed

2 files changed

+88
-68
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

+83-68
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,51 +795,51 @@ 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 {
853-
try XCTSkip("Test not implemented for xcode build system.")
842+
throw XCTSkip("Test not implemented for xcode build system.")
854843
}
855844
}
856845
#endif
@@ -866,9 +855,31 @@ 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+
let debugPath = try await self.execute(["--show-bin-path"], packagePath: fullPath).stdout
877+
XCTAssertMatch(debugPath, .regex(targetPath.appending(components: "Products", "Debug").pathString + "(\\-linux|\\-Windows)?\\n"))
878+
let releasePath = try await self.execute(["-c", "release", "--show-bin-path"], packagePath: fullPath).stdout
879+
XCTAssertMatch(releasePath, .regex(targetPath.appending(components: "Products", "Release").pathString + "(\\-linux|\\-Windows)?\\n"))
880+
}
881+
}
882+
872883
override func testGetTaskAllowEntitlement() async throws {
873884
throw XCTSkip("SWBINTTODO: Test failed because swiftbuild doesn't output precis codesign commands. Once swift run works with swiftbuild the test can be investigated.")
874885
}
@@ -880,13 +891,20 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases {
880891
override func testAtMainSupport() async throws {
881892
#if !os(macOS)
882893
throw XCTSkip("SWBINTTODO: File not found or missing libclang errors on non-macOS platforms. This needs to be investigated")
883-
#endif
884-
894+
#else
885895
try await super.testAtMainSupport()
896+
#endif
886897
}
887898

888899
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")
900+
try await fixture(name: "Miscellaneous/LibraryEvolution") { fixturePath in
901+
do {
902+
let result = try await build([], packagePath: fixturePath)
903+
XCTAssertMatch(
904+
result.moduleContents, [.regex(#"A\.swiftmodule\/.*\.swiftinterface"#)])
905+
XCTAssertMatch(result.moduleContents, [.regex(#"B\.swiftmodule\/.*\.swiftmodule"#)])
906+
}
907+
}
890908
}
891909

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

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-
908922
override func testSymlink() async throws {
909923
throw XCTSkip("SWBINTTODO: Test fails because of a difference in the build layout. This needs to be updated to the expected path")
910924
}
@@ -927,7 +941,7 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases {
927941

928942
override func testBuildSystemDefaultSettings() async throws {
929943
#if os(Linux)
930-
if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false {
944+
if FileManager.default.contents(atPath: "/etc/system-release").map( { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ) ?? false {
931945
throw XCTSkip("Skipping SwiftBuild testing on Amazon Linux because of platform issues.")
932946
}
933947
#endif
@@ -941,9 +955,10 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases {
941955

942956
override func testBuildCompleteMessage() async throws {
943957
#if os(Linux)
944-
try XCTSkip("SWBINTTODO: Need to properly set LD_LIBRARY_PATH on linux")
945-
#endif
958+
throw XCTSkip("SWBINTTODO: Need to properly set LD_LIBRARY_PATH on linux")
959+
#else
946960
try await super.testBuildCompleteMessage()
961+
#endif
947962
}
948963

949964
}

0 commit comments

Comments
 (0)