Support custom path to crubit/rs_bindings_from_cc/support directory.

The generated thunks and other code in ..._rs_api_impl.cc might depend
on Crubit's support headers like so:

    #include "third_party/crubit/rs_bindings_from_cc/support/..."

Before this CL, `src_code_gen.rs` would hardcode the path to the support
directory.  After this CL, this is replaced with an argument of a new
cmdline parameter: --crubit_support_path.

PiperOrigin-RevId: 447003312
diff --git a/rs_bindings_from_cc/bazel_support/rust_bindings_from_cc_utils.bzl b/rs_bindings_from_cc/bazel_support/rust_bindings_from_cc_utils.bzl
index 37e0d2c..81b49af 100644
--- a/rs_bindings_from_cc/bazel_support/rust_bindings_from_cc_utils.bzl
+++ b/rs_bindings_from_cc/bazel_support/rust_bindings_from_cc_utils.bzl
@@ -219,6 +219,8 @@
                 rs_output.path,
                 "--cc_out",
                 cc_output.path,
+                "--crubit_support_path",
+                "rs_bindings_from_cc/support",
                 "--rustfmt_config_path",
                 "external/rustfmt/rustfmt.toml",
             ] + _get_hdrs_command_line(public_hdrs),
diff --git a/rs_bindings_from_cc/cmdline.cc b/rs_bindings_from_cc/cmdline.cc
index c3c3d23..a9d695e 100644
--- a/rs_bindings_from_cc/cmdline.cc
+++ b/rs_bindings_from_cc/cmdline.cc
@@ -26,6 +26,10 @@
 ABSL_FLAG(std::string, ir_out, "",
           "(optional) output path for the JSON IR. If not present, the JSON IR "
           "will not be dumped.");
+ABSL_FLAG(std::string, crubit_support_path, "",
+          "path to a the crubit/rs_bindings/support directory in a format that "
+          "should be used in the #include directives inside the generated .cc "
+          "files.");
 ABSL_FLAG(std::string, rustfmt_config_path, "",
           "(optional) path to a rustfmt.toml file that should replace the "
           "default formatting of the .rs files generated by the tool.");
@@ -64,15 +68,16 @@
 absl::StatusOr<Cmdline> Cmdline::Create() {
   return CreateFromArgs(
       absl::GetFlag(FLAGS_cc_out), absl::GetFlag(FLAGS_rs_out),
-      absl::GetFlag(FLAGS_ir_out), absl::GetFlag(FLAGS_rustfmt_config_path),
-      absl::GetFlag(FLAGS_do_nothing), absl::GetFlag(FLAGS_public_headers),
+      absl::GetFlag(FLAGS_ir_out), absl::GetFlag(FLAGS_crubit_support_path),
+      absl::GetFlag(FLAGS_rustfmt_config_path), absl::GetFlag(FLAGS_do_nothing),
+      absl::GetFlag(FLAGS_public_headers),
       absl::GetFlag(FLAGS_targets_and_headers));
 }
 
 absl::StatusOr<Cmdline> Cmdline::CreateFromArgs(
     std::string cc_out, std::string rs_out, std::string ir_out,
-    std::string rustfmt_config_path, bool do_nothing,
-    std::vector<std::string> public_headers,
+    std::string crubit_support_path, std::string rustfmt_config_path,
+    bool do_nothing, std::vector<std::string> public_headers,
     std::string targets_and_headers_str) {
   Cmdline cmdline;
 
@@ -87,6 +92,12 @@
   cmdline.cc_out_ = std::move(cc_out);
 
   cmdline.ir_out_ = std::move(ir_out);
+
+  if (crubit_support_path.empty()) {
+    return absl::InvalidArgumentError("please specify --crubit_support_path");
+  }
+  cmdline.crubit_support_path_ = std::move(crubit_support_path);
+
   cmdline.rustfmt_config_path_ = std::move(rustfmt_config_path);
   cmdline.do_nothing_ = do_nothing;
 
diff --git a/rs_bindings_from_cc/cmdline.h b/rs_bindings_from_cc/cmdline.h
index c24c178..6b5dd4b 100644
--- a/rs_bindings_from_cc/cmdline.h
+++ b/rs_bindings_from_cc/cmdline.h
@@ -26,11 +26,12 @@
   // `rs_out`, and so forth.
   static absl::StatusOr<Cmdline> CreateForTesting(
       std::string cc_out, std::string rs_out, std::string ir_out,
-      std::string rustfmt_config_path, bool do_nothing,
-      std::vector<std::string> public_headers,
+      std::string crubit_support_path, std::string rustfmt_config_path,
+      bool do_nothing, std::vector<std::string> public_headers,
       std::string targets_and_headers_str) {
-    return CreateFromArgs(cc_out, rs_out, ir_out, rustfmt_config_path,
-                          do_nothing, public_headers, targets_and_headers_str);
+    return CreateFromArgs(cc_out, rs_out, ir_out, crubit_support_path,
+                          rustfmt_config_path, do_nothing, public_headers,
+                          targets_and_headers_str);
   }
 
   Cmdline(const Cmdline&) = delete;
@@ -41,6 +42,7 @@
   absl::string_view cc_out() const { return cc_out_; }
   absl::string_view rs_out() const { return rs_out_; }
   absl::string_view ir_out() const { return ir_out_; }
+  absl::string_view crubit_support_path() const { return crubit_support_path_; }
   absl::string_view rustfmt_config_path() const { return rustfmt_config_path_; }
   bool do_nothing() const { return do_nothing_; }
 
@@ -60,8 +62,8 @@
 
   static absl::StatusOr<Cmdline> CreateFromArgs(
       std::string cc_out, std::string rs_out, std::string ir_out,
-      std::string rustfmt_config_path, bool do_nothing,
-      std::vector<std::string> public_headers,
+      std::string crubit_support_path, std::string rustfmt_config_path,
+      bool do_nothing, std::vector<std::string> public_headers,
       std::string targets_and_headers_str);
 
   absl::StatusOr<BazelLabel> FindHeader(const HeaderName& header) const;
@@ -69,6 +71,7 @@
   std::string cc_out_;
   std::string rs_out_;
   std::string ir_out_;
+  std::string crubit_support_path_;
   std::string rustfmt_config_path_;
   bool do_nothing_ = true;
 
diff --git a/rs_bindings_from_cc/cmdline_test.cc b/rs_bindings_from_cc/cmdline_test.cc
index a25c1b3..e49d93a 100644
--- a/rs_bindings_from_cc/cmdline_test.cc
+++ b/rs_bindings_from_cc/cmdline_test.cc
@@ -25,22 +25,25 @@
 
 absl::StatusOr<Cmdline> TestCmdline(std::vector<std::string> public_headers,
                                     const std::string& targets_and_headers) {
-  return Cmdline::CreateForTesting(
-      "cc_out", "rs_out", "ir_out", "rustfmt_config_path",
-      /* do_nothing= */ false, public_headers, targets_and_headers);
+  return Cmdline::CreateForTesting("cc_out", "rs_out", "ir_out",
+                                   "crubit_support_path", "rustfmt_config_path",
+                                   /* do_nothing= */ false, public_headers,
+                                   targets_and_headers);
 }
 
 }  // namespace
 
 TEST(CmdlineTest, BasicCorrectInput) {
-  ASSERT_OK_AND_ASSIGN(Cmdline cmdline,
-                       Cmdline::CreateForTesting(
-                           "cc_out", "rs_out", "ir_out", "rustfmt_config_path",
-                           /* do_nothing= */ false, {"h1"},
-                           R"([{"t": "t1", "h": ["h1", "h2"]}])"));
+  ASSERT_OK_AND_ASSIGN(
+      Cmdline cmdline,
+      Cmdline::CreateForTesting("cc_out", "rs_out", "ir_out",
+                                "crubit_support_path", "rustfmt_config_path",
+                                /* do_nothing= */ false, {"h1"},
+                                R"([{"t": "t1", "h": ["h1", "h2"]}])"));
   EXPECT_EQ(cmdline.cc_out(), "cc_out");
   EXPECT_EQ(cmdline.rs_out(), "rs_out");
   EXPECT_EQ(cmdline.ir_out(), "ir_out");
+  EXPECT_EQ(cmdline.crubit_support_path(), "crubit_support_path");
   EXPECT_EQ(cmdline.rustfmt_config_path(), "rustfmt_config_path");
   EXPECT_EQ(cmdline.do_nothing(), false);
   EXPECT_EQ(cmdline.current_target().value(), "t1");
@@ -183,7 +186,8 @@
     {"t": "target1", "h": ["a.h", "b.h"]}
   ])";
   ASSERT_THAT(Cmdline::CreateForTesting(
-                  /* cc_out= */ "", "rs_out", "ir_out", "rustfmt_config_path",
+                  /* cc_out= */ "", "rs_out", "ir_out", "crubit_support_path",
+                  "rustfmt_config_path",
                   /* do_nothing= */ false, {"a.h"}, kTargetsAndHeaders),
               StatusIs(absl::StatusCode::kInvalidArgument,
                        HasSubstr("please specify --cc_out")));
@@ -194,7 +198,8 @@
     {"t": "target1", "h": ["a.h", "b.h"]}
   ])";
   ASSERT_THAT(Cmdline::CreateForTesting(
-                  "cc_out", /* rs_out= */ "", "ir_out", "rustfmt_config_path",
+                  "cc_out", /* rs_out= */ "", "ir_out", "crubit_support_path",
+                  "rustfmt_config_path",
                   /* do_nothing= */ false, {"a.h"}, kTargetsAndHeaders),
               StatusIs(absl::StatusCode::kInvalidArgument,
                        HasSubstr("please specify --rs_out")));
@@ -205,16 +210,30 @@
     {"t": "target1", "h": ["a.h", "b.h"]}
   ])";
   ASSERT_OK(Cmdline::CreateForTesting(
-      "cc_out", "rs_out", /* ir_out= */ "", "rustfmt_config_path",
+      "cc_out", "rs_out", /* ir_out= */ "", "crubit_support_path",
+      "rustfmt_config_path",
       /* do_nothing= */ false, {"a.h"}, kTargetsAndHeaders));
 }
 
+TEST(CmdlineTest, CrubitSupportPathEmpty) {
+  constexpr char kTargetsAndHeaders[] = R"([
+    {"t": "target1", "h": ["a.h", "b.h"]}
+  ])";
+  ASSERT_THAT(Cmdline::CreateForTesting(
+                  "cc_out", "rs_out", "ir_out", /* crubit_support_path= */ "",
+                  "rustfmt_config_path",
+                  /* do_nothing= */ false, {"a.h"}, kTargetsAndHeaders),
+              StatusIs(absl::StatusCode::kInvalidArgument,
+                       HasSubstr("please specify --crubit_support_path")));
+}
+
 TEST(CmdlineTest, RustfmtTomlPathEmpty) {
   constexpr char kTargetsAndHeaders[] = R"([
     {"t": "target1", "h": ["a.h", "b.h"]}
   ])";
   ASSERT_OK(Cmdline::CreateForTesting(
-      "cc_out", "rs_out", "ir_out", /* rustfmt_config_path= */ "",
+      "cc_out", "rs_out", "ir_out", "crubit_support_path",
+      /* rustfmt_config_path= */ "",
       /* do_nothing= */ false, {"a.h"}, kTargetsAndHeaders));
 }
 
diff --git a/rs_bindings_from_cc/rs_bindings_from_cc.cc b/rs_bindings_from_cc/rs_bindings_from_cc.cc
index 81361b1..d540548 100644
--- a/rs_bindings_from_cc/rs_bindings_from_cc.cc
+++ b/rs_bindings_from_cc/rs_bindings_from_cc.cc
@@ -59,8 +59,8 @@
         cmdline.ir_out(), std::string(llvm::formatv("{0:2}", ir.ToJson()))));
   }
 
-  crubit::Bindings bindings =
-      crubit::GenerateBindings(ir, cmdline.rustfmt_config_path());
+  crubit::Bindings bindings = crubit::GenerateBindings(
+      ir, cmdline.crubit_support_path(), cmdline.rustfmt_config_path());
   CRUBIT_RETURN_IF_ERROR(SetFileContents(cmdline.rs_out(), bindings.rs_api));
   CRUBIT_RETURN_IF_ERROR(
       SetFileContents(cmdline.cc_out(), bindings.rs_api_impl));
diff --git a/rs_bindings_from_cc/src_code_gen.cc b/rs_bindings_from_cc/src_code_gen.cc
index 590dad2..40b3078 100644
--- a/rs_bindings_from_cc/src_code_gen.cc
+++ b/rs_bindings_from_cc/src_code_gen.cc
@@ -22,6 +22,7 @@
 
 // This function is implemented in Rust.
 extern "C" FfiBindings GenerateBindingsImpl(FfiU8Slice json,
+                                            FfiU8Slice crubit_support_path,
                                             FfiU8Slice rustfmt_config_path);
 
 // Creates `Bindings` instance from copied data from `ffi_bindings`.
@@ -49,11 +50,13 @@
   FreeFfiU8SliceBox(ffi_bindings.rs_api_impl);
 }
 
-Bindings GenerateBindings(const IR& ir, absl::string_view rustfmt_config_path) {
+Bindings GenerateBindings(const IR& ir, absl::string_view crubit_support_path,
+                          absl::string_view rustfmt_config_path) {
   std::string json = llvm::formatv("{0}", ir.ToJson());
 
   FfiBindings ffi_bindings = GenerateBindingsImpl(
-      MakeFfiU8Slice(json), MakeFfiU8Slice(rustfmt_config_path));
+      MakeFfiU8Slice(json), MakeFfiU8Slice(crubit_support_path),
+      MakeFfiU8Slice(rustfmt_config_path));
   Bindings bindings = MakeBindingsFromFfiBindings(ffi_bindings);
   FreeFfiBindings(ffi_bindings);
   return bindings;
diff --git a/rs_bindings_from_cc/src_code_gen.h b/rs_bindings_from_cc/src_code_gen.h
index 84ea625..fc942c7 100644
--- a/rs_bindings_from_cc/src_code_gen.h
+++ b/rs_bindings_from_cc/src_code_gen.h
@@ -21,7 +21,8 @@
 };
 
 // Generates bindings from the given `IR`.
-Bindings GenerateBindings(const IR& ir, absl::string_view rustfmt_config_path);
+Bindings GenerateBindings(const IR& ir, absl::string_view crubit_support_path,
+                          absl::string_view rustfmt_config_path);
 
 }  // namespace crubit
 
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index 1a002b0..1a7b3d4 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -31,26 +31,31 @@
 /// Expectations:
 ///    * `json` should be a FfiU8Slice for a valid array of bytes with the given
 ///      size.
+///    * `crubit_support_path` should be a FfiU8Slice for a valid array of bytes
+///      representing an UTF8-encoded string
 ///    * `rustfmt_config_path` should be a FfiU8Slice for a valid array of bytes
 ///      representing an UTF8-encoded string (without the UTF-8 requirement, it
 ///      seems that Rust doesn't offer a way to convert to OsString on Windows)
-///    * `json` and `rustfmt_config_path` shouldn't change during the call.
+///    * `json`, `crubit_support_path`, and `rustfmt_config_path` shouldn't
+///      change during the call.
 ///
 /// Ownership:
 ///    * function doesn't take ownership of (in other words it borrows) the
-///      input params: `json`, and `rustfmt_config_path`
+///      input params: `json`, `crubit_support_path`, and `rustfmt_config_path`
 ///    * function passes ownership of the returned value to the caller
 #[no_mangle]
 pub unsafe extern "C" fn GenerateBindingsImpl(
     json: FfiU8Slice,
+    crubit_support_path: FfiU8Slice,
     rustfmt_config_path: FfiU8Slice,
 ) -> FfiBindings {
     let json: &[u8] = json.as_slice();
+    let crubit_support_path: &str = std::str::from_utf8(crubit_support_path.as_slice()).unwrap();
     let rustfmt_config_path: OsString =
         std::str::from_utf8(rustfmt_config_path.as_slice()).unwrap().into();
     catch_unwind(|| {
         // It is ok to abort here.
-        let Bindings { rs_api, rs_api_impl } = generate_bindings(json, &rustfmt_config_path).unwrap();
+        let Bindings { rs_api, rs_api_impl } = generate_bindings(json, crubit_support_path, &rustfmt_config_path).unwrap();
         FfiBindings {
             rs_api: FfiU8SliceBox::from_boxed_slice(rs_api.into_bytes().into_boxed_slice()),
             rs_api_impl: FfiU8SliceBox::from_boxed_slice(
@@ -77,10 +82,15 @@
     rs_api_impl: TokenStream,
 }
 
-fn generate_bindings(json: &[u8], rustfmt_config_path: &OsStr) -> Result<Bindings> {
+fn generate_bindings(
+    json: &[u8],
+    crubit_support_path: &str,
+    rustfmt_config_path: &OsStr,
+) -> Result<Bindings> {
     let ir = deserialize_ir(json)?;
 
-    let BindingsTokens { rs_api, rs_api_impl } = generate_bindings_tokens(&ir)?;
+    let BindingsTokens { rs_api, rs_api_impl } =
+        generate_bindings_tokens(&ir, crubit_support_path)?;
     let rs_api = {
         let rustfmt_config = if rustfmt_config_path.is_empty() {
             RustfmtConfig::default()
@@ -1404,10 +1414,10 @@
 
 // Returns the Rust code implementing bindings, plus any auxiliary C++ code
 // needed to support it.
-fn generate_bindings_tokens(ir: &IR) -> Result<BindingsTokens> {
+fn generate_bindings_tokens(ir: &IR, crubit_support_path: &str) -> Result<BindingsTokens> {
     let mut items = vec![];
     let mut thunks = vec![];
-    let mut thunk_impls = vec![generate_rs_api_impl(ir)?];
+    let mut thunk_impls = vec![generate_rs_api_impl(ir, crubit_support_path)?];
     let mut assertions = vec![];
 
     // We import nullable pointers as an Option<&T> and assume that at the ABI
@@ -2209,7 +2219,7 @@
     format_ident!("__rust_thunk__{}", func.mangled_name)
 }
 
-fn generate_rs_api_impl(ir: &IR) -> Result<TokenStream> {
+fn generate_rs_api_impl(ir: &IR, crubit_support_path: &str) -> Result<TokenStream> {
     // This function uses quote! to generate C++ source code out of convenience.
     // This is a bold idea so we have to continously evaluate if it still makes
     // sense or the cost of working around differences in Rust and C++ tokens is
@@ -2317,14 +2327,14 @@
         standard_headers.insert(format_ident!("cstddef"));
     };
 
-    let mut includes = vec![
-        "rs_bindings_from_cc/support/cxx20_backports.h",
-        "rs_bindings_from_cc/support/offsetof.h",
-    ];
+    let mut includes = vec!["cxx20_backports.h", "offsetof.h"]
+        .into_iter()
+        .map(|hdr| format!("{}/{}", crubit_support_path, hdr))
+        .collect_vec();
 
     // In order to generate C++ thunk in all the cases Clang needs to be able to
     // access declarations from public headers of the C++ library.
-    includes.extend(ir.used_headers().map(|i| &i.name as &str));
+    includes.extend(ir.used_headers().map(|hdr| hdr.name.clone()));
 
     Ok(quote! {
         #( __HASH_TOKEN__ include <#standard_headers> __NEWLINE__)*
@@ -2360,6 +2370,10 @@
     };
     use token_stream_printer::{rs_tokens_to_formatted_string_for_tests, tokens_to_string};
 
+    fn generate_bindings_tokens(ir: &IR) -> Result<BindingsTokens> {
+        super::generate_bindings_tokens(ir, "crubit/rs_bindings_support")
+    }
+
     #[test]
     fn test_disable_thread_safety_warnings() -> Result<()> {
         let ir = ir_from_cc("inline void foo() {}")?;
diff --git a/rs_bindings_from_cc/test/rs_bindings_from_cc_test.sh b/rs_bindings_from_cc/test/rs_bindings_from_cc_test.sh
index c4725b0..a725993 100755
--- a/rs_bindings_from_cc/test/rs_bindings_from_cc_test.sh
+++ b/rs_bindings_from_cc/test/rs_bindings_from_cc_test.sh
@@ -31,6 +31,14 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" 2>&1 | \
+      grep 'please specify --crubit_support_path' > /dev/null" \
+    "generator should show help message for --crubit_support_path"
+
+  EXPECT_SUCCEED \
+    "\"${RS_BINDINGS_FROM_CC}\" \
+      --rs_out=\"${rs_out}\" \
+      --cc_out=\"${cc_out}\" 2>&1 \
+      --crubit_support_path=test/crubit/support/path | \
       grep 'please specify --public_headers' > /dev/null" \
     "generator should show help message for --public_headers"
 
@@ -41,6 +49,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --public_headers=\"${hdr}\" 2>&1 | \
       grep 'please specify --targets_and_headers' > /dev/null" \
     "generator should show help message for --targets_and_headers"
@@ -55,6 +64,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --public_headers=\"${hdr}\" \
       --targets_and_headers=\"$(echo "${json}" | quote_escape)\""
 
@@ -76,6 +86,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --public_headers=\"${hdr}\" \
       --targets_and_headers=\"$(echo "${json}" | quote_escape)\" \
       --do_nothing"
@@ -105,6 +116,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --public_headers=\"${hdr}\" \
       --targets_and_headers=\"$(echo "${json}" | quote_escape)\" 2>&1"
 
@@ -132,6 +144,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --public_headers=\"${header_1},${header_2}\" \
       --targets_and_headers=\"$(echo "${json}" | quote_escape)\" 2>&1"
 
@@ -158,6 +171,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --public_headers=\"${hdr}\" \
       --targets_and_headers=\"$(echo "${json}" | quote_escape)\""
 
@@ -184,6 +198,7 @@
     "\"${RS_BINDINGS_FROM_CC}\" \
       --rs_out=\"${rs_out}\" \
       --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/crubit/support/path \
       --rustfmt_config_path=\"${rustfmt_config_path}\" \
       --public_headers=\"${hdr}\" \
       --targets_and_headers=\"$(echo "${json}" | quote_escape)\""
@@ -203,4 +218,31 @@
     "Verify function args are *not on single line when using default rustfmt config (2)"
 }
 
+function test::crubit_support_path() {
+  local rs_out="${TEST_TMPDIR}/rs_api.rs"
+  local cc_out="${TEST_TMPDIR}/rs_api_impl.cc"
+
+  local hdr="${TEST_TMPDIR}/hello_world.h"
+  echo "int MyFunction();" > "${hdr}"
+
+  local json
+  json="$(cat <<-EOT
+  [{"t": "//foo/bar:baz", "h": ["${hdr}"]}]
+EOT
+)"
+
+  EXPECT_SUCCEED \
+    "\"${RS_BINDINGS_FROM_CC}\" \
+      --rs_out=\"${rs_out}\" \
+      --cc_out=\"${cc_out}\" \
+      --crubit_support_path=test/specific/crubit/support/path \
+      --public_headers=\"${hdr}\" \
+      --targets_and_headers=\"$(echo "${json}" | quote_escape)\""
+
+  EXPECT_FILE_NOT_EMPTY "${cc_out}"
+  EXPECT_SUCCEED \
+    "grep \"#include.*test/specific/crubit/support/path/[a-z]\" \"${cc_out}\"" \
+    "Verify #include paths are based on the argument of --crubit_support_path"
+}
+
 gbash::unit::main "$@"