|
| 1 | ++++ |
| 2 | +title = "Changes Announced on January 20, 2026" |
| 3 | +linkTitle = "January 20, 2026" |
| 4 | +toc_hide = "true" |
| 5 | +description = "Changes announced for Protocol Buffers on January 20, 2026." |
| 6 | +type = "docs" |
| 7 | ++++ |
| 8 | + |
| 9 | +## Efficient headers in C++ |
| 10 | + |
| 11 | +As of the 34.0 release, the C++ code generator will start setting the `proto_h` |
| 12 | +option by default. Instead of just producing a `pb.h` header, it will begin |
| 13 | +producing both `pb.h` and `proto.h` ones. This provides a more efficient option |
| 14 | +to reduce build times in systems with large proto trees. |
| 15 | + |
| 16 | +### Opting out |
| 17 | + |
| 18 | +When `proto_h` is set, `pb.h` headers will still be generated for convenience |
| 19 | +when build size isn't a concern. You can continue to use these as before, as |
| 20 | +long as you make sure the `proto.h` headers are provided in your include path. |
| 21 | +The `pb.h` files will now simply import the `proto.h` header and all of their |
| 22 | +dependencies' `pb.h` files instead of defining any symbols themselves. |
| 23 | + |
| 24 | +If you hit problems with getting `proto.h` on your include path, you can restore |
| 25 | +the old behavior by passing the generator argument `proto_h=false` to protoc. |
| 26 | +For example: |
| 27 | + |
| 28 | +``` |
| 29 | +protoc --cpp_opt=proto_h=false --cpp_out=out/dir myproto.proto |
| 30 | +``` |
| 31 | + |
| 32 | +### Why `proto.h`? |
| 33 | + |
| 34 | +The traditional `pb.h` file transitively includes all the `pb.h` files of every |
| 35 | +other `.proto` whose messages are referenced in the file. As some of our message |
| 36 | +types reference hundreds of different message types, this can result in any code |
| 37 | +using a single field from one of these messages paying to compile the headers |
| 38 | +from every one of its referenced messages. This causes heavy load on your builds |
| 39 | +due to excessively long compiles, and even break them due to the amount of code |
| 40 | +being built. |
| 41 | + |
| 42 | +By contrast, `proto.h` headers do not include the headers for all the file's |
| 43 | +referenced messages. Instead, they use forward declarations to minimize the APIs |
| 44 | +exposed, which dramatically reduces compile time for some message types. |
| 45 | + |
| 46 | +### Using `proto.h` |
| 47 | + |
| 48 | +Because `proto.h` files don't include other message types' headers, you may need |
| 49 | +to modify your `#include`s in order to use them. For example, let's say you have |
| 50 | +two `.proto` files, `foo.proto` and `bar.proto`: |
| 51 | + |
| 52 | +```proto |
| 53 | +// my_package/foo.proto |
| 54 | +edition = "2023"; |
| 55 | +
|
| 56 | +package my_package; |
| 57 | +
|
| 58 | +message Foo { |
| 59 | + int32 some_data = 42; |
| 60 | +} |
| 61 | +
|
| 62 | +enum Truthy { |
| 63 | + TRUTHY_UNSPECIFIED = 0; |
| 64 | + TRUTHY_FALSE = 1; |
| 65 | + TRUTHY_TRUE = 2; |
| 66 | + TRUTHY_MAYBE = 3; |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +```proto |
| 71 | +// my_package/bar.proto |
| 72 | +edition = "2023"; |
| 73 | +
|
| 74 | +import "my_package/foo.proto"; |
| 75 | +
|
| 76 | +package my_package; |
| 77 | +
|
| 78 | +message Bar { |
| 79 | + Truthy some_flag = 42; |
| 80 | + repeated Foo foo = 43; |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +Using `pb.h` headers, you can write code like this: |
| 85 | + |
| 86 | +```c++ |
| 87 | +// my_package/test1.cc |
| 88 | +#include "my_package/bar.pb.h" |
| 89 | +namespace my_package { |
| 90 | +void Test1Function1(const Bar &bar_message) { |
| 91 | + if (bar_message.some_flag()) { ... } |
| 92 | +} |
| 93 | +void Test1Function2(const Bar &bar_message) { |
| 94 | + if (bar_message.some_flag() != MAYBE) { ... } |
| 95 | +} |
| 96 | +void Test1Function3(const Bar &bar_message) { |
| 97 | + for (Foo foo : bar_message.foos()) { |
| 98 | + DoSomething(foo.some_data()); |
| 99 | + } |
| 100 | + ... |
| 101 | +} |
| 102 | +``` |
| 103 | +
|
| 104 | +However, this will **not** work with `proto.h`, because you won't have the |
| 105 | +header information for `foo.proto`. To get this code to work, you need to |
| 106 | +`#include` the `proto.h` headers for both `bar.proto` **and** `foo.proto`. |
| 107 | +
|
| 108 | +```c++ |
| 109 | +// my_package/test1.cc |
| 110 | +#include "my_package/bar.proto.h" |
| 111 | +#include "my_package/foo.proto.h" |
| 112 | +namespace my_package { |
| 113 | +void Test1Function1(const Bar &bar_message) { |
| 114 | + if (bar_message.some_flag()) { ... } |
| 115 | +} |
| 116 | +void Test1Function2(const Bar &bar_message) { |
| 117 | + if (bar_message.some_flag() != MAYBE) { ... } |
| 118 | +} |
| 119 | +void Test1Function3(const Bar &bar_message) { |
| 120 | + for (Foo foo : bar_message.foos()) { |
| 121 | + DoSomething(foo.some_data()); |
| 122 | + } |
| 123 | + ... |
| 124 | +} |
| 125 | +``` |
0 commit comments