Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion hpb/backend/cpp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ cc_library(
"//hpb:arena",
"//hpb:extension",
"//hpb:ptr",
"//hpb/internal",
"//hpb/internal:template_help",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/strings:string_view",
Expand Down Expand Up @@ -51,7 +52,7 @@ cc_test(
"//hpb",
"//hpb:arena",
"//hpb:ptr",
"//hpb_generator/tests:test_model_hpb_proto",
"//hpb_generator/tests:trivial_hpb_proto",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
Expand Down
1 change: 1 addition & 0 deletions hpb/backend/cpp/cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "absl/strings/string_view.h"
#include "hpb/arena.h"
#include "hpb/extension.h"
#include "hpb/internal/internal.h"
#include "hpb/internal/template_help.h"
#include "hpb/ptr.h"

Expand Down
25 changes: 16 additions & 9 deletions hpb/backend/cpp/cpp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,33 @@
// https://developers.google.com/open-source/licenses/bsd

#include <gtest/gtest.h>
#include "hpb_generator/tests/test_model.hpb.h"
#include "hpb_generator/tests/trivial.hpb.h"
#include "hpb/arena.h"
#include "hpb/hpb.h"
#include "hpb/ptr.h"

// Tests in this file are run against both backends {upb, cpp} to ensure
// api conformance, compatibility, and correctness.

namespace hpb::testing {
namespace {

using ::hpb_unittest::protos::TestModel;
using ::hpb_unittest::protos::TestModel_Category_IMAGES;

// Tests in this file are run against both backends {upb, cpp} to ensure
// api conformance, compatibility, and correctness.
using ::hpb_unittest::protos::PAINTING_SARGENT;
using ::hpb_unittest::protos::Trivial;

TEST(CppBackend, CanCreateMessage) {
hpb::Arena arena;
hpb::Ptr<TestModel> test_model_ptr = hpb::CreateMessage<TestModel>(arena);
(void)test_model_ptr;
hpb::Ptr<Trivial> trivial_ptr = hpb::CreateMessage<Trivial>(arena);
(void)trivial_ptr;
}

TEST(CppBackend, Enums) { EXPECT_EQ(2, PAINTING_SARGENT); }

TEST(CppBackend, Booleans) {
Trivial cpp_trivial;
EXPECT_FALSE(cpp_trivial.b());
// TODO: set, clear
}

TEST(CppBackend, MessageEnums) { EXPECT_EQ(5, TestModel_Category_IMAGES); }
} // namespace
} // namespace hpb::testing
25 changes: 22 additions & 3 deletions hpb/bazel/hpb_proto_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
- hpb_proto_library()
"""

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain")
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
load("//bazel:upb_proto_library.bzl", "GeneratedSrcsInfo", "UpbWrappedCcInfo", "upb_proto_library_aspect")
load("//bazel/common:proto_common.bzl", "proto_common")
load("//bazel/common:proto_info.bzl", "ProtoInfo")
load("//bazel/private:bazel_cc_proto_library.bzl", "cc_proto_aspect")
load("//bazel/private:upb_proto_library_internal/cc_library_func.bzl", "cc_library_func") # buildifier: disable=bzl-visibility

def upb_use_cpp_toolchain():
Expand Down Expand Up @@ -73,6 +75,10 @@ def _hpb_proto_rule_impl(ctx):
else:
fail("proto_library rule must generate _HpbWrappedCcInfo (aspect should have handled this).")

backend = ctx.attr._hpb_backend[BuildSettingInfo].value
if backend == "cpp" and CcInfo in dep:
cc_info = cc_common.merge_cc_infos(direct_cc_infos = [cc_info, dep[CcInfo]])

lib = cc_info.linking_context.linker_inputs.to_list()[0].libraries[0]
files = _filter_none([
lib.static_library,
Expand All @@ -93,9 +99,15 @@ def _upb_cc_proto_aspect_impl(target, ctx, cc_provider, file_provider):
dep_ccinfos = [dep[CcInfo] for dep in deps if CcInfo in dep]
dep_ccinfos += [dep[UpbWrappedCcInfo].cc_info for dep in deps if UpbWrappedCcInfo in dep]
dep_ccinfos += [dep[_HpbWrappedCcInfo].cc_info for dep in deps if _HpbWrappedCcInfo in dep]
if UpbWrappedCcInfo not in target:
fail("Target should have UpbWrappedCcInfo provider")
dep_ccinfos.append(target[UpbWrappedCcInfo].cc_info)

backend = ctx.attr._hpb_backend[BuildSettingInfo].value

if backend == "upb" and UpbWrappedCcInfo in target:
dep_ccinfos.append(target[UpbWrappedCcInfo].cc_info)

if backend == "cpp" and CcInfo in target:
dep_ccinfos.append(target[CcInfo].cc_info)

proto_info = target[ProtoInfo]

if not getattr(ctx.rule.attr, "srcs", []):
Expand Down Expand Up @@ -137,6 +149,9 @@ _hpb_proto_library_aspect = aspect(
"//hpb:repeated_field",
],
),
"_hpb_backend": attr.label(
default = "//hpb:hpb_backend",
),
},
exec_groups = {
"proto_compiler": exec_group(),
Expand All @@ -160,11 +175,15 @@ hpb_proto_library = rule(
attrs = {
"deps": attr.label_list(
aspects = [
cc_proto_aspect,
upb_proto_library_aspect,
_hpb_proto_library_aspect,
],
allow_rules = ["proto_library"],
providers = [ProtoInfo],
),
"_hpb_backend": attr.label(
default = "//hpb:hpb_backend",
),
},
)
1 change: 1 addition & 0 deletions hpb_generator/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ cc_library(
"//src/google/protobuf/compiler:code_generator",
"//src/google/protobuf/compiler:code_generator_lite",
"//src/google/protobuf/compiler:plugin",
"//src/google/protobuf/compiler/cpp:names",
"//upb_generator:common",
"//upb_generator:file_layout",
"//upb_generator/c:names",
Expand Down
30 changes: 26 additions & 4 deletions hpb_generator/generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "absl/strings/str_replace.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/code_generator_lite.h"
#include "google/protobuf/compiler/cpp/names.h"
#include "hpb_generator/context.h"
#include "hpb_generator/gen_enums.h"
#include "hpb_generator/gen_extensions.h"
Expand Down Expand Up @@ -54,6 +55,22 @@ void WriteForwardDecls(const google::protobuf::FileDescriptor* file, Context& ct
WriteTypedefForwardingHeader(file, this_file_messages, ctx);
}

std::string ScalarGetters(const google::protobuf::Descriptor* message) {
std::string res;
for (int i = 0; i < message->field_count(); ++i) {
const auto* field = message->field(i);
if (field->is_repeated() || field->is_map() || field->is_extension()) {
continue;
}
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) {
absl::StrAppend(
&res, google::protobuf::FieldDescriptor::CppTypeName(field->cpp_type()), " ",
field->name(), "() const { return msg_.", field->name(), "(); }\n");
}
}
return res;
}

void WriteHeader(const google::protobuf::FileDescriptor* file, Context& ctx) {
if (ctx.options().backend == Backend::CPP) {
EmitFileWarning(file, ctx);
Expand Down Expand Up @@ -105,7 +122,10 @@ void WriteHeader(const google::protobuf::FileDescriptor* file, Context& ctx) {
const auto msgs = SortedMessages(file);
for (auto message : msgs) {
ctx.Emit({{"type", QualifiedClassName(message)},
{"cpp_backend_type",
google::protobuf::compiler::cpp::QualifiedClassName(message)},
{"class_name", ClassName(message)},
{"scalar_getters", ScalarGetters(message)},
{"namespace", absl::StrCat(absl::StrReplaceAll(file->package(),
{{".", "::"}}),
"::protos")}},
Expand All @@ -123,12 +143,11 @@ void WriteHeader(const google::protobuf::FileDescriptor* file, Context& ctx) {

$class_name$() = default;

private:
$class_name$($type$* msg) : msg_(msg) {}
$scalar_getters$

$type$* msg_;
private : $cpp_backend_type$ msg_;

$type$* msg() const { return msg_; }
const $cpp_backend_type$* msg() const { return &msg_; }

friend struct ::hpb::internal::PrivateAccess;
};
Expand Down Expand Up @@ -307,6 +326,9 @@ void WriteHeaderMessageForwardDecls(const google::protobuf::FileDescriptor* file
if (ctx.options().backend == Backend::UPB) {
ctx.Emit({{"upb_filename", UpbCFilename(file)}},
"#include \"$upb_filename$\"\n");
} else if (ctx.options().backend == Backend::CPP) {
ctx.Emit({{"cpp_header", ProtoFilename(file)}},
"#include \"$cpp_header$\"\n");
}
WriteForwardDecls(file, ctx);
// Import forward-declaration of types in dependencies.
Expand Down
4 changes: 4 additions & 0 deletions hpb_generator/names.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ std::string UpbCFilename(const google::protobuf::FileDescriptor* file) {
return compiler::StripProto(file->name()) + ".upb.h";
}

std::string ProtoFilename(const google::protobuf::FileDescriptor* file) {
return compiler::StripProto(file->name()) + ".proto.h";
}

std::string CppHeaderFilename(const google::protobuf::FileDescriptor* file) {
return absl::StrCat(compiler::StripProto(file->name()), ".hpb.h");
}
Expand Down
1 change: 1 addition & 0 deletions hpb_generator/names.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ std::string QualifiedInternalClassName(const google::protobuf::Descriptor* descr

std::string CppSourceFilename(const google::protobuf::FileDescriptor* file);
std::string UpbCFilename(const google::protobuf::FileDescriptor* file);
std::string ProtoFilename(const google::protobuf::FileDescriptor* file);
std::string CppHeaderFilename(const google::protobuf::FileDescriptor* file);

void WriteStartNamespace(const google::protobuf::FileDescriptor* file, Context& ctx);
Expand Down
15 changes: 15 additions & 0 deletions hpb_generator/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,21 @@ hpb_proto_library(
deps = [":basic_editions_proto"],
)

proto_library(
name = "trivial_proto",
srcs = [
"trivial.proto",
],
)

hpb_proto_library(
name = "trivial_hpb_proto",
visibility = [
"//hpb:__subpackages__",
],
deps = [":trivial_proto"],
)

proto_library(
name = "set_alias_proto",
srcs = ["set_alias.proto"],
Expand Down
20 changes: 20 additions & 0 deletions hpb_generator/tests/trivial.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2025 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

edition = "2024";

package hpb_unittest;

message Trivial {
bool b = 1;
}

enum TrivialPainting {
PAINTING_UNSPECIFIED = 0;
PAINTING_BOUGUEREAU = 1;
PAINTING_SARGENT = 2;
}
Loading