Merge "Add Rust hello world example" into main
diff --git a/.bazelrc b/.bazelrc
index 28c3ecc..1e5ac16 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -3,10 +3,12 @@
 
 build:fuchsia_x64 --crosstool_top=@fuchsia_clang//:toolchain
 build:fuchsia_x64 --cpu=x86_64
+build:fuchsia_x64 --platforms=@rules_fuchsia//fuchsia/constraints/platforms:fuchsia_x64
 build:fuchsia_x64 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
 build:fuchsia_x64 --copt=--debug --strip=never
 
 build:fuchsia_arm64 --crosstool_top=@fuchsia_clang//:toolchain
 build:fuchsia_arm64 --cpu=aarch64
+build:fuchsia_arm64 --platforms=@rules_fuchsia//fuchsia/constraints/platforms:fuchsia_arm64
 build:fuchsia_arm64 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
 build:fuchsia_arm64 --copt=--debug --strip=never
diff --git a/README.md b/README.md
index 9514185..1cf09db 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
-# Fuchsia samples using the Fuchsia SDK
+# Fuchsia samples using the Fuchsia SDK with Rust
+
+**Note: Rust is not yet supported in the Fuchsia SDK.**
+
+# TODO: Update instructions
 
 This repository contains instructions and source code to build, package and run
 Fuchsia samples using only the Fuchsia SDK.
diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel
index a0412cb..a6287e6 100644
--- a/WORKSPACE.bazel
+++ b/WORKSPACE.bazel
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 
 http_archive(
     name = "bazel_skylib",
@@ -44,3 +45,48 @@
 fuchsia_clang_repository(
     name = "fuchsia_clang",
 )
+
+load("@fuchsia_clang//:defs.bzl", "register_clang_toolchains")
+
+register_clang_toolchains()
+
+http_archive(
+    name = "rules_rust",
+    sha256 = "0cc7e6b39e492710b819e00d48f2210ae626b717a3ab96e048c43ab57e61d204",
+    urls = [
+        "https://github.com/bazelbuild/rules_rust/releases/download/0.10.0/rules_rust-v0.10.0.tar.gz",
+    ],
+)
+
+load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies")
+
+rules_rust_dependencies()
+
+# With luck, we can start using the upstream nightly very soon.
+http_archive(
+    name = "fuchsia_rust",
+    sha256 = "b59128b0bc586fc86a23512ad91ca9476e721ce0ad226022d7ed51a07fc2c2c7",
+    urls = [
+        "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/rust/linux-amd64/+/git_revision:569788e47ee3595c9c6f0e332844d982b3e991c2",
+    ],
+    type = "zip",
+    build_file_content = """
+load("@rules_rust//rust:toolchain.bzl", "rust_stdlib_filegroup")
+
+rust_stdlib_filegroup(
+    name = "rust_std",
+    srcs = glob(["**/*.rlib"]),
+    visibility = ["//visibility:public"],
+)
+
+exports_files([
+    "bin/rustc",
+    "bin/rustdoc",
+])
+    """
+)
+
+register_toolchains(
+    "//tools:rust_linux",
+    "//tools:rust_fuchsia",
+)
diff --git a/scripts/smoke_test.sh b/scripts/smoke_test.sh
index 06bb583..2c6577f 100755
--- a/scripts/smoke_test.sh
+++ b/scripts/smoke_test.sh
@@ -99,9 +99,12 @@
   # register the package repository with on-demand prebuilt packages
   print_and_run tools/ffx target repository register -r $repo_name --alias fuchsia.com
 
+  # build rust target
+  print_and_run tools/bazel build "src/hello_rust"
+
   # run tests on the emulator
-  print_and_run tools/bazel test "src/hello_world:test_pkg"
-  print_and_run tools/bazel test "src/echo:test_pkg"
+  # print_and_run tools/bazel test "src/hello_world:test_pkg"
+  # print_and_run tools/bazel test "src/echo:test_pkg"
 
   # TODO(fxbug.dev/103976): uncomment after bug is fixed
   # print_and_run tools/bazel test "src/routing:test_pkg"
diff --git a/src/hello_rust/BUILD.bazel b/src/hello_rust/BUILD.bazel
new file mode 100644
index 0000000..23ace21
--- /dev/null
+++ b/src/hello_rust/BUILD.bazel
@@ -0,0 +1,32 @@
+load("@rules_fuchsia//fuchsia:defs.bzl", "if_fuchsia")
+load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_doc")
+
+rust_binary(
+    name = "hello_rust",
+    srcs = ["src/main.rs"],
+    edition = "2021",
+
+    # Unfortunately, there doesn't seem to be a way of configuring these in
+    # rust_toolchain.
+    #
+    # The Rust rules always use the C++ linker (clang++) which knows how to find
+    # libc and libzircon, so we only have to specify the remaining libstd dep
+    # here.
+    #
+    # We could use the newly-merged experimental_use_cc_common_link and then
+    # supply stdlib_linkflags (which only works with cc link actions), but
+    # that's a bit of a hack. It wouldn't solve panic=abort, which is needed by
+    # our toolchain dist but not the upstream one.
+    #
+    # So what we probably need is our own macro to wrap this, or to modify
+    # rules_rust somehow.
+    deps = if_fuchsia(["@fuchsia_sdk//pkg/fdio"]),
+    rustc_flags = [
+        "-Cpanic=abort",
+    ],
+)
+
+rust_doc(
+    name = "hello_rust_doc",
+    crate = ":hello_rust",
+)
diff --git a/src/hello_rust/src/main.rs b/src/hello_rust/src/main.rs
new file mode 100644
index 0000000..7066e6c
--- /dev/null
+++ b/src/hello_rust/src/main.rs
@@ -0,0 +1,7 @@
+pub fn say_hello() {
+    println!("Hello, Rust!")
+}
+
+fn main() {
+    say_hello()
+}
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
new file mode 100644
index 0000000..ab4627f
--- /dev/null
+++ b/tools/BUILD.bazel
@@ -0,0 +1,55 @@
+load("@rules_rust//rust:toolchain.bzl", "rust_toolchain")
+
+rust_toolchain(
+    name = "rust_linux_toolchain",
+    rustc = "@fuchsia_rust//:bin/rustc",
+    rust_std = "@fuchsia_rust//:rust_std",
+    rust_doc = "@fuchsia_rust//:bin/rustdoc",
+    binary_ext = "",
+    staticlib_ext = ".a",
+    dylib_ext = ".so",
+    stdlib_linkflags = ["-lpthread", "-ldl"],
+    os = "linux",
+    exec_triple = "x86_64-unknown-linux-gnu",
+    target_triple = "x86_64-unknown-linux-gnu",
+)
+
+toolchain(
+    name = "rust_linux",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:linux",
+    ],
+    toolchain = ":rust_linux_toolchain",
+    toolchain_type = "@rules_rust//rust:toolchain",
+)
+
+rust_toolchain(
+    name = "rust_fuchsia_toolchain",
+    rustc = "@fuchsia_rust//:bin/rustc",
+    rust_std = "@fuchsia_rust//:rust_std",
+    rust_doc = "@fuchsia_rust//:bin/rustdoc",
+    binary_ext = "",
+    staticlib_ext = ".a",
+    dylib_ext = ".so",
+    stdlib_linkflags = [],
+    os = "fuchsia",
+    exec_triple = "x86_64-unknown-fuchsia",
+    target_triple = "x86_64-fuchsia",
+)
+
+toolchain(
+    name = "rust_fuchsia",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@rules_fuchsia//fuchsia/constraints/os:fuchsia",
+    ],
+    toolchain = ":rust_fuchsia_toolchain",
+    toolchain_type = "@rules_rust//rust:toolchain",
+)