Skip to content

Commit 34a99c7

Browse files
Fix build on non-macOS Apple platforms
1 parent 5cb496d commit 34a99c7

File tree

15 files changed

+272
-232
lines changed

15 files changed

+272
-232
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ jobs:
5454
EOS
5555
- run: ./Vendor/checkout-dependency
5656
- run: swift test --sanitize address
57+
- run: xcrun xcodebuild -skipMacroValidation -skipPackagePluginValidation build -scheme WasmKit-Package -destination generic/platform=iOS
58+
- run: xcrun xcodebuild -skipMacroValidation -skipPackagePluginValidation build -scheme WasmKit-Package -destination generic/platform=watchOS
59+
- run: xcrun xcodebuild -skipMacroValidation -skipPackagePluginValidation build -scheme WasmKit-Package -destination generic/platform=tvOS
60+
- run: xcrun xcodebuild -skipMacroValidation -skipPackagePluginValidation build -scheme WasmKit-Package -destination generic/platform=visionOS
5761

5862
build-linux:
5963
strategy:

Sources/CLI/Run/Run.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct Run: ParsableCommand {
4242
log("Started parsing module", verbose: true)
4343

4444
let module: Module
45-
if verbose, #available(macOS 13.0, *) {
45+
if verbose, #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) {
4646
let (parsedModule, parseTime) = try measure {
4747
try parseWasm(filePath: FilePath(path))
4848
}
@@ -70,7 +70,7 @@ struct Run: ParsableCommand {
7070
invoke = entry
7171
}
7272

73-
if #available(macOS 13.0, *) {
73+
if #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) {
7474
let (_, invokeTime) = try measure(execution: invoke)
7575
log("Finished invoking function \"\(path)\": \(invokeTime)", verbose: true)
7676
} else {

Sources/WITExtractor/ModuleTranslation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@available(macOS 11, *)
1+
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
22
struct ModuleTranslation {
33
let diagnostics: DiagnosticCollection
44
let typeMapping: TypeMapping

Sources/WITExtractor/SourceSummary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public struct SwiftFunctionSource {
4949
let name: String
5050
}
5151

52-
@available(macOS 11, *)
52+
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
5353
struct SourceSummaryBuilder {
5454
let diagnostics: DiagnosticCollection
5555
let typeMapping: TypeMapping

Sources/WITExtractor/SwiftAPIDigester.swift

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -116,26 +116,30 @@ struct SwiftAPIDigester {
116116
typealias SDKNodeType = SDKNodeInherit<SDKNodeBody, SDKNodeTypeBody>
117117
typealias SDKNodeTypeNominal = SDKNodeInherit<SDKNodeType, SDKNodeTypeNominalBody>
118118

119-
@available(macOS 11, *)
119+
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
120120
func dumpSDK(moduleName: String, arguments: [String]) throws -> Output {
121-
var args = [
122-
"-dump-sdk",
123-
"-module", moduleName,
124-
// Emit output to stdout
125-
"-o", "-",
126-
]
127-
args += arguments
128-
let process = Process()
129-
process.executableURL = executableURL
130-
process.arguments = args
131-
let stdoutPipe = Pipe()
132-
process.standardOutput = stdoutPipe
133-
try process.run()
134-
guard let output = try stdoutPipe.fileHandleForReading.readToEnd() else {
135-
throw SwiftAPIDigesterError.unexpectedEmptyOutput
136-
}
137-
process.waitUntilExit()
138-
return try Output.parse(output)
121+
#if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
122+
fatalError("WITExtractor does not support platforms where Foundation.Process is unavailable")
123+
#else
124+
var args = [
125+
"-dump-sdk",
126+
"-module", moduleName,
127+
// Emit output to stdout
128+
"-o", "-",
129+
]
130+
args += arguments
131+
let process = Process()
132+
process.executableURL = executableURL
133+
process.arguments = args
134+
let stdoutPipe = Pipe()
135+
process.standardOutput = stdoutPipe
136+
try process.run()
137+
guard let output = try stdoutPipe.fileHandleForReading.readToEnd() else {
138+
throw SwiftAPIDigesterError.unexpectedEmptyOutput
139+
}
140+
process.waitUntilExit()
141+
return try Output.parse(output)
142+
#endif
139143
}
140144
}
141145

Sources/WITExtractor/TypeMapping.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@available(macOS 11, *)
1+
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
22
struct TypeMapping {
33
typealias DeclScope = [SwiftAPIDigester.SDKNodeDecl]
44
struct DeclSource {

Sources/WITExtractor/WITExtractor.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import Foundation
22

3+
@available(iOS, unavailable)
4+
@available(watchOS, unavailable)
5+
@available(tvOS, unavailable)
6+
@available(visionOS, unavailable)
37
public struct WITExtractor {
48
public struct Output {
59
public var witContents: String
@@ -31,7 +35,7 @@ public struct WITExtractor {
3135
}
3236

3337
public func run(moduleName: String) throws -> Output {
34-
guard #available(macOS 11, *) else {
38+
guard #available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else {
3539
fatalError("WITExtractor requires macOS 11+")
3640
}
3741
let header = """
@@ -45,7 +49,7 @@ public struct WITExtractor {
4549
return output
4650
}
4751

48-
@available(macOS 11, *)
52+
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
4953
func runWithoutHeader(moduleName: String) throws -> Output {
5054
let output = try digester.dumpSDK(moduleName: moduleName, arguments: extraDigesterArguments)
5155
var typeMapping = TypeMapping()

Sources/WITTool/WITTool.swift

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -123,45 +123,49 @@ struct ExtractWIT: ParsableCommand {
123123
var digesterArgs: [String] = []
124124

125125
func run() throws {
126-
guard #available(macOS 11, *) else {
127-
fatalError("ExtractWIT requires macOS 11+")
128-
}
129-
130-
let extractor = WITExtractor(
131-
namespace: namespace,
132-
packageName: packageName,
133-
digesterPath: digesterPath,
134-
extraDigesterArguments: digesterArgs
135-
)
136-
let output = try extractor.run(moduleName: moduleName)
137-
try output.witContents.write(toFile: witOutputPath, atomically: true, encoding: .utf8)
138-
139-
for diagnostic in extractor.diagnostics {
140-
try FileHandle.standardError.write(contentsOf: Data((diagnostic.description + "\n").utf8))
141-
}
126+
#if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
127+
fatalError("WITExtractor does not support platforms where Foundation.Process is unavailable")
128+
#else
129+
guard #available(macOS 11, *) else {
130+
fatalError("ExtractWIT requires macOS 11+")
131+
}
142132

143-
// Generate overlay shim to export extracted WIT interface
144-
do {
145-
let sourceFile = try SourceFileSyntax.parse(
146-
output.witContents,
147-
fileName: "<extracted>.wit"
133+
let extractor = WITExtractor(
134+
namespace: namespace,
135+
packageName: packageName,
136+
digesterPath: digesterPath,
137+
extraDigesterArguments: digesterArgs
148138
)
149-
let packageResolver = PackageResolver()
150-
let packageUnit = try packageResolver.register(packageSources: [sourceFile])
151-
let context = SemanticsContext(rootPackage: packageUnit, packageResolver: packageResolver)
152-
let (interface, _) = try context.lookupInterface(name: output.interfaceName, contextPackage: packageUnit)
153-
154-
let swiftSource = try generateGuestExportInterface(
155-
context: context,
156-
sourceFile: sourceFile,
157-
interface: interface,
158-
sourceSummaryProvider: SwiftSourceSummaryProvider(
159-
summary: output.sourceSummary,
160-
typeMapping: output.typeMapping
139+
let output = try extractor.run(moduleName: moduleName)
140+
try output.witContents.write(toFile: witOutputPath, atomically: true, encoding: .utf8)
141+
142+
for diagnostic in extractor.diagnostics {
143+
try FileHandle.standardError.write(contentsOf: Data((diagnostic.description + "\n").utf8))
144+
}
145+
146+
// Generate overlay shim to export extracted WIT interface
147+
do {
148+
let sourceFile = try SourceFileSyntax.parse(
149+
output.witContents,
150+
fileName: "<extracted>.wit"
161151
)
162-
)
163-
try swiftSource.write(toFile: swiftOutputPath, atomically: true, encoding: .utf8)
164-
}
152+
let packageResolver = PackageResolver()
153+
let packageUnit = try packageResolver.register(packageSources: [sourceFile])
154+
let context = SemanticsContext(rootPackage: packageUnit, packageResolver: packageResolver)
155+
let (interface, _) = try context.lookupInterface(name: output.interfaceName, contextPackage: packageUnit)
156+
157+
let swiftSource = try generateGuestExportInterface(
158+
context: context,
159+
sourceFile: sourceFile,
160+
interface: interface,
161+
sourceSummaryProvider: SwiftSourceSummaryProvider(
162+
summary: output.sourceSummary,
163+
typeMapping: output.typeMapping
164+
)
165+
)
166+
try swiftSource.write(toFile: swiftOutputPath, atomically: true, encoding: .utf8)
167+
}
168+
#endif
165169
}
166170

167171
private func writeFile(_ filePath: String, contents: String) throws {

Tests/WATTests/EncoderTests.swift

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -75,35 +75,39 @@ class EncoderTests: XCTestCase {
7575
}
7676

7777
func testSpectest() throws {
78-
guard let wast2json = TestSupport.lookupExecutable("wast2json") else {
79-
throw XCTSkip("wast2json not found in PATH")
80-
}
78+
#if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
79+
throw XCTSkip("Spectest compatibility test requires Foundation.Process")
80+
#else
81+
guard let wast2json = TestSupport.lookupExecutable("wast2json") else {
82+
throw XCTSkip("wast2json not found in PATH")
83+
}
8184

82-
var stats = CompatibilityTestStats()
83-
let excluded: [String] = []
84-
for wastFile in Spectest.wastFiles(include: [], exclude: excluded) {
85-
try TestSupport.withTemporaryDirectory { tempDir, shouldRetain in
86-
let jsonFileName = wastFile.deletingPathExtension().lastPathComponent + ".json"
87-
let json = URL(fileURLWithPath: tempDir).appendingPathComponent(jsonFileName)
85+
var stats = CompatibilityTestStats()
86+
let excluded: [String] = []
87+
for wastFile in Spectest.wastFiles(include: [], exclude: excluded) {
88+
try TestSupport.withTemporaryDirectory { tempDir, shouldRetain in
89+
let jsonFileName = wastFile.deletingPathExtension().lastPathComponent + ".json"
90+
let json = URL(fileURLWithPath: tempDir).appendingPathComponent(jsonFileName)
8891

89-
let wast2jsonProcess = try Process.run(
90-
wast2json,
91-
arguments: [wastFile.path, "-o", json.path]
92-
)
93-
wast2jsonProcess.waitUntilExit()
92+
let wast2jsonProcess = try Process.run(
93+
wast2json,
94+
arguments: [wastFile.path, "-o", json.path]
95+
)
96+
wast2jsonProcess.waitUntilExit()
9497

95-
do {
96-
try checkWabtCompatibility(wast: wastFile, json: json, stats: &stats)
97-
} catch {
98-
stats.failed.insert(wastFile.lastPathComponent)
99-
shouldRetain = true
100-
XCTFail("Error while checking compatibility between \(wastFile) and \(json.path): \(error)")
98+
do {
99+
try checkWabtCompatibility(wast: wastFile, json: json, stats: &stats)
100+
} catch {
101+
stats.failed.insert(wastFile.lastPathComponent)
102+
shouldRetain = true
103+
XCTFail("Error while checking compatibility between \(wastFile) and \(json.path): \(error)")
104+
}
101105
}
102106
}
103-
}
104-
print("Spectest compatibility: \(stats.run - stats.failed.count) / \(stats.run)")
105-
if !stats.failed.isEmpty {
106-
print("Failed test cases: \(stats.failed.sorted())")
107-
}
107+
print("Spectest compatibility: \(stats.run - stats.failed.count) / \(stats.run)")
108+
if !stats.failed.isEmpty {
109+
print("Failed test cases: \(stats.failed.sorted())")
110+
}
111+
#endif
108112
}
109113
}

Tests/WITExtractorPluginTests/TestSupport.swift

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -47,40 +47,44 @@ struct TestSupport {
4747
}
4848

4949
func assertSwiftPackage(fixturePackage: String, _ trailingArguments: [String]) throws -> String {
50-
guard let config = TestSupport.Configuration.default else {
51-
throw XCTSkip("Please create 'Tests/default.json'")
52-
}
53-
let swiftExecutable = config.hostSwiftExecutablePath
54-
let packagePath = URL(fileURLWithPath: #filePath)
55-
.deletingLastPathComponent()
56-
.appendingPathComponent("Fixtures")
57-
.appendingPathComponent(fixturePackage)
58-
59-
return try TestSupport.withTemporaryDirectory { buildDir in
60-
var arguments = ["package", "--package-path", packagePath.path, "--scratch-path", buildDir]
61-
if let sdkRootPath = config.hostSdkRootPath {
62-
arguments += ["--sdk", sdkRootPath]
50+
#if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
51+
throw XCTSkip("WITExtractor does not support platforms where Foundation.Process is unavailable")
52+
#else
53+
guard let config = TestSupport.Configuration.default else {
54+
throw XCTSkip("Please create 'Tests/default.json'")
6355
}
64-
arguments += trailingArguments
65-
let stdoutPipe = Pipe()
66-
let process = Process()
67-
process.executableURL = URL(fileURLWithPath: swiftExecutable.path)
68-
process.arguments = arguments
69-
process.standardOutput = stdoutPipe
70-
try process.run()
71-
process.waitUntilExit()
56+
let swiftExecutable = config.hostSwiftExecutablePath
57+
let packagePath = URL(fileURLWithPath: #filePath)
58+
.deletingLastPathComponent()
59+
.appendingPathComponent("Fixtures")
60+
.appendingPathComponent(fixturePackage)
7261

73-
guard process.terminationStatus == 0 else {
74-
throw TestSupport.Error(
75-
description: "Failed to execute \(([swiftExecutable.path] + arguments).joined(separator: " "))"
76-
)
77-
}
78-
guard let stdoutBytes = try stdoutPipe.fileHandleForReading.readToEnd() else { return "" }
79-
struct Output: Codable {
80-
let witOutputPath: String
81-
let swiftOutputPath: String
62+
return try TestSupport.withTemporaryDirectory { buildDir in
63+
var arguments = ["package", "--package-path", packagePath.path, "--scratch-path", buildDir]
64+
if let sdkRootPath = config.hostSdkRootPath {
65+
arguments += ["--sdk", sdkRootPath]
66+
}
67+
arguments += trailingArguments
68+
let stdoutPipe = Pipe()
69+
let process = Process()
70+
process.executableURL = URL(fileURLWithPath: swiftExecutable.path)
71+
process.arguments = arguments
72+
process.standardOutput = stdoutPipe
73+
try process.run()
74+
process.waitUntilExit()
75+
76+
guard process.terminationStatus == 0 else {
77+
throw TestSupport.Error(
78+
description: "Failed to execute \(([swiftExecutable.path] + arguments).joined(separator: " "))"
79+
)
80+
}
81+
guard let stdoutBytes = try stdoutPipe.fileHandleForReading.readToEnd() else { return "" }
82+
struct Output: Codable {
83+
let witOutputPath: String
84+
let swiftOutputPath: String
85+
}
86+
let jsonOutput = try JSONDecoder().decode(Output.self, from: stdoutBytes)
87+
return try String(contentsOfFile: jsonOutput.witOutputPath)
8288
}
83-
let jsonOutput = try JSONDecoder().decode(Output.self, from: stdoutBytes)
84-
return try String(contentsOfFile: jsonOutput.witOutputPath)
85-
}
89+
#endif
8690
}

0 commit comments

Comments
 (0)