Collect template instantiations.
PiperOrigin-RevId: 447450392
diff --git a/rs_bindings_from_cc/BUILD b/rs_bindings_from_cc/BUILD
index 7b59554..f891e0e 100644
--- a/rs_bindings_from_cc/BUILD
+++ b/rs_bindings_from_cc/BUILD
@@ -85,6 +85,7 @@
srcs = ["generate_bindings_and_metadata.cc"],
hdrs = ["generate_bindings_and_metadata.h"],
deps = [
+ ":cc_collect_instantiations",
":cc_ir",
":cmdline",
":ir_from_cc",
@@ -99,8 +100,9 @@
deps = [
":cmdline",
":generate_bindings_and_metadata",
- "//common:file_io",
+ "//common:test_utils",
"//testing/base/public:gunit_main",
+ "@absl//strings",
"@rust//support:rust_okay_here",
],
)
@@ -231,6 +233,7 @@
":bazel_types",
"//common:check",
"//common:strong_int",
+ "@absl//container:flat_hash_map",
"@absl//strings",
"@llvm///clang:ast",
"@llvm///llvm:Support",
diff --git a/rs_bindings_from_cc/generate_bindings_and_metadata.cc b/rs_bindings_from_cc/generate_bindings_and_metadata.cc
index 4f6b3fa..777d6c6 100644
--- a/rs_bindings_from_cc/generate_bindings_and_metadata.cc
+++ b/rs_bindings_from_cc/generate_bindings_and_metadata.cc
@@ -5,6 +5,7 @@
#include "rs_bindings_from_cc/generate_bindings_and_metadata.h"
#include "common/status_macros.h"
+#include "rs_bindings_from_cc/collect_instantiations.h"
#include "rs_bindings_from_cc/ir_from_cc.h"
#include "rs_bindings_from_cc/src_code_gen.h"
@@ -17,11 +18,16 @@
clang_args.end());
CRUBIT_ASSIGN_OR_RETURN(
- IR ir, crubit::IrFromCc(
- /* extra_source_code= */ "", cmdline.current_target(),
- cmdline.public_headers(),
- /* virtual_headers_contents= */ {},
- cmdline.headers_to_targets(), clang_args_view));
+ std::vector<std::string> requested_instantiations,
+ crubit::CollectInstantiations(cmdline.rust_sources()));
+
+ CRUBIT_ASSIGN_OR_RETURN(
+ IR ir,
+ crubit::IrFromCc(
+ /* extra_source_code= */ "", cmdline.current_target(),
+ cmdline.public_headers(),
+ /* virtual_headers_contents= */ {}, cmdline.headers_to_targets(),
+ clang_args_view, requested_instantiations));
crubit::Bindings bindings = crubit::GenerateBindings(
ir, cmdline.crubit_support_path(), cmdline.rustfmt_config_path());
diff --git a/rs_bindings_from_cc/generate_bindings_and_metadata_test.cc b/rs_bindings_from_cc/generate_bindings_and_metadata_test.cc
index e0b7dd3..927cba5 100644
--- a/rs_bindings_from_cc/generate_bindings_and_metadata_test.cc
+++ b/rs_bindings_from_cc/generate_bindings_and_metadata_test.cc
@@ -6,19 +6,20 @@
#include "testing/base/public/gmock.h"
#include "testing/base/public/gunit.h"
-#include "common/file_io.h"
+#include "common/test_utils.h"
#include "rs_bindings_from_cc/cmdline.h"
namespace crubit {
namespace {
+using ::testing::StrEq;
+
TEST(GenerateBindingsAndMetadataTest, GeneratingIR) {
constexpr absl::string_view kTargetsAndHeaders = R"([
{"t": "target1", "h": ["a.h"]}
])";
- std::string tmpdir = absl::GetFlag(FLAGS_test_tmpdir);
- ASSERT_OK(SetFileContents(absl::StrCat(tmpdir, "/a.h"), "// empty header"));
+ WriteFileForCurrentTest("a.h", "//empty header");
ASSERT_OK_AND_ASSIGN(
Cmdline cmdline,
Cmdline::CreateForTesting(
@@ -31,12 +32,58 @@
ASSERT_OK_AND_ASSIGN(
BindingsAndMetadata result,
- GenerateBindingsAndMetadata(
- cmdline, /* clang_args= */ {std::string("-I"), std::move(tmpdir)}));
+ GenerateBindingsAndMetadata(cmdline, DefaultClangArgs()));
ASSERT_EQ(result.ir.used_headers.size(), 1);
ASSERT_EQ(result.ir.used_headers.front().IncludePath(), "a.h");
}
+TEST(GenerateBindingsAndMetadataTest, InstantiationsAreEmptyInNormalMode) {
+ constexpr absl::string_view kTargetsAndHeaders = R"([
+ {"t": "target1", "h": ["a.h"]}
+ ])";
+ WriteFileForCurrentTest("a.h", "// empty header");
+ ASSERT_OK_AND_ASSIGN(
+ Cmdline cmdline,
+ Cmdline::CreateForTesting(
+ "cc_out", "rs_out", "ir_out", "crubit_support_path",
+ "external/rustfmt/rustfmt.toml",
+ /* do_nothing= */ false,
+ /* public_headers= */ {"a.h"}, std::string(kTargetsAndHeaders),
+ /* rust_sources= */ {},
+ /* instantiations_out= */ ""));
+
+ ASSERT_OK_AND_ASSIGN(
+ BindingsAndMetadata result,
+ GenerateBindingsAndMetadata(cmdline, DefaultClangArgs()));
+
+ ASSERT_THAT(InstantiationsAsJson(result.ir), StrEq("{}"));
+}
+
+TEST(GenerateBindingsAndMetadataTest, InstantiationsJsonGenerated) {
+ constexpr absl::string_view kTargetsAndHeaders = R"([
+ {"t": "target1", "h": ["a.h"]}
+ ])";
+ WriteFileForCurrentTest("a.h", "// empty header");
+ std::string a_rs_path =
+ WriteFileForCurrentTest("a.rs", "cc_template!(MyTemplate<bool>);");
+ ASSERT_OK_AND_ASSIGN(
+ Cmdline cmdline,
+ Cmdline::CreateForTesting(
+ "cc_out", "rs_out", "ir_out", "crubit_support_path",
+ "external/rustfmt/rustfmt.toml",
+ /* do_nothing= */ false,
+ /* public_headers= */ {"a.h"}, std::string(kTargetsAndHeaders),
+ /* rust_sources= */ {a_rs_path}, "instantiations_out"));
+
+ ASSERT_OK_AND_ASSIGN(
+ BindingsAndMetadata result,
+ GenerateBindingsAndMetadata(cmdline, DefaultClangArgs()));
+
+ // TODO(b/440066049): Actually populate the instantiations map once
+ // cl/430823388 is submitted.
+ ASSERT_THAT(InstantiationsAsJson(result.ir), StrEq("{}"));
+}
+
} // namespace
} // namespace crubit
diff --git a/rs_bindings_from_cc/ir.h b/rs_bindings_from_cc/ir.h
index 97cb11b..f0fcbe9 100644
--- a/rs_bindings_from_cc/ir.h
+++ b/rs_bindings_from_cc/ir.h
@@ -21,6 +21,7 @@
#include <variant>
#include <vector>
+#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "common/check.h"
#include "common/strong_int.h"
@@ -714,12 +715,22 @@
UnsupportedItem, Comment, Namespace>;
std::vector<Item> items;
std::vector<ItemId> top_level_item_ids;
+ absl::flat_hash_map<std::string, std::string> instantiations;
};
inline std::string IrToJson(const IR& ir) {
return std::string(llvm::formatv("{0:2}", ir.ToJson()));
}
+// Instantiations from the `IR` serialized as JSON.
+inline std::string InstantiationsAsJson(const IR& ir) {
+ llvm::json::Object obj;
+ for (const auto& entry : ir.instantiations) {
+ obj[entry.first] = entry.second;
+ }
+ return std::string(llvm::formatv("{0:2}", llvm::json::Value(std::move(obj))));
+}
+
inline std::ostream& operator<<(std::ostream& o, const IR& ir) {
return o << IrToJson(ir);
}
diff --git a/rs_bindings_from_cc/ir_from_cc.cc b/rs_bindings_from_cc/ir_from_cc.cc
index 2c573bb..4f2be3f 100644
--- a/rs_bindings_from_cc/ir_from_cc.cc
+++ b/rs_bindings_from_cc/ir_from_cc.cc
@@ -18,10 +18,7 @@
#include "common/check.h"
#include "rs_bindings_from_cc/bazel_types.h"
#include "rs_bindings_from_cc/frontend_action.h"
-#include "rs_bindings_from_cc/importer.h"
#include "rs_bindings_from_cc/ir.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemOptions.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
@@ -38,10 +35,15 @@
absl::flat_hash_map<const HeaderName, const std::string>
virtual_headers_contents,
absl::flat_hash_map<const HeaderName, const BazelLabel> headers_to_targets,
- absl::Span<const absl::string_view> args) {
+ absl::Span<const absl::string_view> args,
+ absl::Span<const std::string> extra_instantiations) {
// Caller should verify that the inputs are not empty.
- CRUBIT_CHECK(!extra_source_code.empty() || !public_headers.empty());
- CRUBIT_CHECK(!extra_source_code.empty() || !headers_to_targets.empty());
+ // TODO(b/440066049): Generate a source file for requested instantiations once
+ // cl/430823388 is submitted.
+ CRUBIT_CHECK(!extra_source_code.empty() || !public_headers.empty() ||
+ !extra_instantiations.empty());
+ CRUBIT_CHECK(!extra_source_code.empty() || !headers_to_targets.empty() ||
+ !extra_instantiations.empty());
std::vector<HeaderName> entrypoint_headers(public_headers.begin(),
public_headers.end());
diff --git a/rs_bindings_from_cc/ir_from_cc.h b/rs_bindings_from_cc/ir_from_cc.h
index c0bd4b8..73d84c8 100644
--- a/rs_bindings_from_cc/ir_from_cc.h
+++ b/rs_bindings_from_cc/ir_from_cc.h
@@ -33,6 +33,8 @@
// `//test:testing_target`. Headers from `virtual_headers_contents` are not
// added automatically.
// * `args`: additional command line arguments for Clang
+// * `extra_instantiations`: names of full C++ class template specializations
+// to instantiate and generate bindings from.
//
absl::StatusOr<IR> IrFromCc(
absl::string_view extra_source_code,
@@ -42,7 +44,8 @@
virtual_headers_contents = {},
absl::flat_hash_map<const HeaderName, const BazelLabel> headers_to_targets =
{},
- absl::Span<const absl::string_view> args = {});
+ absl::Span<const absl::string_view> args = {},
+ absl::Span<const std::string> extra_instantiations = {});
} // namespace crubit
diff --git a/rs_bindings_from_cc/rs_bindings_from_cc.cc b/rs_bindings_from_cc/rs_bindings_from_cc.cc
index 5e724a5..891add6 100644
--- a/rs_bindings_from_cc/rs_bindings_from_cc.cc
+++ b/rs_bindings_from_cc/rs_bindings_from_cc.cc
@@ -63,8 +63,9 @@
SetFileContents(cmdline.cc_out(), bindings_and_metadata.rs_api_impl));
if (!cmdline.instantiations_out().empty()) {
- CRUBIT_RETURN_IF_ERROR(SetFileContents(cmdline.instantiations_out(),
- "// not implemented yet"));
+ CRUBIT_RETURN_IF_ERROR(SetFileContents(
+ cmdline.instantiations_out(),
+ crubit::InstantiationsAsJson(bindings_and_metadata.ir)));
}
return absl::OkStatus();