- Qt 6.6
- Qt Protobuf
- CMake Commands in Qt6 Protobuf
- qt_add_protobuf
- Qt 6.6.2 Reference Documentation

# qt_add_protobuf

Generates Qt-based C++ source code using a protobuf schema

Note: This command is in technology preview and may change in future releases.

This command was introduced in Qt 6.5.

Usually `qtprotobufgen` would be invoked through CMake using the `qt_add_protobuf` command.

     qt_add_protobuf(<target>
         PROTO_FILES <file> ...
         [COPY_COMMENTS]
         [GENERATE_PACKAGE_SUBFOLDERS]
         [EXTRA_NAMESPACE <namespace>]
         [EXPORT_MACRO <infix>]
         [QML [QML_URI <uri>]]
         [PROTO_INCLUDES <path> ...]
         [OUTPUT_DIRECTORY <dir>]
         [OUTPUT_HEADERS <var>]
         [OUTPUT_TARGETS <var>]
     )

The source files generated by `qtprotobufgen` are then added to the target. If the target already exists, the files are added to the target source list. If the target doesn't exist, it is created as a library which you must link to.

## Arguments

- `COPY_COMMENTS` copies comments from `.proto` files. If provided in the parameter list, comments related to messages and fields are copied to generated header files.
- `GENERATE_PACKAGE_SUBFOLDERS` generates a folder structure for the generated files matching the `.proto` file's package name. For example, `package io.qt.test;` would put the generated files into `io/qt/test/`.
- `EXTRA_NAMESPACE` is an optional namespace that will be used for the generated classes. The classes are always generated in a namespace whose name is the same as the package name specified in the `.proto` file. If this option is used, then everything will be nested inside the extra namespace.
- `EXPORT_MACRO` is the base name of the symbol export macro used for the generated code. The generated macro name is constructed as `QPB_<EXPORT_MACRO>_EXPORT`. If the option is not set, the macro is not generated.
- `QML` enables QProtobufMessage types in QML context by registering them as a QML module. Protobuf types can extend an existing QML module. See code examples:

       qt_add_qml_module(targetname
           ...
       )

       qt_add_protobuf(targetname
           QML
           ...
       )

       qt_add_executable(targetname
           ...
       )

       qt_add_protobuf(targetname
           QML
           ...
       )

  If `qt_add_protobuf` is called with a non-existing target or the target is not a QML module, a new QML module will be created implicitly. In case of the new QML module creation, the qt_add_qml_module command is called inside the `qt_add_protobuf` command. See code example:

       qt_add_executable(targetname
           ...
       )

       qt_add_protobuf(targetplugin
           QML
           QML_URI proto.uri.example
       )

  Every QML module has to define a `URI` name. Other QML modules may use this name in import statements to import the module into a user application. Use the `QML_URI` option to set the `URI` name. It has to be specified in dotted notation, e.g. `Qt.Protobuf.Package`. If `QML_URI` is omitted, then the protobuf package name will be used as the module `URI`.

  Note: If `QML_URI` is passed to `qt_add_protobuf` command but `target` already exists, `QML_URI` argument will be ignored.

  Note: If the `QML_URI` is skipped, all *.proto files specified in the `qt_add_protobuf` command should have the same `protobuf` package name, since it shall be used as a default `URI` for the resulting QML module.

  Note: You should avoid creating several QML modules with the same `QML_URI` or proto package name, because it leads to import error in QML context.

- `QML_URI` enables QProtobufMessage types in the QML context by registering them in a QML module via the provided `URI` import path. The `URI` option will be used in the line of the generated `qmldir` file, and also used to form the target path by replacing dots with forward slashes.

  Note: Read Identified Modules for further in-depth discussion of the `URI`.

- `PROTO_FILES` is the list of `.proto` files that will be used in the generation procedure.
- `PROTO_INCLUDES` is the list of directories that will be searched for dependencies.
- `OUTPUT_DIRECTORY` is the directory where the generated files will be put. By default, the current directory (while evaluating the function) is used.
- `OUTPUT_HEADERS` can be used to specify a variable that will hold the list of headers created by the function. This list can be useful for custom project install rules.
- `OUTPUT_TARGETS` can be used to specify a variable that will hold the list of targets created by the function. This list can be useful for custom project install rules.

## Resolving dependencies between protobuf targets

The `qt_add_protobuf` command doesn't consider the dependencies between `.proto` files that are used to generate code for different targets.

The project may have two or more `.proto` files with dependencies:

     syntax = "proto3";

     package test.messages;

     message MyMessage {
         int32 myField = 1;
     }

     syntax = "proto3";

     import "test_messages.proto";

     package test.extensions;

     message MyExtension {
         test.messages.MyMessage baseMessage = 1;
         int32 extension = 2;
     }

The above `.proto` files can be used to generate the standalone libraries:

     qt_add_protobuf(test_messages
         PROTO_FILES
             test_messages.proto
     )
     ...
     qt_add_protobuf(test_extensions
         PROTO_FILES
             test_extensions.proto
     )
     ...

Since the `test_extensions` target depends on messages from the `test_messages` target, users need to link to such targets manually in their `CMake` scripts:

     target_link_libraries(test_extensions PUBLIC test_messages)

Note: It's recommended to use the `PUBLIC` linking scope, since messages from `test_messages` target are referenced in header files that belong to the `test_extensions` target, so targets that link to `test_extensions` should have the `test_messages` target as a transitive dependency.

## Example

     cmake_minimum_required(VERSION 3.16...3.22)
     project(MyThings)

     find_package(Qt6 REQUIRED COMPONENTS Protobuf)
     qt_standard_project_setup()

     qt_add_protobuf(MyMessages
         GENERATE_PACKAGE_SUBFOLDERS
         PROTO_FILES
             path/to/message.proto
             path/to/other_message.proto
         PROTO_INCLUDES
             /path/to/proto/include
     )

     qt_add_executable(MyApp main.cpp)

     target_link_libraries(MyApp PRIVATE MyMessages)

In the example above, we generate a library called `MyMessages`, which contains the message types defined in the paths passed to the `PROTO_FILES` option. The `GENERATE_PACKAGE_SUBFOLDERS` option to generate a folder structure for the generated files. And the `PROTO_INCLUDES` option tells protoc to look for dependencies or imports in the specified directories. We create a target for an executable called `MyApp`, which we link to the `MyMessages` library.

### QML extended protobuf example:

     cmake_minimum_required(VERSION 3.16...3.22)
     project(MyThings)

     find_package(Qt6 REQUIRED COMPONENTS Protobuf Quick)
     qt_standard_project_setup()

     qt_add_protobuf(MyMessagesPlugin
         QML
         QML_URI my.messages.module.uri
         PROTO_FILES
             path/to/message.proto
             path/to/other_message.proto
         PROTO_INCLUDES
             /path/to/proto/include
     )

     qt_add_protobuf(MyApp
         QML
         PROTO_FILES
             path/to/internal_message.proto
         PROTO_INCLUDES
             /path/to/proto/include
     )

     qt_add_qml_module(MyApp
         URI example.uri
         VERSION 1.0
         QML_FILES qml/main.qml
     )

     qt_add_executable(MyApp main.cpp)
     target_link_libraries(MyApp PRIVATE Quick)

In the QML extended example above, by the first `qt_add_protobuf` call, we generate a QML module called `MyMessagesPlugin`, which contains the message types defined in the paths passed to the `PROTO_FILES` option. We use the `QML` option, that enables proto message types registration in the `QML` context. The registered types will be available in `QML` by importing a path that is set by the `QML_URI`. By second `qt_add_protobuf` call we add auto-generated code into the existing `MyApp` QML module. The `QML_URI` is not required in such cases. Finally, we create a target for an executable called `MyApp`, which has a QML module for the graphical part and loads `MyMessagesPlugin` into the main.qml file via the `my.messages.module.uri` import.

See also The qtprotobufgen Tool.