Skip to content

Commit

Permalink
Support WebAssembly target platforms wasm{32,64}-unknown-unknown (#405
Browse files Browse the repository at this point in the history
)
  • Loading branch information
jmillikin authored Oct 18, 2024
1 parent a80f2b4 commit bda1c9f
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 17 deletions.
16 changes: 16 additions & 0 deletions platforms/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,19 @@ platform(
"@platforms//cpu:aarch64",
],
)

platform(
name = "wasm32",
constraint_values = [
"@platforms//os:none",
"@platforms//cpu:wasm32",
],
)

platform(
name = "wasm64",
constraint_values = [
"@platforms//os:none",
"@platforms//cpu:wasm64",
],
)
37 changes: 37 additions & 0 deletions tests/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,40 @@ llvm.toolchain(
exec_arch = "amd64",
)
use_repo(llvm, "llvm_toolchain_linux_exec")

# Toolchain example for WebAssembly.
llvm.toolchain(
name = "llvm_toolchain_wasm",
# WebAssembly tests use a separate (newer) version of LLVM to exercise
# support for experimental features such as wasm64.
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("//wasm:wasi_sdk.bzl", "wasi_sdk_sysroots")
wasi_sdk_sysroots(name = "wasi_sdk_sysroots")

libclang_rt_wasm32 = use_repo_rule("//wasm:wasi_sdk.bzl", "libclang_rt_wasm32")
libclang_rt_wasm32(name = "libclang_rt_wasm32")
35 changes: 35 additions & 0 deletions tests/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,41 @@ llvm_toolchain(
urls = {"": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04.tar.xz"]},
)

# Toolchain example for WebAssembly.
llvm_toolchain(
name = "llvm_toolchain_wasm",
libclang_rt = {
"@libclang_rt_wasm32//:libclang_rt.builtins-wasm32.a": "wasm32-unknown-unknown/libclang_rt.builtins.a",
},
# WebAssembly tests use a separate (newer) version of LLVM to exercise
# support for experimental features such as wasm64.
llvm_versions = {
# The most recent LLVM as of 2024-10-17
"": "19.1.0",
},
stdlib = {
"wasm32": "libc",
"wasm64": "none",
},
sysroot = {
"wasm32": "@wasi_sdk_sysroots//wasm32-wasip2",
"wasm64": "@wasi_sdk_sysroots//empty",
},
)

load(
"@llvm_toolchain_wasm//:toolchains.bzl",
llvm_register_toolchains_wasm = "llvm_register_toolchains",
)

llvm_register_toolchains_wasm()

load("//wasm:wasi_sdk.bzl", "libclang_rt_wasm32", "wasi_sdk_sysroots")

libclang_rt_wasm32(name = "libclang_rt_wasm32")

wasi_sdk_sysroots(name = "wasi_sdk_sysroots")

## Test dependencies.

# Well known repos; present here only for testing.
Expand Down
2 changes: 1 addition & 1 deletion tests/scripts/debian_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ set -exuo pipefail
# Common setup
export DEBIAN_FRONTEND=noninteractive
apt-get -qq update
apt-get -qq -y install curl libtinfo5 zlib1g-dev >/dev/null
apt-get -qq -y install curl libtinfo5 libxml2 zlib1g-dev >/dev/null
# The above command gives some verbose output that can not be silenced easily.
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
Expand Down
2 changes: 1 addition & 1 deletion tests/scripts/linux_sysroot_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ set -exuo pipefail
# Common setup
export DEBIAN_FRONTEND=noninteractive
apt-get -qq update
apt-get -qq -y install curl libtinfo5 zlib1g-dev >/dev/null
apt-get -qq -y install curl libtinfo5 libxml2 zlib1g-dev >/dev/null
# The above command gives some verbose output that can not be silenced easily.
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
Expand Down
2 changes: 1 addition & 1 deletion tests/scripts/run_docker_exec_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ docker build --platform=linux/amd64 --pull --tag=bazel-docker-sandbox - <<-EOF
FROM ${base_image}
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -qq update && \
apt-get -qq -y install libtinfo5 zlib1g-dev libxml2
apt-get -qq -y install libtinfo5 libxml2 zlib1g-dev libxml2
EOF

build_args=(
Expand Down
27 changes: 26 additions & 1 deletion tests/scripts/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@
set -euo pipefail

toolchain_name=""
disable_wasm_tests=""

while getopts "t:h" opt; do
while getopts "t:hW" opt; do
case "${opt}" in
"t") toolchain_name="${OPTARG}" ;;
"h")
echo "Usage:"
echo "-t - Toolchain name to use for testing; default is llvm_toolchain"
exit 2
;;
"W")
disable_wasm_tests="yes"
;;
*)
echo "invalid option: -${OPTARG}"
exit 1
Expand Down Expand Up @@ -62,3 +66,24 @@ fi
# Note that the following flags are currently known to cause issues in migration tests:
# --incompatible_disallow_struct_provider_syntax # https://github.com/bazelbuild/bazel/issues/7347
# --incompatible_no_rule_outputs_param # from rules_rust

# WebAssembly tests use a separate (newer) version of LLVM to exercise support
# for experimental features such as wasm64, which can cause the CI environment
# to run out of disk space.
#
# Mitigate this by expunging the workspace before trying to build Wasm targets.
if [[ -z ${toolchain_name} && -z ${disable_wasm_tests} ]]; then
# Redefine `test_args` without `--linkopt=-Wl,-v`, which breaks `wasm-ld`.
#
# https://github.com/llvm/llvm-project/issues/112836
test_args=(
"--copt=-v"
"--linkopt=-Wl,-t"
)
wasm_targets=(
"//wasm:all"
)
"${bazel}" clean --expunge
"${bazel}" ${TEST_MIGRATION:+"--strict"} --bazelrc=/dev/null test \
"${common_test_args[@]}" "${test_args[@]}" "${wasm_targets[@]}"
fi
8 changes: 6 additions & 2 deletions tests/scripts/ubuntu_20_04_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ set -exuo pipefail
# Common setup
export DEBIAN_FRONTEND=noninteractive
apt-get -qq update
apt-get -qq -y install apt-utils curl libtinfo5 pkg-config zlib1g-dev >/dev/null
apt-get -qq -y install apt-utils curl libtinfo5 libxml2 pkg-config zlib1g-dev >/dev/null
# The above command gives some verbose output that can not be silenced easily.
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
# The WebAssembly tests use an LLVM version that is too new for the GNU libc
# distributed in Ubuntu 20.04.
disable_wasm_tests='-W'
# Run tests
cd /src
tests/scripts/run_tests.sh
tests/scripts/run_tests.sh \${disable_wasm_tests}
"""
done
2 changes: 1 addition & 1 deletion tests/scripts/ubuntu_22_04_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ set -exuo pipefail
# Common setup
export DEBIAN_FRONTEND=noninteractive
apt-get -qq update
apt-get -qq -y install curl libtinfo5 zlib1g-dev >/dev/null
apt-get -qq -y install curl libtinfo5 libxml2 zlib1g-dev >/dev/null
# The above command gives some verbose output that can not be silenced easily.
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
Expand Down
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
44 changes: 44 additions & 0 deletions tests/wasm/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@rules_cc//cc:defs.bzl", "cc_binary")
load("//:transitions.bzl", "transition_binary_to_platform")

build_test(
name = "wasm_targets_test",
targets = [
":wasm32_strlen",
":wasm32_strlen_nolibc",
":wasm64_strlen_nolibc",
],
)

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

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"],
tags = ["manual"],
)

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",
)
49 changes: 49 additions & 0 deletions tests/wasm/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/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/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;
}
1 change: 1 addition & 0 deletions toolchain/BUILD.llvm_repo
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ filegroup(
srcs = [
"bin/ld.lld",
"bin/ld64.lld",
"bin/wasm-ld",
],
)

Expand Down
Loading

0 comments on commit bda1c9f

Please sign in to comment.