// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
\page qt_add_protobuf.html
\ingroup cmake-commands-qtprotobuf

\title qt_add_protobuf
\keyword qt6_add_protobuf
\summary {Generates Qt-based C++ source code using a protobuf schema.}

\include cmake-find-package-protobuf.qdocinc

\cmakecommandsince 6.5

Use qt_add_protobuf to invoke \c qtprotobufgen in your CMake scripts and generate
the code from the .proto schemes for your projects.\c qtprotobufgen would be
invoked through CMake using the \c qt_add_protobuf command.

\section1 Synopsis

\badcode
    qt_add_protobuf(<target>
        PROTO_FILES <file> ...
        [PROTO_INCLUDES <path> ...]
        [QML [QML_URI <uri>]]
        [OUTPUT_DIRECTORY <dir>]
        [GENERATE_PACKAGE_SUBFOLDERS]
        [COPY_COMMENTS]
        [EXPORT_MACRO <infix>]
        [OUTPUT_HEADERS <var>]
        [OUTPUT_TARGETS <var>]
        [HEADER_GUARD <pragma|filename>]
        [GENERATE_NON_FINAL_MESSAGES]
    )
\endcode

\versionlessCMakeCommandsNote qt6_add_protobuf()

\section1 Description

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


\list
    \include qtprotoccommon.qdocinc proto_files-li
    \include qtprotoccommon.qdocinc proto_includes-li
    \li \c {QML}
        enables the generation of QML-compatible message types from protobuf
        definitions and registers them as a QML module. If \c {qt_add_protobuf}
        is called on a non-existent target or a target that is not a QML
        module, a new QML module will be created implicitly.

        \badcode
            find_package(Qt6 6.8 REQUIRED COMPONENTS Quick Protobuf ProtobufQuick)
            ...
            qt_add_executable(target
                ...
            )
            // creates a new QML module
            qt_add_protobuf(target
                QML
                ...
            )
        \endcode

        If \e {target} is an existing QML module, \c {qt_add_protobuf} will
        attach the generated protobuf types to that module.

        \badcode
            find_package(Qt6 6.8 REQUIRED COMPONENTS Quick Protobuf ProtobufQuick)
            ...
            qt_add_qml_module(target
                ...
            )
            // adds to existing QML module
            qt_add_protobuf(target
                QML
                ...
            )
        \endcode

        \note If you use QML argument, you have to add ProtobufQuick into
              find_package call. See examples above.

    \li \c {QML_URI}
        defines the \c URI used for the QML module.

        Every QML module must define a \c {URI}, which is used in \l
        {qtqml-syntax-imports.html} {import statements} to expose its protobuf
        types to QML.

        \badcode
            qt_add_protobuf(target
                QML
                QML_URI proto.uri.example
            )
        \endcode

        If \c {QML_URI} is omitted, the protobuf package name will be used as
        the module's \c {URI}.

        \note If the \c {QML_URI} is omitted, all \e {.proto} files specified
        in the \c {PROTO_FILES} section must share the same protobuf package
        name, as it will be used as the default \c {URI} for the resulting QML
        module.

        \note You should avoid creating several protobuf QML modules with the
        same \c {QML_URI} or proto package name, because it leads to import
        error in the QML context.

        \note If \c {QML_URI} is passed to the \c {qt_add_protobuf} function
        but the target already exists, the \c {QML_URI} argument will be
        ignored.

        Read \l [QtQml] {Identified Modules} for further in-depth discussion of
        the \c URI.

    \include qtprotoccommon.qdocinc output_directory-li
    \include qtprotoccommon.qdocinc generate_package_subfolders-li
    \include qtprotoccommon.qdocinc copy_comments-li
    \include qtprotoccommon.qdocinc export_macro-cmake-li
    \include qtprotoccommon.qdocinc output_headers-li
    \include qtprotoccommon.qdocinc output_targets-li
    \include qtprotoccommon.qdocinc header_guard-li
    \include qtprotoccommon.qdocinc generate_non_final_messages-li
\endlist

\sa{The qtprotobufgen Tool}

\section1 Resolving dependencies between protobuf targets

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

The project may have two or more \c .proto files with dependencies:
\badcode
// test_messages.proto
syntax = "proto3";

package test.messages;

message MyMessage {
    int32 myField = 1;
}
\endcode

\badcode
// test_extensions.proto
syntax = "proto3";

import "test_messages.proto";

package test.extensions;

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

\endcode

The above \c .proto files can be used to generate the standalone libraries:
\badcode
qt_add_protobuf(test_messages
    PROTO_FILES
        test_messages.proto
)
...
qt_add_protobuf(test_extensions
    PROTO_FILES
        test_extensions.proto
)
...
\endcode

Since the \c test_extensions target depends on messages from the
\c test_messages target, you need to link to such targets manually in your
\c CMake scripts:
\badcode
target_link_libraries(test_extensions PUBLIC test_messages)
\endcode

\note Messages from \c test_messages target are used in header files that belong
to the \c test_extensions target, so targets that link to \c test_extensions
should have the \c test_messages target as a transitive dependency. It's
recommended to use the \c PUBLIC linking scope, to have the proper
\c INTERFACE_INCLUDE_DIRECTORIES and \c INTERFACE_LINK_LIBRARIES properties for
protobuf library targets.

\section1 Example

\include qt-add-protobuf-example.qdocinc 0
\include qt-add-protobuf-example.qdocinc 1
*/
