Improve Rust build infrastructure

Further usage of this (coming in future changes) revealed some issues.

Change-Id: Ib60968c580db4e7bb4bd60c782ce7f93a7fc594d
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/WORKSPACE b/WORKSPACE
index e33527c..6afd00c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -297,7 +297,9 @@
     "//tools/rust:rust-toolchain-x86",
     "//tools/rust:rust-toolchain-armv7",
     "//tools/rust:rust-toolchain-arm64",
-    "//tools/rust:rust-toolchain-roborio",
+    # TODO(Brian): Make this work. See the comment on
+    # //tools/platforms:linux_roborio for details.
+    #"//tools/rust:rust-toolchain-roborio",
     "//tools/rust:noop_rust_toolchain",
     "//tools/ts:noop_node_toolchain",
 )
@@ -849,9 +851,9 @@
         "armv7-unknown-linux-gnueabihf",
         "aarch64-unknown-linux-gnu",
     ],
-    rustfmt_version = "1.58.1",
+    rustfmt_version = "1.62.0",
     toolchain_name_prefix = "toolchain_for",
-    version = "1.58.1",
+    version = "1.62.0",
 )
 
 load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
diff --git a/build_tests/BUILD b/build_tests/BUILD
index 24fdad8..dc76f45 100644
--- a/build_tests/BUILD
+++ b/build_tests/BUILD
@@ -141,19 +141,19 @@
 rust_library(
     name = "hello_lib",
     srcs = ["hello_lib.rs"],
-    target_compatible_with = ["@platforms//os:linux"],
+    target_compatible_with = ["//tools/platforms/rust:has_support"],
 )
 
 rust_test(
     name = "hello_lib_test",
     crate = ":hello_lib",
-    target_compatible_with = ["@platforms//os:linux"],
+    target_compatible_with = ["//tools/platforms/rust:has_support"],
 )
 
 rust_binary(
     name = "rust_hello",
     srcs = ["rust_hello.rs"],
-    target_compatible_with = ["@platforms//os:linux"],
+    target_compatible_with = ["//tools/platforms/rust:has_support"],
     deps = [":hello_lib"],
 )
 
@@ -182,7 +182,7 @@
 rust_library(
     name = "rust_in_cc_rs",
     srcs = ["rust_in_cc.rs"],
-    target_compatible_with = ["@platforms//os:linux"],
+    target_compatible_with = ["//tools/platforms/rust:has_support"],
 )
 
 cc_test(
diff --git a/third_party/cargo/cxx/include.BUILD.bazel b/third_party/cargo/cxx/include.BUILD.bazel
index f6b9f5a..31afbfb 100644
--- a/third_party/cargo/cxx/include.BUILD.bazel
+++ b/third_party/cargo/cxx/include.BUILD.bazel
@@ -6,4 +6,5 @@
     hdrs = ["include/cxx.h"],
     srcs = ["src/cxx.cc"],
     includes = ["include"],
+    target_compatible_with = ["@//tools/platforms/rust:has_support"],
 )
diff --git a/third_party/cargo/remote/BUILD.cxx-1.0.71.bazel b/third_party/cargo/remote/BUILD.cxx-1.0.71.bazel
index 4158d4d..1ede3fc 100644
--- a/third_party/cargo/remote/BUILD.cxx-1.0.71.bazel
+++ b/third_party/cargo/remote/BUILD.cxx-1.0.71.bazel
@@ -81,4 +81,5 @@
     hdrs = ["include/cxx.h"],
     srcs = ["src/cxx.cc"],
     includes = ["include"],
+    target_compatible_with = ["@//tools/platforms/rust:has_support"],
 )
diff --git a/third_party/cargo_raze/cargo_raze.patch b/third_party/cargo_raze/cargo_raze.patch
index 306fcf3..f4cd02a 100644
--- a/third_party/cargo_raze/cargo_raze.patch
+++ b/third_party/cargo_raze/cargo_raze.patch
@@ -95,12 +95,13 @@
 
 --- third_party/libssh2/BUILD.libssh2.bazel	2022-02-04 00:03:43.831120614 -0800
 +++ third_party/libssh2/BUILD.libssh2.bazel	2022-02-04 00:04:19.100745883 -0800
-@@ -29,6 +29,14 @@ cmake(
+@@ -29,6 +29,15 @@ cmake(
          "@rules_rust//rust/platform:windows": ["ssh2.lib"],
          "//conditions:default": ["libssh2.a"],
      }),
 +    copts = [
 +        "-Wno-cast-qual",
++        # See https://github.com/openbsd/src/commit/04a2240bd8f465bcae6b595d912af3e2965856de, it's a false positive.
 +        "-Wno-sizeof-array-div",
 +        "-Wno-unused-parameter",
 +        "-DHAVE_SNPRINTF=1",
@@ -162,6 +163,15 @@
 
 --- third_party/cargo/remote/BUILD.libssh2-sys-0.2.21.bazel	2022-02-04 00:54:43.031966734 -0800
 +++ third_party/cargo/remote/BUILD.libssh2-sys-0.2.21.bazel	2022-02-04 00:54:44.272023742 -0800
+@@ -41,6 +41,8 @@ cargo_build_script(
+     name = "libssh2_sys_build_script",
+     srcs = glob(["**/*.rs"]),
+     build_script_env = {
++        # See https://github.com/openbsd/src/commit/04a2240bd8f465bcae6b595d912af3e2965856de, it's a false positive.
++        "CFLAGS": "-Wno-sizeof-array-div",
+     },
+     crate_features = [
+     ],
 @@ -48,6 +48,7 @@ cargo_build_script(
      data = glob(["**"]) + [
          "@cargo_raze__libssh2//:libssh2",
diff --git a/tools/platforms/BUILD b/tools/platforms/BUILD
index 37fed2e..1d79f06 100644
--- a/tools/platforms/BUILD
+++ b/tools/platforms/BUILD
@@ -42,7 +42,12 @@
         "@platforms//cpu:armv7",
         "//tools/platforms/hardware:roborio",
         "//tools/platforms/go:lacks_support",
-        "//tools/platforms/rust:has_support",
+        # TODO(Brian): This almost works, but cxx assumes llvm-ld's linking
+        # behavior and doesn't have an easy way to support GNU ld. See
+        # https://github.com/dtolnay/cxx/pull/1069 for a bit more explanation.
+        # Bazel needs to group multiple things into a single cc_library to
+        # handle that, need to figure out how to do that here or switch linkers.
+        "//tools/platforms/rust:lacks_support",
         "//tools/platforms/nodejs:lacks_support",
     ],
 )
diff --git a/tools/rust/BUILD b/tools/rust/BUILD
index 74ed92d..a5a2f89 100644
--- a/tools/rust/BUILD
+++ b/tools/rust/BUILD
@@ -98,7 +98,7 @@
     exec_triple = "none",
     os = "none",
     rust_doc = ":noop_error_exit",
-    rust_lib = ":empty_stdlib",
+    rust_std = ":empty_stdlib",
     rustc = ":noop_error_exit",
     rustc_lib = ":noop_error_exit",
     rustc_srcs = None,
@@ -124,7 +124,7 @@
 rust_binary(
     name = "tweak_cargo_raze_output",
     srcs = ["tweak_cargo_raze_output.rs"],
-    target_compatible_with = ["@platforms//os:linux"],
+    target_compatible_with = ["//tools/platforms/rust:has_support"],
     visibility = ["//visibility:public"],
     deps = [
         "//third_party/cargo:anyhow",
diff --git a/tools/rust/forward_allocator.c b/tools/rust/forward_allocator.c
index 3e6ba96..a321af3 100644
--- a/tools/rust/forward_allocator.c
+++ b/tools/rust/forward_allocator.c
@@ -2,7 +2,8 @@
 
 // This file has some exciting magic to get Rust code linking in a cc_binary.
 // The Rust compiler generates some similar symbol aliases when it links, so we
-// have to do it manually.
+// have to do it manually. We mark all our symbols as weak so that linking this
+// via Rust tooling to produce a binary with a Rust main works.
 //
 // It is intended to be used in rust_toolchain.allocator_library.
 //
@@ -20,27 +21,32 @@
 // not work with any other allocated switched in via `#[global_allocator]`.
 
 // New feature as of https://github.com/rust-lang/rust/pull/88098.
-uint8_t __rust_alloc_error_handler_should_panic = 0;
+__attribute__((weak)) uint8_t __rust_alloc_error_handler_should_panic = 0;
 
 uint8_t *__rdl_alloc(uintptr_t size, uintptr_t align);
+__attribute__((weak))
 uint8_t *__rust_alloc(uintptr_t size, uintptr_t align) {
   return __rdl_alloc(size, align);
 }
 void __rdl_dealloc(uint8_t *ptr, uintptr_t size, uintptr_t align);
+__attribute__((weak))
 void __rust_dealloc(uint8_t *ptr, uintptr_t size, uintptr_t align) {
   __rdl_dealloc(ptr, size, align);
 }
 uint8_t *__rdl_realloc(uint8_t *ptr, uintptr_t old_size, uintptr_t align,
                        uintptr_t new_size);
+__attribute__((weak))
 uint8_t *__rust_realloc(uint8_t *ptr, uintptr_t old_size, uintptr_t align,
                         uintptr_t new_size) {
   return __rdl_realloc(ptr, old_size, align, new_size);
 }
 uint8_t *__rdl_alloc_zeroed(uintptr_t size, uintptr_t align);
+__attribute__((weak))
 uint8_t *__rust_alloc_zeroed(uintptr_t size, uintptr_t align) {
   return __rdl_alloc_zeroed(size, align);
 }
 void __rdl_oom(uintptr_t size, uintptr_t align);
+__attribute__((weak))
 void __rust_alloc_error_handler(uintptr_t size, uintptr_t align) {
   __rdl_oom(size, align);
 }