Yeah, I thought the same thing. Using toolsets and similar should get us most of the way there with very little effort. The linking part IMHO is the biggest hurdle.
Out of curiosity, when linking the full wasi-libc instead of only select symbols (like dlalloc + a few utilities): Do we know if wasm-opt be able to strip it down to a similar size, or will there be a price to pay for using libc?
wasm-opt should be able to strip it down, otherwise it can also be built with -ffunction-sections. --gc-sections is the default for --wasm-ld.
After all, wasi-libc static archive (libc.a) is made of a lot of separate object files: 745 according to llvm-ar in swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle. I'd expect wasm-ld not to include unused object files with no relevant symbols in the final binary at all, even without --ffunction-sections.
FWIW JavaScriptKit 0.26.0 includes relevant fixes specifically for Embedded Swift:
JSString: Equatable no longer needs Unicode tables. Now you can back enums with JSString instead of String (enum Foo: JSString) in Embedded Swift, this helps to avoid dependencies on String: Equatable.
JSObject is now ExpressibleByDictionaryLiteral , which means you can write let foo: JSObject = ["bar": "baz"], also removing the dependency on Unicode tables introduced by String: Hashable.
So I actually really dislike all of these solution. We need to SwiftPM to not pass these intermediate object files to the link command period.
Emitting dead .o or telling the linker to ignore things is really a kludge. @kubamracek and I are very slowly getting towards a better defined linkage model, but we haven't prioritized this enough, I think.
This is really important because SwiftPM, Xcode, CMake, and Bazel all need to learn the exact same set of skills here to avoid user pain when using different build systems.
FWIW stuff like this would be great to bring up in the embedded community hour. I'd love to work through real world issue!
Agreed. While most of the core people working on SwiftPM are getting the replatforming onto Swift Build done, I am starting to think and chatting with people about how SwiftPM can support embedded better and all the platforms and SDKs I see coming out of that. It's great to keep these conversations going so we can come up with solutions that can stand the test of time.
I managed to package it up somewhat nicely in a simple script. (example here)
The cool thing is, I can now build the same package without any flags or changes as embedded (with wasi libc.a) and "normal" wasm-wasi build (via SDK). And I can finally use versioned dependencies and go on with life ; )
This example builds fine with the latest main-snapshot, but fails a lot when adding -Xfrontend -mergeable-symbols. I can create an issue tomorrow.
I also have a second issue with a build regression for this example (used to build fine, fails with latest main). I will create an issue for this one as well.
Thanks for the info, I would love to see some progress in this area.
I also noticed this here
but I fail to see how this fits in the entire "which object files to give to the linker" story? Is there way already a get @expose symbols from dependencies to the linker?
[48/50] Compiling ElementaryDOM Environment+ReactiveObject.swift
error: compile command failed due to signal 6 (use -v to see invocation)
Begin Error in Function: '$e11EmbeddedApp9GuessViewV10Elementary4HTMLAadEP7_render_4into4withyxn_qd__zAD17_RenderingContextVntAD14_HTMLRenderingRd__lFZTW'
Found an operand with a value that is not compatible with the operand's operand ownership kind map.
Value: %191 = struct_extract %33 : $_RenderingContext, #_RenderingContext.attributes // user: %193
Value Ownership Kind: guaranteed
Instruction:
%191 = struct_extract %33 : $_RenderingContext, #_RenderingContext.attributes // user: %193
%192 = struct_element_addr %189 : $*_RenderingContext, #_RenderingContext.attributes // user: %193
-> store %191 to [init] %192 : $*_AttributeStorage // id: %193
Constraint: <Constraint Kind:owned LifetimeConstraint:LifetimeEnding>
End Error in Function: '$e11EmbeddedApp9GuessViewV10Elementary4HTMLAadEP7_render_4into4withyxn_qd__zAD17_RenderingContextVntAD14_HTMLRenderingRd__lFZTW'
Found ownership error?!
This would be great to get a bugreport and reproducer for, too. Maybe @Erik_Eckstein might be interested in this one?
This is largely orthogonal, in embedded we want the leaf most module to produce the final object and deadstrip everything thats not needed in the final image.
In order to do this compiler determines some set of "liveness roots" e.g. an entry point symbol, @_used symbols in its module, etc... Kuba's patch extends this logic to also consider @_used symbols in module dependencies to also be liveness roots, so they make it into the leaf module's object.
And, the cooler bit, I have a working prototype of ElementaryCSS (a layout/styling API for Elementary) that works for both server-side and client-side rendering.
I was able to port the Swiftle example from tailwind to ElementaryCSS, resulting in code like this:
@View
struct GuessView {
var guess: Guess
var content: some View {
FlexRow(gap: 1) {
for letter in guess.letters {
LetterView(guess: letter)
}
}
}
}
@View
struct LetterView {
var guess: LetterGuess?
var content: some View {
Block(.width(10), .height(10), .display(.flex)) {
Paragraph(.margin(.auto)) {
guess?.letter.value ?? ""
}
}
.style(
.color(guess?.status == .unknown ? .gray200 : .white),
.borderColor(guess == nil ? .gray700 : .gray400),
.borderWidth(guess == nil || guess?.status == .unknown ? .px(2) : 0),
.background(guess?.status.backgroundColor ?? .transparent)
)
}
}
Especially deciding on the shape of the styling and layout system is tricky for me. Nobody "loves" CSS (well, certainly not me), but there is no way around it and SwiftUIs layout system just does not map well onto it. Trying to implement SwiftUI-APIs (and expecting similar behavior) would be a constant uphill battle in the browser (either by using brittle and complicated CSS-tricks, or calculating layout yourself in Swift code - both not ideal).
So I am trying to thread the needle between offering a SwiftUI-feel for the APIs, but sticking to CSS behavior (ie: a person knowing CSS should not be confused, but a person knowing SwiftUI should be able to find a way in).
I would love some eyes on this early on, so if you have opinions: please let me hear it!