Skip to content

Commit

Permalink
Disable Dylib loading code in SwiftBundlerRuntime on Linux until impl…
Browse files Browse the repository at this point in the history
…emented
  • Loading branch information
stackotter committed May 20, 2024
1 parent 5ba9c04 commit d5b56cf
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 60 deletions.
59 changes: 29 additions & 30 deletions Sources/SwiftBundlerRuntime/Dylib.swift
Original file line number Diff line number Diff line change
@@ -1,43 +1,42 @@
import Darwin
import Foundation

#if !canImport(Darwin)
#error("Dylib only implemented for Darwin")
#endif
#if canImport(Darwin)
import Darwin

/// A dynamic library.
public struct Dylib {
private var dylib: UnsafeMutableRawPointer
/// A dynamic library.
public struct Dylib {
private var dylib: UnsafeMutableRawPointer

/// Opens the dynamic library at the provided path.
public static func open(_ path: URL) throws -> Dylib {
guard let dylib = dlopen(path.path, RTLD_NOW | RTLD_LOCAL) else {
throw DylibError.failedToOpen
/// Opens the dynamic library at the provided path.
public static func open(_ path: URL) throws -> Dylib {
guard let dylib = dlopen(path.path, RTLD_NOW | RTLD_LOCAL) else {
throw DylibError.failedToOpen
}
return Dylib(dylib: dylib)
}
return Dylib(dylib: dylib)
}

/// Retrieves a symbol from a dynamic library. Protects against the symbol not
/// existing, but doesn't protect against type mismatches.
public func symbol<T>(named name: String, ofType type: T.Type) -> T? {
guard let symbolPointer = dlsym(dylib, name) else {
return nil
/// Retrieves a symbol from a dynamic library. Protects against the symbol not
/// existing, but doesn't protect against type mismatches.
public func symbol<T>(named name: String, ofType type: T.Type) -> T? {
guard let symbolPointer = dlsym(dylib, name) else {
return nil
}
return unsafeBitCast(symbolPointer, to: T.self)
}
return unsafeBitCast(symbolPointer, to: T.self)
}

public func close() {
dlclose(dylib)
public func close() {
dlclose(dylib)
}
}
}

public enum DylibError: LocalizedError {
case failedToOpen
public enum DylibError: LocalizedError {
case failedToOpen

public var errorDescription: String? {
switch self {
case .failedToOpen:
return "Failed to open dynamic library"
public var errorDescription: String? {
switch self {
case .failedToOpen:
return "Failed to open dynamic library"
}
}
}
}
#endif
62 changes: 32 additions & 30 deletions Sources/SwiftBundlerRuntime/HotReloadingClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,39 +40,41 @@ public struct HotReloadingClient {
} catch Errno.socketIsConnected {}
}

public mutating func handlePackets(handleDylib: (Dylib) -> Void) async throws {
while true {
let packet: Packet
do {
packet = try await Packet.read(from: &server)
} catch Errno.timedOut {
continue
}
#if canImport(Darwin)
public mutating func handlePackets(handleDylib: (Dylib) -> Void) async throws {
while true {
let packet: Packet
do {
packet = try await Packet.read(from: &server)
} catch Errno.timedOut {
continue
}

switch packet {
case .ping:
print("client: Received ping")
try await Packet.pong.write(to: &server)
case let .reloadDylib(path):
print("client: Received new dylib")
// Copy dylib to new partially randomized path to avoid `dlopen` just giving
// us back the same pointer again.
let newPath =
path
.deletingLastPathComponent()
.appendingPathComponent(UUID().uuidString + ".dylib")
try FileManager.default.copyItem(
at: path,
to: newPath
)
let dylib = try Dylib.open(newPath)
handleDylib(dylib)
try FileManager.default.removeItem(at: newPath)
case .pong:
print("client: Received pong")
switch packet {
case .ping:
print("client: Received ping")
try await Packet.pong.write(to: &server)
case let .reloadDylib(path):
print("client: Received new dylib")
// Copy dylib to new partially randomized path to avoid `dlopen` just giving
// us back the same pointer again.
let newPath =
path
.deletingLastPathComponent()
.appendingPathComponent(UUID().uuidString + ".dylib")
try FileManager.default.copyItem(
at: path,
to: newPath
)
let dylib = try Dylib.open(newPath)
handleDylib(dylib)
try FileManager.default.removeItem(at: newPath)
case .pong:
print("client: Received pong")
}
}
}
}
#endif

/// Parses an IPv4 address of the form `x.x.x.x:yyyyy`.
public static func parseAddress(_ addressString: String) throws -> IPv4SocketAddress {
Expand Down

0 comments on commit d5b56cf

Please sign in to comment.