Refactor _qt_internal_protobuf_preparse_proto_files

Move the logic that is unreleated to the pre-parsing of the .proto
files to the qt6_add_protobuf function. This leave the single
responsibility for _qt_internal_protobuf_preparse_proto_files and
unlocks the file manipulations for the furter Qml API improvements.

Pick-to: 6.6
Task-number: QTBUG-114077
Task-number: QTBUG-104513
Change-Id: I9d18fbb5d26be1ffb19844cb7d7c3f8736136a76
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Alexey Edelev 2023-05-30 17:49:22 +02:00
parent 37d28cc226
commit 16713c6e32
1 changed files with 91 additions and 105 deletions

View File

@ -170,91 +170,58 @@ function(_qt_internal_protoc_generate target generator output_directory)
target_include_directories(${target} PUBLIC "$<BUILD_INTERFACE:${output_directory}>")
endfunction()
# The function looks for the enum and message definitions inside provided PROTO_FILES and returns
# list of the absolute .proto file paths, protobuf include paths and files that are expected to be
# generated by qtprotobufgen.
# Optional arguments:
# GENERATE_PACKAGE_SUBFOLDERS - generated files will be located in package-base subdirectories.
#
# Multi-value arguments:
# PROTO_FILES - input list of the proto files. May contain either absolute or relative paths.
function(_qt_internal_protobuf_preparse_proto_files
out_proto_files out_proto_includes out_generated_files out_qml_uri base_dir)
# The function looks for the enum and message definitions inside provided proto files and returns
# list of the absolute .proto file paths, protobuf include paths and packages found here.
function(_qt_internal_protobuf_preparse_proto_files target base_dir
out_proto_files out_proto_includes out_proto_packages)
cmake_parse_arguments(arg "GENERATE_PACKAGE_SUBFOLDERS;QML" "QML_URI" "PROTO_FILES" ${ARGN})
unset(proto_files)
unset(proto_includes)
unset(output_files)
set(proto_files "")
set(proto_includes "")
set(proto_packages "")
foreach(f IN LISTS arg_PROTO_FILES)
foreach(f IN LISTS ARGN)
if(NOT IS_ABSOLUTE "${f}")
set(f "${base_dir}/${f}")
get_filename_component(f "${f}" ABSOLUTE)
endif()
get_filename_component(f "${f}" REALPATH)
list(APPEND proto_files "${f}")
if("${f}" IN_LIST proto_files)
message(WARNING "The .proto file ${f} is listed twice for ${target}."
" Skip processing for the second time.")
continue()
endif()
_qt_internal_preparse_proto_file_common(result proto_package "${f}" "message;enum")
if(NOT result)
message(STATUS "No messages or enums found in ${f}. Skipping.")
return()
continue()
endif()
get_filename_component(proto_file_base_dir "${f}" DIRECTORY)
list(PREPEND proto_includes "${proto_file_base_dir}")
string(REPLACE "." "/" package_full_path "${proto_package}")
set(folder_path "")
if(arg_GENERATE_PACKAGE_SUBFOLDERS)
set(folder_path "${package_full_path}/")
endif()
get_filename_component(basename "${f}" NAME_WLE)
list(APPEND output_files
"${folder_path}${basename}.qpb.h"
"${folder_path}${basename}.qpb.cpp"
"${folder_path}${basename}_protobuftyperegistrations.cpp"
)
if(arg_QML)
list(APPEND proto_packages "${proto_package}")
endif()
list(APPEND proto_files "${f}")
list(APPEND proto_includes "${proto_file_base_dir}")
list(APPEND proto_packages "${proto_package}")
endforeach()
list(REMOVE_DUPLICATES proto_files)
list(REMOVE_DUPLICATES proto_includes)
list(REMOVE_DUPLICATES output_files)
if(arg_QML)
if(arg_QML_URI)
set(qml_uri "${arg_QML_URI}")
elseif(proto_packages)
list(REMOVE_DUPLICATES proto_packages)
list(LENGTH proto_packages length)
if(NOT length EQUAL 1)
string(JOIN "\n" proto_packages_string "${proto_packages}")
message(FATAL_ERROR "All *.proto files must have single package name,"
" that will be used for QML plugin registration."
"\nThe following packages found in the .proto files for ${target}:"
"\n${proto_packages_string}."
" Please split the ${target} target per package."
)
endif()
list(GET proto_packages 0 qml_uri)
else()
message(FATAL_ERROR ".proto files of ${target} don't specify a package."
" Please, set QML_URI when using .proto without package name."
)
endif()
if(qml_uri)
string(REPLACE "." "_" plguin_base_name "${qml_uri}")
list(APPEND output_files "${plguin_base_name}plugin.cpp")
set(${out_qml_uri} "${qml_uri}" PARENT_SCOPE)
endif()
endif()
set(${out_proto_files} "${proto_files}" PARENT_SCOPE)
set(${out_proto_includes} "${proto_includes}" PARENT_SCOPE)
set(${out_generated_files} "${output_files}" PARENT_SCOPE)
set(${out_proto_packages} "${proto_packages}" PARENT_SCOPE)
endfunction()
function(_qt_internal_protobuf_package_qml_uri out_uri)
list(REMOVE_DUPLICATES ARGN)
list(LENGTH ARGN length)
if(NOT length EQUAL 1)
string(JOIN "\n" proto_packages_string "${ARGN}")
message(FATAL_ERROR "All *.proto files must have single package name,"
" that will be used for QML plugin registration."
"\nThe following packages found in the .proto files for ${target}:"
"\n${proto_packages_string}."
" Please split the ${target} target per package."
)
endif()
list(GET ARGN 0 qml_uri)
set(${out_uri} ${qml_uri} PARENT_SCOPE)
endfunction()
# TODO Qt6:
@ -296,25 +263,61 @@ function(qt6_add_protobuf target)
else()
set(base_dir "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
unset(extra_pre_parse_options)
if(arg_GENERATE_PACKAGE_SUBFOLDERS)
list(APPEND extra_pre_parse_options "GENERATE_PACKAGE_SUBFOLDERS")
_qt_internal_protobuf_preparse_proto_files(${target}
"${base_dir}"
proto_files proto_includes proto_packages
${arg_PROTO_FILES}
)
set(output_directory "${CMAKE_CURRENT_BINARY_DIR}")
if(DEFINED arg_OUTPUT_DIRECTORY)
set(output_directory "${arg_OUTPUT_DIRECTORY}")
endif()
set(cpp_sources "")
set(idx 0)
foreach(f IN LISTS proto_files)
if(arg_GENERATE_PACKAGE_SUBFOLDERS)
if(proto_packages)
list(GET proto_packages ${idx} package)
else()
set(package "")
endif()
string(REPLACE "." "/" package_full_path "${package}/")
math(EXPR idx "${idx} + 1")
else()
set(package_full_path "")
endif()
get_filename_component(basename "${f}" NAME_WLE)
list(APPEND cpp_sources
"${output_directory}/${package_full_path}${basename}.qpb.h"
"${output_directory}/${package_full_path}${basename}.qpb.cpp"
)
list(APPEND type_registrations
"${output_directory}/${package_full_path}${basename}_protobuftyperegistrations.cpp")
endforeach()
set(qml_sources "")
if(arg_QML)
set(arg_QML QML)
else()
set(arg_QML "")
if(arg_QML_URI)
set(qml_uri "${arg_QML_URI}")
elseif(proto_packages)
_qt_internal_protobuf_package_qml_uri(qml_uri ${proto_packages})
else()
message(FATAL_ERROR ".proto files of ${target} don't specify a package."
" Please, set QML_URI when using .proto without package name."
)
endif()
list(APPEND generation_options "QML_URI=${qml_uri}")
string(REPLACE "." "_" qml_plugin_base_name "${qml_uri}")
list(APPEND qml_sources
"${output_directory}/${qml_plugin_base_name}plugin.cpp")
endif()
_qt_internal_protobuf_preparse_proto_files(proto_files proto_includes generated_files qml_uri
"${base_dir}"
${extra_pre_parse_options}
${arg_QML}
QML_URI
${arg_QML_URI}
PROTO_FILES
${arg_PROTO_FILES}
)
if(arg_PROTO_INCLUDES)
list(APPEND proto_includes ${arg_PROTO_INCLUDES})
endif()
@ -351,40 +354,23 @@ function(qt6_add_protobuf target)
PRIVATE "QT_BUILD_${target_upper}_LIB")
endif()
if(qml_uri)
list(APPEND generation_options "QML_URI=${qml_uri}")
endif()
set(output_directory "${CMAKE_CURRENT_BINARY_DIR}")
if(DEFINED arg_OUTPUT_DIRECTORY)
set(output_directory "${arg_OUTPUT_DIRECTORY}")
endif()
list(TRANSFORM generated_files PREPEND "${output_directory}/")
_qt_internal_protoc_generate(${target} qtprotobufgen "${output_directory}"
PROTO_FILES ${proto_files}
PROTO_INCLUDES ${proto_includes}
GENERATED_FILES ${generated_files}
GENERATED_FILES ${cpp_sources} ${qml_sources} ${type_registrations}
OPTIONS ${generation_options}
)
# Filter generated headers
unset(generated_headers)
unset(generated_sources)
unset(generated_typeregistrations)
foreach(generated_file IN LISTS generated_files)
foreach(generated_file IN LISTS cpp_sources)
get_filename_component(extension "${generated_file}" LAST_EXT)
if(extension STREQUAL ".h")
list(APPEND generated_headers "${generated_file}")
elseif(generated_file MATCHES "_protobuftyperegistrations.cpp$")
list(APPEND generated_typeregistrations "${generated_file}")
elseif(extension STREQUAL ".cpp")
list(APPEND generated_sources "${generated_file}")
endif()
endforeach()
target_sources(${target} PRIVATE ${generated_headers} ${generated_sources})
target_sources(${target} PRIVATE ${cpp_sources} ${qml_sources})
if(is_static OR is_shared)
set_target_properties(${target}
@ -404,9 +390,9 @@ function(qt6_add_protobuf target)
if(is_static OR (WIN32 AND NOT is_executable))
if(TARGET ${target}_protobuf_registration)
target_sources(${target}_protobuf_registration PRIVATE ${generated_typeregistrations})
target_sources(${target}_protobuf_registration PRIVATE ${type_registrations})
else()
add_library(${target}_protobuf_registration OBJECT ${generated_typeregistrations})
add_library(${target}_protobuf_registration OBJECT ${type_registrations})
target_link_libraries(${target}
INTERFACE "$<TARGET_OBJECTS:$<TARGET_NAME:${target}_protobuf_registration>>")
add_dependencies(${target} ${target}_protobuf_registration)
@ -430,7 +416,7 @@ function(qt6_add_protobuf target)
"${target}_protobuf_registration")
endif()
else()
target_sources(${target} PRIVATE ${generated_typeregistrations})
target_sources(${target} PRIVATE ${type_registrations})
endif()
if(DEFINED arg_OUTPUT_HEADERS)