Browse Source

Use CMake script to make the pre-parsing of a proto file

- Replace the golang script with the CMake script
- Rework the 'qtprotobuf_generate' function
- Fix generating of messages that contains preceding spaces in
  declaration
Fixes #214
Alexey Edelev 2 years ago
parent
commit
63bc9404bb

+ 1 - 2
CMakeLists.txt

@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.14)
-cmake_policy(VERSION 3.6...3.14)
+cmake_minimum_required(VERSION 3.16...3.22)
 
 set(QT_PROTOBUF_VERSION 0.6.0)
 set(QT_PROTOBUF_NAMESPACE QtProtobuf)

+ 5 - 14
README.md

@@ -418,7 +418,7 @@ file(GLOB PROTO_FILES ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/path/to/protofile1.pr
 # and link them to the MyTarget as static library
 add_executable(MyTarget main.cpp) # Add your target here
 qtprotobuf_generate(TARGET MyTarget
-OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
+OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated
 PROTO_FILES ${PROTO_FILES})
 
 ```
@@ -427,16 +427,9 @@ Another option is to pre-specify expected generated headers to prevent dummy-par
 
 ```cmake
 ...
-set(GENERATED_HEADERS
-# List of artifacts expected after qtprotobufgen job done.
-# Usually it's full list of messages in all packages with .h header suffix
-...
-)
-...
 qtprotobuf_generate(TARGET MyTarget
-OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
-PROTO_FILES ${PROTO_FILES}
-GENERATED_HEADERS ${GENERATED_HEADERS})
+OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated
+PROTO_FILES ${PROTO_FILES})
 ...
 ```
 
@@ -454,13 +447,11 @@ qtprotobuf_generate is cmake helper function that automatically generates STATIC
 
 ***Parameters:***
 
-*TARGET* - name of you target that generated code archive will be linked to
+*TARGET* - a name of your target that the generated code will be linked to.
 
 *GENERATED_TARGET* - name that will be used for generated archive library target. It's usefull when you supposed to have multiple generated targets to be linked to single one.
 
-*OUT_DIR* - output directory that will contain generated artifacts. Usually subfolder in build directory should be used
-
-*GENERATED_HEADERS* - List of header files expected after generator job finished
+*OUTPUT_DIRECTORY* - output directory that will contain generated artifacts. Usually subfolder in build directory should be used
 
 *EXCLUDE_HEADERS* - List of header files to be excluded from pre-parsed list of expected header files (e.g. nested messages that are not supported by QtProtobuf generator)
 

+ 98 - 0
cmake/QtPreParseProtoFile.cmake

@@ -0,0 +1,98 @@
+cmake_minimum_required(VERSION 3.16)
+
+function(extract_proto_keys out_var regex file_content)
+    cmake_parse_arguments(arg "SINGLE_VALUE" "" "" ${ARGN})
+
+
+endfunction()
+
+if(NOT PROTO_FILE OR NOT EXISTS "${PROTO_FILE}")
+    message(FATAL_ERROR "Unable to scan '${PROTO_FILE}': file doesn't exist.")
+endif()
+
+file(READ "${PROTO_FILE}" file_content)
+if(NOT file_content)
+    message(FATAL_ERROR "Unable to read ${PROTO_FILE}.")
+endif()
+
+STRING(REPLACE ";" "\\\\;" file_content "${file_content}")
+STRING(REPLACE "\n" ";" file_content "${file_content}")
+
+set(proto_key_common_regex "[\t ]+([a-zA-Z0-9_]+)")
+
+set(unclosed_braces 0)
+set(in_message_scope FALSE)
+foreach(item IN LISTS file_content)
+    if(item MATCHES "^[\t ]*package[\t ]+([a-zA-Z0-9_\.\-]+)")
+        set(proto_package "${CMAKE_MATCH_1}")
+    elseif(item MATCHES "^[\t ]*message${proto_key_common_regex}")
+        # Skip adding nested messages to the list.
+        # Multi-file generator puts the nested messages to the same file as the parent one. So
+        # generated
+        if(unclosed_braces EQUAL 0)
+            list(APPEND proto_messages "${CMAKE_MATCH_1}")
+            set(in_message_scope TRUE)
+        endif()
+    elseif(item MATCHES "^[\t ]*service${proto_key_common_regex}")
+        list(APPEND proto_services "${CMAKE_MATCH_1}")
+    elseif(item MATCHES "^[\t ]*enum${proto_key_common_regex}")
+        list(APPEND proto_enums "${CMAKE_MATCH_1}")
+    endif()
+    if(in_message_scope)
+        if(item MATCHES "[^/]*\\{")
+            math(EXPR unclosed_braces "${unclosed_braces} + 1")
+        endif()
+        if(item MATCHES "[^/]*\\}")
+            math(EXPR unclosed_braces "${unclosed_braces} - 1")
+            if(unclosed_braces EQUAL 0)
+                set(in_message_scope FALSE)
+            endif()
+        endif()
+    endif()
+endforeach()
+
+unset(output_files)
+string(REPLACE "." "/" package_full_path "${proto_package}")
+if(MULTI)
+    foreach(item IN LISTS proto_messages)
+        string(TOLOWER "${item}" item)
+        list(APPEND output_files
+            "${package_full_path}/${item}.h"
+            "${package_full_path}/${item}.cpp"
+        )
+    endforeach()
+    foreach(item IN LISTS proto_services)
+        string(TOLOWER "${item}" item)
+        list(APPEND output_files
+            "${package_full_path}/${item}client.h"
+            "${package_full_path}/${item}client.cpp"
+        # TODO: Generating of a server side code is not supported yet.
+        #     "${package_full_path}/${item}server.h"
+        #     "${package_full_path}/${item}server.cpp"
+        )
+    endforeach()
+else()
+    get_filename_component(basename "${PROTO_FILE}" NAME_WLE)
+    list(LENGTH proto_messages message_count)
+    list(LENGTH proto_enums enum_count)
+    list(LENGTH proto_services service_count)
+
+    set(folder_path "")
+    if(FOLDER)
+        set(folder_path "${package_full_path}/")
+    endif()
+    if(proto_messages OR proto_enums)
+        list(APPEND output_files
+            "${folder_path}${basename}.qpb.h"
+            "${folder_path}${basename}.qpb.cpp"
+        )
+    endif()
+    if(proto_services)
+        list(APPEND output_files
+            "${folder_path}${basename}_grpc.qpb.h"
+            "${folder_path}${basename}_grpc.qpb.cpp"
+        )
+    endif()
+endif()
+
+message("${output_files}")

+ 140 - 122
cmake/QtProtobufGen.cmake

@@ -1,190 +1,208 @@
-function(qtprotobuf_link_target TARGET GENERATED_TARGET)
-    target_sources(${TARGET} PRIVATE $<TARGET_OBJECTS:${GENERATED_TARGET}>)
-    target_include_directories(${TARGET} PRIVATE $<TARGET_PROPERTY:${GENERATED_TARGET},INTERFACE_INCLUDE_DIRECTORIES>)
-    add_dependencies(${TARGET} ${GENERATED_TARGET})
+# TODO: give the variable a proper name while migrating to Qt6
+set(_qt_internal_qtprotobuf_top_level_dir "${CMAKE_CURRENT_LIST_DIR}")
+
+function(qtprotobuf_link_target target generated_target)
+    target_sources(${target} PRIVATE $<TARGET_OBJECTS:${generated_target}>)
+    target_include_directories(${target} PRIVATE $<TARGET_PROPERTY:${generated_target},INTERFACE_INCLUDE_DIRECTORIES>)
+    add_dependencies(${target} ${generated_target})
 endfunction()
 
 function(qtprotobuf_generate)
     set(options MULTI QML COMMENTS FOLDER FIELDENUM)
-    set(oneValueArgs OUT_DIR TARGET GENERATED_TARGET EXTRA_NAMESPACE)
-    set(multiValueArgs GENERATED_HEADERS EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
-    cmake_parse_arguments(qtprotobuf_generate "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
-    if(DEFINED qtprotobuf_generate_GENERATED_TARGET)
-        set(GENERATED_TARGET_NAME ${qtprotobuf_generate_GENERATED_TARGET})
-    elseif(DEFINED qtprotobuf_generate_TARGET)
-        set(GENERATED_TARGET_NAME ${qtprotobuf_generate_TARGET}_qtprotobuf_gen)
-    else()
-        message(FATAL_ERROR "Either TARGET or GENERATED_TARGET must be specified")
+    set(oneValueArgs OUTPUT_DIRECTORY TARGET GENERATED_TARGET EXTRA_NAMESPACE)
+    set(multiValueArgs EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
+    cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    if(NOT DEFINED arg_PROTO_FILES)
+        message(FATAL_ERROR "Missing the PROTO_FILES argument.")
     endif()
 
-    set(deps_target ${GENERATED_TARGET_NAME}_deps)
+    if(DEFINED arg_GENERATED_TARGET)
+        set(generated_target_name ${arg_GENERATED_TARGET})
+    elseif(TARGET ${arg_TARGET})
+        set(generated_target_name ${arg_TARGET}_qtprotobuf_gen)
+    else()
+        message(FATAL_ERROR "Either 'TARGET' or 'GENERATED_TARGET' argument needs to be set.")
+    endif()
 
-    set(QT_PROTOBUF_EXECUTABLE $<TARGET_FILE:${QT_PROTOBUF_NAMESPACE}::qtprotobufgen>)
+    set(generation_options "")
+    set(extra_pre_parse_options "")
 
-    #Options handling
-    set(GENERATION_TYPE "SIGNLE")
-    if(qtprotobuf_generate_MULTI)
-        set(GENERATION_TYPE "MULTI")
-        set(qtprotobuf_generate_FOLDER TRUE)
-        message(STATUS "Multi-file generation is set. Folder-based generation enabled automatically for ${GENERATED_TARGET_NAME}")
+    set(generation_type "SIGNLE")
+    if(arg_MULTI)
+        set(generation_type "MULTI")
+        list(APPEND extra_pre_parse_options "-DMULTI=TRUE")
+        set(arg_FOLDER TRUE)
+        message(STATUS "Enabling Multi-file generation. Folder-based generation is enabled"
+            " automatically for ${generated_target_name}.")
     endif()
-    set(GENERATION_OPTIONS ${GENERATION_TYPE})
+    list(APPEND generation_options "${generation_type}")
 
-    if(qtprotobuf_generate_QML)
-        if(NOT TARGET Qt5::Qml)
-            message(FATAL_ERROR "Trying to enable QML support for ${GENERATED_TARGET_NAME}, but Qt5::Qml is not a target."
-                " find_package(Qt5 COMPONENTS Qml) is missing?")
+    if(arg_QML)
+        if(NOT TARGET Qt::Qml)
+            message(FATAL_ERROR "Trying to enable QML support for '${generated_target_name}',"
+                " but Qt::Qml is not a target."
+                "\nfind_package(Qt<VERSION> COMPONENTS Qml) is missing?"
+            )
         endif()
-        message(STATUS "Enabling QML generation for ${GENERATED_TARGET_NAME}")
-        set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:QML")
+        message(STATUS "Enabling QML generation for ${generated_target_name}")
+        list(APPEND generation_options "QML")
     endif()
 
-    if(qtprotobuf_generate_COMMENTS)
-        message(STATUS "Enabled COMMENTS generation for ${GENERATED_TARGET_NAME}")
-        set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:COMMENTS")
+    if(arg_COMMENTS)
+        message(STATUS "Enabling COMMENTS generation for ${generated_target_name}")
+        list(APPEND generation_options "COMMENTS")
     endif()
 
-    if(qtprotobuf_generate_FOLDER)
-        message(STATUS "Enabled FOLDER generation for ${GENERATED_TARGET_NAME}")
-        set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:FOLDER")
-        set(FOLDER_ENABLED "FOLDER")
+    if(arg_FOLDER)
+        message(STATUS "Enabling FOLDER generation for ${generated_target_name}")
+        list(APPEND generation_options "FOLDER")
+        list(APPEND extra_pre_parse_options "-DFOLDER=TRUE")
     endif()
 
-    if(qtprotobuf_generate_FIELDENUM)
-        message(STATUS "Enabled FIELDENUM generation for ${GENERATED_TARGET_NAME}")
-        set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:FIELDENUM")
+    if(arg_FIELDENUM)
+        message(STATUS "Enabling FIELDENUM generation for ${generated_target_name}")
+        list(APPEND generation_options "FIELDENUM")
     endif()
 
-    if(qtprotobuf_generate_EXTRA_NAMESPACE)
-        set(GENERATION_OPTIONS
-            "${GENERATION_OPTIONS}:EXTRA_NAMESPACE=\"${qtprotobuf_generate_EXTRA_NAMESPACE}\""
-        )
+    list(JOIN generation_options ":" generation_options_string)
+    if(arg_EXTRA_NAMESPACE)
+        set(generation_options_string "${generation_options_string}:EXTRA_NAMESPACE=\"${arg_EXTRA_NAMESPACE}\"")
     endif()
 
     if(WIN32)
-        set(PROTOC_COMMAND set QT_PROTOBUF_OPTIONS=${GENERATION_OPTIONS}&& $<TARGET_FILE:protobuf::protoc>)
+        set(PROTOC_COMMAND set QT_PROTOBUF_OPTIONS=${generation_options_string}&& $<TARGET_FILE:protobuf::protoc>)
     else()
-        set(PROTOC_COMMAND "QT_PROTOBUF_OPTIONS=${GENERATION_OPTIONS}" $<TARGET_FILE:protobuf::protoc>)
+        set(PROTOC_COMMAND "QT_PROTOBUF_OPTIONS=${generation_options_string}" $<TARGET_FILE:protobuf::protoc>)
     endif()
 
-    set(PROTO_INCLUDES ${qtprotobuf_generate_PROTO_INCLUDES})
+    set(proto_includes ${arg_PROTO_INCLUDES})
 
-    if(DEFINED qtprotobuf_generate_GENERATED_HEADERS)
-        set(GENERATED_HEADERS ${qtprotobuf_generate_GENERATED_HEADERS})
-    else()
-        find_program(GO_EXECUTABLE "go")
-        if (GO_EXECUTABLE STREQUAL GO_EXECUTABLE-NOTFOUND)
-            message(FATAL_ERROR "Golang is mandatory dependency for QtProtobuf if GENERATED_HEADERS is not specified. Please install it and ensure that it's accessible by PATH environment variable")
-        endif()
-
-        get_target_property(PROTO_PARSER ${QT_PROTOBUF_NAMESPACE}::qtprotobufgen PROTO_PARSER)
-        if(NOT PROTO_PARSER)
-            message(FATAL_ERROR "Unable to locate parsemessages.go script")
-        endif()
+    set(pre_parse_script "${_qt_internal_qtprotobuf_top_level_dir}/QtPreParseProtoFile.cmake")
 
-        foreach(PROTO_FILE IN LISTS qtprotobuf_generate_PROTO_FILES)
-            get_filename_component(BASE_DIR ${PROTO_FILE} DIRECTORY)
-            set(PROTO_INCLUDES "-I\"${BASE_DIR}\"" ${PROTO_INCLUDES})
-            execute_process(COMMAND ${GO_EXECUTABLE} run ${PROTO_PARSER} ${PROTO_FILE} ${GENERATION_TYPE} ${FOLDER_ENABLED} OUTPUT_VARIABLE GENERATED_HEADERS_PART ERROR_VARIABLE PARSER_ERROR)
-            list(APPEND GENERATED_HEADERS ${GENERATED_HEADERS_PART})
-        endforeach()
+    if(NOT EXISTS "${pre_parse_script}")
+        message(FATAL_ERROR "Unable to locate the QtPreParseProtoFile script"
+            " ${pre_parse_script}.")
     endif()
 
-    if(qtprotobuf_generate_MULTI)
-        #TODO: add globalenums by default. But it's better to verify if proto file contains any global enum
-        set(GENERATED_HEADERS ${GENERATED_HEADERS} globalenums.h)
+    unset(generated_files)
+    foreach(proto_file IN LISTS arg_PROTO_FILES)
+        get_filename_component(proto_file_base_dir "${proto_file}" DIRECTORY)
+        list(PREPEND proto_includes "-I\"${proto_file_base_dir}\"")
+        execute_process(COMMAND ${CMAKE_COMMAND}
+            "${extra_pre_parse_options}"
+            -DPROTO_FILE=${proto_file}
+            -P ${pre_parse_script}
+            OUTPUT_VARIABLE output
+            ERROR_VARIABLE error_output # CMake writes messages to standard error.
+            RESULT_VARIABLE result)
+        string(STRIP "${output}" output)
+        string(STRIP "${error_output}" error_output)
+        if(NOT result EQUAL 0)
+            message(FATAL_ERROR "Unable to parse '${proto_file}': ${error_output}")
+        endif()
+        list(APPEND generated_files ${output} ${error_output})
+    endforeach()
+
+    if(NOT generated_files)
+        message(FATAL_ERROR "Unable to get the list of generated sources for target"
+            " '${generated_target_name}'")
     endif()
 
-    if(NOT "${PARSER_ERROR}" STREQUAL "")
-        message(FATAL_ERROR "Go parser error ${PARSER_ERROR}")
+    if(arg_MULTI)
+        # TODO: add globalenums by default. But it's better to verify if proto file contains a
+        # global enum.
+        list(APPEND generated_files globalenums.h)
     endif()
 
-    foreach(EXCLUDE_HEADER IN LISTS qtprotobuf_generate_EXCLUDE_HEADERS)
-        list(REMOVE_ITEM GENERATED_HEADERS ${EXCLUDE_HEADER})
+    foreach(header IN LISTS arg_EXCLUDE_HEADERS)
+        list(REMOVE_ITEM generated_files ${header})
     endforeach()
 
-    list(REMOVE_DUPLICATES GENERATED_HEADERS)
+    list(REMOVE_DUPLICATES generated_files)
 
-    if(NOT DEFINED qtprotobuf_generate_OUT_DIR)
-        set(OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
+    if(NOT DEFINED arg_OUTPUT_DIRECTORY OR "${arg_OUTPUT_DIRECTORY}" STREQUAL "")
+        set(out_dir ${CMAKE_CURRENT_BINARY_DIR})
     else()
-        set(OUT_DIR ${qtprotobuf_generate_OUT_DIR})
+        set(out_dir ${arg_OUTPUT_DIRECTORY})
     endif()
 
-    file(MAKE_DIRECTORY ${OUT_DIR})
+    file(MAKE_DIRECTORY ${out_dir})
 
-    unset(GENERATED_SOURCES_FULL)
-    unset(GENERATED_HEADERS_FULL)
-    foreach(GENERATED_HEADER IN LISTS GENERATED_HEADERS)
-        get_filename_component(GENERATED_DIRECTORY ${GENERATED_HEADER} DIRECTORY)
-        get_filename_component(GENERATED_BASENAME ${GENERATED_HEADER} NAME)
-        string(REGEX REPLACE "\\.[^.]*$" "" GENERATED_BASENAME ${GENERATED_BASENAME})
+    list(TRANSFORM generated_files PREPEND "${out_dir}/")
 
-        if(qtprotobuf_generate_FOLDER)
-            list(APPEND GENERATED_SOURCES_FULL "${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp")
-            list(APPEND GENERATED_HEADERS_FULL "${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.h")
-        else()
-            list(APPEND GENERATED_SOURCES_FULL "${OUT_DIR}/${GENERATED_BASENAME}.cpp")
-            list(APPEND GENERATED_HEADERS_FULL "${OUT_DIR}/${GENERATED_BASENAME}.h")
-        endif()
-    endforeach()
-
-    set_source_files_properties(${GENERATED_SOURCES_FULL};${GENERATED_HEADERS_FULL} PROPERTIES
+    set_source_files_properties(${generated_files} PROPERTIES
         GENERATED TRUE
-        SKIP_AUTOMOC ON
-        SKIP_AUTOUIC ON
         SKIP_AUTOGEN ON
     )
 
-    qt5_wrap_cpp(MOC_SOURCES ${GENERATED_HEADERS_FULL})
-
-    add_custom_command(
-            OUTPUT ${GENERATED_SOURCES_FULL} ${GENERATED_HEADERS_FULL}
-            COMMAND ${PROTOC_COMMAND}
-                --plugin=protoc-gen-qtprotobufgen=${QT_PROTOBUF_EXECUTABLE}
-                --qtprotobufgen_out=${OUT_DIR}
-                ${PROTO_INCLUDES}
-                ${qtprotobuf_generate_PROTO_FILES}
-            WORKING_DIRECTORY ${OUT_DIR}
-            DEPENDS ${qtprotobuf_generate_PROTO_FILES} ${QT_PROTOBUF_EXECUTABLE}
-            COMMENT "Generating QtProtobuf ${GENERATED_TARGET_NAME} sources..."
-            COMMAND_EXPAND_LISTS
-    )
+    # Filter generated headers
+    unset(generated_headers)
+    foreach(header IN LISTS generated_files)
+        get_filename_component(extension "${header}" LAST_EXT)
+        if(extension STREQUAL ".h")
+            list(APPEND generated_headers "${header}")
+        endif()
+    endforeach()
 
-    add_custom_target(${deps_target} DEPENDS ${GENERATED_SOURCES_FULL} ${GENERATED_HEADERS_FULL}
-        ${qtprotobuf_generate_PROTO_FILES}
+    qt5_wrap_cpp(moc_sources ${generated_headers})
+
+    get_property(num_deps GLOBAL PROPERTY ${generated_target_name}_deps_num)
+    if(NOT num_deps)
+        set(num_deps 0)
+    endif()
+    set(deps_target ${generated_target_name}_deps_${num_deps})
+
+    math(EXPR num_deps "${num_deps} + 1")
+    set_property(GLOBAL PROPERTY ${generated_target_name}_deps_num "${num_deps}")
+
+    add_custom_command(OUTPUT ${generated_files}
+        COMMAND ${PROTOC_COMMAND}
+            --plugin=protoc-gen-qtprotobufgen=$<TARGET_FILE:${QT_PROTOBUF_NAMESPACE}::qtprotobufgen>
+            --qtprotobufgen_out=${out_dir}
+            ${proto_includes}
+            ${arg_PROTO_FILES}
+        WORKING_DIRECTORY ${out_dir}
+        DEPENDS
+            ${QT_PROTOBUF_NAMESPACE}::qtprotobufgen
+            ${arg_PROTO_FILES}
+        COMMENT "Generating QtProtobuf ${generated_target_name} sources..."
+        COMMAND_EXPAND_LISTS
     )
+    add_custom_target(${deps_target} DEPENDS ${generated_files})
 
-    add_library(${GENERATED_TARGET_NAME} OBJECT ${GENERATED_SOURCES_FULL} ${MOC_SOURCES})
-    add_dependencies(${GENERATED_TARGET_NAME} ${deps_target})
-    if(qtprotobuf_generate_TARGET)
-        set_property(TARGET ${qtprotobuf_generate_TARGET} APPEND PROPERTY PUBLIC_HEADER ${GENERATED_HEADERS_FULL})
+    if(NOT TARGET ${generated_target_name})
+        add_library(${generated_target_name} OBJECT ${generated_files} ${moc_sources})
+    else()
+        target_sources(${generated_target_name} PRIVATE ${generated_files} ${moc_sources})
     endif()
-    set_target_properties(${GENERATED_TARGET_NAME} PROPERTIES PUBLIC_HEADER "${GENERATED_HEADERS_FULL}")
+
+    add_dependencies(${generated_target_name} ${deps_target})
+
+    set_target_properties(${generated_target_name} PROPERTIES PUBLIC_HEADER "${generated_headers}")
 
     #Add include directories in case if targets are found by find_project or in source tree
-    target_include_directories(${GENERATED_TARGET_NAME} PUBLIC ${OUT_DIR} PRIVATE
+    target_include_directories(${generated_target_name} PUBLIC ${out_dir} PRIVATE
         $<TARGET_PROPERTY:${QT_PROTOBUF_NAMESPACE}::Protobuf,INTERFACE_INCLUDE_DIRECTORIES>)
 
     #TODO: Do not link targets if they are not used in .proto files.
     if(TARGET ${QT_PROTOBUF_NAMESPACE}::Grpc)
-        target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
+        target_include_directories(${generated_target_name} PRIVATE
             $<TARGET_PROPERTY:${QT_PROTOBUF_NAMESPACE}::Grpc,INTERFACE_INCLUDE_DIRECTORIES>)
     endif()
 
     if(TARGET ${QT_PROTOBUF_NAMESPACE}::ProtobufWellKnownTypes)
-        target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
+        target_include_directories(${generated_target_name} PRIVATE
             $<TARGET_PROPERTY:${QT_PROTOBUF_NAMESPACE}::ProtobufWellKnownTypes,INTERFACE_INCLUDE_DIRECTORIES>)
     endif()
 
     if(TARGET ${QT_PROTOBUF_NAMESPACE}::ProtobufQtTypes)
-        target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
+        target_include_directories(${generated_target_name} PRIVATE
             $<TARGET_PROPERTY:${QT_PROTOBUF_NAMESPACE}::ProtobufQtTypes,INTERFACE_INCLUDE_DIRECTORIES>)
     endif()
 
-    #Automatically link whole static library to specified in parameters target
-    if(DEFINED qtprotobuf_generate_TARGET)
-        qtprotobuf_link_target(${qtprotobuf_generate_TARGET} ${GENERATED_TARGET_NAME})
+    # Automatically link whole static library to specified in parameters target
+    if(TARGET ${arg_TARGET})
+        qtprotobuf_link_target(${arg_TARGET} ${generated_target_name})
     endif()
 endfunction()

+ 4 - 5
cmake/QtProtobufInternalHelpers.cmake

@@ -16,7 +16,7 @@ endfunction()
 function(qt_protobuf_internal_add_test)
     set(options MULTI QML FIELDENUM)
     set(oneValueArgs QML_DIR TARGET EXTRA_NAMESPACE)
-    set(multiValueArgs SOURCES GENERATED_HEADERS EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
+    set(multiValueArgs SOURCES EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
     cmake_parse_arguments(add_test_target "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
     ## test sources build
@@ -50,9 +50,8 @@ function(qt_protobuf_internal_add_test)
     endif()
 
     qtprotobuf_generate(TARGET ${add_test_target_TARGET}
-        OUT_DIR ${GENERATED_SOURCES_DIR}
+        OUTPUT_DIRECTORY ${GENERATED_SOURCES_DIR}
         PROTO_FILES ${proto_files}
-        GENERATED_HEADERS ${add_test_target_GENERATED_HEADERS}
         EXCLUDE_HEADERS ${add_test_target_EXCLUDE_HEADERS}
         ${EXTRA_OPTIONS}
         PROTO_INCLUDES ${add_test_target_PROTO_INCLUDES})
@@ -77,13 +76,13 @@ function(qt_protobuf_internal_add_example)
     cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
     set(CMAKE_INCLUDE_CURRENT_DIR ON)
-    
+
     file(GLOB PROTO_FILES ABSOLUTE ${arg_PROTO_FILES})
     file(GLOB SOURCES ${arg_SOURCES})
 
     add_executable(${arg_TARGET} ${SOURCES} ${arg_RESOURCES})
     qtprotobuf_generate(TARGET ${arg_TARGET}
-        OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
+        OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated
         PROTO_FILES ${PROTO_FILES}
         QML)
 

+ 7 - 7
cmake/QtProtobufTestHelpers.cmake

@@ -1,6 +1,6 @@
 function(qt_protobuf_internal_protobuf_generate_all)
     set(options)
-    set(oneValueArgs OUT_DIR TARGET)
+    set(oneValueArgs OUTPUT_DIRECTORY TARGET)
     set(multiValueArgs GENERATED_SOURCES PROTO_FILES)
     cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
@@ -11,13 +11,13 @@ function(qt_protobuf_internal_protobuf_generate_all)
         list(APPEND PROTO_INCLUDES "-I${BASE_DIR}")
     endforeach()
 
-    if(NOT DEFINED arg_OUT_DIR)
-        set(OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+    if(NOT DEFINED arg_OUTPUT_DIRECTORY)
+        set(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
     else()
-        set(OUT_DIR "${arg_OUT_DIR}")
+        set(OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}")
     endif()
 
-    file(MAKE_DIRECTORY "${OUT_DIR}")
+    file(MAKE_DIRECTORY "${OUTPUT_DIRECTORY}")
 
     if(NOT TARGET gRPC::grpc_cpp_plugin)
         message(FATAL_ERROR "gRPC plugin is not found")
@@ -26,8 +26,8 @@ function(qt_protobuf_internal_protobuf_generate_all)
     add_custom_command(
         OUTPUT ${GENERATED_SOURCES}
         COMMAND protobuf::protoc
-        ARGS --grpc_out="${OUT_DIR}"
-            --cpp_out="${OUT_DIR}"
+        ARGS --grpc_out="${OUTPUT_DIRECTORY}"
+            --cpp_out="${OUTPUT_DIRECTORY}"
             ${PROTO_INCLUDES}
             "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
             ${arg_PROTO_FILES}

+ 3 - 7
src/generator/CMakeLists.txt

@@ -23,21 +23,17 @@ qt_protobuf_internal_add_executable(qtprotobufgen
         protobuf::libprotoc
 )
 
-set_property(TARGET qtprotobufgen
-    PROPERTY PROTO_PARSER "${QT_PROTOBUF_BINARY_DIR}/parsemessages.go"
-)
-
 configure_file("${QT_PROTOBUF_CMAKE_DIR}/QtProtobufGen.cmake"
     "${QT_PROTOBUF_BINARY_DIR}/QtProtobufGen.cmake" COPYONLY
 )
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/parsemessages.go"
-    "${QT_PROTOBUF_BINARY_DIR}/parsemessages.go" COPYONLY
+configure_file("${QT_PROTOBUF_CMAKE_DIR}/QtPreParseProtoFile.cmake"
+    "${QT_PROTOBUF_BINARY_DIR}/QtPreParseProtoFile.cmake" COPYONLY
 )
 
 if(QT_PROTOBUF_INSTALL)
     install(FILES
            "${QT_PROTOBUF_BINARY_DIR}/QtProtobufGen.cmake"
-           "${QT_PROTOBUF_BINARY_DIR}/parsemessages.go"
+           "${QT_PROTOBUF_BINARY_DIR}/QtPreParseProtoFile.cmake"
         DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}"
         COMPONENT dev
     )

+ 0 - 4
src/generator/QtqtprotobufgenConfig.cmake.in

@@ -10,9 +10,5 @@ if(NOT TARGET @QT_PROTOBUF_NAMESPACE@::@target@)
     include("${CMAKE_CURRENT_LIST_DIR}/@target_export@.cmake")
 endif()
 
-set_property(TARGET @QT_PROTOBUF_NAMESPACE@::@target@
-    PROPERTY PROTO_PARSER "${CMAKE_CURRENT_LIST_DIR}/parsemessages.go"
-)
-
 @PACKAGE_INIT@
 include("${CMAKE_CURRENT_LIST_DIR}/QtProtobufGen.cmake")

+ 2 - 3
src/generator/generatorbase.h

@@ -89,10 +89,9 @@ namespace generator {
  *
  * \brief qtprotobuf_generate is cmake helper function that automatically generates STATIC library target from your .proto files
  *
- * \param TARGET name of you target that generated code archive will be linked to
+ * \param TARGET a name of your target that the generated code will be linked to.
  * \param GENERATED_TARGET name that will be used for generated archive library target. It's usefull when you supposed to have multiple generated targets to be linked to single one.
- * \param OUT_DIR output directory that will contain generated artifacts. Usually subfolder in build directory should be used
- * \param GENERATED_HEADERS List of header files expected after generator job finished
+ * \param OUTPUT_DIRECTORY output directory that will contain generated artifacts. Usually subfolder in build directory should be used
  * \param EXCLUDE_HEADERS List of header files to be excluded from pre-parsed list of expected header files (e.g. nested messages that are not supported by QtProtobuf generator)
  * \param PROTO_FILES List of .proto files that will be used in generation procedure
  * \param MULTI Enables multi-files generation mode. If provided in parameter list generator will create pair of header/source files for each message

+ 1 - 1
src/qttypes/CMakeLists.txt

@@ -26,7 +26,7 @@ if(TARGET Qt5::Qml)
 endif()
 
 qtprotobuf_generate(TARGET ProtobufQtTypes
-    OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
+    OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated
     PROTO_FILES ${PROTO_FILE}
     FOLDER
     ${qml_enabled}

+ 1 - 1
src/wellknowntypes/CMakeLists.txt

@@ -26,7 +26,7 @@ function(add_wellknowntype type_name)
             message(STATUS "Add well-known type ${PROTO_FILE}")
             qtprotobuf_generate(TARGET ProtobufWellKnownTypes
                 GENERATED_TARGET ${type_name}
-                OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated"
+                OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated"
                 PROTO_FILES "${PROTO_FILE}"
                 PROTO_INCLUDES "-I\"${dir}\""
                 ${qml_enabled}