From 97be67210942379c0e7aabb9d1756206c11e92d3 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 17 Oct 2024 15:31:53 +0900 Subject: [PATCH 01/10] Support `stdlib="libc"` for targets with `libc.a` but no `libc++.a` --- toolchain/cc_toolchain_config.bzl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl index 7e6a38e64..fb32d1ea8 100644 --- a/toolchain/cc_toolchain_config.bzl +++ b/toolchain/cc_toolchain_config.bzl @@ -134,10 +134,15 @@ def cc_toolchain_config( link_flags = [ "--target=" + target_system_name, - "-lm", "-no-canonical-prefixes", ] + stdlib = compiler_configuration["stdlib"] + if stdlib != "none": + link_flags.extend([ + "-lm", + ]) + # Similar to link_flags, but placed later in the command line such that # unused symbols are not stripped. link_libs = [] @@ -183,7 +188,6 @@ def cc_toolchain_config( # The linker has no way of knowing if there are C++ objects; so we # always link C++ libraries. cxx_standard = compiler_configuration["cxx_standard"] - stdlib = compiler_configuration["stdlib"] sysroot_path = compiler_configuration["sysroot_path"] if stdlib == "builtin-libc++" and is_xcompile: stdlib = "stdc++" @@ -253,11 +257,14 @@ def cc_toolchain_config( link_flags.extend([ "-l:libstdc++.a", ]) + elif stdlib == "libc": + cxx_flags = [ + "-std=" + cxx_standard, + ] elif stdlib == "none": cxx_flags = [ "-nostdlib", ] - link_flags.extend([ "-nostdlib", ]) From 672a6a1f6df9e0b035165897c6a2b219cbd61fa3 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 17 Oct 2024 15:51:46 +0900 Subject: [PATCH 02/10] Support overlaying `libclang_rt` into the downloaded LLVM distribution. --- toolchain/internal/llvm_distributions.bzl | 8 ++++++++ toolchain/internal/repo.bzl | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/toolchain/internal/llvm_distributions.bzl b/toolchain/internal/llvm_distributions.bzl index 8d383988d..db0dc2f35 100644 --- a/toolchain/internal/llvm_distributions.bzl +++ b/toolchain/internal/llvm_distributions.bzl @@ -623,6 +623,14 @@ def download_llvm(rctx): auth = _get_auth(rctx, urls), ) + if rctx.attr.libclang_rt: + clang_versions = rctx.path("lib/clang").readdir() + for libclang_rt, lib_name in rctx.attr.libclang_rt.items(): + libclang_rt_content = rctx.read(libclang_rt) + for clang_version in clang_versions: + lib_path = clang_version.get_child("lib", lib_name) + rctx.file(lib_path, libclang_rt_content, legacy_utf8=False) + updated_attrs = _attr_dict(rctx.attr) if update_sha256: updated_attrs["sha256"].update([(key, res.sha256)]) diff --git a/toolchain/internal/repo.bzl b/toolchain/internal/repo.bzl index df89c4c1c..3bd95a933 100644 --- a/toolchain/internal/repo.bzl +++ b/toolchain/internal/repo.bzl @@ -102,6 +102,12 @@ llvm_repo_attrs.update({ "As with `llvm_mirror`, these sources will take precedence over the official LLVM " + "release sources.", ), + "libclang_rt": attr.label_keyed_string_dict( + mandatory = False, + doc = ("Additional libclang_rt libraries to overlay into the downloaded LLVM " + + "distribution. The key is the label of a libclang_rt library, " + + "and the value is `\"{llvm_target_name}/{library_name}.a\"`."), + ), "netrc": attr.string( mandatory = False, doc = "Path to the netrc file for authenticated LLVM URL downloads.", From 879fe7ec8d625fc0784180902cda3f9f369c265c Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 17 Oct 2024 16:01:23 +0900 Subject: [PATCH 03/10] Support WebAssembly target platforms `wasm{32,64}-unknown-unknown` --- platforms/BUILD.bazel | 16 ++++++++++++++++ toolchain/BUILD.llvm_repo | 1 + toolchain/cc_toolchain_config.bzl | 20 ++++++++++++++++++++ toolchain/internal/common.bzl | 16 ++++++++++++++-- toolchain/internal/configure.bzl | 13 ++++++++++++- 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/platforms/BUILD.bazel b/platforms/BUILD.bazel index d9c7140dc..d1cc84ed8 100644 --- a/platforms/BUILD.bazel +++ b/platforms/BUILD.bazel @@ -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", + ], +) diff --git a/toolchain/BUILD.llvm_repo b/toolchain/BUILD.llvm_repo index 76cac99cc..bbcbd1d51 100644 --- a/toolchain/BUILD.llvm_repo +++ b/toolchain/BUILD.llvm_repo @@ -41,6 +41,7 @@ filegroup( srcs = [ "bin/ld.lld", "bin/ld64.lld", + "bin/wasm-ld", ], ) diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl index fb32d1ea8..7bb55f35b 100644 --- a/toolchain/cc_toolchain_config.bzl +++ b/toolchain/cc_toolchain_config.bzl @@ -89,6 +89,22 @@ def cc_toolchain_config( "clang", "glibc_unknown", ), + "wasm32": ( + "clang-wasm32", + "wasm32", + "unknown", + "clang", + "unknown", + "unknown", + ), + "wasm64": ( + "clang-wasm64", + "wasm64", + "unknown", + "clang", + "unknown", + "unknown", + ), }[target_os_arch_key] # Unfiltered compiler flags; these are placed at the end of the command @@ -171,6 +187,10 @@ def cc_toolchain_config( archive_flags.extend([ "-static", ]) + elif target_arch in ["wasm32", "wasm64"]: + # lld is invoked as wasm-ld for WebAssembly targets. + use_lld = True + use_libtool = False else: # Note that for xcompiling from darwin to linux, the native ld64 is # not an option because it is not a cross-linker, so lld is the diff --git a/toolchain/internal/common.bzl b/toolchain/internal/common.bzl index ff94bfb22..fe56b6a85 100644 --- a/toolchain/internal/common.bzl +++ b/toolchain/internal/common.bzl @@ -12,7 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -SUPPORTED_TARGETS = [("linux", "x86_64"), ("linux", "aarch64"), ("darwin", "x86_64"), ("darwin", "aarch64")] +SUPPORTED_TARGETS = [ + ("linux", "x86_64"), + ("linux", "aarch64"), + ("darwin", "x86_64"), + ("darwin", "aarch64"), + ("none", "wasm32"), + ("none", "wasm64"), +] # Map of tool name to its symlinked name in the tools directory. # See tool_paths in toolchain/cc_toolchain_config.bzl. @@ -120,7 +127,7 @@ def os(rctx): def os_bzl(os): # Return the OS string as used in bazel platform constraints. - return {"darwin": "osx", "linux": "linux"}[os] + return {"darwin": "osx", "linux": "linux", "none": "none"}[os] def arch(rctx): arch = rctx.attr.exec_arch @@ -139,7 +146,12 @@ def arch(rctx): return "x86_64" return arch +def is_standalone_arch(os, arch): + return os == "none" and arch in ["wasm32", "wasm64"] + def os_arch_pair(os, arch): + if is_standalone_arch(os, arch): + return arch return "{}-{}".format(os, arch) _supported_os_arch = [os_arch_pair(os, arch) for (os, arch) in SUPPORTED_TARGETS] diff --git a/toolchain/internal/configure.bzl b/toolchain/internal/configure.bzl index 8731af75a..37a0ab61f 100644 --- a/toolchain/internal/configure.bzl +++ b/toolchain/internal/configure.bzl @@ -25,6 +25,7 @@ load( _check_os_arch_keys = "check_os_arch_keys", _exec_os_arch_dict_value = "exec_os_arch_dict_value", _is_absolute_path = "is_absolute_path", + _is_standalone_arch = "is_standalone_arch", _list_to_string = "list_to_string", _os = "os", _os_arch_pair = "os_arch_pair", @@ -243,7 +244,10 @@ def _cc_toolchains_str( cc_toolchains_str = "" toolchain_names = [] for (target_os, target_arch) in _supported_targets: - suffix = "{}-{}".format(target_arch, target_os) + if _is_standalone_arch(target_os, target_arch): + suffix = target_arch + else: + suffix = "{}-{}".format(target_arch, target_os) cc_toolchain_str = _cc_toolchain_str( rctx, suffix, @@ -315,6 +319,8 @@ def _cc_toolchain_str( "darwin-aarch64": "aarch64-apple-macosx", "linux-aarch64": "aarch64-unknown-linux-gnu", "linux-x86_64": "x86_64-unknown-linux-gnu", + "wasm32": "wasm32-unknown-unknown", + "wasm64": "wasm64-unknown-unknown", }[target_pair] cxx_builtin_include_directories = [ toolchain_path_prefix + "include/c++/v1", @@ -341,6 +347,11 @@ def _cc_toolchain_str( _join(sysroot_prefix, "/usr/include"), _join(sysroot_prefix, "/System/Library/Frameworks"), ]) + elif target_os == "none": + if sysroot_prefix: + cxx_builtin_include_directories.extend([ + _join(sysroot_prefix, "/include"), + ]) else: fail("Unreachable") From c287c5e93d050eaf57174f677c765d638980207c Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 17 Oct 2024 17:37:19 +0900 Subject: [PATCH 04/10] Add integration tests for building WebAssembly binaries. --- tests/BUILD.bazel | 39 +++++++++++++++++++++++++++++- 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, 159 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 02ab2032f..b30990811 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,35 @@ cc_test( tags = ["manual"], deps = [":test_cxx_standard_lib_transitioned"], ) + +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", +) diff --git a/tests/MODULE.bazel b/tests/MODULE.bazel index 04401fdc3..588eb3d5b 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 ac7316ed7..0bffa076e 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 000000000..86c390af6 --- /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 000000000..7ff60cc2c --- /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 000000000..00f0a8343 --- /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; +} From f8d7c8581bfc385dc4d7ab3f462d2592d14ddcb4 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Fri, 18 Oct 2024 09:35:28 +0900 Subject: [PATCH 05/10] Move WebAssembly tests to a subdirectory and expunge before building --- tests/BUILD.bazel | 39 +----------------------- tests/MODULE.bazel | 6 ++-- tests/scripts/run_tests.sh | 14 +++++++++ tests/wasm/BUILD.bazel | 44 +++++++++++++++++++++++++++ tests/{ => wasm}/wasi_sdk.bzl | 0 tests/{ => wasm}/wasm_strlen.c | 0 tests/{ => wasm}/wasm_strlen_nolibc.c | 0 7 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 tests/wasm/BUILD.bazel rename tests/{ => wasm}/wasi_sdk.bzl (100%) rename tests/{ => wasm}/wasm_strlen.c (100%) rename tests/{ => wasm}/wasm_strlen_nolibc.c (100%) diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index b30990811..02ab2032f 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -14,12 +14,7 @@ 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_binary_to_platform", - "transition_library_to_platform", -) +load(":transitions.bzl", "dwp_file", "transition_library_to_platform") cc_library( name = "stdlib", @@ -205,35 +200,3 @@ cc_test( tags = ["manual"], deps = [":test_cxx_standard_lib_transitioned"], ) - -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", -) diff --git a/tests/MODULE.bazel b/tests/MODULE.bazel index 588eb3d5b..6703c10a1 100644 --- a/tests/MODULE.bazel +++ b/tests/MODULE.bazel @@ -183,6 +183,8 @@ 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", @@ -209,8 +211,8 @@ llvm.sysroot( 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 = use_repo_rule("//wasm: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 = use_repo_rule("//wasm:wasi_sdk.bzl", "libclang_rt_wasm32") libclang_rt_wasm32(name = "libclang_rt_wasm32") diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh index c50a346a1..a17b62a12 100755 --- a/tests/scripts/run_tests.sh +++ b/tests/scripts/run_tests.sh @@ -62,3 +62,17 @@ 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} ]]; then + wasm_targets=( + "//wasm:all" + ) + "${bazel}" clean --expunge + "${bazel}" ${TEST_MIGRATION:+"--strict"} --bazelrc=/dev/null test \ + "${common_test_args[@]}" "${test_args[@]}" "${wasm_targets[@]}" +fi diff --git a/tests/wasm/BUILD.bazel b/tests/wasm/BUILD.bazel new file mode 100644 index 000000000..1d837985e --- /dev/null +++ b/tests/wasm/BUILD.bazel @@ -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", +) diff --git a/tests/wasi_sdk.bzl b/tests/wasm/wasi_sdk.bzl similarity index 100% rename from tests/wasi_sdk.bzl rename to tests/wasm/wasi_sdk.bzl diff --git a/tests/wasm_strlen.c b/tests/wasm/wasm_strlen.c similarity index 100% rename from tests/wasm_strlen.c rename to tests/wasm/wasm_strlen.c diff --git a/tests/wasm_strlen_nolibc.c b/tests/wasm/wasm_strlen_nolibc.c similarity index 100% rename from tests/wasm_strlen_nolibc.c rename to tests/wasm/wasm_strlen_nolibc.c From 3683d4e795f7626602768db7cbf41aa37a26bbc0 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Fri, 18 Oct 2024 09:35:46 +0900 Subject: [PATCH 06/10] Add a WebAssembly toolchain to `tests/WORKSPACE` --- tests/WORKSPACE | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/WORKSPACE b/tests/WORKSPACE index 98a812f6d..f1e9aa2b4 100644 --- a/tests/WORKSPACE +++ b/tests/WORKSPACE @@ -156,6 +156,38 @@ 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", + # 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", + }, + sysroot = { + "wasm32": "@wasi_sdk_sysroots//wasm32-wasip2", + "wasm64": "@wasi_sdk_sysroots//empty", + }, + stdlib = { + "wasm32": "libc", + "wasm64": "none", + }, + libclang_rt = { + "@libclang_rt_wasm32//:libclang_rt.builtins-wasm32.a": "wasm32-unknown-unknown/libclang_rt.builtins.a", + }, +) + +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. From 6bfa69f2e96d4cdfd50213560785f4685dbb7141 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Fri, 18 Oct 2024 13:13:44 +0900 Subject: [PATCH 07/10] Add `libxml2` to `apt-get` prelude in tests (required by `wasm-ld`) --- tests/scripts/debian_test.sh | 2 +- tests/scripts/linux_sysroot_test.sh | 2 +- tests/scripts/run_docker_exec_test.sh | 2 +- tests/scripts/ubuntu_20_04_test.sh | 2 +- tests/scripts/ubuntu_22_04_test.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/scripts/debian_test.sh b/tests/scripts/debian_test.sh index 3391bfc20..02806cd32 100755 --- a/tests/scripts/debian_test.sh +++ b/tests/scripts/debian_test.sh @@ -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 diff --git a/tests/scripts/linux_sysroot_test.sh b/tests/scripts/linux_sysroot_test.sh index 238e45a84..a2935c245 100755 --- a/tests/scripts/linux_sysroot_test.sh +++ b/tests/scripts/linux_sysroot_test.sh @@ -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 diff --git a/tests/scripts/run_docker_exec_test.sh b/tests/scripts/run_docker_exec_test.sh index eeaaa32a5..fe582aadd 100755 --- a/tests/scripts/run_docker_exec_test.sh +++ b/tests/scripts/run_docker_exec_test.sh @@ -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=( diff --git a/tests/scripts/ubuntu_20_04_test.sh b/tests/scripts/ubuntu_20_04_test.sh index f43ed8c5a..3a0997b8f 100755 --- a/tests/scripts/ubuntu_20_04_test.sh +++ b/tests/scripts/ubuntu_20_04_test.sh @@ -30,7 +30,7 @@ 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 diff --git a/tests/scripts/ubuntu_22_04_test.sh b/tests/scripts/ubuntu_22_04_test.sh index 95c6105a5..f5341fd8e 100755 --- a/tests/scripts/ubuntu_22_04_test.sh +++ b/tests/scripts/ubuntu_22_04_test.sh @@ -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 From a633424ab19e9ef243d11da51395c4bb3f8bc27b Mon Sep 17 00:00:00 2001 From: John Millikin Date: Fri, 18 Oct 2024 13:42:58 +0900 Subject: [PATCH 08/10] Redefine `test_args` without `--linkopt=-Wl,-v`, which breaks `wasm-ld` --- tests/scripts/run_tests.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh index a17b62a12..6043ce5be 100755 --- a/tests/scripts/run_tests.sh +++ b/tests/scripts/run_tests.sh @@ -69,6 +69,13 @@ fi # # Mitigate this by expunging the workspace before trying to build Wasm targets. if [[ -z ${toolchain_name} ]]; 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" ) From 513876deca1465510b20783188c22b558a435a71 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Fri, 18 Oct 2024 16:20:45 +0900 Subject: [PATCH 09/10] buildifier --- tests/WORKSPACE | 15 +++++++++------ toolchain/internal/llvm_distributions.bzl | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/WORKSPACE b/tests/WORKSPACE index f1e9aa2b4..d2139a909 100644 --- a/tests/WORKSPACE +++ b/tests/WORKSPACE @@ -159,22 +159,22 @@ llvm_toolchain( # 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", }, - sysroot = { - "wasm32": "@wasi_sdk_sysroots//wasm32-wasip2", - "wasm64": "@wasi_sdk_sysroots//empty", - }, stdlib = { "wasm32": "libc", "wasm64": "none", }, - libclang_rt = { - "@libclang_rt_wasm32//:libclang_rt.builtins-wasm32.a": "wasm32-unknown-unknown/libclang_rt.builtins.a", + sysroot = { + "wasm32": "@wasi_sdk_sysroots//wasm32-wasip2", + "wasm64": "@wasi_sdk_sysroots//empty", }, ) @@ -182,10 +182,13 @@ 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. diff --git a/toolchain/internal/llvm_distributions.bzl b/toolchain/internal/llvm_distributions.bzl index db0dc2f35..73dc56d1b 100644 --- a/toolchain/internal/llvm_distributions.bzl +++ b/toolchain/internal/llvm_distributions.bzl @@ -629,7 +629,7 @@ def download_llvm(rctx): libclang_rt_content = rctx.read(libclang_rt) for clang_version in clang_versions: lib_path = clang_version.get_child("lib", lib_name) - rctx.file(lib_path, libclang_rt_content, legacy_utf8=False) + rctx.file(lib_path, libclang_rt_content, legacy_utf8 = False) updated_attrs = _attr_dict(rctx.attr) if update_sha256: From 6e111054dd0f014be7e9e4c03d9f373f31ba9203 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Fri, 18 Oct 2024 16:43:37 +0900 Subject: [PATCH 10/10] Disable WebAssembly tests on Ubuntu 20.04: libc is too old for LLVM 19 --- tests/scripts/run_tests.sh | 8 ++++++-- tests/scripts/ubuntu_20_04_test.sh | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh index 6043ce5be..64652b98b 100755 --- a/tests/scripts/run_tests.sh +++ b/tests/scripts/run_tests.sh @@ -16,8 +16,9 @@ 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") @@ -25,6 +26,9 @@ while getopts "t:h" opt; do 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 @@ -68,7 +72,7 @@ fi # to run out of disk space. # # Mitigate this by expunging the workspace before trying to build Wasm targets. -if [[ -z ${toolchain_name} ]]; then +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 diff --git a/tests/scripts/ubuntu_20_04_test.sh b/tests/scripts/ubuntu_20_04_test.sh index 3a0997b8f..38e6d20ec 100755 --- a/tests/scripts/ubuntu_20_04_test.sh +++ b/tests/scripts/ubuntu_20_04_test.sh @@ -34,8 +34,12 @@ apt-get -qq -y install apt-utils curl libtinfo5 libxml2 pkg-config zlib1g-dev >/ # 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