Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,16 @@ use_repo(witness, "witness_toolchain")

register_toolchains("@witness_toolchain//:witness_toolchain")

# synth toolchain: WebAssembly-to-ARM ahead-of-time compiler
synth = use_extension("//wasm:extensions.bzl", "synth")
synth.register(
name = "synth",
version = "0.3.1",
)
use_repo(synth, "synth_toolchain")

register_toolchains("@synth_toolchain//:synth_toolchain")

# MoonBit hermetic toolchain for WebAssembly component builds (dev only)
# NOTE: Not eagerly loaded - MoonBit uses rolling /latest/ URLs that cause
# checksum drift and build failures, same as componentize-py.
Expand Down
46 changes: 35 additions & 11 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions checksums/tools/synth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"tool_name": "synth",
"github_repo": "pulseengine/synth",
"description": "WebAssembly-to-ARM ahead-of-time compiler (WASM core module -> Cortex-M ELF)",
"latest_version": "0.3.1",
"last_checked": "2026-05-21T00:00:00Z",
"supported_platforms": ["darwin_amd64", "darwin_arm64", "linux_amd64", "linux_arm64"],
"versions": {
"0.3.1": {
"release_date": "2026-05-21",
"platforms": {
"darwin_amd64": {
"sha256": "ae2b5b9767304b30e4e7416a4e63fe0581940f3ef193ff9879838ff2fd4419a9",
"url_suffix": "x86_64-apple-darwin.tar.gz"
},
"darwin_arm64": {
"sha256": "bc50fbd4e07585b10316d665a2b68e2c5ab2391e91f1bbec827de29a50ce5a6e",
"url_suffix": "aarch64-apple-darwin.tar.gz"
},
"linux_amd64": {
"sha256": "521e05065f9058374e99e8dfd3d2fce29dd2bbe1a5e16d0e9b082c1a933a0af9",
"url_suffix": "x86_64-unknown-linux-gnu.tar.gz"
},
"linux_arm64": {
"sha256": "938bf641daf4de8e9fa6aac9cf2b5d265f45db0570f81a5aa1b990469aa24515",
"url_suffix": "aarch64-unknown-linux-gnu.tar.gz"
}
}
}
}
}
29 changes: 29 additions & 0 deletions examples/synth_example/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Example: compile a WASM core module to an ARM Cortex-M ELF with synth.

synth is the final stage of the PulseEngine pipeline — it performs ahead-of-
time compilation from WebAssembly to bare-metal ARM machine code:

... -> meld (fuse to core module) -> synth_compile -> ARM Cortex-M ELF

synth operates on core modules. Here the subject is a small pre-built core
module (math.wat -> math.wasm); in a real pipeline the `wasm_module` would be
a meld_fuse target. The synth binary comes from the registered toolchain
(pulseengine/synth releases) — no locally-built binary needed.
"""

load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@rules_wasm_component//wasm:defs.bzl", "synth_compile")

package(default_visibility = ["//visibility:public"])

# math.wasm exports two plain-integer functions (see math.wat for the source).
synth_compile(
name = "math_firmware",
src = "math.wasm",
target = "cortex-m3",
)

build_test(
name = "synth_example_test",
targets = [":math_firmware"],
)
6 changes: 6 additions & 0 deletions toolchains/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ toolchain_type(
visibility = ["//visibility:public"],
)

# Toolchain type for synth (WebAssembly-to-ARM ahead-of-time compiler)
toolchain_type(
name = "synth_toolchain_type",
visibility = ["//visibility:public"],
)

# Bzl library for tool versions (single source of truth)
bzl_library(
name = "tool_versions",
Expand Down
129 changes: 129 additions & 0 deletions toolchains/synth_toolchain.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Copyright 2026 Ralf Anton Beier. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0

"""synth toolchain: WebAssembly-to-ARM ahead-of-time compiler.

synth compiles a WebAssembly core module to a bare-metal ARM Cortex-M ELF —
the final stage of the PulseEngine pipeline. It is distributed as per-platform
tar.gz archives with a flat layout (the `synth` binary at the archive root).
No Windows binary is published.
"""

load("//checksums:registry.bzl", "validate_tool_exists")
load("//toolchains:tool_registry.bzl", "tool_registry")

# Platforms where synth release archives are published (no Windows).
_SUPPORTED_PLATFORMS = [
"darwin_amd64",
"darwin_arm64",
"linux_amd64",
"linux_arm64",
]

def _synth_toolchain_impl(ctx):
"""Implementation of synth_toolchain rule."""
return [platform_common.ToolchainInfo(
synth = ctx.file.synth,
)]

synth_toolchain = rule(
implementation = _synth_toolchain_impl,
attrs = {
"synth": attr.label(
allow_single_file = True,
executable = True,
cfg = "exec",
doc = "synth binary for WebAssembly-to-ARM compilation",
),
},
doc = "Declares a synth toolchain for ahead-of-time ARM compilation",
)

_STUB_BUILD = '''"""synth toolchain stub: unsupported platform.

synth publishes no release archive for this host (e.g. Windows), so we
register a toolchain marked incompatible with any target. Toolchain
resolution for synth_compile targets fails cleanly here; builds that never
touch synth_compile are unaffected.
"""

load("@rules_wasm_component//toolchains:synth_toolchain.bzl", "synth_toolchain")

package(default_visibility = ["//visibility:public"])

exports_files(["synth_stub"])

synth_toolchain(
name = "synth_toolchain_impl",
synth = "synth_stub",
)

toolchain(
name = "synth_toolchain",
target_compatible_with = ["@platforms//:incompatible"],
toolchain = ":synth_toolchain_impl",
toolchain_type = "@rules_wasm_component//toolchains:synth_toolchain_type",
)
'''

def _synth_repository_impl(repository_ctx):
"""Download the synth archive and create a toolchain repository."""
platform = tool_registry.detect_platform(repository_ctx)
version = repository_ctx.attr.version

# Unsupported host (Windows / unknown): emit a stub so module resolution
# still works. synth_compile targets simply won't be buildable there.
if platform not in _SUPPORTED_PLATFORMS or not validate_tool_exists(repository_ctx, "synth", version, platform):
print("synth: no release archive for platform {} (version {}); emitting stub".format(platform, version))
repository_ctx.file("synth_stub", content = "", executable = True)
repository_ctx.file("BUILD.bazel", _STUB_BUILD)
return

print("Setting up synth {} for platform {}".format(version, platform))

# Extract the release archive into dist/ (flat layout: dist/synth).
tool_registry.download(
repository_ctx,
"synth",
version,
platform,
output_dir = "dist",
)

repository_ctx.file("BUILD.bazel", '''"""synth toolchain repository"""

load("@rules_wasm_component//toolchains:synth_toolchain.bzl", "synth_toolchain")

package(default_visibility = ["//visibility:public"])

exports_files(["dist/synth"])

synth_toolchain(
name = "synth_toolchain_impl",
synth = "dist/synth",
)

toolchain(
name = "synth_toolchain",
exec_compatible_with = [],
target_compatible_with = [],
toolchain = ":synth_toolchain_impl",
toolchain_type = "@rules_wasm_component//toolchains:synth_toolchain_type",
)
''')

synth_repository = repository_rule(
implementation = _synth_repository_impl,
attrs = {
"version": attr.string(
default = "0.3.1",
doc = "synth version to download",
),
},
doc = "Downloads synth and creates a toolchain repository",
)
5 changes: 5 additions & 0 deletions toolchains/tool_registry.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ _URL_PATTERNS = {
"base": "https://github.com/{repo}/releases/download/v{version}",
"filename": "witness-v{version}-{suffix}",
},
"synth": {
# synth releases are tar.gz archives: synth-v{version}-{triple}.tar.gz
"base": "https://github.com/{repo}/releases/download/v{version}",
"filename": "synth-v{version}-{suffix}",
},
}

def _build_download_url(tool_name, version, platform, tool_info, github_repo):
Expand Down
Loading
Loading