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)