Add Bazel build files for cc_bindings_from_rs

PiperOrigin-RevId: 477163499
diff --git a/cc_bindings_from_rs/BUILD b/cc_bindings_from_rs/BUILD
new file mode 100644
index 0000000..adfb665
--- /dev/null
+++ b/cc_bindings_from_rs/BUILD
@@ -0,0 +1,86 @@
+"""Generates C++ bindings from Rust APIs."""
+
+load(
+    "@rules_rust//rust:defs.bzl",
+    "rust_binary",
+    "rust_test",
+)
+
+licenses(["notice"])
+
+# The current Rust toolchain uses shared libraries for rustc_driver and friends, and we don't have
+# easily usable support for setting up the environment for shared libraries in Bazel. Either:
+# * use `:cc_bindings_from_rs_legacy_toolchain_runner`
+# * use the new toolchain by passing
+#   `--extra_toolchains=//nowhere/llvm/rust:rust_x86_64` to Bazel.
+# TODO(hlopko): Remove legacy_toolchain support scripts once we roll out the bazel-built toolchain.
+rust_binary(
+    name = "cc_bindings_from_rs",
+    srcs = [
+        "cc_bindings_from_rs.rs",
+        "cmdline.rs",
+        "lib.rs",
+    ],
+    crate_root = "cc_bindings_from_rs.rs",
+    # TODO(b/242703401): Remove once cc_common.link works for rustc libraries.
+    experimental_use_cc_common_link = 0,
+    # TODO(hlopko): Remove once we roll out the bazel-built toolchain.
+    tags = [
+        "manual",
+        "nobuilder",
+        "notap",
+    ],
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//common:rust_allocator_shims",
+        "//common:token_stream_printer",
+        "@crate_index//:anyhow",
+        "@crate_index//:getopts",
+        "@crate_index//:itertools",
+        "@crate_index//:proc-macro2",
+        "@crate_index//:quote",
+        "@crate_index//:tracing",
+    ],
+)
+
+sh_binary(
+    name = "cc_bindings_from_rs_legacy_toolchain_runner",
+    srcs = ["cc_bindings_from_rs_legacy_toolchain_runner.sh"],
+    data = [
+        ":cc_bindings_from_rs",
+        "//third_party/unsupported_toolchains/rust/toolchains/nightly:rustc_driver_libs",
+        "//third_party/unsupported_toolchains/rust/toolchains/nightly:stdlibs_generated",
+    ],
+    deps = ["//util/shell/gbash"],
+)
+
+rust_test(
+    name = "cc_bindings_from_rs_test",
+    crate = ":cc_bindings_from_rs",
+    data = [
+        "//nowhere/llvm/rust:std_libs",
+    ],
+    # TODO(b/242703401): Remove once cc_common.link works for rustc libraries.
+    experimental_use_cc_common_link = 0,
+    # TODO(hlopko): Remove once we roll out the bazel-built toolchain.
+    tags = [
+        "manual",
+        "nobuilder",
+        "notap",
+    ],
+    deps = [
+        "@crate_index//:tempfile",
+        "@rules_rust//tools/runfiles",
+    ],
+)
+
+sh_test(
+    name = "cc_bindings_from_rs_legacy_toolchain_test",
+    srcs = ["legacy_toolchain_test_wrapper.sh"],
+    data = [
+        ":cc_bindings_from_rs_test",
+        "//third_party/unsupported_toolchains/rust/toolchains/nightly:rustc_driver_libs",
+        "//third_party/unsupported_toolchains/rust/toolchains/nightly:stdlibs_generated",
+    ],
+    env = {"LEGACY_TOOLCHAIN_RUST_TEST": "cc_bindings_from_rs_test"},
+)
diff --git a/cc_bindings_from_rs/Cargo.toml b/cc_bindings_from_rs/Cargo.toml
deleted file mode 100644
index ac7abe5..0000000
--- a/cc_bindings_from_rs/Cargo.toml
+++ /dev/null
@@ -1,28 +0,0 @@
-# Part of the Crubit project, under the Apache License v2.0 with LLVM
-# Exceptions. See /LICENSE for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-# TODO(lukasza): Switch to Bazel.  (Having `cargo` support in the long-term
-# would be nice, but in the short-term we expect to use only Bazel during
-# development.  Therefore any `cargo` support would probably rot and get stale
-# quickly.)
-
-[package]
-name = "cc_bindings_from_rs"
-version = "0.1.0"
-edition = "2021"
-
-[[bin]]
-name = "cc_bindings_from_rs"
-path = "main.rs"
-
-[dependencies]
-anyhow = "1.0.65"
-getopts = "0.2"
-itertools = "0.10.4"
-lazy_static = "1.4.0"
-proc-macro2 = "1.0.43"
-quote = "1.0.21"
-
-[dev-dependencies]
-tempfile = "3.3.0"
diff --git a/cc_bindings_from_rs/README.md b/cc_bindings_from_rs/README.md
index b76b324..0a24446 100644
--- a/cc_bindings_from_rs/README.md
+++ b/cc_bindings_from_rs/README.md
@@ -11,22 +11,22 @@
 Example:
 
 ```
-# Set CARGO_TARGET_DIR to avoid generating build artifacts inside of the source
-# tree (i.e. generate them elsewhere - where `hg status` cannot see them).
-$ export CARGO_TARGET_DIR=$HOME/scratch/cargo-target
 
-$ cat $HOME/scratch/test.rs
+$ cat scratch/test.rs
 pub fn public_function() {
     private_function()
 }
 
 fn private_function() {}
 
-$ cargo run -- \
-    --h_out=$HOME/scratch/test.h -- \
-    $HOME/scratch/test.rs --crate-type=lib --sysroot `rustc --print sysroot`
+$ bazel run \
+    //cc_bindings_from_rs:cc_bindings_from_rs_legacy_toolchain_runner -- \
+    --h_out=$(pwd)/test.h -- \
+    $(pwd)/test.rs \
+    --crate-type=lib \
+    --sysroot $(pwd)/third_party/unsupported_toolchains/rust/toolchains/nightly
 
-$ cat $HOME/scratch/test.h
+$ cat bazel-out/scratch/test.h
 // Automatically @generated C++ bindings for the following Rust crate:
 // test
 
@@ -34,7 +34,6 @@
 // public_function
 ```
 
-
 ## Contributing
 
 See
diff --git a/cc_bindings_from_rs/main.rs b/cc_bindings_from_rs/cc_bindings_from_rs.rs
similarity index 96%
rename from cc_bindings_from_rs/main.rs
rename to cc_bindings_from_rs/cc_bindings_from_rs.rs
index 98a4db9..24a9f58 100644
--- a/cc_bindings_from_rs/main.rs
+++ b/cc_bindings_from_rs/cc_bindings_from_rs.rs
@@ -5,8 +5,6 @@
 #![feature(rustc_private)]
 #![deny(rustc::internal)]
 
-// TODO(lukasza): Remove the `extern crate` declarations - they shouldn't be
-// needed once we switch to Bazel.
 extern crate rustc_driver;
 extern crate rustc_error_codes;
 extern crate rustc_errors;
@@ -20,8 +18,6 @@
 // Bazel).
 mod cmdline;
 mod lib;
-#[path = "../common/token_stream_printer.rs"]
-mod token_stream_printer;
 
 use cmdline::Cmdline;
 use itertools::Itertools;
@@ -34,7 +30,7 @@
 
     use crate::cmdline::Cmdline;
     use crate::lib::GeneratedBindings;
-    use crate::token_stream_printer::tokens_to_string;
+    use token_stream_printer::tokens_to_string;
 
     pub fn main(cmdline: &Cmdline, tcx: TyCtxt) -> anyhow::Result<()> {
         let bindings = GeneratedBindings::generate(tcx);
diff --git a/cc_bindings_from_rs/cc_bindings_from_rs_legacy_toolchain_runner.sh b/cc_bindings_from_rs/cc_bindings_from_rs_legacy_toolchain_runner.sh
new file mode 100755
index 0000000..2d10712
--- /dev/null
+++ b/cc_bindings_from_rs/cc_bindings_from_rs_legacy_toolchain_runner.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Part of the Crubit project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+source gbash.sh || exit
+
+set -euo pipefail
+
+RUST_LIBRARIES="${RUNFILES}/google3/third_party/unsupported_toolchains/rust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib"
+export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}${RUST_LIBRARIES}"
+
+exec "${RUNFILES}/cc_bindings_from_rs/cc_bindings_from_rs" "${@}"
\ No newline at end of file
diff --git a/cc_bindings_from_rs/legacy_toolchain_test_wrapper.sh b/cc_bindings_from_rs/legacy_toolchain_test_wrapper.sh
new file mode 100755
index 0000000..26898c7
--- /dev/null
+++ b/cc_bindings_from_rs/legacy_toolchain_test_wrapper.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Part of the Crubit project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+set -euo pipefail
+
+RUST_LIBRARIES="${TEST_SRCDIR}/google3/third_party/unsupported_toolchains/rust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib"
+export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}${RUST_LIBRARIES}"
+
+TEST_BINARY_PATH="$(find "${TEST_SRCDIR}/cc_bindings_from_rs/" -name "${LEGACY_TOOLCHAIN_RUST_TEST}")"
+exec "${TEST_BINARY_PATH}" "${@}"
\ No newline at end of file
diff --git a/cc_bindings_from_rs/lib.rs b/cc_bindings_from_rs/lib.rs
index 68540e0..9d3cb2e 100644
--- a/cc_bindings_from_rs/lib.rs
+++ b/cc_bindings_from_rs/lib.rs
@@ -80,7 +80,7 @@
     use anyhow::Result;
     use itertools::Itertools;
 
-    use crate::token_stream_printer::tokens_to_string;
+    use token_stream_printer::tokens_to_string;
 
     #[test]
     fn test_get_names_of_exported_fns_public_vs_private() {
@@ -146,24 +146,7 @@
         F: for<'tcx> FnOnce(rustc_middle::ty::TyCtxt<'tcx>) -> T + Send,
         T: Send,
     {
-        use lazy_static::lazy_static;
         use rustc_session::config::{CrateType, Input, Options, OutputType, OutputTypes};
-        use std::path::PathBuf;
-
-        // TODO(lukasza): This probably won't work in Bazel...
-        lazy_static! {
-            static ref RUSTC_SYSROOT: String = {
-                let output = std::process::Command::new("rustc")
-                    .arg("--print=sysroot")
-                    .current_dir(".")
-                    .output()
-                    .expect("For now we depend on `rustc` invocation to succeed... sorry...");
-                std::str::from_utf8(&output.stdout)
-                    .expect("Only UTF-8 compatible rustc sysroot is supported... sorry...")
-                    .trim()
-                    .into()
-            };
-        }
 
         const TEST_FILENAME: &str = "crubit_unittests.rs";
 
@@ -173,9 +156,16 @@
         // `Mir`, etc. would also trigger code gen).
         let output_types = OutputTypes::new(&[(OutputType::Bitcode, None /* PathBuf */)]);
 
+        let runfiles = runfiles::Runfiles::create().unwrap();
+        let sysroot_path =
+            runfiles.rlocation(if std::env::var("LEGACY_TOOLCHAIN_RUST_TEST").is_ok() {
+                "google3/third_party/unsupported_toolchains/rust/toolchains/nightly"
+            } else {
+                "google3/nowhere/llvm/rust"
+            });
         let opts = Options {
             crate_types: vec![CrateType::Rlib], // Test inputs simulate library crates.
-            maybe_sysroot: Some(PathBuf::from(RUSTC_SYSROOT.clone())),
+            maybe_sysroot: Some(sysroot_path),
             output_types,
             ..Default::default()
         };