From 05148b4a15fa677c48ec5aab5b400052de6d0a0c Mon Sep 17 00:00:00 2001 From: Benjamin Rippel Date: Sat, 25 Apr 2026 22:32:51 +0200 Subject: [PATCH] Add --bfbs-gen-embed-constexpr flag Why: The existing --bfbs-gen-embed generates a struct with a function-local static array, making the binary schema inaccessible in constexpr contexts (e.g. compile-time schema processing). How: A new flag --bfbs-gen-embed-constexpr generates an inline constexpr file-scope array and size constant instead: inline constexpr uint8_t FooBinarySchema[] = { ... }; inline constexpr size_t FooBinarySchemaSize = N; The existing --bfbs-gen-embed output is unchanged. --- include/flatbuffers/idl.h | 2 ++ src/flatc.cpp | 5 +++ src/idl_gen_cpp.cpp | 64 ++++++++++++++++++++++++--------------- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 9e58d4be95..55ebed2bdc 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -694,6 +694,7 @@ struct IDLOptions { bool binary_schema_comments; bool binary_schema_builtins; bool binary_schema_gen_embed; + bool binary_schema_gen_embed_constexpr; bool binary_schema_absolute_paths; std::string go_import; std::string go_namespace; @@ -846,6 +847,7 @@ struct IDLOptions { binary_schema_comments(false), binary_schema_builtins(false), binary_schema_gen_embed(false), + binary_schema_gen_embed_constexpr(false), binary_schema_absolute_paths(false), protobuf_ascii_alike(false), size_prefixed(false), diff --git a/src/flatc.cpp b/src/flatc.cpp index ee34044fdd..f07ddc8069 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -201,6 +201,8 @@ const static FlatCOption flatc_options[] = { "Add builtin attributes to the binary schema files."}, {"", "bfbs-gen-embed", "", "Generate code to embed the bfbs schema to the source."}, + {"", "bfbs-gen-embed-constexpr", "", + "Generate file-scope constexpr array to embed the bfbs schema."}, {"", "conform", "FILE", "Specify a schema the following schemas should be an evolution of. Gives " "errors if not."}, @@ -629,6 +631,9 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc, opts.binary_schema_builtins = true; } else if (arg == "--bfbs-gen-embed") { opts.binary_schema_gen_embed = true; + } else if (arg == "--bfbs-gen-embed-constexpr") { + opts.binary_schema_gen_embed = true; + opts.binary_schema_gen_embed_constexpr = true; } else if (arg == "--bfbs-absolute-paths") { opts.binary_schema_absolute_paths = true; } else if (arg == "--reflect-types") { diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 9ad18a7b48..94925de426 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -397,29 +397,41 @@ class CppGenerator : public BaseGenerator { code_.SetValue("STRUCT_NAME", name); // Create code to return the binary schema data. - auto binary_schema_hex_text = - BufferToHexText(parser_.builder_.GetBufferPointer(), - parser_.builder_.GetSize(), 105, " ", ""); - - code_ += "struct {{STRUCT_NAME}}BinarySchema {"; - code_ += " static const uint8_t *data() {"; - code_ += " // Buffer containing the binary schema."; - code_ += " static const uint8_t bfbsData[" + - NumToString(parser_.builder_.GetSize()) + "] = {"; - code_ += binary_schema_hex_text; - code_ += " };"; - code_ += " return bfbsData;"; - code_ += " }"; - code_ += " static size_t size() {"; - code_ += " return " + NumToString(parser_.builder_.GetSize()) + ";"; - code_ += " }"; - code_ += " const uint8_t *begin() {"; - code_ += " return data();"; - code_ += " }"; - code_ += " const uint8_t *end() {"; - code_ += " return data() + size();"; - code_ += " }"; - code_ += "};"; + if (parser_.opts.binary_schema_gen_embed_constexpr) { + // File-scope constexpr array, usable in constant expressions. + auto binary_schema_hex_text = + BufferToHexText(parser_.builder_.GetBufferPointer(), + parser_.builder_.GetSize(), 105, " ", ""); + code_ += "inline constexpr uint8_t {{STRUCT_NAME}}BinarySchema[] = {"; + code_ += binary_schema_hex_text; + code_ += "};"; + code_ += "inline constexpr size_t {{STRUCT_NAME}}BinarySchemaSize = " + + NumToString(parser_.builder_.GetSize()) + ";"; + } else { + // Struct wrapper with function-local static. + auto binary_schema_hex_text = + BufferToHexText(parser_.builder_.GetBufferPointer(), + parser_.builder_.GetSize(), 105, " ", ""); + code_ += "struct {{STRUCT_NAME}}BinarySchema {"; + code_ += " static const uint8_t *data() {"; + code_ += " // Buffer containing the binary schema."; + code_ += " static const uint8_t bfbsData[" + + NumToString(parser_.builder_.GetSize()) + "] = {"; + code_ += binary_schema_hex_text; + code_ += " };"; + code_ += " return bfbsData;"; + code_ += " }"; + code_ += " static size_t size() {"; + code_ += " return " + NumToString(parser_.builder_.GetSize()) + ";"; + code_ += " }"; + code_ += " const uint8_t *begin() {"; + code_ += " return data();"; + code_ += " }"; + code_ += " const uint8_t *end() {"; + code_ += " return data() + size();"; + code_ += " }"; + code_ += "};"; + } code_ += ""; if (cur_name_space_) SetNameSpace(nullptr); @@ -2378,9 +2390,11 @@ class CppGenerator : public BaseGenerator { } // Adds a typedef to the binary schema type so one could get the bfbs based - // on the type at runtime. + // on the type at runtime. Skipped in constexpr mode because the schema is a + // file-scope array, not a struct with data()/size() methods. void GenBinarySchemaTypeDef(const StructDef* struct_def) { - if (struct_def && opts_.binary_schema_gen_embed) { + if (struct_def && opts_.binary_schema_gen_embed && + !opts_.binary_schema_gen_embed_constexpr) { code_ += " typedef " + WrapInNameSpace(*struct_def) + "BinarySchema BinarySchema;"; }