Skip to content

Commit

Permalink
Add integration tests for building WebAssembly binaries.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmillikin committed Oct 17, 2024
1 parent 8800a0f commit 716fd8a
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 5 deletions.
37 changes: 36 additions & 1 deletion tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@

load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load(":transitions.bzl", "dwp_file", "transition_library_to_platform")
load(
":transitions.bzl",
"dwp_file",
"transition_binary_to_platform",
"transition_library_to_platform",
)

cc_library(
name = "stdlib",
Expand Down Expand Up @@ -200,3 +205,33 @@ cc_test(
tags = ["manual"],
deps = [":test_cxx_standard_lib_transitioned"],
)

cc_binary(
name = "wasm_strlen",
srcs = ["wasm_strlen.c"],
linkopts = ["-Wl,--no-entry"],
)

transition_binary_to_platform(
name = "wasm32_strlen",
bin = ":wasm_strlen",
platform = "@toolchains_llvm//platforms:wasm32",
)

cc_binary(
name = "wasm_strlen_nolibc",
srcs = ["wasm_strlen_nolibc.c"],
linkopts = ["-Wl,--no-entry"],
)

transition_binary_to_platform(
name = "wasm32_strlen_nolibc",
bin = ":wasm_strlen_nolibc",
platform = "@toolchains_llvm//platforms:wasm32",
)

transition_binary_to_platform(
name = "wasm64_strlen_nolibc",
bin = ":wasm_strlen_nolibc",
platform = "@toolchains_llvm//platforms:wasm64",
)
35 changes: 35 additions & 0 deletions tests/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,38 @@ llvm.toolchain(
exec_arch = "amd64",
)
use_repo(llvm, "llvm_toolchain_linux_exec")

# Toolchain example for WebAssembly.
llvm.toolchain(
name = "llvm_toolchain_wasm",
llvm_versions = {
# The most recent LLVM as of 2024-10-17
"": "19.1.0",
},
stdlib = {
"wasm32": "libc",
"wasm64": "none",
},
libclang_rt = {
"@libclang_rt_wasm32//:libclang_rt.builtins-wasm32.a": "wasm32-unknown-unknown/libclang_rt.builtins.a",
},
)
llvm.sysroot(
name = "llvm_toolchain_wasm",
label = "@wasi_sdk_sysroots//wasm32-wasip2",
targets = ["wasm32"],
)
llvm.sysroot(
name = "llvm_toolchain_wasm",
label = "@wasi_sdk_sysroots//empty",
targets = ["wasm64"],
)

use_repo(llvm, "llvm_toolchain_wasm")
register_toolchains("@llvm_toolchain_wasm//:all")

wasi_sdk_sysroots = use_repo_rule("//:wasi_sdk.bzl", "wasi_sdk_sysroots")
wasi_sdk_sysroots(name = "wasi_sdk_sysroots")

libclang_rt_wasm32 = use_repo_rule("//:wasi_sdk.bzl", "libclang_rt_wasm32")
libclang_rt_wasm32(name = "libclang_rt_wasm32")
28 changes: 24 additions & 4 deletions tests/transitions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ dwp_file = rule(
},
)

def _transition_library_to_platform_transition_impl(_, attr):
def _transition_to_platform_transition_impl(_, attr):
return {"//command_line_option:platforms": str(attr.platform)}

_transition_library_to_platform_transition = transition(
implementation = _transition_library_to_platform_transition_impl,
_transition_to_platform_transition = transition(
implementation = _transition_to_platform_transition_impl,
inputs = [],
outputs = ["//command_line_option:platforms"],
)
Expand All @@ -114,7 +114,27 @@ def _transition_library_to_platform_impl(ctx):
transition_library_to_platform = rule(
implementation = _transition_library_to_platform_impl,
attrs = {
"lib": attr.label(mandatory = True, cfg = _transition_library_to_platform_transition),
"lib": attr.label(mandatory = True, cfg = _transition_to_platform_transition),
"platform": attr.label(mandatory = True),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)

def _transition_binary_to_platform_impl(ctx):
out = ctx.actions.declare_file(ctx.attr.name)
ctx.actions.symlink(output = out, target_file = ctx.file.bin)
return DefaultInfo(files = depset([out]))

transition_binary_to_platform = rule(
implementation = _transition_binary_to_platform_impl,
attrs = {
"bin": attr.label(
mandatory = True,
allow_single_file = True,
cfg = _transition_to_platform_transition,
),
"platform": attr.label(mandatory = True),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
Expand Down
49 changes: 49 additions & 0 deletions tests/wasi_sdk.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
_SYSROOT_BUILD = """
filegroup(
name = {name},
srcs = glob(["include/**/*", "lib/**/*", "share/**/*"], allow_empty=True),
visibility = ["//visibility:public"],
)
"""

_WASI_SDK_ABIS = [
"wasm32-wasi",
"wasm32-wasip1",
"wasm32-wasip1-threads",
"wasm32-wasip2",
"wasm32-wasi-threads",
]

def _wasi_sdk_sysroots(ctx):
ctx.download_and_extract(
integrity = "sha256-NRcvfSeZSFsVpGsdh/UKWF2RXsZiCA8AXZkVOlCIjwg=",
stripPrefix = "wasi-sysroot-24.0",
url = ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sysroot-24.0.tar.gz"],
)

ctx.file("empty/BUILD.bazel", _SYSROOT_BUILD.format(
name = repr("empty"),
))

for abi in _WASI_SDK_ABIS:
ctx.file("%s/BUILD.bazel" % (abi,), _SYSROOT_BUILD.format(
name = repr(abi),
))
ctx.execute(["mv", "include/" + abi, "%s/include" % (abi,)])
ctx.execute(["mv", "lib/" + abi, "%s/lib" % (abi,)])
ctx.execute(["mv", "share/" + abi, "%s/share" % (abi,)])

wasi_sdk_sysroots = repository_rule(_wasi_sdk_sysroots)

def _libclang_rt_wasm32(ctx):
ctx.file("BUILD.bazel", """
exports_files(glob(["*.a"]))
""")

ctx.download_and_extract(
integrity = "sha256-fjPA33WLkEabHePKFY4tCn9xk01YhFJbpqNy3gs7Dsc=",
stripPrefix = "libclang_rt.builtins-wasm32-wasi-24.0",
url = ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/libclang_rt.builtins-wasm32-wasi-24.0.tar.gz"],
)

libclang_rt_wasm32 = repository_rule(_libclang_rt_wasm32)
7 changes: 7 additions & 0 deletions tests/wasm_strlen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <stdint.h>
#include <string.h>

__attribute__((export_name("strlen")))
uint32_t wasm_strlen(char *s) {
return strlen(s);
}
6 changes: 6 additions & 0 deletions tests/wasm_strlen_nolibc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
__attribute__((export_name("strlen")))
unsigned long wasm_strlen(char *s) {
unsigned long len = 0;
for (; *s; len++) {}
return len;
}

0 comments on commit 716fd8a

Please sign in to comment.