Skip to content

Commit f7def45

Browse files
committed
feat: wire bundle versions to all toolchain repository rules
This commit completes the Option B (Full Integration) architecture for toolchain version bundles: Changes: - Add get_version_for_tool() and log_bundle_usage() helpers to bundle.bzl - Add 'bundle' attribute to all 8 toolchain repository rules: - wasm_toolchain_repository (wasm-tools, wac, wit-bindgen) - wasmtime_repository - wizer_toolchain_repository - wkg_toolchain_repository - tinygo_toolchain_repository - wasi_sdk_repository - cpp_component_toolchain_repository - jco_toolchain_repository - Add unified wasm_component_bundle extension to wasm/extensions.bzl that configures all toolchains from a single bundle parameter Architecture: MODULE.bazel │ wasm_component_bundle.configure(bundle = "stable-2025-12") ▼ Module Extension (wasm/extensions.bzl) │ Pass bundle to each toolchain repo rule ▼ Repository Rules (each toolchain) │ Read checksums/toolchain_bundles.json via Label path │ Extract version for this tool from bundle ▼ Downloaded Tools (with compatible versions) Each repository rule: 1. Accepts optional 'bundle' attribute 2. If bundle set, reads version from toolchain_bundles.json 3. Falls back to explicit version attribute if not in bundle 4. Logs bundle usage for debugging This ensures all tools are downloaded with compatible, pre-validated versions when using a bundle, eliminating version mismatch issues. Part of #254: Toolchain Version Bundles for Guaranteed Compatibility
1 parent 8620aa4 commit f7def45

File tree

10 files changed

+366
-20
lines changed

10 files changed

+366
-20
lines changed

toolchains/bundle.bzl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,58 @@ def print_bundle_info(repository_ctx, bundle_name = None):
198198

199199
return "\n".join(lines)
200200

201+
def get_version_for_tool(repository_ctx, tool_name, bundle_name = None, fallback_version = None):
202+
"""Get version for a specific tool from bundle, with fallback support.
203+
204+
This is the main entry point for toolchain repository rules to get their version.
205+
206+
Args:
207+
repository_ctx: Repository context for file operations.
208+
tool_name: Name of the tool (e.g., "wasm-tools", "wasmtime").
209+
bundle_name: Name of the bundle to use. If empty/None, uses default bundle.
210+
fallback_version: Version to use if tool not found in bundle.
211+
212+
Returns:
213+
Version string for the tool.
214+
"""
215+
# If no bundle specified, try to use default
216+
effective_bundle = bundle_name if bundle_name else None
217+
218+
version = get_bundle_tool_version(repository_ctx, effective_bundle, tool_name)
219+
220+
if version:
221+
return version
222+
223+
# Tool not in bundle - use fallback or fail
224+
if fallback_version:
225+
return fallback_version
226+
227+
# No fallback - check if bundle exists but doesn't have this tool
228+
bundle = get_bundle(repository_ctx, effective_bundle)
229+
if bundle:
230+
available_tools = list(bundle.get("tools", {}).keys())
231+
fail("Tool '{}' not found in bundle '{}'. Available tools: {}".format(
232+
tool_name,
233+
effective_bundle or get_default_bundle_name(repository_ctx),
234+
", ".join(available_tools) if available_tools else "none",
235+
))
236+
237+
# No bundle found at all - fail with helpful message
238+
fail("Could not determine version for tool '{}'. No bundle found and no fallback specified.".format(tool_name))
239+
240+
def log_bundle_usage(repository_ctx, tool_name, version, bundle_name = None):
241+
"""Log which version is being used from which bundle (for debugging).
242+
243+
Args:
244+
repository_ctx: Repository context for file operations.
245+
tool_name: Name of the tool.
246+
version: Version being used.
247+
bundle_name: Bundle name (or None for default).
248+
"""
249+
effective_bundle = bundle_name or get_default_bundle_name(repository_ctx)
250+
# buildifier: disable=print
251+
print("Bundle '{}': using {} version {}".format(effective_bundle, tool_name, version))
252+
201253
# Public API
202254
bundle_api = struct(
203255
get_bundle = get_bundle,
@@ -207,6 +259,8 @@ bundle_api = struct(
207259
validate_bundle = validate_bundle,
208260
resolve_tool_versions = resolve_tool_versions,
209261
print_bundle_info = print_bundle_info,
262+
get_version_for_tool = get_version_for_tool,
263+
log_bundle_usage = log_bundle_usage,
210264

211265
# Constants
212266
STATUS_STABLE = BUNDLE_STATUS_STABLE,

toolchains/cpp_component_toolchain.bzl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""C/C++ WebAssembly component toolchain definitions for Preview2"""
22

3+
load("//toolchains:bundle.bzl", "get_version_for_tool", "log_bundle_usage")
34
load("//toolchains:diagnostics.bzl", "format_diagnostic_error", "validate_system_tool")
45

56
def _cpp_component_toolchain_impl(ctx):
@@ -98,7 +99,19 @@ def _cpp_component_toolchain_repository_impl(repository_ctx):
9899

99100
strategy = repository_ctx.attr.strategy
100101
platform = _detect_host_platform(repository_ctx)
101-
wasi_sdk_version = repository_ctx.attr.wasi_sdk_version
102+
bundle_name = repository_ctx.attr.bundle
103+
104+
# Resolve version from bundle if specified, otherwise use explicit version
105+
if bundle_name:
106+
wasi_sdk_version = get_version_for_tool(
107+
repository_ctx,
108+
"wasi-sdk",
109+
bundle_name = bundle_name,
110+
fallback_version = repository_ctx.attr.wasi_sdk_version,
111+
)
112+
log_bundle_usage(repository_ctx, "wasi-sdk", wasi_sdk_version, bundle_name)
113+
else:
114+
wasi_sdk_version = repository_ctx.attr.wasi_sdk_version
102115

103116
if strategy == "download":
104117
_setup_downloaded_cpp_tools(repository_ctx, platform, wasi_sdk_version)
@@ -345,13 +358,17 @@ alias(
345358
cpp_component_toolchain_repository = repository_rule(
346359
implementation = _cpp_component_toolchain_repository_impl,
347360
attrs = {
361+
"bundle": attr.string(
362+
doc = "Toolchain bundle name. If set, wasi_sdk_version is read from checksums/toolchain_bundles.json",
363+
default = "",
364+
),
348365
"strategy": attr.string(
349366
doc = "Tool acquisition strategy: 'download' or 'build'",
350367
default = "download",
351368
values = ["download", "build"],
352369
),
353370
"wasi_sdk_version": attr.string(
354-
doc = "WASI SDK version to use",
371+
doc = "WASI SDK version to use. Ignored if bundle is specified.",
355372
default = "27",
356373
),
357374
},

toolchains/jco_toolchain.bzl

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""jco (JavaScript Component Tools) toolchain definitions"""
22

3+
load("//toolchains:bundle.bzl", "get_version_for_tool", "log_bundle_usage")
34
load("//toolchains:diagnostics.bzl", "format_diagnostic_error", "validate_system_tool")
45
load("//toolchains:tool_cache.bzl", "cache_tool", "retrieve_cached_tool", "validate_tool_functionality")
56
load("//checksums:registry.bzl", "get_tool_info")
@@ -86,8 +87,27 @@ def _jco_toolchain_repository_impl(repository_ctx):
8687
"""Create jco toolchain repository"""
8788

8889
platform = _detect_host_platform(repository_ctx)
89-
jco_version = repository_ctx.attr.version
90-
node_version = repository_ctx.attr.node_version
90+
bundle_name = repository_ctx.attr.bundle
91+
92+
# Resolve versions from bundle if specified, otherwise use explicit versions
93+
if bundle_name:
94+
jco_version = get_version_for_tool(
95+
repository_ctx,
96+
"jco",
97+
bundle_name = bundle_name,
98+
fallback_version = repository_ctx.attr.version,
99+
)
100+
node_version = get_version_for_tool(
101+
repository_ctx,
102+
"nodejs",
103+
bundle_name = bundle_name,
104+
fallback_version = repository_ctx.attr.node_version,
105+
)
106+
log_bundle_usage(repository_ctx, "jco", jco_version, bundle_name)
107+
log_bundle_usage(repository_ctx, "nodejs", node_version, bundle_name)
108+
else:
109+
jco_version = repository_ctx.attr.version
110+
node_version = repository_ctx.attr.node_version
91111

92112
# Always use download strategy with hermetic Node.js + jco
93113
_setup_downloaded_jco_tools(repository_ctx, platform, jco_version, node_version)
@@ -360,12 +380,16 @@ alias(
360380
jco_toolchain_repository = repository_rule(
361381
implementation = _jco_toolchain_repository_impl,
362382
attrs = {
383+
"bundle": attr.string(
384+
doc = "Toolchain bundle name. If set, versions are read from checksums/toolchain_bundles.json",
385+
default = "",
386+
),
363387
"version": attr.string(
364-
doc = "jco version to use",
388+
doc = "jco version to use. Ignored if bundle is specified.",
365389
default = "1.4.0",
366390
),
367391
"node_version": attr.string(
368-
doc = "Node.js version to use for download strategy",
392+
doc = "Node.js version to use for download strategy. Ignored if bundle is specified.",
369393
default = "18.19.0",
370394
),
371395
},

toolchains/tinygo_toolchain.bzl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Architecture:
1010
- wasm-tools for component transformation
1111
"""
1212

13+
load("//toolchains:bundle.bzl", "get_version_for_tool", "log_bundle_usage")
14+
15+
_TINYGO_TOOLCHAIN_DOC = """
16+
"""
17+
1318
def _detect_host_platform(repository_ctx):
1419
"""Detect the host platform for tool downloads"""
1520
os_name = repository_ctx.os.name.lower()
@@ -267,7 +272,19 @@ def _tinygo_toolchain_repository_impl(repository_ctx):
267272
"""Implementation of TinyGo toolchain repository rule"""
268273

269274
platform = _detect_host_platform(repository_ctx)
270-
tinygo_version = repository_ctx.attr.tinygo_version
275+
bundle_name = repository_ctx.attr.bundle
276+
277+
# Resolve version from bundle if specified, otherwise use explicit version
278+
if bundle_name:
279+
tinygo_version = get_version_for_tool(
280+
repository_ctx,
281+
"tinygo",
282+
bundle_name = bundle_name,
283+
fallback_version = repository_ctx.attr.tinygo_version,
284+
)
285+
log_bundle_usage(repository_ctx, "tinygo", tinygo_version, bundle_name)
286+
else:
287+
tinygo_version = repository_ctx.attr.tinygo_version
271288

272289
print("Setting up TinyGo toolchain v{} for {}".format(tinygo_version, platform))
273290

@@ -387,8 +404,12 @@ toolchain(
387404
tinygo_toolchain_repository = repository_rule(
388405
implementation = _tinygo_toolchain_repository_impl,
389406
attrs = {
407+
"bundle": attr.string(
408+
doc = "Toolchain bundle name. If set, version is read from checksums/toolchain_bundles.json",
409+
default = "",
410+
),
390411
"tinygo_version": attr.string(
391-
doc = "TinyGo version to download and use",
412+
doc = "TinyGo version to download and use. Ignored if bundle is specified.",
392413
default = "0.39.0",
393414
),
394415
},

toolchains/wasi_sdk_toolchain.bzl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""WASI SDK toolchain definitions"""
22

33
load("//checksums:registry.bzl", "get_tool_info")
4+
load("//toolchains:bundle.bzl", "get_version_for_tool", "log_bundle_usage")
45

56
def _get_wasi_sdk_platform_info(platform, version):
67
"""Get platform info and checksum for WASI SDK from centralized registry"""
@@ -121,7 +122,20 @@ def _wasi_sdk_repository_impl(repository_ctx):
121122
def _setup_downloaded_wasi_sdk(repository_ctx):
122123
"""Download WASI SDK from GitHub releases"""
123124

124-
version = repository_ctx.attr.version
125+
bundle_name = repository_ctx.attr.bundle
126+
127+
# Resolve version from bundle if specified, otherwise use explicit version
128+
if bundle_name:
129+
version = get_version_for_tool(
130+
repository_ctx,
131+
"wasi-sdk",
132+
bundle_name = bundle_name,
133+
fallback_version = repository_ctx.attr.version,
134+
)
135+
log_bundle_usage(repository_ctx, "wasi-sdk", version, bundle_name)
136+
else:
137+
version = repository_ctx.attr.version
138+
125139
platform = _detect_host_platform(repository_ctx)
126140

127141
# Download WASI SDK
@@ -423,13 +437,17 @@ wasm_cc_toolchain_config = rule(
423437
wasi_sdk_repository = repository_rule(
424438
implementation = _wasi_sdk_repository_impl,
425439
attrs = {
440+
"bundle": attr.string(
441+
doc = "Toolchain bundle name. If set, version is read from checksums/toolchain_bundles.json",
442+
default = "",
443+
),
426444
"strategy": attr.string(
427445
doc = "Strategy: 'download'",
428446
default = "download",
429447
values = ["download"],
430448
),
431449
"version": attr.string(
432-
doc = "WASI SDK version",
450+
doc = "WASI SDK version. Ignored if bundle is specified.",
433451
default = "27",
434452
),
435453
"url": attr.string(

toolchains/wasm_toolchain.bzl

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""WebAssembly toolchain definitions with enhanced tool management"""
22

33
load("//checksums:registry.bzl", "get_tool_info", "validate_tool_compatibility")
4+
load("//toolchains:bundle.bzl", "get_version_for_tool", "log_bundle_usage")
45
load("//toolchains:diagnostics.bzl", "create_retry_wrapper", "format_diagnostic_error", "log_diagnostic_info", "validate_system_tool")
56
load("//toolchains:monitoring.bzl", "add_build_telemetry", "create_health_check")
67
load("//toolchains:tool_cache.bzl", "cache_tool", "clean_expired_cache", "retrieve_cached_tool", "validate_tool_functionality")
@@ -125,7 +126,19 @@ def _wasm_toolchain_repository_impl(repository_ctx):
125126

126127
strategy = repository_ctx.attr.strategy
127128
platform = _detect_host_platform(repository_ctx)
128-
version = repository_ctx.attr.version
129+
bundle_name = repository_ctx.attr.bundle
130+
131+
# Resolve version from bundle or use explicit version attribute
132+
if bundle_name:
133+
version = get_version_for_tool(
134+
repository_ctx,
135+
"wasm-tools",
136+
bundle_name = bundle_name,
137+
fallback_version = repository_ctx.attr.version,
138+
)
139+
log_bundle_usage(repository_ctx, "wasm-tools", version, bundle_name)
140+
else:
141+
version = repository_ctx.attr.version
129142

130143
# Log diagnostic information
131144
log_diagnostic_info(repository_ctx, "wasm-tools", platform, version, strategy)
@@ -498,7 +511,19 @@ def _download_wasm_tools(repository_ctx):
498511
def _download_wac(repository_ctx):
499512
"""Download wac only"""
500513
platform = _detect_host_platform(repository_ctx)
501-
wac_version = get_tool_version("wac") # From tool_versions.bzl
514+
bundle_name = repository_ctx.attr.bundle
515+
516+
# Get version from bundle if specified, otherwise from tool_versions.bzl
517+
if bundle_name:
518+
wac_version = get_version_for_tool(
519+
repository_ctx,
520+
"wac",
521+
bundle_name = bundle_name,
522+
fallback_version = get_tool_version("wac"),
523+
)
524+
log_bundle_usage(repository_ctx, "wac", wac_version, bundle_name)
525+
else:
526+
wac_version = get_tool_version("wac") # From tool_versions.bzl
502527

503528
# Get checksum and platform info from tool_versions.bzl
504529
tool_info = get_tool_info("wac", wac_version, platform)
@@ -520,7 +545,19 @@ def _download_wac(repository_ctx):
520545
def _download_wit_bindgen(repository_ctx):
521546
"""Download wit-bindgen only"""
522547
platform = _detect_host_platform(repository_ctx)
523-
wit_bindgen_version = get_tool_version("wit-bindgen") # From tool_versions.bzl
548+
bundle_name = repository_ctx.attr.bundle
549+
550+
# Get version from bundle if specified, otherwise from tool_versions.bzl
551+
if bundle_name:
552+
wit_bindgen_version = get_version_for_tool(
553+
repository_ctx,
554+
"wit-bindgen",
555+
bundle_name = bundle_name,
556+
fallback_version = get_tool_version("wit-bindgen"),
557+
)
558+
log_bundle_usage(repository_ctx, "wit-bindgen", wit_bindgen_version, bundle_name)
559+
else:
560+
wit_bindgen_version = get_tool_version("wit-bindgen") # From tool_versions.bzl
524561

525562
# Get checksum and platform info from tool_versions.bzl
526563
tool_info = get_tool_info("wit-bindgen", wit_bindgen_version, platform)
@@ -724,13 +761,17 @@ toolchain(
724761
wasm_toolchain_repository = repository_rule(
725762
implementation = _wasm_toolchain_repository_impl,
726763
attrs = {
764+
"bundle": attr.string(
765+
doc = "Toolchain bundle name from checksums/toolchain_bundles.json (e.g., 'stable-2025-12', 'minimal'). If set, version is read from bundle.",
766+
default = "",
767+
),
727768
"strategy": attr.string(
728769
doc = "Tool acquisition strategy: 'download' only (other strategies removed in dependency management cleanup)",
729770
default = "download",
730771
values = ["download"],
731772
),
732773
"version": attr.string(
733-
doc = "Version to use (for download/build strategies)",
774+
doc = "Version to use (for download/build strategies). Ignored if bundle is specified.",
734775
default = "1.235.0",
735776
),
736777
"git_commit": attr.string(

0 commit comments

Comments
 (0)