From 590fbb4bba322cf8f380118803710429021330a8 Mon Sep 17 00:00:00 2001 From: Matt Crane Date: Tue, 2 Apr 2024 18:20:03 -0700 Subject: [PATCH] wip: allow building of wasm targets --- examples/toolchains/rust/BUILD | 10 +- examples/toolchains/rust/WORKSPACE | 17 ++- examples/toolchains/rust/hello.rs | 9 +- nixpkgs/toolchains/rust.bzl | 3 + toolchains/rust/BUILD.bazel | 2 +- toolchains/rust/wasm.bzl | 219 +++++++++++++++++++++++++++++ 6 files changed, 253 insertions(+), 7 deletions(-) create mode 100644 toolchains/rust/wasm.bzl diff --git a/examples/toolchains/rust/BUILD b/examples/toolchains/rust/BUILD index 092e9a2e3..508ab305a 100644 --- a/examples/toolchains/rust/BUILD +++ b/examples/toolchains/rust/BUILD @@ -1,4 +1,5 @@ load("@rules_rust//rust:defs.bzl", "rust_binary") +load("@rules_rust//wasm_bindgen:defs.bzl", "rust_wasm_bindgen") load("@crate_index//:defs.bzl", "all_crate_deps") exports_files([ @@ -10,5 +11,12 @@ exports_files([ rust_binary( name = "hello", srcs = ["hello.rs"], - deps = all_crate_deps(normal = True), + deps = [], # all_crate_deps(normal = True), + edition = "2021", +) + +rust_wasm_bindgen( + name = "wasm", + target = "web", + wasm_file = ":hello", ) diff --git a/examples/toolchains/rust/WORKSPACE b/examples/toolchains/rust/WORKSPACE index fa6e66961..0405afe3b 100644 --- a/examples/toolchains/rust/WORKSPACE +++ b/examples/toolchains/rust/WORKSPACE @@ -43,7 +43,7 @@ nixpkgs_cc_configure( ], ) -load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/rust.bzl", "nixpkgs_rust_configure") +load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/rust.bzl", "nixpkgs_rust_configure", "nixpkgs_rust_wasm_configure") nixpkgs_rust_configure( repository = "@nixpkgs", @@ -53,6 +53,14 @@ nixpkgs_rust_configure( ], ) +nixpkgs_rust_wasm_configure( + repository = "@nixpkgs", + name = "nix_wasm_rust", + nix_file_deps = [ + "//:nixpkgs.json" + ], +) + nixpkgs_package( name = "openssl-static", repository = "@nixpkgs", @@ -66,6 +74,13 @@ load("@rules_rust//rust:repositories.bzl", "rust_repositories") rust_repositories() +load("@rules_rust//wasm_bindgen:repositories.bzl", "rust_wasm_bindgen_dependencies", "rust_wasm_bindgen_register_toolchains") + +rust_wasm_bindgen_dependencies() + +rust_wasm_bindgen_register_toolchains() + + # crate_universe as a way of governing deps load("@rules_rust//crate_universe:repositories.bzl", "crate_universe_dependencies") diff --git a/examples/toolchains/rust/hello.rs b/examples/toolchains/rust/hello.rs index 0219b747f..21afdc37c 100644 --- a/examples/toolchains/rust/hello.rs +++ b/examples/toolchains/rust/hello.rs @@ -1,6 +1,7 @@ fn main() { - println!( - "Hello world from {:?}", - openssl::version::version() - ); + println!( + "Hello world from {:?}", + String::from("wasm??"), + // openssl::version::version() + ); } diff --git a/nixpkgs/toolchains/rust.bzl b/nixpkgs/toolchains/rust.bzl index fe0575720..0913198e1 100644 --- a/nixpkgs/toolchains/rust.bzl +++ b/nixpkgs/toolchains/rust.bzl @@ -1,5 +1,8 @@ # alias to Bazel module `toolchains/go` load("@rules_nixpkgs_rust//:rust.bzl", _nixpkgs_rust_configure = "nixpkgs_rust_configure") +load("@rules_nixpkgs_rust//:wasm.bzl", _nixpkgs_rust_wasm_configure = "nixpkgs_rust_wasm_configure") nixpkgs_rust_configure = _nixpkgs_rust_configure +nixpkgs_rust_wasm_configure = _nixpkgs_rust_wasm_configure + diff --git a/toolchains/rust/BUILD.bazel b/toolchains/rust/BUILD.bazel index c1a13aa3f..0f622453e 100644 --- a/toolchains/rust/BUILD.bazel +++ b/toolchains/rust/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( bzl_library( name = "rust", - srcs = ["//:rust.bzl"], + srcs = ["//:rust.bzl", "//:wasm.bzl"], deps = [ "@rules_nixpkgs_core//:nixpkgs", ], diff --git a/toolchains/rust/wasm.bzl b/toolchains/rust/wasm.bzl new file mode 100644 index 000000000..d4864d916 --- /dev/null +++ b/toolchains/rust/wasm.bzl @@ -0,0 +1,219 @@ +""" + +Rules for importing a Rust toolchain from Nixpkgs. + +# Rules + +* [nixpkgs_rust_wasm_configure](#nixpkgs_rust_configure) +""" + +load("@rules_nixpkgs_core//:nixpkgs.bzl", "nixpkgs_package") +load("@rules_nixpkgs_core//:util.bzl", "ensure_constraints") + +# Adapted from rules_rust toolchain BUILD: +# https://github.com/bazelbuild/rules_rust/blob/fd436df9e2d4ac1b234ca5e969e34a4cb5891910/rust/private/repository_utils.bzl#L17-L46 +# Nix generation is used to dynamically compute both Linux and Darwin environments +_rust_nix_contents = """\ +let + pkgs = import {{ + config = {{}}; + overrides = []; + }}; + rust = pkgs.rust; + os = rust.toTargetOs pkgs.stdenv.targetPlatform; + build-triple = rust.toRustTargetSpec pkgs.stdenv.buildPlatform; + target-triple = rust.toRustTargetSpec pkgs.stdenv.targetPlatform; + rustc-wasm32 = if os == "macos" then + # rustc on MacOS expects the `strip` binary in PATH, create a wrapper adding the bin + # folder from `binutils` to the PATH + pkgs.symlinkJoin + {{ + name = "rustc-wasm32"; + paths = [ pkgs.rustc-wasm32 ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/rustc --suffix PATH : ${{pkgs.binutils}}/bin + ''; + }} + else pkgs.rustc-wasm32; + rustdoc = pkgs.stdenv.mkDerivation {{ + name = "rustdoc"; + src = pkgs.rustc; + phases = ["unpackPhase"]; + unpackPhase = '' + mkdir -p $out/bin + cp $src/bin/rustdoc $out/bin/ + ''; + }}; + binary-ext = ""; + staticlib-ext = ".a"; + dylib-ext = if os == "macos" then ".dylib" else ".so"; +in +pkgs.buildEnv {{ + extraOutputsToInstall = ["out" "bin" "lib"]; + name = "bazel-rust-wasm-toolchain"; + paths = [ rustc-wasm32 rustdoc pkgs.rustfmt pkgs.cargo pkgs.clippy ]; + postBuild = '' + cat < $out/BUILD + filegroup( + name = "rustc", + srcs = ["bin/rustc"], + visibility = ["//visibility:public"], + ) + + filegroup( + name = "rustfmt", + srcs = ["bin/rustfmt"], + visibility = ["//visibility:public"], + ) + + filegroup( + name = "cargo", + srcs = ["bin/cargo"], + visibility = ["//visibility:public"], + ) + + filegroup( + name = "clippy_driver", + srcs = ["bin/clippy-driver"], + visibility = ["//visibility:public"], + ) + + filegroup( + name = "rustc_lib", + srcs = glob( + [ + "bin/*.so", + "lib/*.so", + "lib/rustlib/*/codegen-backends/*.so", + "lib/rustlib/*/codegen-backends/*.dylib", + "lib/rustlib/*/bin/rust-lld", + "lib/rustlib/*/lib/*.so", + "lib/rustlib/*/lib/*.dylib", + ], + allow_empty = True, + ), + visibility = ["//visibility:public"], + ) + + load("@rules_rust//rust:toolchain.bzl", "rust_stdlib_filegroup") + rust_stdlib_filegroup( + name = "rust_std", + srcs = glob( + [ + "lib/rustlib/*/lib/*.rlib", + "lib/rustlib/*/lib/*.so", + "lib/rustlib/*/lib/*.dylib", + "lib/rustlib/*/lib/*.a", + "lib/rustlib/*/lib/self-contained/**", + ], + # Some patterns (e.g. `lib/*.a`) don't match anything, see https://github.com/bazelbuild/rules_rust/pull/245 + allow_empty = True, + ), + visibility = ["//visibility:public"], + ) + + filegroup( + name = "rust_doc", + srcs = ["bin/rustdoc"], + visibility = ["//visibility:public"], + ) + + load('@rules_rust//rust:toolchain.bzl', 'rust_toolchain') + rust_toolchain( + name = "rust_wasm_nix_impl", + rust_doc = ":rust_doc", + rust_std = ":rust_std", + rustc = ":rustc", + rustfmt = ":rustfmt", + cargo = ":cargo", + clippy_driver = ":clippy_driver", + rustc_lib = ":rustc_lib", + binary_ext = "${{binary-ext}}", + staticlib_ext = "${{staticlib-ext}}", + dylib_ext = "${{dylib-ext}}", + exec_triple = "${{build-triple}}", + default_edition = "{default_edition}", + stdlib_linkflags = {stdlib_linkflags}, + visibility = ["//visibility:public"], + target_triple = "wasm32-unknown-unknown", + ) + + EOF + ''; +}} +""" + +_rust_nix_toolchain = """ +toolchain( + name = "rust_wasm_nix", + toolchain = "@{toolchain_repo}//:rust_wasm_nix_impl", + toolchain_type = "@rules_rust//rust:toolchain", + exec_compatible_with = {exec_constraints}, + target_compatible_with = [ + "@platforms//cpu:wasm32", + "@platforms//os:none", + ], +) +""" + +def _nixpkgs_rust_toolchain_impl(repository_ctx): + exec_constraints, target_constraints = ensure_constraints(repository_ctx) + repository_ctx.file( + "BUILD.bazel", + executable = False, + content = _rust_nix_toolchain.format( + toolchain_repo = repository_ctx.attr.toolchain_repo, + exec_constraints = exec_constraints, + target_constraints = target_constraints, + ), + ) + +_nixpkgs_rust_toolchain = repository_rule( + _nixpkgs_rust_toolchain_impl, + attrs = { + "toolchain_repo": attr.string(), + "exec_constraints": attr.string_list(), + "target_constraints": attr.string_list(), + }, +) + +def nixpkgs_rust_wasm_configure( + name = "nixpkgs_rust", + default_edition = "2018", + repository = None, + repositories = {}, + nix_file = None, + nix_file_deps = None, + nix_file_content = None, + nixopts = [], + fail_not_supported = True, + quiet = False, + exec_constraints = None, + target_constraints = None, + register = True): + if not nix_file and not nix_file_content: + nix_file_content = _rust_nix_contents.format( + default_edition = default_edition, + stdlib_linkflags = '["-lpthread", "-ldl"]', + ) + + nixpkgs_package( + name = name, + repository = repository, + repositories = repositories, + nix_file = nix_file, + nix_file_deps = nix_file_deps, + nix_file_content = nix_file_content, + nixopts = nixopts, + fail_not_supported = fail_not_supported, + quiet = quiet, + ) + _nixpkgs_rust_toolchain( + name = name + "_toolchain", + toolchain_repo = name, + exec_constraints = exec_constraints, + target_constraints = target_constraints, + ) + if register: + native.register_toolchains("@{}_toolchain//:rust_wasm_nix".format(name))