I’ve been experimenting with SwiftWASM recently as I’m gearing up for developing a web version of a macOS app I’ve worked on. So far I understand I should be able to reuse the Swift model layer from the Mac and I’m quite excited about that.
I’m rather new to using Swift on non-Darwin platforms and there's definitely a number a challenges I'm facing doing that, but I’ll start with what’s immediately blocking me right now.
Using Carton, I set up a simple website where Swift code is loading an HTML-embedded asset and renders several objects to the DOM via JavaScriptKit. I’d like to add HTML parsing so I’ve added the SwiftSoup package but I hit a snag because the package won’t compile for WASM.
Compiling (with swift build --triple wasm32-unknown-wasi) returns about 70 errors, all about missing APIs in Foundation's FileHandle. If SwiftSoup made calls to API not yet implemented in swift-corelibs-foundation that would have made sense to me, but each call I sampled appears to have been ported.
For example, here's one such error:
SwiftSoup/Sources/StreamReader.swift:23:42: error: incorrect argument label in call (have 'forReadingAtPath:', expected 'fileDescriptor:') guard let fileHandle = FileHandle(forReadingAtPath: path), ^~~~~~~~~~~~~~~~~ fileDescriptor
The compiler is basically pointing out that init(forReadingAtPath:) does not exist on FileHandle but it does appear to exist.
I've also isolated the call out to a new package and got the same error.
Would anyone know what's the cause and how to work around it? Thanks!
Yes, files don't exist, so FileHandle can't, but that commit didn't remove it.
I can see that FileHandle.init?(path:...) calls _CFOpenFileWithMode which doesn't exist in WASI, and FileHandle.swift has no conditionals for WASI, so I think that FileHandle.swift can't be being compiled at all, but I don't see what's excluding it :(
Thank you for trying SwiftWasm toolchain and sorry for the inconvenience.
In theory, WASI provides most of typical file system features now, so FileHandle can be imported to wasm32-wasi. As far as I remember, the current guard condition is just for a tentative fix, so we can improve it to unlock those APIs.
Having said that, if you want to read/write file on WASI now, you can still use libc API fopen / fread / fwrite and so on like here.
Thanks for your responses, they helped me sort this out.
Looks like my mistake was assuming that SwiftWASM uses the upstream swift-corelibs-foundation, where in fact it has its own fork, in which there are indeed WASI conditionals in FileHandle.swift.
I am still a bit perplexed because, like @KeithBauerANZ , I can't see such conditionals used to exclude init(forReadingAtPath:) specifically. I'd love to understand what's going on there if anyone knows, but that's not crucial for continuing my experimentation.
Now that I know that the FileHandle API actually doesn't fully exist on WASI, I decided to simply fork SwiftSoup and move the calling code to a separate target that a WASI compilation skips.
If anyone is interested in how, check out my changes.