Web App with Embedded Swift - POC demo

Quick update on my continued adventures into Embedded Wasm apps with Swift:

I managed to set up an Observation like system that works for Embedded Swift and integrate it with the Elementary DOM renderer. Lacking a better name I went with a @Reactive macro.

So you can define a type like this...

@Reactive
class MyData {
    var hello: String
    var there: Int
}

... and the DOM will update as you change it (just as you'd expect like using @Observable in SwiftUI). You can see it in action in the example app in the repo.


I am still (almost) successfully using SwiftPM to build it all, with a couple more road blocks I stubbed my toe on:

CLI Flags for swift build
Initially I thought utilizing CLI flags instead of settings defined in the Package.swift file was a great idea to keep the package manifests clean and compatible with "normal" as well as Embedded builds. However, once macro targets entered the chat this quickly fell apart. SwiftPM really does not like it when it gets "global" flags set for building when macro targets need to run on the host instead of the target system (has been discussed before, and is pretty understandable).

In addition to .unsafeFlags(["-Xfrontend", "-emit-empty-object-file"]) (as mentioned in my initial post) this adds -fdeclspec to the list of unsafeFlags which are blocking the portable use of SwiftPM.

cSettings: shouldBuildForEmbedded ? [.unsafeFlags(["-fdeclspec"])] : nil,

hasFeature(Embedded) for C targets
Especially the JavaScriptKit bits needed a bit of adjustment, including a C target. Originally a __Embedded macro was defined to configure the C code for an Embedded build. However, this was basically just a patch to know that the target is built in an Embedded Swift context (there is no built-in way that I know of). That alone would be quite ok, but...

.define("MY_THING") not working?
...but I was quite surprised to find that using a .define("__Embedded") as a cSetting in the Package.swift file on the C target did not work. It only worked if it was a) defined via an -Xcc -D CLI option, or b) defined on every (swift!) target up the dependency chain, including the entry-point app.
That is, if I added cSettings with the identical __Embedded define to all swift targets, it worked (app -> elementary module -> javascriptkit swift target -> javascriptkit C target). If any one of these targets did not define the same macro, I got a clang build issue as if the macro was not defined.


I have been hesitant to create github issues so far because of the experimental nature of this whole ordeal. If I should create one, please let me know. (especially the C macro topic feels very strange to me)

9 Likes