From 716fd8aadba077314a4bb1698ddac07b951989b5 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 17 Oct 2024 17:37:19 +0900 Subject: [PATCH] Add integration tests for building WebAssembly binaries. --- tests/BUILD.bazel | 37 +++++++++++++++++++++++++++- tests/MODULE.bazel | 35 +++++++++++++++++++++++++++ tests/transitions.bzl | 28 ++++++++++++++++++---- tests/wasi_sdk.bzl | 49 ++++++++++++++++++++++++++++++++++++++ tests/wasm_strlen.c | 7 ++++++ tests/wasm_strlen_nolibc.c | 6 +++++ 6 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 tests/wasi_sdk.bzl create mode 100644 tests/wasm_strlen.c create mode 100644 tests/wasm_strlen_nolibc.c diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index 02ab2032..41d54842 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -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", @@ -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", +) diff --git a/tests/MODULE.bazel b/tests/MODULE.bazel index 04401fdc..588eb3d5 100644 --- a/tests/MODULE.bazel +++ b/tests/MODULE.bazel @@ -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") diff --git a/tests/transitions.bzl b/tests/transitions.bzl index ac7316ed..0bffa076 100644 --- a/tests/transitions.bzl +++ b/tests/transitions.bzl @@ -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"], ) @@ -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", diff --git a/tests/wasi_sdk.bzl b/tests/wasi_sdk.bzl new file mode 100644 index 00000000..86c390af --- /dev/null +++ b/tests/wasi_sdk.bzl @@ -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) diff --git a/tests/wasm_strlen.c b/tests/wasm_strlen.c new file mode 100644 index 00000000..7ff60cc2 --- /dev/null +++ b/tests/wasm_strlen.c @@ -0,0 +1,7 @@ +#include +#include + +__attribute__((export_name("strlen"))) +uint32_t wasm_strlen(char *s) { + return strlen(s); +} diff --git a/tests/wasm_strlen_nolibc.c b/tests/wasm_strlen_nolibc.c new file mode 100644 index 00000000..00f0a834 --- /dev/null +++ b/tests/wasm_strlen_nolibc.c @@ -0,0 +1,6 @@ +__attribute__((export_name("strlen"))) +unsigned long wasm_strlen(char *s) { + unsigned long len = 0; + for (; *s; len++) {} + return len; +}