Skip to content

Commit 9bb02b1

Browse files
committed
feat: implement hybrid build/download strategy for WASM toolchain
Add support for selective tool building in wasm_toolchain_repository. This allows users to build specific tools from custom git repositories while downloading stable releases for others, enabling testing of forked tools without the overhead of building all tools from source. Key changes: - Add _setup_hybrid_tools() function to determine build vs download per tool - Add helper functions for individual tool downloads - Fix git clone operations to handle commit hashes properly - Support custom URLs and per-tool commit specification - Add "hybrid" as valid strategy option alongside "system", "download", "build" The hybrid strategy determines build vs download based on whether custom URLs or commits are provided for each tool. This is particularly useful for testing fixes in forked repositories while maintaining fast builds for stable tools.
1 parent 9905b76 commit 9bb02b1

File tree

1 file changed

+210
-22
lines changed

1 file changed

+210
-22
lines changed

toolchains/wasm_toolchain.bzl

Lines changed: 210 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,10 @@ def _wasm_toolchain_repository_impl(repository_ctx):
8989
_setup_downloaded_tools(repository_ctx)
9090
elif strategy == "build":
9191
_setup_built_tools(repository_ctx)
92+
elif strategy == "hybrid":
93+
_setup_hybrid_tools(repository_ctx)
9294
else:
93-
fail("Unknown strategy: {}. Must be 'system', 'download', or 'build'".format(strategy))
95+
fail("Unknown strategy: {}. Must be 'system', 'download', 'build', or 'hybrid'".format(strategy))
9496

9597
# Create BUILD files for all strategies
9698
_create_build_files(repository_ctx)
@@ -184,22 +186,42 @@ def _setup_built_tools(repository_ctx):
184186

185187
git_commit = repository_ctx.attr.git_commit
186188

189+
# Get per-tool commits or use fallback
190+
wasm_tools_commit = repository_ctx.attr.wasm_tools_commit or git_commit
191+
wac_commit = repository_ctx.attr.wac_commit or git_commit
192+
wit_bindgen_commit = repository_ctx.attr.wit_bindgen_commit or git_commit
193+
194+
# Get custom URLs or use defaults
195+
wasm_tools_url = repository_ctx.attr.wasm_tools_url or "https://github.com/bytecodealliance/wasm-tools.git"
196+
wac_url = repository_ctx.attr.wac_url or "https://github.com/bytecodealliance/wac.git"
197+
wit_bindgen_url = repository_ctx.attr.wit_bindgen_url or "https://github.com/bytecodealliance/wit-bindgen.git"
198+
187199
# Clone and build wasm-tools
188-
repository_ctx.execute([
200+
result = repository_ctx.execute([
189201
"git",
190202
"clone",
191-
"--depth=1",
192-
"--branch=" + git_commit,
193-
"https://github.com/bytecodealliance/wasm-tools.git",
203+
wasm_tools_url,
194204
"wasm-tools-src",
195205
])
196-
197-
repository_ctx.execute([
206+
if result.return_code == 0:
207+
result = repository_ctx.execute([
208+
"git",
209+
"-C",
210+
"wasm-tools-src",
211+
"checkout",
212+
wasm_tools_commit,
213+
])
214+
if result.return_code != 0:
215+
fail("Failed to clone wasm-tools from {}: {}".format(wasm_tools_url, result.stderr))
216+
217+
result = repository_ctx.execute([
198218
"cargo",
199219
"build",
200220
"--release",
201221
"--manifest-path=wasm-tools-src/Cargo.toml",
202222
])
223+
if result.return_code != 0:
224+
fail("Failed to build wasm-tools: {}".format(result.stderr))
203225

204226
repository_ctx.execute([
205227
"cp",
@@ -208,21 +230,31 @@ def _setup_built_tools(repository_ctx):
208230
])
209231

210232
# Clone and build wac
211-
repository_ctx.execute([
233+
result = repository_ctx.execute([
212234
"git",
213235
"clone",
214-
"--depth=1",
215-
"--branch=" + git_commit,
216-
"https://github.com/bytecodealliance/wac.git",
236+
wac_url,
217237
"wac-src",
218238
])
219-
220-
repository_ctx.execute([
239+
if result.return_code == 0:
240+
result = repository_ctx.execute([
241+
"git",
242+
"-C",
243+
"wac-src",
244+
"checkout",
245+
wac_commit,
246+
])
247+
if result.return_code != 0:
248+
fail("Failed to clone wac from {}: {}".format(wac_url, result.stderr))
249+
250+
result = repository_ctx.execute([
221251
"cargo",
222252
"build",
223253
"--release",
224254
"--manifest-path=wac-src/Cargo.toml",
225255
])
256+
if result.return_code != 0:
257+
fail("Failed to build wac: {}".format(result.stderr))
226258

227259
repository_ctx.execute([
228260
"cp",
@@ -231,28 +263,172 @@ def _setup_built_tools(repository_ctx):
231263
])
232264

233265
# Clone and build wit-bindgen
234-
repository_ctx.execute([
266+
result = repository_ctx.execute([
235267
"git",
236268
"clone",
237-
"--depth=1",
238-
"--branch=" + git_commit,
239-
"https://github.com/bytecodealliance/wit-bindgen.git",
269+
wit_bindgen_url,
240270
"wit-bindgen-src",
241271
])
242-
243-
repository_ctx.execute([
272+
if result.return_code == 0:
273+
result = repository_ctx.execute([
274+
"git",
275+
"-C",
276+
"wit-bindgen-src",
277+
"checkout",
278+
wit_bindgen_commit,
279+
])
280+
if result.return_code != 0:
281+
fail("Failed to clone wit-bindgen from {}: {}".format(wit_bindgen_url, result.stderr))
282+
283+
result = repository_ctx.execute([
244284
"cargo",
245285
"build",
246286
"--release",
247287
"--manifest-path=wit-bindgen-src/Cargo.toml",
248288
])
289+
if result.return_code != 0:
290+
fail("Failed to build wit-bindgen: {}".format(result.stderr))
249291

250292
repository_ctx.execute([
251293
"cp",
252294
"wit-bindgen-src/target/release/wit-bindgen",
253295
"wit-bindgen",
254296
])
255297

298+
def _setup_hybrid_tools(repository_ctx):
299+
"""Setup tools using hybrid build/download strategy"""
300+
301+
# Determine which tools to build vs download based on custom URLs/commits
302+
build_wasm_tools = repository_ctx.attr.wasm_tools_url != "" or repository_ctx.attr.wasm_tools_commit != ""
303+
build_wac = repository_ctx.attr.wac_url != "" or repository_ctx.attr.wac_commit != ""
304+
build_wit_bindgen = repository_ctx.attr.wit_bindgen_url != "" or repository_ctx.attr.wit_bindgen_commit != ""
305+
306+
# Get commits and URLs for tools we're building
307+
git_commit = repository_ctx.attr.git_commit
308+
wasm_tools_commit = repository_ctx.attr.wasm_tools_commit or git_commit
309+
wac_commit = repository_ctx.attr.wac_commit or git_commit
310+
wit_bindgen_commit = repository_ctx.attr.wit_bindgen_commit or git_commit
311+
312+
wasm_tools_url = repository_ctx.attr.wasm_tools_url or "https://github.com/bytecodealliance/wasm-tools.git"
313+
wac_url = repository_ctx.attr.wac_url or "https://github.com/bytecodealliance/wac.git"
314+
wit_bindgen_url = repository_ctx.attr.wit_bindgen_url or "https://github.com/bytecodealliance/wit-bindgen.git"
315+
316+
# Build or download wasm-tools
317+
if build_wasm_tools:
318+
result = repository_ctx.execute([
319+
"git", "clone", wasm_tools_url, "wasm-tools-src",
320+
])
321+
if result.return_code == 0:
322+
result = repository_ctx.execute([
323+
"git", "-C", "wasm-tools-src", "checkout", wasm_tools_commit,
324+
])
325+
if result.return_code != 0:
326+
fail("Failed to clone wasm-tools from {}: {}".format(wasm_tools_url, result.stderr))
327+
328+
result = repository_ctx.execute([
329+
"cargo", "build", "--release", "--manifest-path=wasm-tools-src/Cargo.toml",
330+
])
331+
if result.return_code != 0:
332+
fail("Failed to build wasm-tools: {}".format(result.stderr))
333+
334+
repository_ctx.execute(["cp", "wasm-tools-src/target/release/wasm-tools", "wasm-tools"])
335+
else:
336+
_download_wasm_tools(repository_ctx)
337+
338+
# Build or download wac
339+
if build_wac:
340+
result = repository_ctx.execute([
341+
"git", "clone", wac_url, "wac-src",
342+
])
343+
if result.return_code == 0:
344+
result = repository_ctx.execute([
345+
"git", "-C", "wac-src", "checkout", wac_commit,
346+
])
347+
if result.return_code != 0:
348+
fail("Failed to clone wac from {}: {}".format(wac_url, result.stderr))
349+
350+
result = repository_ctx.execute([
351+
"cargo", "build", "--release", "--manifest-path=wac-src/Cargo.toml",
352+
])
353+
if result.return_code != 0:
354+
fail("Failed to build wac: {}".format(result.stderr))
355+
356+
repository_ctx.execute(["cp", "wac-src/target/release/wac", "wac"])
357+
else:
358+
_download_wac(repository_ctx)
359+
360+
# Build or download wit-bindgen
361+
if build_wit_bindgen:
362+
result = repository_ctx.execute([
363+
"git", "clone", wit_bindgen_url, "wit-bindgen-src",
364+
])
365+
if result.return_code == 0:
366+
result = repository_ctx.execute([
367+
"git", "-C", "wit-bindgen-src", "checkout", wit_bindgen_commit,
368+
])
369+
if result.return_code != 0:
370+
fail("Failed to clone wit-bindgen from {}: {}".format(wit_bindgen_url, result.stderr))
371+
372+
result = repository_ctx.execute([
373+
"cargo", "build", "--release", "--manifest-path=wit-bindgen-src/Cargo.toml",
374+
])
375+
if result.return_code != 0:
376+
fail("Failed to build wit-bindgen: {}".format(result.stderr))
377+
378+
repository_ctx.execute(["cp", "wit-bindgen-src/target/release/wit-bindgen", "wit-bindgen"])
379+
else:
380+
_download_wit_bindgen(repository_ctx)
381+
382+
def _download_wasm_tools(repository_ctx):
383+
"""Download wasm-tools only"""
384+
platform = _detect_host_platform(repository_ctx)
385+
version = repository_ctx.attr.version
386+
platform_suffix = _get_platform_suffix(platform)
387+
388+
wasm_tools_url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v{}/wasm-tools-{}-{}.tar.gz".format(
389+
version, version, platform_suffix,
390+
)
391+
392+
repository_ctx.download_and_extract(
393+
url = wasm_tools_url,
394+
stripPrefix = "wasm-tools-{}-{}".format(version, platform_suffix),
395+
)
396+
397+
def _download_wac(repository_ctx):
398+
"""Download wac only"""
399+
platform = _detect_host_platform(repository_ctx)
400+
platform_suffix = _get_platform_suffix(platform)
401+
402+
wac_version = "0.7.0"
403+
wac_platform_map = {
404+
"aarch64-macos": "aarch64-apple-darwin",
405+
"x86_64-macos": "x86_64-apple-darwin",
406+
"x86_64-linux": "x86_64-unknown-linux-musl",
407+
"aarch64-linux": "aarch64-unknown-linux-musl",
408+
"x86_64-windows": "x86_64-pc-windows-gnu",
409+
}
410+
wac_platform = wac_platform_map.get(platform_suffix, "x86_64-unknown-linux-musl")
411+
wac_url = "https://github.com/bytecodealliance/wac/releases/download/v{}/wac-cli-{}".format(
412+
wac_version, wac_platform,
413+
)
414+
415+
repository_ctx.download(url = wac_url, output = "wac", executable = True)
416+
417+
def _download_wit_bindgen(repository_ctx):
418+
"""Download wit-bindgen only"""
419+
platform = _detect_host_platform(repository_ctx)
420+
platform_suffix = _get_platform_suffix(platform)
421+
422+
wit_bindgen_version = "0.43.0"
423+
wit_bindgen_url = "https://github.com/bytecodealliance/wit-bindgen/releases/download/v{}/wit-bindgen-{}-{}.tar.gz".format(
424+
wit_bindgen_version, wit_bindgen_version, platform_suffix,
425+
)
426+
427+
repository_ctx.download_and_extract(
428+
url = wit_bindgen_url,
429+
stripPrefix = "wit-bindgen-{}-{}".format(wit_bindgen_version, platform_suffix),
430+
)
431+
256432
def _get_platform_suffix(platform):
257433
"""Get platform suffix for download URLs"""
258434
platform_suffixes = {
@@ -324,18 +500,30 @@ wasm_toolchain_repository = repository_rule(
324500
implementation = _wasm_toolchain_repository_impl,
325501
attrs = {
326502
"strategy": attr.string(
327-
doc = "Tool acquisition strategy: 'system', 'download', or 'build'",
503+
doc = "Tool acquisition strategy: 'system', 'download', 'build', or 'hybrid'",
328504
default = "system",
329-
values = ["system", "download", "build"],
505+
values = ["system", "download", "build", "hybrid"],
330506
),
331507
"version": attr.string(
332508
doc = "Version to use (for download/build strategies)",
333509
default = "1.235.0",
334510
),
335511
"git_commit": attr.string(
336-
doc = "Git commit/tag to build from (for build strategy)",
512+
doc = "Git commit/tag to build from (for build strategy) - fallback for all tools",
337513
default = "main",
338514
),
515+
"wasm_tools_commit": attr.string(
516+
doc = "Git commit/tag for wasm-tools (overrides git_commit)",
517+
default = "",
518+
),
519+
"wac_commit": attr.string(
520+
doc = "Git commit/tag for wac (overrides git_commit)",
521+
default = "",
522+
),
523+
"wit_bindgen_commit": attr.string(
524+
doc = "Git commit/tag for wit-bindgen (overrides git_commit)",
525+
default = "",
526+
),
339527
"wasm_tools_url": attr.string(
340528
doc = "Custom download URL for wasm-tools (optional)",
341529
default = "",

0 commit comments

Comments
 (0)