diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..540b8af --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM swift:6.0-noble AS build + +WORKDIR /app +COPY . ./ +RUN ["swift", "package", "clean"] +CMD ["swift", "test", "--parallel"] diff --git a/Package.swift b/Package.swift index 270b045..8348065 100644 --- a/Package.swift +++ b/Package.swift @@ -1,6 +1,4 @@ // swift-tools-version:6.0 -// The swift-tools-version declares the minimum version of Swift required to build this package. - import PackageDescription let package = Package( @@ -14,30 +12,34 @@ let package = Package( .visionOS("1.0"), ], products: [ - // Products define the executables and libraries a package produces, making them visible to other packages. - .library( - name: "MCP", - targets: ["MCP"]) + .library(name: "MCP", targets: ["MCP"]), ], dependencies: [ - .package(url: "https://github.com/apple/swift-system.git", from: "1.0.0"), - .package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"), + .package(url: "https://github.com/apple/swift-system", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.5.0"), ], targets: [ - // Targets are the basic building blocks of a package, defining a module or a test suite. - // Targets can depend on other targets in this package and products from dependencies. .target( name: "MCP", dependencies: [ .product(name: "SystemPackage", package: "swift-system"), .product(name: "Logging", package: "swift-log"), - ]), + .target(name: "libmcp"), + ] + ), + .target( + name: "libmcp", + dependencies: [ + + ] + ), .testTarget( name: "MCPTests", dependencies: [ "MCP", .product(name: "SystemPackage", package: "swift-system"), .product(name: "Logging", package: "swift-log"), - ]), + ] + ), ] ) diff --git a/Sources/MCP/Base/Transports.swift b/Sources/MCP/Base/Transports.swift index f9e8151..6ff6c82 100644 --- a/Sources/MCP/Base/Transports.swift +++ b/Sources/MCP/Base/Transports.swift @@ -1,6 +1,5 @@ -import Darwin +import libmcp import Logging - import struct Foundation.Data #if canImport(System) @@ -72,11 +71,11 @@ public actor StdioTransport: Transport { } private func setNonBlocking(fileDescriptor: FileDescriptor) throws { - let flags = fcntl(fileDescriptor.rawValue, F_GETFL) + let flags = fcntl_int(fileDescriptor.rawValue, F_GETFL) guard flags >= 0 else { throw MCPError.transportError(Errno.badFileDescriptor) } - let result = fcntl(fileDescriptor.rawValue, F_SETFL, flags | O_NONBLOCK) + let result = fcntl_int_long(fileDescriptor.rawValue, F_SETFL, Int(flags | O_NONBLOCK)) guard result >= 0 else { throw MCPError.transportError(Errno.badFileDescriptor) } diff --git a/Sources/libmcp/include/shims.h b/Sources/libmcp/include/shims.h new file mode 100644 index 0000000..1de92dd --- /dev/null +++ b/Sources/libmcp/include/shims.h @@ -0,0 +1,16 @@ +#include +#include +#include + +/* open functions */ +int open_int(const char *path, int oflag); +int open_int_mode(const char *path, int oflag, mode_t mode); + +/* fcntl functions */ +int fcntl_int(int fildes, int cmd); +int fcntl_int_flock(int fildes, int cmd, struct flock* flock); +int fcntl_int_long(int fildes, int cmd, long arg); + +/* ioctl functions */ +int ioctl_long(int fd, unsigned long request); +int ioctl_long_void(int fd, unsigned long request, void* data); diff --git a/Sources/libmcp/module.modulemap b/Sources/libmcp/module.modulemap new file mode 100644 index 0000000..98971de --- /dev/null +++ b/Sources/libmcp/module.modulemap @@ -0,0 +1,5 @@ +module libmcp [system] { + header "/usr/local/include/shims.h" + link "libmcp" + export * +} diff --git a/Sources/libmcp/shims.c b/Sources/libmcp/shims.c new file mode 100644 index 0000000..8138136 --- /dev/null +++ b/Sources/libmcp/shims.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include +#include "shims.h" + +/* open functions */ +int open_int(const char *path, int oflag) { + return open(path, oflag); +} +int open_int_mode(const char *path, int oflag, mode_t mode) { + return open(path, oflag, mode); +} + +/* fcntl functions */ +int fcntl_int(int fildes, int cmd) { + return fcntl(fildes, cmd); +} +int fcntl_int_flock(int fildes, int cmd, struct flock* flock) { + return fcntl(fildes, cmd, flock); +} +int fcntl_int_long(int fildes, int cmd, long arg) { + return fcntl(fildes, cmd, arg); +} + +/* ioctl functions */ +int ioctl_long(int fd, unsigned long request) { + return ioctl(fd, request); +} +int ioctl_long_void(int fd, unsigned long request, void* data) { + return ioctl(fd, request, data); +} diff --git a/Tests/MCPTests/RoundtripTests.swift b/Tests/MCPTests/RoundtripTests.swift index e8bccb9..695518a 100644 --- a/Tests/MCPTests/RoundtripTests.swift +++ b/Tests/MCPTests/RoundtripTests.swift @@ -127,7 +127,7 @@ struct RoundtripTests { let pingTask = Task { try await client.ping() // Ping doesn't return anything, so just getting here without throwing is success - #expect(true) // Test passed if we reach this point + #expect(Bool(true)) // Test passed if we reach this point } try await withThrowingTaskGroup(of: Void.self) { group in