From da4dbea57b3b7caa7d53c6920d9c37ab657586c4 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 7 Jan 2026 10:39:23 +0000 Subject: [PATCH 1/6] Make CLI commands reusable with new `CLICommands` module Prerequisite for https://github.com/swiftwasm/WasmKit/pull/248 to make existing CLI commands reused in both `wasmkit` and `wasmkit-llvm` executables. --- Package.swift | 8 ++ Package@swift-6.1.swift | 13 +- Sources/CLI/CLI.swift | 1 + Sources/CLI/CMakeLists.txt | 15 ++- Sources/CLI/Commands/Parse.swift | 20 --- Sources/CLICommands/CMakeLists.txt | 21 +++ Sources/CLICommands/DebuggerServer.swift | 120 ++++++++++++++++++ .../Commands => CLICommands}/Explore.swift | 8 +- .../{CLI/Commands => CLICommands}/Run.swift | 50 +++++++- .../Commands => CLICommands}/Wat2wasm.swift | 8 +- Sources/CMakeLists.txt | 1 + 11 files changed, 225 insertions(+), 40 deletions(-) delete mode 100644 Sources/CLI/Commands/Parse.swift create mode 100644 Sources/CLICommands/CMakeLists.txt create mode 100644 Sources/CLICommands/DebuggerServer.swift rename Sources/{CLI/Commands => CLICommands}/Explore.swift (91%) rename Sources/{CLI/Commands => CLICommands}/Run.swift (85%) rename Sources/{CLI/Commands => CLICommands}/Wat2wasm.swift (95%) diff --git a/Package.swift b/Package.swift index aa82983a2..09b47cb49 100644 --- a/Package.swift +++ b/Package.swift @@ -22,6 +22,14 @@ let package = Package( targets: [ .executableTarget( name: "CLI", + dependencies: [ + "CLICommands" + ], + exclude: ["CMakeLists.txt"] + ), + + .target( + name: "CLICommands", dependencies: [ "WAT", "WasmKit", diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index 229258880..9f9e556b6 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -6,8 +6,8 @@ import class Foundation.ProcessInfo let DarwinPlatforms: [Platform] = [.macOS, .iOS, .watchOS, .tvOS, .visionOS] -let cliTarget = Target.executableTarget( - name: "CLI", +let cliCommandsTarget = Target.target( + name: "CLICommands", dependencies: [ "WAT", "WasmKit", @@ -36,7 +36,12 @@ let package = Package( "WasmDebuggingSupport", ], targets: [ - cliTarget, + cliCommandsTarget, + .executableTarget( + name: "CLI", + dependencies: ["CLICommands"], + exclude: ["CMakeLists.txt"] + ), .target( name: "WasmKit", dependencies: [ @@ -193,7 +198,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { ), ]) - cliTarget.dependencies.append(contentsOf: [ + cliCommandsTarget.dependencies.append(contentsOf: [ .product(name: "Logging", package: "swift-log", condition: .when(traits: ["WasmDebuggingSupport"])), .product(name: "NIOCore", package: "swift-nio", condition: .when(traits: ["WasmDebuggingSupport"])), .product(name: "NIOPosix", package: "swift-nio", condition: .when(traits: ["WasmDebuggingSupport"])), diff --git a/Sources/CLI/CLI.swift b/Sources/CLI/CLI.swift index 14d53166b..bf410ea61 100644 --- a/Sources/CLI/CLI.swift +++ b/Sources/CLI/CLI.swift @@ -1,4 +1,5 @@ import ArgumentParser +import CLICommands @main struct CLI: AsyncParsableCommand { diff --git a/Sources/CLI/CMakeLists.txt b/Sources/CLI/CMakeLists.txt index bba5cda12..5b473505c 100644 --- a/Sources/CLI/CMakeLists.txt +++ b/Sources/CLI/CMakeLists.txt @@ -1,12 +1,13 @@ -add_executable(wasmkit-cli - Commands/Explore.swift - Commands/Run.swift - Commands/Wat2wasm.swift +add_executable(wasmkit CLI.swift ) -target_link_wasmkit_libraries(wasmkit-cli PUBLIC - ArgumentParser WAT WasmKitWASI) +target_compile_options(wasmkit PRIVATE + -package-name WasmKitPackage +) + +target_link_wasmkit_libraries(wasmkit PUBLIC + CLICommands) -install(TARGETS wasmkit-cli +install(TARGETS wasmkit RUNTIME DESTINATION bin) diff --git a/Sources/CLI/Commands/Parse.swift b/Sources/CLI/Commands/Parse.swift deleted file mode 100644 index 121edc724..000000000 --- a/Sources/CLI/Commands/Parse.swift +++ /dev/null @@ -1,20 +0,0 @@ -import SystemPackage -import WAT -import WasmKit - -/// Parses a `.wasm` or `.wat` module. -func parseWasm(filePath: FilePath) throws -> Module { - if filePath.extension == "wat", #available(macOS 11.0, iOS 14.0, macCatalyst 14.0, tvOS 14.0, visionOS 1.0, watchOS 7.0, *) { - let fileHandle = try FileDescriptor.open(filePath, .readOnly) - defer { try? fileHandle.close() } - - let size = try fileHandle.seek(offset: 0, from: .end) - - let wat = try String(unsafeUninitializedCapacity: Int(size)) { - try fileHandle.read(fromAbsoluteOffset: 0, into: .init($0)) - } - return try WasmKit.parseWasm(bytes: wat2wasm(wat)) - } else { - return try WasmKit.parseWasm(filePath: filePath) - } -} diff --git a/Sources/CLICommands/CMakeLists.txt b/Sources/CLICommands/CMakeLists.txt new file mode 100644 index 000000000..ec9324e7a --- /dev/null +++ b/Sources/CLICommands/CMakeLists.txt @@ -0,0 +1,21 @@ +if(WASMKIT_BUILD_CLI) + set(BUILD_TESTING OFF) # disable ArgumentParser tests + find_package(ArgumentParser CONFIG) + if(NOT ArgumentParser_FOUND) + message("-- Vending ArgumentParser") + FetchContent_Declare(ArgumentParser + GIT_REPOSITORY https://github.com/apple/swift-argument-parser + GIT_TAG 1.6.1 + ) + FetchContent_MakeAvailable(ArgumentParser) + endif() +endif() + +add_wasmkit_library(CLICommands + Explore.swift + Run.swift + Wat2wasm.swift +) + +target_link_wasmkit_libraries(CLICommands PUBLIC + ArgumentParser WAT WasmKitWASI) diff --git a/Sources/CLICommands/DebuggerServer.swift b/Sources/CLICommands/DebuggerServer.swift new file mode 100644 index 000000000..3f348bb26 --- /dev/null +++ b/Sources/CLICommands/DebuggerServer.swift @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if WasmDebuggingSupport + + import GDBRemoteProtocol + import Logging + import NIOCore + import NIOPosix + import SystemPackage + import WasmKit + import WasmKitGDBHandler + + struct DebuggerServer { + var host = "127.0.0.1" + var port: Int + var logLevel = Logger.Level.info + let wasmModulePath: FilePath + let engineConfiguration: EngineConfiguration + + func run() async throws { + let logger = { + var result = Logger(label: "org.swiftwasm.WasmKit") + result.logLevel = self.logLevel + return result + }() + + try await MultiThreadedEventLoopGroup.withEventLoopGroup(numberOfThreads: System.coreCount) { group in + let bootstrap = ServerBootstrap(group: group) + // Specify backlog and enable SO_REUSEADDR for the server itself + .serverChannelOption(.backlog, value: 256) + .serverChannelOption(.socketOption(.so_reuseaddr), value: 1) + + // Set the handlers that are applied to the accepted child `Channel`s. + .childChannelInitializer { channel in + // Ensure we don't read faster then we can write by adding the BackPressureHandler into the pipeline. + channel.eventLoop.makeCompletedFuture { + try channel.pipeline.syncOperations.addHandler(BackPressureHandler()) + // make sure to instantiate your `ChannelHandlers` inside of + // the closure as it will be invoked once per connection. + try channel.pipeline.syncOperations.addHandlers([ + ByteToMessageHandler(GDBHostCommandDecoder(logger: logger)), + MessageToByteHandler(GDBTargetResponseEncoder(logger: logger)), + ]) + } + } + + // Enable SO_REUSEADDR for the accepted Channels + .childChannelOption(.socketOption(.so_reuseaddr), value: 1) + .childChannelOption(.maxMessagesPerRead, value: 16) + .childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator()) + + let serverChannel = try await bootstrap.bind(host: self.host, port: self.port) { childChannel in + childChannel.eventLoop.makeCompletedFuture { + try NIOAsyncChannel, GDBTargetResponse>( + wrappingChannelSynchronously: childChannel + ) + } + } + /* the server will now be accepting connections */ + logger.info("Debugger server listening on port \(port)") + + let debuggerHandler = try await WasmKitGDBHandler( + moduleFilePath: self.wasmModulePath, + engineConfiguration: self.engineConfiguration, + logger: logger, + allocator: serverChannel.channel.allocator + ) + + // Discarding task group was designed for persistent server purposes, where a single failing request + // isn't taking down the entire server. In our case we need to be able to shut down the server on + // debugger client's request, so let's wrap the discarding task group with a throwing task group + // for cancellation. + await withThrowingTaskGroup { cancellableGroup in + // Use `AsyncStream` for sending a signal out of the discarding group. + let (shutDownStream, shutDownContinuation) = AsyncStream<()>.makeStream() + + cancellableGroup.addTask { + try await withThrowingDiscardingTaskGroup { discardingGroup in + try await serverChannel.executeThenClose { serverChannelInbound in + for try await connectionChannel in serverChannelInbound { + discardingGroup.addTask { + do { + try await connectionChannel.executeThenClose { connectionChannelInbound, connectionChannelOutbound in + for try await inboundData in connectionChannelInbound { + try await connectionChannelOutbound.write(debuggerHandler.handle(command: inboundData.payload)) + } + } + } catch WasmKitGDBHandler.Error.killRequestReceived { + logger.info("Debugger shut down request received") + shutDownContinuation.yield() + } catch { + logger.error("Error in GDB remote protocol connection channel", metadata: ["error": "\(error)"]) + } + } + } + } + } + } + + // The stream isn't really sending data, just a single empty value, wait for the first one. + await shutDownStream.first { _ in true } + cancellableGroup.cancelAll() + } + } + } + } + +#endif diff --git a/Sources/CLI/Commands/Explore.swift b/Sources/CLICommands/Explore.swift similarity index 91% rename from Sources/CLI/Commands/Explore.swift rename to Sources/CLICommands/Explore.swift index 9af9d9498..df424c941 100644 --- a/Sources/CLI/Commands/Explore.swift +++ b/Sources/CLICommands/Explore.swift @@ -2,9 +2,9 @@ import ArgumentParser import SystemPackage @_spi(OnlyForCLI) import WasmKit -struct Explore: ParsableCommand { +package struct Explore: ParsableCommand { - static let configuration = CommandConfiguration( + package static let configuration = CommandConfiguration( abstract: "Explore the compiled functions of a WebAssembly module", discussion: """ This command will parse a WebAssembly module and dump the compiled functions. @@ -22,7 +22,9 @@ struct Explore: ParsableCommand { } } - func run() throws { + package init() {} + + package func run() throws { let module = try parseWasm(filePath: FilePath(path)) // Instruction dumping requires token threading model for now let configuration = EngineConfiguration(threadingModel: .token) diff --git a/Sources/CLI/Commands/Run.swift b/Sources/CLICommands/Run.swift similarity index 85% rename from Sources/CLI/Commands/Run.swift rename to Sources/CLICommands/Run.swift index 32769a72d..579f1fcb6 100644 --- a/Sources/CLI/Commands/Run.swift +++ b/Sources/CLICommands/Run.swift @@ -1,5 +1,6 @@ import ArgumentParser import SystemPackage +import WAT import WasmKit import WasmKitWASI @@ -7,8 +8,8 @@ import WasmKitWASI import os.signpost #endif -struct Run: AsyncParsableCommand { - static let configuration = CommandConfiguration( +package struct Run: AsyncParsableCommand { + package static let configuration = CommandConfiguration( abstract: "Run a WebAssembly module", discussion: """ This command will parse a WebAssembly module and run it. @@ -128,7 +129,9 @@ struct Run: AsyncParsableCommand { ) var arguments: [String] = [] - func run() async throws { + package init() {} + + package func run() async throws { #if WasmDebuggingSupport if let debuggerPort { @@ -311,3 +314,44 @@ struct Run: AsyncParsableCommand { } } } + +/// Parses a `.wasm` or `.wat` module. +func parseWasm(filePath: FilePath) throws -> Module { + if filePath.extension == "wat", #available(macOS 11.0, iOS 14.0, macCatalyst 14.0, tvOS 14.0, visionOS 1.0, watchOS 7.0, *) { + let fileHandle = try FileDescriptor.open(filePath, .readOnly) + defer { try? fileHandle.close() } + + let size = try fileHandle.seek(offset: 0, from: .end) + + let wat = try String(unsafeUninitializedCapacity: Int(size)) { + try fileHandle.read(fromAbsoluteOffset: 0, into: .init($0)) + } + return try WasmKit.parseWasm(bytes: wat2wasm(wat)) + } else { + return try WasmKit.parseWasm(filePath: filePath) + } +} + +extension Run { + package static func parseInvocation(arguments: [String]) -> (functionName: String?, parameters: [Value]) { + let functionName = arguments.first + let arguments = arguments.dropFirst() + + var parameters: [Value] = [] + for argument in arguments { + let parameter: Value + let type = argument.prefix { $0 != ":" } + let value = argument.drop { $0 != ":" }.dropFirst() + switch type { + case "i32": parameter = Value(signed: Int32(value)!) + case "i64": parameter = Value(signed: Int64(value)!) + case "f32": parameter = .f32(Float32(value)!.bitPattern) + case "f64": parameter = .f64(Float64(value)!.bitPattern) + default: fatalError("unknown type") + } + parameters.append(parameter) + } + + return (functionName, parameters) + } +} diff --git a/Sources/CLI/Commands/Wat2wasm.swift b/Sources/CLICommands/Wat2wasm.swift similarity index 95% rename from Sources/CLI/Commands/Wat2wasm.swift rename to Sources/CLICommands/Wat2wasm.swift index aa47735f9..7f3f61e63 100644 --- a/Sources/CLI/Commands/Wat2wasm.swift +++ b/Sources/CLICommands/Wat2wasm.swift @@ -3,8 +3,8 @@ import SystemPackage import WAT import WasmKit -struct Wat2wasm: ParsableCommand { - static let configuration = CommandConfiguration( +package struct Wat2wasm: ParsableCommand { + package static let configuration = CommandConfiguration( abstract: "Assemble WebAssembly text into a WebAssembly binary", discussion: """ Parse a file in WebAssembly Text Format (`.wat`), \ @@ -58,7 +58,9 @@ struct Wat2wasm: ParsableCommand { ) var output: String? - func run() throws { + package init() {} + + package func run() throws { let filePath = FilePath(path) guard filePath.extension == "wat" else { throw Error.unknownFileExtension(filePath.extension) } let fileHandle = try FileDescriptor.open(filePath, .readOnly) diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt index 1f7732675..5e28ac124 100644 --- a/Sources/CMakeLists.txt +++ b/Sources/CMakeLists.txt @@ -9,4 +9,5 @@ add_subdirectory(WAT) if(WASMKIT_BUILD_CLI) add_subdirectory(CLI) + add_subdirectory(CLICommands) endif() From 8d845eccd2f63b1cfc3dc4d32808ab6082fe9cd7 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 7 Jan 2026 10:42:54 +0000 Subject: [PATCH 2/6] Fix `wasmkit` executable naming in `main.yml` GHA workflow --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5970a6d46..ba2d19209 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -305,7 +305,7 @@ jobs: curl -L https://github.com/Kitware/CMake/releases/download/v3.29.2/cmake-3.29.2-linux-x86_64.tar.gz | tar xz --strip-component 1 -C /usr/local/ - run: cmake -G Ninja -B ./build - run: cmake --build ./build - - run: ./build/bin/wasmkit-cli --version + - run: ./build/bin/wasmkit --version build-wasi: runs-on: ubuntu-24.04 From 58634fc5a708a8045fcaa79a93d5b0b3d9a12f38 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 7 Jan 2026 10:41:31 +0000 Subject: [PATCH 3/6] CMake: remove duplicated `FetchContent(ArgumentParser...)` # Conflicts: # CMakeLists.txt --- CMakeLists.txt | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6289e5ee..cbfc1a043 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,19 +64,6 @@ endif() option(WASMKIT_BUILD_CLI "Build wasmkit-cli" ON) -if(WASMKIT_BUILD_CLI) - set(BUILD_TESTING OFF) # disable ArgumentParser tests - find_package(ArgumentParser CONFIG) - if(NOT ArgumentParser_FOUND) - message("-- Vending ArgumentParser") - FetchContent_Declare(ArgumentParser - GIT_REPOSITORY https://github.com/apple/swift-argument-parser - GIT_TAG 1.6.1 - ) - FetchContent_MakeAvailable(ArgumentParser) - endif() -endif() - add_subdirectory(Sources) add_subdirectory(Tests) add_subdirectory(cmake/modules) From 8c2b599de56b0b8351658d5a339447f0e4adea8b Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 7 Jan 2026 10:48:00 +0000 Subject: [PATCH 4/6] Delete Sources/CLI/DebuggerServer.swift --- Sources/CLI/DebuggerServer.swift | 120 ------------------------------- 1 file changed, 120 deletions(-) delete mode 100644 Sources/CLI/DebuggerServer.swift diff --git a/Sources/CLI/DebuggerServer.swift b/Sources/CLI/DebuggerServer.swift deleted file mode 100644 index 3f348bb26..000000000 --- a/Sources/CLI/DebuggerServer.swift +++ /dev/null @@ -1,120 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftNIO open source project -// -// Copyright (c) 2017-2025 Apple Inc. and the SwiftNIO project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftNIO project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#if WasmDebuggingSupport - - import GDBRemoteProtocol - import Logging - import NIOCore - import NIOPosix - import SystemPackage - import WasmKit - import WasmKitGDBHandler - - struct DebuggerServer { - var host = "127.0.0.1" - var port: Int - var logLevel = Logger.Level.info - let wasmModulePath: FilePath - let engineConfiguration: EngineConfiguration - - func run() async throws { - let logger = { - var result = Logger(label: "org.swiftwasm.WasmKit") - result.logLevel = self.logLevel - return result - }() - - try await MultiThreadedEventLoopGroup.withEventLoopGroup(numberOfThreads: System.coreCount) { group in - let bootstrap = ServerBootstrap(group: group) - // Specify backlog and enable SO_REUSEADDR for the server itself - .serverChannelOption(.backlog, value: 256) - .serverChannelOption(.socketOption(.so_reuseaddr), value: 1) - - // Set the handlers that are applied to the accepted child `Channel`s. - .childChannelInitializer { channel in - // Ensure we don't read faster then we can write by adding the BackPressureHandler into the pipeline. - channel.eventLoop.makeCompletedFuture { - try channel.pipeline.syncOperations.addHandler(BackPressureHandler()) - // make sure to instantiate your `ChannelHandlers` inside of - // the closure as it will be invoked once per connection. - try channel.pipeline.syncOperations.addHandlers([ - ByteToMessageHandler(GDBHostCommandDecoder(logger: logger)), - MessageToByteHandler(GDBTargetResponseEncoder(logger: logger)), - ]) - } - } - - // Enable SO_REUSEADDR for the accepted Channels - .childChannelOption(.socketOption(.so_reuseaddr), value: 1) - .childChannelOption(.maxMessagesPerRead, value: 16) - .childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator()) - - let serverChannel = try await bootstrap.bind(host: self.host, port: self.port) { childChannel in - childChannel.eventLoop.makeCompletedFuture { - try NIOAsyncChannel, GDBTargetResponse>( - wrappingChannelSynchronously: childChannel - ) - } - } - /* the server will now be accepting connections */ - logger.info("Debugger server listening on port \(port)") - - let debuggerHandler = try await WasmKitGDBHandler( - moduleFilePath: self.wasmModulePath, - engineConfiguration: self.engineConfiguration, - logger: logger, - allocator: serverChannel.channel.allocator - ) - - // Discarding task group was designed for persistent server purposes, where a single failing request - // isn't taking down the entire server. In our case we need to be able to shut down the server on - // debugger client's request, so let's wrap the discarding task group with a throwing task group - // for cancellation. - await withThrowingTaskGroup { cancellableGroup in - // Use `AsyncStream` for sending a signal out of the discarding group. - let (shutDownStream, shutDownContinuation) = AsyncStream<()>.makeStream() - - cancellableGroup.addTask { - try await withThrowingDiscardingTaskGroup { discardingGroup in - try await serverChannel.executeThenClose { serverChannelInbound in - for try await connectionChannel in serverChannelInbound { - discardingGroup.addTask { - do { - try await connectionChannel.executeThenClose { connectionChannelInbound, connectionChannelOutbound in - for try await inboundData in connectionChannelInbound { - try await connectionChannelOutbound.write(debuggerHandler.handle(command: inboundData.payload)) - } - } - } catch WasmKitGDBHandler.Error.killRequestReceived { - logger.info("Debugger shut down request received") - shutDownContinuation.yield() - } catch { - logger.error("Error in GDB remote protocol connection channel", metadata: ["error": "\(error)"]) - } - } - } - } - } - } - - // The stream isn't really sending data, just a single empty value, wait for the first one. - await shutDownStream.first { _ in true } - cancellableGroup.cancelAll() - } - } - } - } - -#endif From 3da41f94cd9a14f9c1895fdf1708ae55d6334369 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 10 Jan 2026 12:48:02 +0000 Subject: [PATCH 5/6] Address PR feedback --- CMakeLists.txt | 13 +++++++++++++ Sources/CLICommands/CMakeLists.txt | 13 ------------- Sources/CLICommands/Run.swift | 18 +----------------- 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbfc1a043..8104cffba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,19 @@ add_compile_definitions( include(FetchContent) +if(WASMKIT_BUILD_CLI) + set(BUILD_TESTING OFF) # disable ArgumentParser tests + find_package(ArgumentParser CONFIG) + if(NOT ArgumentParser_FOUND) + message("-- Vending ArgumentParser") + FetchContent_Declare(ArgumentParser + GIT_REPOSITORY https://github.com/apple/swift-argument-parser + GIT_TAG 1.6.1 + ) + FetchContent_MakeAvailable(ArgumentParser) + endif() +endif() + find_package(SwiftSystem CONFIG) if(NOT SwiftSystem_FOUND) message("-- Vending SwiftSystem") diff --git a/Sources/CLICommands/CMakeLists.txt b/Sources/CLICommands/CMakeLists.txt index ec9324e7a..ada5b5b7c 100644 --- a/Sources/CLICommands/CMakeLists.txt +++ b/Sources/CLICommands/CMakeLists.txt @@ -1,16 +1,3 @@ -if(WASMKIT_BUILD_CLI) - set(BUILD_TESTING OFF) # disable ArgumentParser tests - find_package(ArgumentParser CONFIG) - if(NOT ArgumentParser_FOUND) - message("-- Vending ArgumentParser") - FetchContent_Declare(ArgumentParser - GIT_REPOSITORY https://github.com/apple/swift-argument-parser - GIT_TAG 1.6.1 - ) - FetchContent_MakeAvailable(ArgumentParser) - endif() -endif() - add_wasmkit_library(CLICommands Explore.swift Run.swift diff --git a/Sources/CLICommands/Run.swift b/Sources/CLICommands/Run.swift index 579f1fcb6..4c1ce43c8 100644 --- a/Sources/CLICommands/Run.swift +++ b/Sources/CLICommands/Run.swift @@ -260,23 +260,7 @@ package struct Run: AsyncParsableCommand { } func instantiateNonWASI(module: Module, interceptor: EngineInterceptor?) throws -> (() throws -> Void)? { - let functionName = arguments.first - let arguments = arguments.dropFirst() - - var parameters: [Value] = [] - for argument in arguments { - let parameter: Value - let type = argument.prefix { $0 != ":" } - let value = argument.drop { $0 != ":" }.dropFirst() - switch type { - case "i32": parameter = Value(signed: Int32(value)!) - case "i64": parameter = Value(signed: Int64(value)!) - case "f32": parameter = .f32(Float32(value)!.bitPattern) - case "f64": parameter = .f64(Float64(value)!.bitPattern) - default: fatalError("unknown type") - } - parameters.append(parameter) - } + let (functionName, parameters) = Run.parseInvocation(arguments: self.arguments) guard let functionName else { log("Error: No function specified to run in a given module.") return nil From ec963b60e95cd32184a691e8aa06f7d3bc460efb Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 10 Jan 2026 13:34:35 +0000 Subject: [PATCH 6/6] Move `WASMKIT_BUILD_CLI` decl above its use --- CMakeLists.txt | 3 ++- Sources/CLICommands/CMakeLists.txt | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8104cffba..048419d27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,8 @@ add_compile_definitions( include(FetchContent) +option(WASMKIT_BUILD_CLI "Build wasmkit-cli" ON) + if(WASMKIT_BUILD_CLI) set(BUILD_TESTING OFF) # disable ArgumentParser tests find_package(ArgumentParser CONFIG) @@ -75,7 +77,6 @@ if(NOT SwiftSystem_FOUND) FetchContent_MakeAvailable(SwiftSystem) endif() -option(WASMKIT_BUILD_CLI "Build wasmkit-cli" ON) add_subdirectory(Sources) add_subdirectory(Tests) diff --git a/Sources/CLICommands/CMakeLists.txt b/Sources/CLICommands/CMakeLists.txt index ada5b5b7c..910c4120c 100644 --- a/Sources/CLICommands/CMakeLists.txt +++ b/Sources/CLICommands/CMakeLists.txt @@ -5,4 +5,16 @@ add_wasmkit_library(CLICommands ) target_link_wasmkit_libraries(CLICommands PUBLIC - ArgumentParser WAT WasmKitWASI) + WAT WasmKitWASI) + +add_dependencies( + CLICommands + + ArgumentParser +) + +target_link_libraries(CLICommands + + PUBLIC + ArgumentParser +)