diff --git a/.bazelrc b/.bazelrc index 1709da4..9fcfefb 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,6 +3,8 @@ build --cxxopt="-std=c++17" build --jobs=4 build --verbose_failures build --keep_going + +build --registry=https://bcr.wheelos.cn/ build --registry=https://raw.githubusercontent.com/wheelos/bazel-central-registry/fastdds-2.14.x # Enable Bzlmod for every Bazel command diff --git a/MODULE.bazel b/MODULE.bazel index fe163cf..c5ecfd0 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -34,3 +34,7 @@ bazel_dep(name = "ncurses", version = "6.4.20221231") bazel_dep(name = "libuuid", version = "2.39.3.bcr.1") bazel_dep(name = "fastcdr", version = "2.2.2") bazel_dep(name = "fastdds", version = "2.14.3") + +# FlatBuffers system-installed runtime (header-only, provided via local repo). +flatbuffers_ext = use_extension("//bazel:flatbuffers.bzl", "flatbuffers_extension") +use_repo(flatbuffers_ext, "flatbuffers") diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000..4fca31e --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +./docs/doxy-docs \ No newline at end of file diff --git a/bazel/flatbuffers.bzl b/bazel/flatbuffers.bzl new file mode 100644 index 0000000..6cb813b --- /dev/null +++ b/bazel/flatbuffers.bzl @@ -0,0 +1,53 @@ +# Copyright 2018 The Apollo Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Module extension that exposes the system-installed FlatBuffers headers +as a Bazel repository named @flatbuffers. + +The FlatBuffers C++ runtime is header-only, so no library linking is required. +The repository rule simply symlinks the system include directory and writes a +minimal BUILD file that declares a cc_library for the headers. +""" + +def _system_flatbuffers_impl(ctx): + include_dir = ctx.os.environ.get( + "FLATBUFFERS_INCLUDE_DIR", + "/usr/include", + ) + ctx.symlink(include_dir + "/flatbuffers", "flatbuffers") + ctx.file("BUILD", """ +load("@rules_cc//cc:defs.bzl", "cc_library") + +package(default_visibility = ["//visibility:public"]) + +# Header-only FlatBuffers runtime library. +cc_library( + name = "flatbuffers", + hdrs = glob(["flatbuffers/**/*.h"]), + includes = ["."], +) +""") + +_system_flatbuffers = repository_rule( + implementation = _system_flatbuffers_impl, + local = True, + environ = ["FLATBUFFERS_INCLUDE_DIR"], +) + +def _flatbuffers_extension_impl(module_ctx): + _system_flatbuffers(name = "flatbuffers") + +flatbuffers_extension = module_extension( + implementation = _flatbuffers_extension_impl, +) diff --git a/cyber/examples/BUILD b/cyber/examples/BUILD index 48f3fa5..c17e19c 100644 --- a/cyber/examples/BUILD +++ b/cyber/examples/BUILD @@ -46,3 +46,24 @@ cc_binary( "//cyber/proto:record_cc_proto", ], ) + +# FlatBuffers zero-copy talker/listener pair. +cc_binary( + name = "talker_fb", + srcs = ["talker_fb.cc"], + deps = [ + "//cyber", + "//cyber/examples/proto:examples_fbs", + "//cyber/message:flatbuffers_message", + ], +) + +cc_binary( + name = "listener_fb", + srcs = ["listener_fb.cc"], + deps = [ + "//cyber", + "//cyber/examples/proto:examples_fbs", + "//cyber/message:flatbuffers_message", + ], +) diff --git a/cyber/examples/listener_fb.cc b/cyber/examples/listener_fb.cc new file mode 100644 index 0000000..29f4cb3 --- /dev/null +++ b/cyber/examples/listener_fb.cc @@ -0,0 +1,55 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +/** + * @file listener_fb.cc + * @brief FlatBuffers-based listener demonstrating zero-copy message access. + * + * This example mirrors listener.cc but subscribes to FlatBufferMessage + * payloads. On receipt the callback calls GetRoot() to access the + * FlatBuffers root object directly from the buffer — no copy, no allocation. + */ + +#include "cyber/cyber.h" +#include "cyber/examples/proto/examples_generated.h" +#include "cyber/message/flatbuffers_message.h" + +using apollo::cyber::message::FlatBufferMessage; +using apollo::cyber::examples::proto::Chatter; + +void MessageCallback(const std::shared_ptr& msg) { + // Zero-copy: access the FlatBuffers root directly from the buffer. + const Chatter* chatter = msg->GetRoot(); + if (chatter == nullptr) { + AERROR << "listener_fb: received an empty FlatBufferMessage"; + return; + } + AINFO << "listener_fb received seq->" << chatter->seq(); + if (chatter->content()) { + AINFO << "listener_fb content->" << chatter->content()->str(); + } +} + +int main(int argc, char* argv[]) { + apollo::cyber::Init(argv[0]); + + auto listener_node = apollo::cyber::CreateNode("listener_fb"); + auto listener = listener_node->CreateReader( + "channel/chatter_fb", MessageCallback); + + apollo::cyber::WaitForShutdown(); + return 0; +} diff --git a/cyber/examples/proto/BUILD b/cyber/examples/proto/BUILD index 4d11cc5..bccf132 100644 --- a/cyber/examples/proto/BUILD +++ b/cyber/examples/proto/BUILD @@ -1,8 +1,8 @@ -load("@rules_cc//cc:defs.bzl", "cc_proto_library") - -## Auto generated by `proto_build_generator.py` -load("@rules_proto//proto:defs.bzl", "proto_library") -load("//:bazel/python_rules.bzl", "py_proto_library") +## Auto generated by `proto_build_generator.sh` +load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library") +load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") +load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) @@ -20,7 +20,15 @@ proto_library( py_proto_library( name = "examples_py_pb2", + deps = [":examples_proto"], +) + +# FlatBuffers pre-generated header for the Chatter schema. +# Generated from examples.fbs with: flatc --cpp examples.fbs +cc_library( + name = "examples_fbs", + hdrs = ["examples_generated.h"], deps = [ - ":examples_proto", + "@flatbuffers//:flatbuffers", ], ) diff --git a/cyber/examples/proto/examples.fbs b/cyber/examples/proto/examples.fbs new file mode 100644 index 0000000..02da729 --- /dev/null +++ b/cyber/examples/proto/examples.fbs @@ -0,0 +1,27 @@ +// Copyright 2018 The Apollo Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// FlatBuffers schema equivalent to examples.proto +// Enables zero-copy message passing via cyber shared-memory transport. + +namespace apollo.cyber.examples.proto; + +table Chatter { + timestamp:uint64; + lidar_timestamp:uint64; + seq:uint64; + content:string; +} + +root_type Chatter; diff --git a/cyber/examples/proto/examples_generated.h b/cyber/examples/proto/examples_generated.h new file mode 100644 index 0000000..7fe8c87 --- /dev/null +++ b/cyber/examples/proto/examples_generated.h @@ -0,0 +1,145 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// NOLINTBEGIN + +#ifndef FLATBUFFERS_GENERATED_EXAMPLES_APOLLO_CYBER_EXAMPLES_PROTO_H_ +#define FLATBUFFERS_GENERATED_EXAMPLES_APOLLO_CYBER_EXAMPLES_PROTO_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace apollo { +namespace cyber { +namespace examples { +namespace proto { + +struct Chatter; +struct ChatterBuilder; + +struct Chatter FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ChatterBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TIMESTAMP = 4, + VT_LIDAR_TIMESTAMP = 6, + VT_SEQ = 8, + VT_CONTENT = 10 + }; + uint64_t timestamp() const { + return GetField(VT_TIMESTAMP, 0); + } + uint64_t lidar_timestamp() const { + return GetField(VT_LIDAR_TIMESTAMP, 0); + } + uint64_t seq() const { + return GetField(VT_SEQ, 0); + } + const flatbuffers::String *content() const { + return GetPointer(VT_CONTENT); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TIMESTAMP, 8) && + VerifyField(verifier, VT_LIDAR_TIMESTAMP, 8) && + VerifyField(verifier, VT_SEQ, 8) && + VerifyOffset(verifier, VT_CONTENT) && + verifier.VerifyString(content()) && + verifier.EndTable(); + } +}; + +struct ChatterBuilder { + typedef Chatter Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_timestamp(uint64_t timestamp) { + fbb_.AddElement(Chatter::VT_TIMESTAMP, timestamp, 0); + } + void add_lidar_timestamp(uint64_t lidar_timestamp) { + fbb_.AddElement(Chatter::VT_LIDAR_TIMESTAMP, lidar_timestamp, 0); + } + void add_seq(uint64_t seq) { + fbb_.AddElement(Chatter::VT_SEQ, seq, 0); + } + void add_content(flatbuffers::Offset content) { + fbb_.AddOffset(Chatter::VT_CONTENT, content); + } + explicit ChatterBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateChatter( + flatbuffers::FlatBufferBuilder &_fbb, + uint64_t timestamp = 0, + uint64_t lidar_timestamp = 0, + uint64_t seq = 0, + flatbuffers::Offset content = 0) { + ChatterBuilder builder_(_fbb); + builder_.add_seq(seq); + builder_.add_lidar_timestamp(lidar_timestamp); + builder_.add_timestamp(timestamp); + builder_.add_content(content); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateChatterDirect( + flatbuffers::FlatBufferBuilder &_fbb, + uint64_t timestamp = 0, + uint64_t lidar_timestamp = 0, + uint64_t seq = 0, + const char *content = nullptr) { + auto content__ = content ? _fbb.CreateString(content) : 0; + return apollo::cyber::examples::proto::CreateChatter( + _fbb, + timestamp, + lidar_timestamp, + seq, + content__); +} + +inline const apollo::cyber::examples::proto::Chatter *GetChatter( + const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const apollo::cyber::examples::proto::Chatter *GetSizePrefixedChatter( + const void *buf) { + return flatbuffers::GetSizePrefixedRoot< + apollo::cyber::examples::proto::Chatter>(buf); +} + +inline bool VerifyChatterBuffer(flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer( + nullptr); +} + +inline bool VerifySizePrefixedChatterBuffer(flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer< + apollo::cyber::examples::proto::Chatter>(nullptr); +} + +inline void FinishChatterBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedChatterBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace proto +} // namespace examples +} // namespace cyber +} // namespace apollo + +// NOLINTEND + +#endif // FLATBUFFERS_GENERATED_EXAMPLES_APOLLO_CYBER_EXAMPLES_PROTO_H_ diff --git a/cyber/examples/talker_fb.cc b/cyber/examples/talker_fb.cc new file mode 100644 index 0000000..077ed08 --- /dev/null +++ b/cyber/examples/talker_fb.cc @@ -0,0 +1,70 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +/** + * @file talker_fb.cc + * @brief FlatBuffers-based talker demonstrating zero-copy publishing. + * + * This example mirrors talker.cc but uses FlatBufferMessage instead of a + * Protobuf-generated Chatter. The payload is serialized once into a + * FlatBufferBuilder and then wrapped in a FlatBufferMessage for publishing. + * Because the cyber shared-memory transport copies the raw byte buffer + * directly into SHM, the receiver can access the FlatBuffers root object + * without any additional deserialization. + */ + +#include "cyber/cyber.h" +#include "cyber/examples/proto/examples_generated.h" +#include "cyber/message/flatbuffers_message.h" +#include "cyber/time/rate.h" +#include "cyber/time/time.h" + +using apollo::cyber::Rate; +using apollo::cyber::Time; +using apollo::cyber::message::FlatBufferMessage; +using apollo::cyber::examples::proto::CreateChatterDirect; + +int main(int argc, char* argv[]) { + apollo::cyber::Init(argv[0]); + + auto talker_node = apollo::cyber::CreateNode("talker_fb"); + auto talker = talker_node->CreateWriter("channel/chatter_fb"); + + Rate rate(1.0); + uint64_t seq = 0; + + while (apollo::cyber::OK()) { + flatbuffers::FlatBufferBuilder fbb; + auto chatter = CreateChatterDirect( + fbb, + /*timestamp=*/Time::Now().ToNanosecond(), + /*lidar_timestamp=*/Time::Now().ToNanosecond(), + /*seq=*/seq, + /*content=*/"Hello, FlatBuffers!"); + fbb.Finish(chatter); + + auto msg = std::make_shared( + "apollo.cyber.examples.proto.Chatter", + fbb.GetBufferPointer(), fbb.GetSize()); + msg->set_timestamp(Time::Now().ToNanosecond()); + + talker->Write(msg); + AINFO << "talker_fb sent a FlatBuffers message! No. " << seq; + ++seq; + rate.Sleep(); + } + return 0; +} diff --git a/cyber/message/BUILD b/cyber/message/BUILD index 07d88bc..020c5fe 100644 --- a/cyber/message/BUILD +++ b/cyber/message/BUILD @@ -21,6 +21,7 @@ cc_library( name = "message_traits", hdrs = ["message_traits.h"], deps = [ + ":flatbuffers_traits", ":message_header", ":protobuf_traits", ":py_message_traits", @@ -35,8 +36,10 @@ cc_test( srcs = ["message_traits_test.cc"], deps = [ "//cyber", + "//cyber/message:flatbuffers_message", "//cyber/proto:unit_test_cc_proto", "@com_google_googletest//:gtest_main", + "@flatbuffers//:flatbuffers", ], ) @@ -114,3 +117,31 @@ cc_library( ":raw_message", ], ) + +cc_library( + name = "flatbuffers_message", + hdrs = ["flatbuffers_message.h"], + deps = [ + "@flatbuffers//:flatbuffers", + ], +) + +cc_library( + name = "flatbuffers_traits", + hdrs = ["flatbuffers_traits.h"], + deps = [ + ":flatbuffers_message", + ], +) + +cc_test( + name = "flatbuffers_message_test", + size = "small", + srcs = ["flatbuffers_message_test.cc"], + deps = [ + ":flatbuffers_message", + "//cyber/examples/proto:examples_fbs", + "@com_google_googletest//:gtest_main", + "@flatbuffers//:flatbuffers", + ], +) diff --git a/cyber/message/flatbuffers_message.h b/cyber/message/flatbuffers_message.h new file mode 100644 index 0000000..b5f075c --- /dev/null +++ b/cyber/message/flatbuffers_message.h @@ -0,0 +1,191 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_MESSAGE_FLATBUFFERS_MESSAGE_H_ +#define CYBER_MESSAGE_FLATBUFFERS_MESSAGE_H_ + +#include +#include +#include + +#include "flatbuffers/flatbuffers.h" + +namespace apollo { +namespace cyber { +namespace message { + +/** + * @brief Zero-copy message wrapper for FlatBuffers-serialized data. + * + * FlatBufferMessage stores a serialized FlatBuffers byte buffer and exposes + * the standard Cyber RT message interface (SerializeToArray, ParseFromArray, + * etc.) so it can be used interchangeably with RawMessage or Protobuf messages + * in the Cyber transport layer. + * + * Zero-copy semantics: when data arrives via the shared-memory transport, the + * underlying buffer pointer can be accessed directly through GetRoot() + * without any deserialization step. + * + * Usage example: + * @code + * flatbuffers::FlatBufferBuilder fbb; + * auto content = fbb.CreateString("Hello FlatBuffers"); + * auto chatter = CreateChatter(fbb, 123, 456, 1, content); + * fbb.Finish(chatter); + * + * FlatBufferMessage msg("my.type", fbb.GetBufferPointer(), fbb.GetSize()); + * + * // Zero-copy read: + * const auto* root = msg.GetRoot(); + * @endcode + */ +class FlatBufferMessage { + public: + FlatBufferMessage() : type_name_(""), timestamp_(0) {} + + /** + * @brief Construct from a type name and a pre-built FlatBuffers byte buffer. + * + * @param type_name Logical type identifier (used by the transport layer). + * @param data Pointer to the FlatBuffers serialized bytes. + * @param size Number of bytes in @p data. + */ + FlatBufferMessage(const std::string& type_name, const uint8_t* data, + size_t size) + : type_name_(type_name), + buffer_(data, data + size), + timestamp_(0) {} + + FlatBufferMessage(const FlatBufferMessage&) = default; + FlatBufferMessage& operator=(const FlatBufferMessage&) = default; + ~FlatBufferMessage() = default; + + // ----- Descriptor / type identity (mirrors RawMessage interface) ---------- + + class Descriptor { + public: + std::string full_name() const { + return "apollo.cyber.message.FlatBufferMessage"; + } + std::string name() const { + return "apollo.cyber.message.FlatBufferMessage"; + } + }; + + static const Descriptor* descriptor() { + static Descriptor desc; + return &desc; + } + + static std::string TypeName() { + return "apollo.cyber.message.FlatBufferMessage"; + } + + // ----- Serialization interface (required by message_traits.h) ------------- + + bool SerializeToArray(void* data, int size) const { + if (data == nullptr || size < ByteSize()) { + return false; + } + std::memcpy(data, buffer_.data(), buffer_.size()); + return true; + } + + bool SerializeToString(std::string* str) const { + if (str == nullptr) { + return false; + } + str->assign(reinterpret_cast(buffer_.data()), buffer_.size()); + return true; + } + + bool ParseFromArray(const void* data, int size) { + if (data == nullptr || size <= 0) { + return false; + } + const auto* bytes = static_cast(data); + buffer_.assign(bytes, bytes + size); + return true; + } + + bool ParseFromString(const std::string& str) { + buffer_.assign(str.begin(), str.end()); + return true; + } + + int ByteSize() const { return static_cast(buffer_.size()); } + + // ----- Zero-copy accessors ------------------------------------------------ + + /** + * @brief Return a pointer to the raw serialized bytes. + * + * When the transport layer writes this buffer directly into shared memory, + * the receiver can call GetRoot() on the same pointer without copying. + */ + const uint8_t* data() const { return buffer_.data(); } + + size_t size() const { return buffer_.size(); } + + /** + * @brief Zero-copy typed access to the FlatBuffers root object. + * + * @tparam T The FlatBuffers-generated root table type. + * @return Pointer into the existing buffer — no copy, no allocation. + */ + template + const T* GetRoot() const { + if (buffer_.empty()) { + return nullptr; + } + return flatbuffers::GetRoot(buffer_.data()); + } + + // ----- Ancillary fields used by the transport layer ----------------------- + + const std::string& type_name() const { return type_name_; } + + /** + * @brief Lowercase setter following conventional C++ naming style. + */ + void set_type_name(const std::string& name) { type_name_ = name; } + + /** + * @brief UpperCamelCase setter required by the `HasSetType` trait in + * message_traits.h. + * + * Both `set_type_name()` and `SetTypeName()` exist intentionally: + * `set_type_name()` follows standard C++ getter/setter naming, while + * `SetTypeName()` is the name detected by `DEFINE_TYPE_TRAIT(HasSetType, + * SetTypeName)` so the transport layer (e.g., `ParseFromHC`) can propagate + * the message type identifier through a generic template interface. + */ + void SetTypeName(const std::string& name) { type_name_ = name; } + + uint64_t timestamp() const { return timestamp_; } + void set_timestamp(uint64_t ts) { timestamp_ = ts; } + + private: + std::string type_name_; + std::vector buffer_; + uint64_t timestamp_; +}; + +} // namespace message +} // namespace cyber +} // namespace apollo + +#endif // CYBER_MESSAGE_FLATBUFFERS_MESSAGE_H_ diff --git a/cyber/message/flatbuffers_message_test.cc b/cyber/message/flatbuffers_message_test.cc new file mode 100644 index 0000000..605060e --- /dev/null +++ b/cyber/message/flatbuffers_message_test.cc @@ -0,0 +1,219 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/message/flatbuffers_message.h" + +#include +#include +#include + +#include "gtest/gtest.h" + +#include "cyber/examples/proto/examples_generated.h" + +namespace apollo { +namespace cyber { +namespace message { + +// --------------------------------------------------------------------------- +// Helper: build a Chatter FlatBuffer and return the detached buffer bytes. +// --------------------------------------------------------------------------- +static std::vector BuildChatterBuffer(uint64_t seq, + const char* content) { + flatbuffers::FlatBufferBuilder fbb; + auto content_str = fbb.CreateString(content); + auto chatter = + examples::proto::CreateChatter(fbb, /*timestamp=*/1000, + /*lidar_timestamp=*/2000, seq, content_str); + fbb.Finish(chatter); + return {fbb.GetBufferPointer(), fbb.GetBufferPointer() + fbb.GetSize()}; +} + +// --------------------------------------------------------------------------- +// Construction tests +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, DefaultConstructor) { + FlatBufferMessage msg; + EXPECT_EQ(msg.ByteSize(), 0); + EXPECT_EQ(msg.type_name(), ""); + EXPECT_EQ(msg.timestamp(), 0u); + EXPECT_EQ(msg.data(), nullptr); +} + +TEST(FlatBufferMessageTest, ConstructFromBuffer) { + auto buf = BuildChatterBuffer(42, "hello"); + FlatBufferMessage msg("my.Chatter", buf.data(), buf.size()); + + EXPECT_EQ(msg.type_name(), "my.Chatter"); + EXPECT_EQ(static_cast(msg.ByteSize()), buf.size()); + EXPECT_NE(msg.data(), nullptr); +} + +// --------------------------------------------------------------------------- +// Zero-copy access +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, ZeroCopyGetRoot) { + auto buf = BuildChatterBuffer(7, "zero-copy"); + FlatBufferMessage msg("my.Chatter", buf.data(), buf.size()); + + const auto* chatter = msg.GetRoot(); + ASSERT_NE(chatter, nullptr); + EXPECT_EQ(chatter->seq(), 7u); + EXPECT_STREQ(chatter->content()->c_str(), "zero-copy"); + EXPECT_EQ(chatter->timestamp(), 1000u); + EXPECT_EQ(chatter->lidar_timestamp(), 2000u); +} + +TEST(FlatBufferMessageTest, GetRootOnEmptyMessageReturnsNull) { + FlatBufferMessage msg; + EXPECT_EQ(msg.GetRoot(), nullptr); +} + +// --------------------------------------------------------------------------- +// Serialization round-trip +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, SerializeToArrayAndParseBack) { + auto buf = BuildChatterBuffer(3, "array-roundtrip"); + FlatBufferMessage src("my.Chatter", buf.data(), buf.size()); + + std::vector scratch(src.ByteSize()); + ASSERT_TRUE(src.SerializeToArray(scratch.data(), static_cast(scratch.size()))); + + FlatBufferMessage dst; + ASSERT_TRUE(dst.ParseFromArray(scratch.data(), static_cast(scratch.size()))); + + const auto* chatter = dst.GetRoot(); + ASSERT_NE(chatter, nullptr); + EXPECT_EQ(chatter->seq(), 3u); + EXPECT_STREQ(chatter->content()->c_str(), "array-roundtrip"); +} + +TEST(FlatBufferMessageTest, SerializeToStringAndParseBack) { + auto buf = BuildChatterBuffer(9, "string-roundtrip"); + FlatBufferMessage src("my.Chatter", buf.data(), buf.size()); + + std::string serialized; + ASSERT_TRUE(src.SerializeToString(&serialized)); + EXPECT_EQ(serialized.size(), buf.size()); + + FlatBufferMessage dst; + ASSERT_TRUE(dst.ParseFromString(serialized)); + + const auto* chatter = dst.GetRoot(); + ASSERT_NE(chatter, nullptr); + EXPECT_EQ(chatter->seq(), 9u); + EXPECT_STREQ(chatter->content()->c_str(), "string-roundtrip"); +} + +// --------------------------------------------------------------------------- +// Serialize edge-cases +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, SerializeToArrayNullFails) { + auto buf = BuildChatterBuffer(1, "x"); + FlatBufferMessage msg("t", buf.data(), buf.size()); + EXPECT_FALSE(msg.SerializeToArray(nullptr, 128)); +} + +TEST(FlatBufferMessageTest, SerializeToArrayTooSmallFails) { + auto buf = BuildChatterBuffer(1, "x"); + FlatBufferMessage msg("t", buf.data(), buf.size()); + EXPECT_FALSE(msg.SerializeToArray(buf.data(), 0)); +} + +TEST(FlatBufferMessageTest, SerializeToStringNullFails) { + auto buf = BuildChatterBuffer(1, "x"); + FlatBufferMessage msg("t", buf.data(), buf.size()); + EXPECT_FALSE(msg.SerializeToString(nullptr)); +} + +TEST(FlatBufferMessageTest, ParseFromArrayNullFails) { + FlatBufferMessage msg; + EXPECT_FALSE(msg.ParseFromArray(nullptr, 8)); +} + +TEST(FlatBufferMessageTest, ParseFromArrayZeroSizeFails) { + FlatBufferMessage msg; + uint8_t dummy = 0; + EXPECT_FALSE(msg.ParseFromArray(&dummy, 0)); +} + +// --------------------------------------------------------------------------- +// Descriptor / TypeName +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, TypeName) { + EXPECT_EQ(FlatBufferMessage::TypeName(), + "apollo.cyber.message.FlatBufferMessage"); +} + +TEST(FlatBufferMessageTest, Descriptor) { + const auto* desc = FlatBufferMessage::descriptor(); + ASSERT_NE(desc, nullptr); + EXPECT_EQ(desc->full_name(), "apollo.cyber.message.FlatBufferMessage"); + EXPECT_EQ(desc->name(), "apollo.cyber.message.FlatBufferMessage"); +} + +// --------------------------------------------------------------------------- +// Ancillary fields +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, TypeNameSetter) { + FlatBufferMessage msg; + msg.set_type_name("foo.bar.Baz"); + EXPECT_EQ(msg.type_name(), "foo.bar.Baz"); +} + +TEST(FlatBufferMessageTest, TimestampSetter) { + FlatBufferMessage msg; + msg.set_timestamp(999u); + EXPECT_EQ(msg.timestamp(), 999u); +} + +// --------------------------------------------------------------------------- +// Copy semantics +// --------------------------------------------------------------------------- + +TEST(FlatBufferMessageTest, CopyConstructor) { + auto buf = BuildChatterBuffer(5, "copy"); + FlatBufferMessage src("my.Chatter", buf.data(), buf.size()); + FlatBufferMessage dst(src); + + EXPECT_EQ(dst.ByteSize(), src.ByteSize()); + EXPECT_EQ(dst.type_name(), src.type_name()); + + const auto* chatter = dst.GetRoot(); + ASSERT_NE(chatter, nullptr); + EXPECT_EQ(chatter->seq(), 5u); +} + +TEST(FlatBufferMessageTest, CopyAssignment) { + auto buf = BuildChatterBuffer(6, "assign"); + FlatBufferMessage src("my.Chatter", buf.data(), buf.size()); + FlatBufferMessage dst; + dst = src; + + const auto* chatter = dst.GetRoot(); + ASSERT_NE(chatter, nullptr); + EXPECT_EQ(chatter->seq(), 6u); +} + +} // namespace message +} // namespace cyber +} // namespace apollo diff --git a/cyber/message/flatbuffers_traits.h b/cyber/message/flatbuffers_traits.h new file mode 100644 index 0000000..2558d6a --- /dev/null +++ b/cyber/message/flatbuffers_traits.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_MESSAGE_FLATBUFFERS_TRAITS_H_ +#define CYBER_MESSAGE_FLATBUFFERS_TRAITS_H_ + +#include + +#include "cyber/message/flatbuffers_message.h" + +namespace apollo { +namespace cyber { +namespace message { + +/** + * Inline overloads for FlatBufferMessage. + * + * These follow the same pattern as raw_message_traits.h and + * py_message_traits.h: plain (non-template) overloads that the compiler + * selects ahead of the generic SFINAE templates in message_traits.h, + * ensuring correct ByteSize / serialization behaviour for + * FlatBufferMessage in the Cyber RT transport layer. + */ + +inline bool SerializeToArray(const FlatBufferMessage& message, void* data, + int size) { + return message.SerializeToArray(data, size); +} + +inline bool ParseFromArray(const void* data, int size, + FlatBufferMessage* message) { + return message->ParseFromArray(data, size); +} + +/** + * @brief Return the serialized byte size of a FlatBufferMessage. + * + * FlatBufferMessage::ByteSize() is the canonical size accessor. This + * overload ensures message::ByteSize(msg) returns the correct value for + * the shared-memory transmitter (which would otherwise get -1 from the + * generic SFINAE template that looks for ByteSizeLong()). + */ +inline int ByteSize(const FlatBufferMessage& message) { + return message.ByteSize(); +} + +} // namespace message +} // namespace cyber +} // namespace apollo + +#endif // CYBER_MESSAGE_FLATBUFFERS_TRAITS_H_ diff --git a/cyber/message/message_traits.h b/cyber/message/message_traits.h index 506203b..da84dab 100644 --- a/cyber/message/message_traits.h +++ b/cyber/message/message_traits.h @@ -21,6 +21,7 @@ #include "cyber/base/macros.h" #include "cyber/common/log.h" +#include "cyber/message/flatbuffers_traits.h" #include "cyber/message/message_header.h" #include "cyber/message/protobuf_traits.h" #include "cyber/message/py_message_traits.h" diff --git a/cyber/message/message_traits_test.cc b/cyber/message/message_traits_test.cc index c83d052..4bf7c79 100644 --- a/cyber/message/message_traits_test.cc +++ b/cyber/message/message_traits_test.cc @@ -20,6 +20,7 @@ #include "gtest/gtest.h" +#include "cyber/message/flatbuffers_message.h" #include "cyber/proto/unit_test.pb.h" namespace apollo { @@ -96,6 +97,10 @@ TEST(MessageTraitsTest, type_trait) { EXPECT_TRUE(HasSerializer::value); EXPECT_TRUE(HasGetDescriptorString::value); + EXPECT_TRUE(HasType::value); + EXPECT_TRUE(HasSerializer::value); + EXPECT_TRUE(HasSetType::value); + Message msg; EXPECT_EQ("type", MessageType(msg)); @@ -127,6 +132,12 @@ TEST(MessageTraitsTest, byte_size) { EXPECT_EQ(ByteSize(py_msg), 0); py_msg.set_data("123"); EXPECT_EQ(ByteSize(py_msg), 3); + + FlatBufferMessage fb_msg; + EXPECT_EQ(ByteSize(fb_msg), 0); + const uint8_t buf[] = {0x01, 0x02, 0x03}; + fb_msg.ParseFromArray(buf, static_cast(sizeof(buf))); + EXPECT_EQ(ByteSize(fb_msg), static_cast(sizeof(buf))); } TEST(MessageTraitsTest, serialize_to_array) { @@ -162,6 +173,12 @@ TEST(MessageTraitsTest, serialize_to_array) { std::string arr_str(array); EXPECT_EQ("content", arr_str); } + + memset(array, 0, sizeof(array)); + const uint8_t fb_buf[] = {0xAA, 0xBB, 0xCC}; + FlatBufferMessage fb_msg("test.type", fb_buf, sizeof(fb_buf)); + EXPECT_TRUE(SerializeToArray(fb_msg, array, sizeof(array))); + EXPECT_EQ(memcmp(array, fb_buf, sizeof(fb_buf)), 0); } TEST(MessageTraitsTest, serialize_to_string) { @@ -188,6 +205,13 @@ TEST(MessageTraitsTest, serialize_to_string) { RawMessage raw("content"); EXPECT_TRUE(SerializeToString(raw, &str)); EXPECT_EQ("content", str); + + str = ""; + const uint8_t fb_buf[] = {0x01, 0x02, 0x03}; + FlatBufferMessage fb_msg("test.type", fb_buf, sizeof(fb_buf)); + EXPECT_TRUE(SerializeToString(fb_msg, &str)); + EXPECT_EQ(str.size(), sizeof(fb_buf)); + EXPECT_EQ(memcmp(str.data(), fb_buf, sizeof(fb_buf)), 0); } TEST(MessageTraitsTest, parse_from_array) { @@ -211,6 +235,11 @@ TEST(MessageTraitsTest, parse_from_array) { RawMessage raw; EXPECT_TRUE(ParseFromArray(array, arr_str_len, &raw)); EXPECT_EQ(raw.message, arr_str); + + FlatBufferMessage fb_msg; + EXPECT_TRUE(ParseFromArray(array, arr_str_len, &fb_msg)); + EXPECT_EQ(fb_msg.ByteSize(), arr_str_len); + EXPECT_EQ(memcmp(fb_msg.data(), array, arr_str_len), 0); } TEST(MessageTraitsTest, parse_from_string) { @@ -230,6 +259,10 @@ TEST(MessageTraitsTest, parse_from_string) { RawMessage raw; EXPECT_TRUE(ParseFromString(str, &raw)); EXPECT_EQ(str, raw.message); + + FlatBufferMessage fb_msg; + EXPECT_TRUE(ParseFromString(str, &fb_msg)); + EXPECT_EQ(fb_msg.ByteSize(), static_cast(str.size())); } TEST(MessageTraitsTest, serialize_parse_hc) { @@ -275,6 +308,12 @@ TEST(MessageTraitsTest, message_type) { proto::UnitTest ut; msg_type = MessageType(ut); EXPECT_EQ(msg_type, "apollo.cyber.proto.UnitTest"); + + FlatBufferMessage fb_msg; + msg_type = MessageType(); + EXPECT_EQ(msg_type, "apollo.cyber.message.FlatBufferMessage"); + msg_type = MessageType(fb_msg); + EXPECT_EQ(msg_type, "apollo.cyber.message.FlatBufferMessage"); } TEST(MessageTraitsTest, descriptor) { @@ -303,6 +342,12 @@ TEST(MessageTraitsTest, descriptor) { desc = ""; GetDescriptorString("apollo", &desc); EXPECT_EQ("message", desc); + + // FlatBuffers messages have no Protobuf descriptor string. + desc = "non-empty"; + GetDescriptorString("apollo.cyber.message.FlatBufferMessage", + &desc); + EXPECT_EQ("", desc); } } // namespace message diff --git a/cyber/proto/BUILD b/cyber/proto/BUILD index 6b9a886..7098ebb 100644 --- a/cyber/proto/BUILD +++ b/cyber/proto/BUILD @@ -1,164 +1,139 @@ -load("@rules_cc//cc:defs.bzl", "cc_proto_library") - -## Auto generated by `proto_build_generator.py` -load("@rules_proto//proto:defs.bzl", "proto_library") -load("//:bazel/python_rules.bzl", "py_proto_library") +## Auto generated by `proto_build_generator.sh` +load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library") +load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") package(default_visibility = ["//visibility:public"]) cc_proto_library( - name = "topology_change_cc_proto", + name = "choreography_conf_cc_proto", deps = [ - ":topology_change_proto", + ":choreography_conf_proto", ], ) proto_library( - name = "topology_change_proto", - srcs = ["topology_change.proto"], - deps = [ - ":role_attributes_proto", - ], + name = "choreography_conf_proto", + srcs = ["choreography_conf.proto"], ) py_proto_library( - name = "topology_change_py_pb2", - deps = [ - ":role_attributes_py_pb2", - ":topology_change_proto", - ], + name = "choreography_conf_py_pb2", + deps = [":choreography_conf_proto"], ) cc_proto_library( - name = "dag_conf_cc_proto", + name = "classic_conf_cc_proto", deps = [ - ":dag_conf_proto", + ":classic_conf_proto", ], ) proto_library( - name = "dag_conf_proto", - srcs = ["dag_conf.proto"], - deps = [ - ":component_conf_proto", - ], + name = "classic_conf_proto", + srcs = ["classic_conf.proto"], ) py_proto_library( - name = "dag_conf_py_pb2", - deps = [ - ":component_conf_py_pb2", - ":dag_conf_proto", - ], + name = "classic_conf_py_pb2", + deps = [":classic_conf_proto"], ) cc_proto_library( - name = "proto_desc_cc_proto", + name = "clock_cc_proto", deps = [ - ":proto_desc_proto", + ":clock_proto", ], ) proto_library( - name = "proto_desc_proto", - srcs = ["proto_desc.proto"], + name = "clock_proto", + srcs = ["clock.proto"], ) py_proto_library( - name = "proto_desc_py_pb2", - deps = [ - ":proto_desc_proto", - ], + name = "clock_py_pb2", + deps = [":clock_proto"], ) cc_proto_library( - name = "choreography_conf_cc_proto", + name = "component_conf_cc_proto", deps = [ - ":choreography_conf_proto", + ":component_conf_proto", ], ) proto_library( - name = "choreography_conf_proto", - srcs = ["choreography_conf.proto"], + name = "component_conf_proto", + srcs = ["component_conf.proto"], + deps = [ + ":qos_profile_proto", + ], ) py_proto_library( - name = "choreography_conf_py_pb2", - deps = [ - ":choreography_conf_proto", - ], + name = "component_conf_py_pb2", + deps = [":component_conf_proto"], ) cc_proto_library( - name = "record_cc_proto", + name = "cyber_conf_cc_proto", deps = [ - ":record_proto", + ":cyber_conf_proto", ], ) proto_library( - name = "record_proto", - srcs = ["record.proto"], + name = "cyber_conf_proto", + srcs = ["cyber_conf.proto"], + deps = [ + ":perf_conf_proto", + ":run_mode_conf_proto", + ":scheduler_conf_proto", + ":transport_conf_proto", + ], ) py_proto_library( - name = "record_py_pb2", - deps = [ - ":record_proto", - ], + name = "cyber_conf_py_pb2", + deps = [":cyber_conf_proto"], ) cc_proto_library( - name = "component_conf_cc_proto", + name = "dag_conf_cc_proto", deps = [ - ":component_conf_proto", + ":dag_conf_proto", ], ) proto_library( - name = "component_conf_proto", - srcs = ["component_conf.proto"], + name = "dag_conf_proto", + srcs = ["dag_conf.proto"], deps = [ - ":qos_profile_proto", + ":component_conf_proto", ], ) py_proto_library( - name = "component_conf_py_pb2", - deps = [ - ":component_conf_proto", - ":qos_profile_py_pb2", - ], + name = "dag_conf_py_pb2", + deps = [":dag_conf_proto"], ) cc_proto_library( - name = "cyber_conf_cc_proto", + name = "parameter_cc_proto", deps = [ - ":cyber_conf_proto", + ":parameter_proto", ], ) proto_library( - name = "cyber_conf_proto", - srcs = ["cyber_conf.proto"], - deps = [ - ":perf_conf_proto", - ":run_mode_conf_proto", - ":scheduler_conf_proto", - ":transport_conf_proto", - ], + name = "parameter_proto", + srcs = ["parameter.proto"], ) py_proto_library( - name = "cyber_conf_py_pb2", - deps = [ - ":cyber_conf_proto", - ":perf_conf_py_pb2", - ":run_mode_conf_py_pb2", - ":scheduler_conf_py_pb2", - ":transport_conf_py_pb2", - ], + name = "parameter_py_pb2", + deps = [":parameter_proto"], ) cc_proto_library( @@ -175,68 +150,80 @@ proto_library( py_proto_library( name = "perf_conf_py_pb2", - deps = [ - ":perf_conf_proto", - ], + deps = [":perf_conf_proto"], ) cc_proto_library( - name = "classic_conf_cc_proto", + name = "proto_desc_cc_proto", deps = [ - ":classic_conf_proto", + ":proto_desc_proto", ], ) proto_library( - name = "classic_conf_proto", - srcs = ["classic_conf.proto"], + name = "proto_desc_proto", + srcs = ["proto_desc.proto"], ) py_proto_library( - name = "classic_conf_py_pb2", - deps = [ - ":classic_conf_proto", - ], + name = "proto_desc_py_pb2", + deps = [":proto_desc_proto"], ) cc_proto_library( - name = "parameter_cc_proto", + name = "qos_profile_cc_proto", deps = [ - ":parameter_proto", + ":qos_profile_proto", ], ) proto_library( - name = "parameter_proto", - srcs = ["parameter.proto"], + name = "qos_profile_proto", + srcs = ["qos_profile.proto"], ) py_proto_library( - name = "parameter_py_pb2", - deps = [ - ":parameter_proto", - ], + name = "qos_profile_py_pb2", + deps = [":qos_profile_proto"], ) cc_proto_library( - name = "unit_test_cc_proto", + name = "role_attributes_cc_proto", deps = [ - ":unit_test_proto", + ":role_attributes_proto", ], ) proto_library( - name = "unit_test_proto", - srcs = ["unit_test.proto"], + name = "role_attributes_proto", + srcs = ["role_attributes.proto"], + deps = [ + ":qos_profile_proto", + ], ) py_proto_library( - name = "unit_test_py_pb2", + name = "role_attributes_py_pb2", + deps = [":role_attributes_proto"], +) + +cc_proto_library( + name = "run_mode_conf_cc_proto", deps = [ - ":unit_test_proto", + ":run_mode_conf_proto", ], ) +proto_library( + name = "run_mode_conf_proto", + srcs = ["run_mode_conf.proto"], +) + +py_proto_library( + name = "run_mode_conf_py_pb2", + deps = [":run_mode_conf_proto"], +) + cc_proto_library( name = "scheduler_conf_cc_proto", deps = [ @@ -255,108 +242,76 @@ proto_library( py_proto_library( name = "scheduler_conf_py_pb2", - deps = [ - ":choreography_conf_py_pb2", - ":classic_conf_py_pb2", - ":scheduler_conf_proto", - ], + deps = [":scheduler_conf_proto"], ) cc_proto_library( - name = "transport_conf_cc_proto", + name = "topology_change_cc_proto", deps = [ - ":transport_conf_proto", + ":topology_change_proto", ], ) proto_library( - name = "transport_conf_proto", - srcs = ["transport_conf.proto"], -) - -py_proto_library( - name = "transport_conf_py_pb2", - deps = [ - ":transport_conf_proto", - ], -) - -cc_proto_library( - name = "qos_profile_cc_proto", + name = "topology_change_proto", + srcs = ["topology_change.proto"], deps = [ - ":qos_profile_proto", + ":role_attributes_proto", ], ) -proto_library( - name = "qos_profile_proto", - srcs = ["qos_profile.proto"], -) - py_proto_library( - name = "qos_profile_py_pb2", - deps = [ - ":qos_profile_proto", - ], + name = "topology_change_py_pb2", + deps = [":topology_change_proto"], ) cc_proto_library( - name = "run_mode_conf_cc_proto", + name = "unit_test_cc_proto", deps = [ - ":run_mode_conf_proto", + ":unit_test_proto", ], ) proto_library( - name = "run_mode_conf_proto", - srcs = ["run_mode_conf.proto"], + name = "unit_test_proto", + srcs = ["unit_test.proto"], ) py_proto_library( - name = "run_mode_conf_py_pb2", - deps = [ - ":run_mode_conf_proto", - ], + name = "unit_test_py_pb2", + deps = [":unit_test_proto"], ) cc_proto_library( - name = "role_attributes_cc_proto", + name = "record_cc_proto", deps = [ - ":role_attributes_proto", + ":record_proto", ], ) proto_library( - name = "role_attributes_proto", - srcs = ["role_attributes.proto"], - deps = [ - ":qos_profile_proto", - ], + name = "record_proto", + srcs = ["record.proto"], ) py_proto_library( - name = "role_attributes_py_pb2", - deps = [ - ":qos_profile_py_pb2", - ":role_attributes_proto", - ], + name = "record_py_pb2", + deps = [":record_proto"], ) cc_proto_library( - name = "clock_cc_proto", + name = "transport_conf_cc_proto", deps = [ - ":clock_proto", + ":transport_conf_proto", ], ) proto_library( - name = "clock_proto", - srcs = ["clock.proto"], + name = "transport_conf_proto", + srcs = ["transport_conf.proto"], ) py_proto_library( - name = "clock_py_pb2", - deps = [ - ":clock_proto", - ], + name = "transport_conf_py_pb2", + deps = [":transport_conf_proto"], )