Skip to content

Commit 35088ec

Browse files
andrewle10copybara-github
authored andcommitted
Modify Crubit to natively generate inline_cpp! and global_cpp!
PiperOrigin-RevId: 949213817
1 parent ebaef63 commit 35088ec

36 files changed

Lines changed: 477 additions & 57 deletions

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cargo/cc_bindings_from_rs/cpp_api_from_rust_lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ clap.workspace = true
3030
itertools.workspace = true
3131
crubit_feature = { path = "../../../cargo/common/crubit_feature"}
3232
flagset.workspace = true
33+
quote.workspace = true
3334
rustversion.workspace = true
3435
[dev-dependencies]
3536
run_compiler_test_support = { path = "../../../cargo/cc_bindings_from_rs/run_compiler_test_support", package = "cc_bindings_from_rs_run_compiler_test_support"}

cc_bindings_from_rs/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ rust_library(
3939
"@crate_index//:clap", # v4
4040
"@crate_index//:flagset", # v0_4
4141
"@crate_index//:itertools", # v0_13
42+
"@crate_index//:quote", # v1
4243
],
4344
)
4445

cc_bindings_from_rs/bazel_support/cc_bindings_from_rust_library_config_aspect_hint.bzl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,14 @@ def get_additional_cc_hdrs_and_srcs(aspect_hints):
7373
"""Returns any additional C++ headers and sources that should be compiled with the generated bindings.
7474
7575
Args:
76-
aspect_ctx: The ctx from an aspect_hint.
76+
aspect_hints: A list of aspect hints (Target list).
7777
7878
Returns:
7979
A list of `File` and its module paths as specified by the `extra_rs_srcs`.
8080
"""
8181
additional_cc_hdrs = []
8282
additional_cc_srcs = []
83+
8384
for hint in aspect_hints:
8485
if CcBindingsFromRustLibraryConfigInfo in hint:
8586
for target in hint[CcBindingsFromRustLibraryConfigInfo].extra_cc_hdrs:

cc_bindings_from_rs/bazel_support/cc_bindings_from_rust_rule.bzl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ def _generate_bindings(ctx, dep_bindings_infos, config, label, features, cli_fla
261261
crubit_args.add("--source-crate-name", self_crate_name)
262262
if self_rmeta != None:
263263
crubit_args.add("--extern={}={}".format(self_crate_name, self_rmeta.path))
264+
264265
crubit_args.add("--enable-rmeta-interface")
265266
is_golden_test = is_golden_test_override if is_golden_test_override != None else ctx.attr._is_golden_test[BuildSettingInfo].value
266267
if is_golden_test:
@@ -393,6 +394,8 @@ def _cc_bindings_from_rust_aspect_impl(target, ctx):
393394

394395
if CrateInfo not in target:
395396
return []
397+
if CcBindingsFromRustInfo in target:
398+
return []
396399
if str(target.label) in targets_to_remove:
397400
return []
398401

@@ -486,6 +489,11 @@ def _cc_bindings_from_rust_aspect_impl(target, ctx):
486489
aspect_hints = ctx.rule.attr.aspect_hints,
487490
rust_infos = dep_bindings_infos,
488491
)
492+
(extra_cc_hdrs, extra_cc_srcs) = get_additional_cc_hdrs_and_srcs(ctx.rule.attr.aspect_hints)
493+
for hdr in extra_cc_hdrs:
494+
if hdr.short_path.endswith("_extracted_cc.h"):
495+
cli_flags.append("--extra-rs-srcs-include=" + hdr.short_path)
496+
489497
bindings_info, features, config, output_depset = _generate_bindings(
490498
ctx,
491499
dep_bindings_infos = dep_bindings_infos,
@@ -504,8 +512,6 @@ def _cc_bindings_from_rust_aspect_impl(target, ctx):
504512

505513
dep_variant_info = _compile_rs_out_file(ctx, ctx.rule.attr, bindings_info.rust_file, target[CrateInfo].name, [target])
506514

507-
(extra_cc_hdrs, extra_cc_srcs) = get_additional_cc_hdrs_and_srcs(ctx.rule.attr.aspect_hints)
508-
509515
cc_info = _make_cc_info_for_h_out_file(
510516
ctx,
511517
bindings_info.h_file,

cc_bindings_from_rs/cmdline.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ pub struct Cmdline {
141141
value_name = "CRATE_NAME=RENAMED")]
142142
pub crate_rename: Vec<(String, String)>,
143143

144+
/// Extra headers to `#include` and re-export via IWYU in the generated C++ API header.
145+
///
146+
/// Re-exports user headers required by embedded C++ declarations (such as `inline_cpp!`).
147+
/// This ensures C++ callers using the generated C++ API header automatically receive
148+
/// the necessary includes for those types without encountering missing symbol errors.
149+
#[clap(long = "extra-rs-srcs-include", value_name = "FILE")]
150+
pub extra_rs_srcs_includes: Vec<String>,
151+
144152
/// The name of the crate to generate bindings for.
145153
///
146154
/// If provided, this value must correspond to the name of an extern crate provided to the

cc_bindings_from_rs/lib.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_middle::ty::TyCtxt;
1919
use rustc_session::config::OptionsTargetModifiers;
2020

2121
use arc_anyhow::{bail, Context, Result};
22-
use std::collections::{HashMap, HashSet};
22+
use std::collections::{BTreeSet, HashMap, HashSet};
2323
use std::path::{Path, PathBuf};
2424
use std::rc::Rc;
2525

@@ -121,11 +121,24 @@ fn run_with_tcx(cmdline: &Cmdline, tcx: TyCtxt) -> Result<()> {
121121
ErrorReport::new_rc_or_ignore(generate_error_report, SourceLanguage::Rust);
122122
let fatal_errors = Rc::new(FatalErrors::new());
123123

124-
let BindingsTokens { cc_api, cc_api_impl } = {
124+
let BindingsTokens { mut cc_api, cc_api_impl } = {
125125
let db = new_db(cmdline, tcx, errors, fatal_errors.clone());
126126
generate_bindings(&db)?
127127
};
128128

129+
if !cmdline.extra_rs_srcs_includes.is_empty() {
130+
let extra_includes: BTreeSet<CcInclude> = cmdline
131+
.extra_rs_srcs_includes
132+
.iter()
133+
.map(|include| CcInclude::exported_user_header(include.as_str().into()))
134+
.collect();
135+
let extra_includes_tokens = code_gen_utils::format_cc_includes(&extra_includes);
136+
cc_api = quote::quote! {
137+
#extra_includes_tokens
138+
#cc_api
139+
};
140+
}
141+
129142
let fatal_error_message = fatal_errors.take_string();
130143
if !fatal_error_message.is_empty() {
131144
return Err(arc_anyhow::Error::msg(fatal_error_message));

common/code_gen_utils.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,8 @@ pub enum CcInclude {
959959
/// format specifier for what comes after `#include` and path of the support
960960
/// library header.
961961
SupportLibHeader(Format<1>, Rc<str>),
962+
/// Represents a user header which should be re-exported by IWYU.
963+
ExportedUserHeader(Rc<str>),
962964
}
963965

964966
impl CcInclude {
@@ -1043,6 +1045,11 @@ impl CcInclude {
10431045
Self::UserHeader(path)
10441046
}
10451047

1048+
/// Creates a user include: `#include "some/path/to/header.h" // IWYU pragma: export`
1049+
pub fn exported_user_header(path: Rc<str>) -> Self {
1050+
Self::ExportedUserHeader(path)
1051+
}
1052+
10461053
/// Creates a `CcInclude` and detects whether it's a system header or a user
10471054
/// header based on the path.
10481055
///
@@ -1074,6 +1081,9 @@ impl ToTokens for CcInclude {
10741081
Self::UserHeader(path) => {
10751082
quote! { __HASH_TOKEN__ include #path __NEWLINE__ }.to_tokens(tokens)
10761083
}
1084+
Self::ExportedUserHeader(path) => {
1085+
quote! { __HASH_TOKEN__ include #path __COMMENT__ "IWYU pragma: export" __NEWLINE__ }.to_tokens(tokens)
1086+
}
10771087
Self::SupportLibHeader(format, path) => {
10781088
let full_path: TokenStream = format
10791089
.format(&[&*path])

rs_bindings_from_cc/cmdline.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ ABSL_FLAG(std::string, template_blocklist_path_regex, "",
135135
"If nonempty, do not instantiate templates defined in files with "
136136
"paths matching this llvm::Regex.");
137137

138+
ABSL_FLAG(bool, carcinize, false,
139+
"If true, enables the carcinize pipeline for automated porting, "
140+
"which emits inline_cpp! blocks and modifies structure.");
141+
138142
namespace crubit {
139143

140144
namespace {
@@ -253,6 +257,7 @@ absl::StatusOr<Cmdline> Cmdline::FromFlags() {
253257
.do_not_bind_allowlist = absl::GetFlag(FLAGS_do_not_bind_allowlist),
254258
.template_blocklist_path_regex =
255259
absl::GetFlag(FLAGS_template_blocklist_path_regex),
260+
.carcinize = absl::GetFlag(FLAGS_carcinize),
256261
};
257262

258263
absl::Status parse_target_args_status =

rs_bindings_from_cc/cmdline.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct CmdlineArgs {
5959
std::optional<std::vector<std::string>> do_not_bind_allowlist;
6060

6161
std::string template_blocklist_path_regex;
62+
bool carcinize = false;
6263
};
6364

6465
// A valid command line invocation.

0 commit comments

Comments
 (0)