Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Windows Support #100

Merged
merged 9 commits into from
Jul 1, 2024
14 changes: 10 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ jobs:

steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- id: setup-swiftwasm
uses: swiftwasm/setup-swiftwasm@v1
with:
Expand All @@ -75,14 +73,22 @@ jobs:
- run: ./CI/check-spectest.sh
- run: ./CI/check-wasi-testsuite.sh

build-windows:
runs-on: windows-latest
steps:
- uses: compnerd/gha-setup-swift@main
with:
branch: swift-5.10.1-release
tag: 5.10.1-RELEASE
- uses: actions/checkout@v4
- run: swift test

build-cmake:
runs-on: ubuntu-20.04
container:
image: swift:5.8-focal
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Ninja
run: apt-get update && apt-get install -y ninja-build
- name: Install CMake
Expand Down
130 changes: 77 additions & 53 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ let package = Package(
name: "WasmParser",
targets: ["WasmParser"]
),
.library(
name: "WasmKitWASI",
targets: ["WasmKitWASI"]
),
.library(
name: "WASI",
targets: ["WASI"]
),
.library(
name: "WIT", targets: ["WIT"]
),
Expand All @@ -31,15 +23,12 @@ let package = Package(
targets: ["CLI"]
),
.library(name: "_CabiShims", targets: ["_CabiShims"]),
.plugin(name: "WITOverlayPlugin", targets: ["WITOverlayPlugin"]),
.plugin(name: "WITExtractorPlugin", targets: ["WITExtractorPlugin"]),
],
targets: [
.executableTarget(
name: "CLI",
dependencies: [
"WasmKit",
"WasmKitWASI",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "SystemPackage", package: "swift-system"),
],
Expand All @@ -49,16 +38,10 @@ let package = Package(
name: "WasmTypes",
exclude: ["CMakeLists.txt"]
),
.target(
name: "WASI",
dependencies: ["WasmTypes", "SystemExtras"],
exclude: ["CMakeLists.txt"]
),
.target(
name: "WasmKit",
dependencies: [
"WasmParser",
"SystemExtras",
"WasmTypes",
.product(name: "SystemPackage", package: "swift-system"),
],
Expand All @@ -72,18 +55,6 @@ let package = Package(
],
exclude: ["CMakeLists.txt"]
),
.target(
name: "WasmKitWASI",
dependencies: ["WasmKit", "WASI"],
exclude: ["CMakeLists.txt"]
),
.target(
name: "SystemExtras",
dependencies: [
.product(name: "SystemPackage", package: "swift-system")
],
exclude: ["CMakeLists.txt"]
),
.executableTarget(
name: "Spectest",
dependencies: [
Expand All @@ -96,31 +67,11 @@ let package = Package(
.testTarget(name: "WITTests", dependencies: ["WIT"]),
.target(name: "WITOverlayGenerator", dependencies: ["WIT"]),
.target(name: "_CabiShims"),
.plugin(name: "WITOverlayPlugin", capability: .buildTool(), dependencies: ["WITTool"]),
.plugin(name: "GenerateOverlayForTesting", capability: .buildTool(), dependencies: ["WITTool"]),
.testTarget(
name: "WITOverlayGeneratorTests",
dependencies: ["WITOverlayGenerator", "WasmKit", "WasmKitWASI"],
exclude: ["Fixtures", "Compiled", "Generated"],
plugins: [.plugin(name: "GenerateOverlayForTesting")]
),
.target(name: "WITExtractor"),
.testTarget(
name: "WITExtractorTests",
dependencies: ["WITExtractor", "WIT"]
),
.plugin(
name: "WITExtractorPlugin",
capability: .command(
intent: .custom(verb: "extract-wit", description: "Extract WIT definition from Swift module"),
permissions: []
),
dependencies: ["WITTool"]
),
.testTarget(
name: "WITExtractorPluginTests",
exclude: ["Fixtures"]
),
.executableTarget(
name: "WITTool",
dependencies: [
Expand All @@ -138,10 +89,6 @@ let package = Package(
name: "WasmParserTests",
dependencies: ["WasmParser"]
),
.testTarget(
name: "WASITests",
dependencies: ["WASI"]
),
],
swiftLanguageVersions: [.v5]
)
Expand All @@ -159,3 +106,80 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
.package(path: "../swift-system"),
]
}

#if !os(Windows)
// Add WASI-related products and targets
package.products.append(contentsOf: [
.library(
name: "WasmKitWASI",
targets: ["WasmKitWASI"]
),
.library(
name: "WASI",
targets: ["WASI"]
),
])
package.targets.append(contentsOf: [
.target(
name: "WASI",
dependencies: ["WasmTypes", "SystemExtras"],
exclude: ["CMakeLists.txt"]
),
.target(
name: "WasmKitWASI",
dependencies: ["WasmKit", "WASI"],
exclude: ["CMakeLists.txt"]
),
.target(
name: "SystemExtras",
dependencies: [
.product(name: "SystemPackage", package: "swift-system")
],
exclude: ["CMakeLists.txt"]
),
.testTarget(
name: "WASITests",
dependencies: ["WASI"]
),
])
let targetDependenciesToAdd = [
"CLI": ["WasmKitWASI"],
"WasmKit": ["SystemExtras"],
]
for (targetName, dependencies) in targetDependenciesToAdd {
if let target = package.targets.first(where: { $0.name == targetName }) {
target.dependencies += dependencies.map { .target(name: $0) }
} else {
fatalError("Target \(targetName) not found!?")
}
}

// Add build tool plugins only for non-Windows platforms
package.products.append(contentsOf: [
.plugin(name: "WITOverlayPlugin", targets: ["WITOverlayPlugin"]),
.plugin(name: "WITExtractorPlugin", targets: ["WITExtractorPlugin"]),
])

package.targets.append(contentsOf: [
.plugin(name: "WITOverlayPlugin", capability: .buildTool(), dependencies: ["WITTool"]),
.plugin(name: "GenerateOverlayForTesting", capability: .buildTool(), dependencies: ["WITTool"]),
.testTarget(
name: "WITOverlayGeneratorTests",
dependencies: ["WITOverlayGenerator", "WasmKit", "WasmKitWASI"],
exclude: ["Fixtures", "Compiled", "Generated"],
plugins: [.plugin(name: "GenerateOverlayForTesting")]
),
.plugin(
name: "WITExtractorPlugin",
capability: .command(
intent: .custom(verb: "extract-wit", description: "Extract WIT definition from Swift module"),
permissions: []
),
dependencies: ["WITTool"]
),
.testTarget(
name: "WITExtractorPluginTests",
exclude: ["Fixtures"]
),
])
#endif
13 changes: 13 additions & 0 deletions Sources/CLI/Run/Run.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import ArgumentParser
import SystemPackage
#if canImport(WasmKitWASI)
import WasmKitWASI
#endif
import WasmKit

struct Run: ParsableCommand {
Expand Down Expand Up @@ -78,6 +80,7 @@ struct Run: ParsableCommand {
}
}

#if canImport(SystemExtras)
func deriveInterceptor() throws -> (interceptor: GuestTimeProfiler, finalize: () -> Void)? {
guard let outputPath = self.profileOutput else { return nil }
let fileHandle = try FileDescriptor.open(
Expand All @@ -97,8 +100,15 @@ struct Run: ParsableCommand {
}
)
}
#else
// GuestTimeProfiler is not available without SystemExtras
func deriveInterceptor() throws -> (interceptor: RuntimeInterceptor, finalize: () -> Void)? {
nil
}
#endif

func instantiateWASI(module: Module, interceptor: RuntimeInterceptor?) throws -> () throws -> Void {
#if canImport(WasmKitWASI)
// Flatten environment variables into a dictionary (Respect the last value if a key is duplicated)
let environment = environment.reduce(into: [String: String]()) {
$0[$1.key] = $1.value
Expand All @@ -113,6 +123,9 @@ struct Run: ParsableCommand {
let exitCode = try wasi.start(moduleInstance, runtime: runtime)
throw ExitCode(Int32(exitCode))
}
#else
fatalError("WASI is not supported on this platform")
#endif
}

func instantiateNonWASI(module: Module, interceptor: RuntimeInterceptor?) throws -> (() throws -> Void)? {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Spectest/Spectest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct Spectest: AsyncParsableCommand {

let rootPath: String
let filePath = FilePath(path)
if (try? FileDescriptor.open(filePath, FileDescriptor.AccessMode.readOnly, options: .directory)) != nil {
if isDirectory(filePath) {
rootPath = path
} else {
rootPath = URL(fileURLWithPath: path).deletingLastPathComponent().path
Expand Down
33 changes: 22 additions & 11 deletions Sources/Spectest/TestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,6 @@ struct TestCase {
let content: Content
let path: String

private static func isDirectory(_ path: FilePath) -> Bool {
let fd = try? FileDescriptor.open(path, FileDescriptor.AccessMode.readOnly, options: .directory)
let isDirectory = fd != nil
try? fd?.close()
return isDirectory
}

static func load(include: [String], exclude: [String], in path: String, log: ((String) -> Void)? = nil) throws -> [TestCase] {
let fileManager = FileManager.default
let filePath = FilePath(path)
Expand Down Expand Up @@ -419,9 +412,9 @@ extension TestCase.Command {
}
}

private func deriveFeatureSet(rootPath: String) -> WasmFeatureSet {
private func deriveFeatureSet(rootPath: FilePath) -> WasmFeatureSet {
var features = WasmFeatureSet.default
if rootPath.hasSuffix("/proposals/memory64") {
if rootPath.ends(with: "proposals/memory64") {
features.insert(.memory64)
// memory64 doesn't expect reference-types proposal
// and it depends on the fact reference-types is disabled
Expand All @@ -431,9 +424,10 @@ extension TestCase.Command {
}

private func parseModule(rootPath: String, filename: String) throws -> Module {
let url = URL(fileURLWithPath: rootPath).appendingPathComponent(filename)
let rootPath = FilePath(rootPath)
let path = rootPath.appending(filename)

let module = try parseWasm(filePath: FilePath(url.path), features: deriveFeatureSet(rootPath: rootPath))
let module = try parseWasm(filePath: path, features: deriveFeatureSet(rootPath: rootPath))
return module
}

Expand Down Expand Up @@ -563,3 +557,20 @@ extension Swift.Error {
return "unknown error: \(self)"
}
}

#if os(Windows)
import WinSDK
#endif
internal func isDirectory(_ path: FilePath) -> Bool {
#if os(Windows)
return path.withPlatformString {
let result = GetFileAttributesW($0)
return result != INVALID_FILE_ATTRIBUTES && result & DWORD(FILE_ATTRIBUTE_DIRECTORY) != 0
}
#else
let fd = try? FileDescriptor.open(path, FileDescriptor.AccessMode.readOnly, options: .directory)
let isDirectory = fd != nil
try? fd?.close()
return isDirectory
#endif
}
3 changes: 3 additions & 0 deletions Sources/SystemExtras/Clock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import ucrt

import SystemPackage

#if !os(Windows)

@frozen
public struct Clock: RawRepresentable {

Expand Down Expand Up @@ -110,3 +112,4 @@ extension Clock {
}
}
}
#endif
Loading
Loading