Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support WebAssembly target platforms wasm{32,64}-unknown-unknown #405

Merged
merged 10 commits into from
Oct 18, 2024
Merged
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
Loading