Skip to content

Commit abb2586

Browse files
author
Rules WASM Component
committed
feat: add core infrastructure for WASM rules
Implement the foundational infrastructure needed for WebAssembly component development including providers, toolchains, and utilities. Providers: - WitInfo: Information about WIT libraries and dependencies - WasmComponentInfo: Component metadata with profile support - WacCompositionInfo: Composition details and connections - WasmValidationInfo: Validation results and diagnostics Toolchains: - wasm_tools_toolchain: Manages wasm-tools, wac, and wit-bindgen - Platform detection for Linux, macOS, and Windows - Automatic tool download and repository setup - Module extension for toolchain registration Common utilities: - WASM target triple constants (wasip2, wasip1, unknown) - Helper functions for profile-based builds - File extension constants This infrastructure enables hermetic, reproducible builds across different platforms and development environments.
1 parent 83c5da0 commit abb2586

File tree

7 files changed

+276
-0
lines changed

7 files changed

+276
-0
lines changed

common/BUILD.bazel

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""BUILD file for common utilities"""
2+
3+
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
4+
5+
package(default_visibility = ["//visibility:public"])
6+
7+
bzl_library(
8+
name = "common",
9+
srcs = ["common.bzl"],
10+
)

common/common.bzl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Common constants and utilities"""
2+
3+
# WebAssembly target triples
4+
WASM_TARGET_TRIPLE = "wasm32-wasip2"
5+
WASM_TARGET_TRIPLE_P1 = "wasm32-wasip1"
6+
WASM_TARGET_TRIPLE_UNKNOWN = "wasm32-unknown-unknown"
7+
8+
# File extensions
9+
WASM_EXTENSION = ".wasm"
10+
WIT_EXTENSION = ".wit"
11+
12+
def get_wasm_target(preview2 = True):
13+
"""Get the appropriate WASM target triple"""
14+
return WASM_TARGET_TRIPLE if preview2 else WASM_TARGET_TRIPLE_P1

providers/BUILD.bazel

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""BUILD file for providers"""
2+
3+
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
4+
5+
package(default_visibility = ["//visibility:public"])
6+
7+
bzl_library(
8+
name = "providers",
9+
srcs = ["providers.bzl"],
10+
)

providers/providers.bzl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""Provider definitions for WebAssembly Component Model rules"""
2+
3+
# Provider for WIT library information
4+
WitInfo = provider(
5+
doc = "Information about a WIT library",
6+
fields = {
7+
"wit_files": "Depset of WIT source files",
8+
"wit_deps": "Depset of WIT dependencies",
9+
"package_name": "WIT package name",
10+
"world_name": "Optional world name",
11+
"interface_names": "List of interface names",
12+
},
13+
)
14+
15+
# Provider for WASM component information
16+
WasmComponentInfo = provider(
17+
doc = "Information about a WebAssembly component",
18+
fields = {
19+
"wasm_file": "The compiled WASM component file",
20+
"wit_info": "WitInfo provider from the component's interfaces",
21+
"component_type": "Type of component (module or component)",
22+
"imports": "List of imported interfaces",
23+
"exports": "List of exported interfaces",
24+
"metadata": "Component metadata dict",
25+
"profile": "Build profile (debug, release, custom)",
26+
"profile_variants": "Dict of profile -> wasm_file for multi-profile components",
27+
},
28+
)
29+
30+
# Provider for WAC composition information
31+
WacCompositionInfo = provider(
32+
doc = "Information about a WAC composition",
33+
fields = {
34+
"composed_wasm": "The composed WASM file",
35+
"components": "Dict of component name to WasmComponentInfo",
36+
"composition_wit": "WIT file describing the composition",
37+
"instantiations": "List of component instantiations",
38+
"connections": "List of inter-component connections",
39+
},
40+
)
41+
42+
# Provider for WASM validation results
43+
WasmValidationInfo = provider(
44+
doc = "Results from WASM validation",
45+
fields = {
46+
"is_valid": "Whether the WASM is valid",
47+
"validation_log": "Validation output log file",
48+
"errors": "List of validation errors",
49+
"warnings": "List of validation warnings",
50+
},
51+
)

toolchains/BUILD.bazel

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""Toolchain type definitions"""
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
# Toolchain type for WebAssembly tools
6+
toolchain_type(
7+
name = "wasm_tools_toolchain_type",
8+
visibility = ["//visibility:public"],
9+
)

toolchains/wasm_toolchain.bzl

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
"""WebAssembly toolchain definitions"""
2+
3+
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
4+
5+
WASM_TOOLS_PLATFORMS = {
6+
"darwin_amd64": struct(
7+
sha256 = "1234567890abcdef", # TODO: Add real checksums
8+
url_suffix = "x86_64-macos.tar.gz",
9+
),
10+
"darwin_arm64": struct(
11+
sha256 = "1234567890abcdef",
12+
url_suffix = "aarch64-macos.tar.gz",
13+
),
14+
"linux_amd64": struct(
15+
sha256 = "1234567890abcdef",
16+
url_suffix = "x86_64-linux.tar.gz",
17+
),
18+
"linux_arm64": struct(
19+
sha256 = "1234567890abcdef",
20+
url_suffix = "aarch64-linux.tar.gz",
21+
),
22+
"windows_amd64": struct(
23+
sha256 = "1234567890abcdef",
24+
url_suffix = "x86_64-windows.tar.gz",
25+
),
26+
}
27+
28+
def _wasm_tools_toolchain_impl(ctx):
29+
"""Implementation of wasm_tools_toolchain rule"""
30+
31+
# Create toolchain info
32+
toolchain_info = platform_common.ToolchainInfo(
33+
wasm_tools = ctx.file.wasm_tools,
34+
wac = ctx.file.wac,
35+
wit_bindgen = ctx.file.wit_bindgen,
36+
)
37+
38+
return [toolchain_info]
39+
40+
wasm_tools_toolchain = rule(
41+
implementation = _wasm_tools_toolchain_impl,
42+
attrs = {
43+
"wasm_tools": attr.label(
44+
allow_single_file = True,
45+
executable = True,
46+
cfg = "exec",
47+
doc = "wasm-tools binary",
48+
),
49+
"wac": attr.label(
50+
allow_single_file = True,
51+
executable = True,
52+
cfg = "exec",
53+
doc = "wac (WebAssembly Composition) binary",
54+
),
55+
"wit_bindgen": attr.label(
56+
allow_single_file = True,
57+
executable = True,
58+
cfg = "exec",
59+
doc = "wit-bindgen binary",
60+
),
61+
},
62+
doc = "Declares a WebAssembly toolchain",
63+
)
64+
65+
def _detect_host_platform(repository_ctx):
66+
"""Detect the host platform"""
67+
68+
os_name = repository_ctx.os.name.lower()
69+
arch = repository_ctx.os.arch.lower()
70+
71+
if os_name == "mac os x":
72+
os_name = "darwin"
73+
74+
if arch == "x86_64":
75+
arch = "amd64"
76+
elif arch == "aarch64":
77+
arch = "arm64"
78+
79+
return "{}_{}".format(os_name, arch)
80+
81+
def _wasm_toolchain_repository_impl(repository_ctx):
82+
"""Create toolchain repository with downloaded tools"""
83+
84+
platform = _detect_host_platform(repository_ctx)
85+
platform_info = WASM_TOOLS_PLATFORMS.get(platform)
86+
87+
if not platform_info:
88+
fail("Unsupported platform: {}".format(platform))
89+
90+
version = repository_ctx.attr.wasm_tools_version
91+
92+
# Download wasm-tools
93+
repository_ctx.download_and_extract(
94+
url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v{}/wasm-tools-{}-{}".format(
95+
version,
96+
version,
97+
platform_info.url_suffix,
98+
),
99+
sha256 = platform_info.sha256,
100+
)
101+
102+
# Create BUILD file
103+
repository_ctx.file("BUILD.bazel", """
104+
load("@rules_wasm_component//toolchains:wasm_toolchain.bzl", "wasm_tools_toolchain")
105+
106+
package(default_visibility = ["//visibility:public"])
107+
108+
wasm_tools_toolchain(
109+
name = "wasm_tools_impl",
110+
wasm_tools = "@{name}//:wasm-tools",
111+
wac = "@{name}//:wac",
112+
wit_bindgen = "@{name}//:wit-bindgen",
113+
)
114+
115+
toolchain(
116+
name = "wasm_tools_toolchain",
117+
toolchain = ":wasm_tools_impl",
118+
toolchain_type = "@rules_wasm_component//toolchains:wasm_tools_toolchain_type",
119+
exec_compatible_with = [
120+
# TODO: Add platform constraints
121+
],
122+
target_compatible_with = [
123+
"@platforms//cpu:wasm32",
124+
],
125+
)
126+
""".format(name = repository_ctx.name))
127+
128+
wasm_toolchain_repository = repository_rule(
129+
implementation = _wasm_toolchain_repository_impl,
130+
attrs = {
131+
"wasm_tools_version": attr.string(
132+
doc = "Version of wasm-tools to download",
133+
default = "1.0.60",
134+
),
135+
},
136+
)

wasm/extensions.bzl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Module extensions for WebAssembly toolchain configuration"""
2+
3+
load("//toolchains:wasm_toolchain.bzl", "wasm_toolchain_repository")
4+
5+
def _wasm_toolchain_extension_impl(module_ctx):
6+
"""Implementation of wasm_toolchain module extension"""
7+
8+
registrations = {}
9+
10+
# Collect all toolchain registrations
11+
for mod in module_ctx.modules:
12+
for registration in mod.tags.register:
13+
registrations[registration.name] = registration
14+
15+
# Create toolchain repositories
16+
for name, registration in registrations.items():
17+
wasm_toolchain_repository(
18+
name = name + "_toolchains",
19+
wasm_tools_version = registration.version,
20+
)
21+
22+
# If no registrations, create default
23+
if not registrations:
24+
wasm_toolchain_repository(
25+
name = "wasm_tools_toolchains",
26+
wasm_tools_version = "1.0.60",
27+
)
28+
29+
# Module extension for WASM toolchain
30+
wasm_toolchain = module_extension(
31+
implementation = _wasm_toolchain_extension_impl,
32+
tag_classes = {
33+
"register": tag_class(
34+
attrs = {
35+
"name": attr.string(
36+
doc = "Name for this toolchain registration",
37+
default = "wasm_tools",
38+
),
39+
"version": attr.string(
40+
doc = "Version of wasm-tools to use",
41+
default = "1.0.60",
42+
),
43+
},
44+
),
45+
},
46+
)

0 commit comments

Comments
 (0)