QtProtobufGen.cmake 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. function(qtprotobuf_link_target TARGET GENERATED_TARGET)
  2. target_sources(${TARGET} PRIVATE $<TARGET_OBJECTS:${GENERATED_TARGET}>)
  3. target_include_directories(${TARGET} PRIVATE $<TARGET_PROPERTY:${GENERATED_TARGET},INTERFACE_INCLUDE_DIRECTORIES>)
  4. add_dependencies(${TARGET} ${GENERATED_TARGET})
  5. endfunction()
  6. function(qtprotobuf_generate)
  7. set(options MULTI QML COMMENTS FOLDER FIELDENUM)
  8. set(oneValueArgs OUT_DIR TARGET GENERATED_TARGET)
  9. set(multiValueArgs GENERATED_HEADERS EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
  10. cmake_parse_arguments(qtprotobuf_generate "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  11. if(DEFINED qtprotobuf_generate_GENERATED_TARGET)
  12. set(GENERATED_TARGET_NAME ${qtprotobuf_generate_GENERATED_TARGET})
  13. elseif(DEFINED qtprotobuf_generate_TARGET)
  14. set(GENERATED_TARGET_NAME ${qtprotobuf_generate_TARGET}_qtprotobuf_gen)
  15. else()
  16. message(FATAL_ERROR "Either TARGET or GENERATED_TARGET must be specified")
  17. endif()
  18. set(GEN_TARGET ${GENERATED_TARGET_NAME}_generate)
  19. set(QT_PROTOBUF_EXECUTABLE $<TARGET_FILE:${QT_PROTOBUF_PROJECT}::${GENERATOR_TARGET}>)
  20. #Options handling
  21. set(GENERATION_TYPE "SIGNLE")
  22. if(qtprotobuf_generate_MULTI)
  23. set(GENERATION_TYPE "MULTI")
  24. set(qtprotobuf_generate_FOLDER TRUE)
  25. message(STATUS "Multi-file generation is set. Folder-based generation enabled automatically for ${GENERATED_TARGET_NAME}")
  26. endif()
  27. set(GENERATION_OPTIONS ${GENERATION_TYPE})
  28. if(qtprotobuf_generate_QML)
  29. message(STATUS "Enabled QML generation for ${GENERATED_TARGET_NAME}")
  30. set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:QML")
  31. endif()
  32. if(qtprotobuf_generate_COMMENTS)
  33. message(STATUS "Enabled COMMENTS generation for ${GENERATED_TARGET_NAME}")
  34. set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:COMMENTS")
  35. endif()
  36. if(qtprotobuf_generate_FOLDER)
  37. message(STATUS "Enabled FOLDER generation for ${GENERATED_TARGET_NAME}")
  38. set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:FOLDER")
  39. set(FOLDER_ENABLED "FOLDER")
  40. endif()
  41. if(qtprotobuf_generate_FIELDENUM)
  42. message(STATUS "Enabled FIELDENUM generation for ${GENERATED_TARGET_NAME}")
  43. set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:FIELDENUM")
  44. endif()
  45. if(WIN32)
  46. set(PROTOC_COMMAND set QT_PROTOBUF_OPTIONS=${GENERATION_OPTIONS}&& $<TARGET_FILE:protobuf::protoc>)
  47. else()
  48. set(PROTOC_COMMAND "QT_PROTOBUF_OPTIONS=${GENERATION_OPTIONS}" $<TARGET_FILE:protobuf::protoc>)
  49. endif()
  50. set(PROTO_INCLUDES ${qtprotobuf_generate_PROTO_INCLUDES})
  51. if(DEFINED qtprotobuf_generate_GENERATED_HEADERS)
  52. set(GENERATED_HEADERS ${qtprotobuf_generate_GENERATED_HEADERS})
  53. else()
  54. find_program(GO_EXECUTABLE "go")
  55. if (GO_EXECUTABLE STREQUAL GO_EXECUTABLE-NOTFOUND)
  56. 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")
  57. endif()
  58. get_target_property(PROTO_PARSER ${QT_PROTOBUF_PROJECT}::${GENERATOR_TARGET} PROTO_PARSER)
  59. if(NOT PROTO_PARSER)
  60. message(FATAL_ERROR "Unable to locate parsemessages.go script")
  61. endif()
  62. foreach(PROTO_FILE IN LISTS qtprotobuf_generate_PROTO_FILES)
  63. get_filename_component(BASE_DIR ${PROTO_FILE} DIRECTORY)
  64. set(PROTO_INCLUDES "-I\"${BASE_DIR}\"" ${PROTO_INCLUDES})
  65. execute_process(COMMAND ${GO_EXECUTABLE} run ${PROTO_PARSER} ${PROTO_FILE} ${GENERATION_TYPE} ${FOLDER_ENABLED} OUTPUT_VARIABLE GENERATED_HEADERS_PART ERROR_VARIABLE PARSER_ERROR)
  66. set(GENERATED_HEADERS ${GENERATED_HEADERS} ${GENERATED_HEADERS_PART})
  67. endforeach()
  68. endif()
  69. if(qtprotobuf_generate_MULTI)
  70. #TODO: add globalenums by default. But it's better to verify if proto file contains any global enum
  71. set(GENERATED_HEADERS ${GENERATED_HEADERS} globalenums.h)
  72. endif()
  73. if(NOT "${PARSER_ERROR}" STREQUAL "")
  74. message(FATAL_ERROR "Go parser error ${PARSER_ERROR}")
  75. endif()
  76. foreach(EXCLUDE_HEADER IN LISTS qtprotobuf_generate_EXCLUDE_HEADERS)
  77. list(REMOVE_ITEM GENERATED_HEADERS ${EXCLUDE_HEADER})
  78. endforeach()
  79. list(REMOVE_DUPLICATES GENERATED_HEADERS)
  80. if(NOT DEFINED qtprotobuf_generate_OUT_DIR)
  81. set(OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
  82. else()
  83. set(OUT_DIR ${qtprotobuf_generate_OUT_DIR})
  84. endif()
  85. file(MAKE_DIRECTORY ${OUT_DIR})
  86. unset(GENERATED_SOURCES_FULL)
  87. unset(GENERATED_HEADERS_FULL)
  88. foreach(GENERATED_HEADER IN LISTS GENERATED_HEADERS)
  89. get_filename_component(GENERATED_DIRECTORY ${GENERATED_HEADER} DIRECTORY)
  90. get_filename_component(GENERATED_BASENAME ${GENERATED_HEADER} NAME)
  91. string(REGEX REPLACE "\\.[^.]*$" "" GENERATED_BASENAME ${GENERATED_BASENAME})
  92. if(qtprotobuf_generate_FOLDER)
  93. list(APPEND GENERATED_SOURCES_FULL ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp)
  94. list(APPEND GENERATED_HEADERS_FULL ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.h)
  95. else()
  96. list(APPEND GENERATED_SOURCES_FULL ${OUT_DIR}/${GENERATED_BASENAME}.cpp)
  97. list(APPEND GENERATED_HEADERS_FULL ${OUT_DIR}/${GENERATED_BASENAME}.h)
  98. endif()
  99. set_property(SOURCE ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOMOC ON)
  100. set_property(SOURCE ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOUIC ON)
  101. set_property(SOURCE ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOGEN ON)
  102. endforeach()
  103. set_source_files_properties(${GENERATED_SOURCES_FULL} PROPERTIES GENERATED TRUE)
  104. qt5_wrap_cpp(MOC_SOURCES ${GENERATED_HEADERS_FULL})
  105. add_custom_command(
  106. OUTPUT ${GENERATED_SOURCES_FULL} ${GENERATED_HEADERS_FULL}
  107. COMMAND ${PROTOC_COMMAND}
  108. --plugin=protoc-gen-${GENERATOR_TARGET}=${QT_PROTOBUF_EXECUTABLE}
  109. --${GENERATOR_TARGET}_out=${OUT_DIR}
  110. ${PROTO_INCLUDES}
  111. ${qtprotobuf_generate_PROTO_FILES}
  112. WORKING_DIRECTORY ${OUT_DIR}
  113. DEPENDS ${qtprotobuf_generate_PROTO_FILES} ${QT_PROTOBUF_EXECUTABLE}
  114. COMMENT "Generating QtProtobuf ${GENERATED_TARGET_NAME} sources..."
  115. COMMAND_EXPAND_LISTS
  116. )
  117. add_custom_target(${GEN_TARGET} DEPENDS ${GENERATED_SOURCES_FULL} ${GENERATED_HEADERS_FULL} ${qtprotobuf_generate_PROTO_FILES})
  118. add_library(${GENERATED_TARGET_NAME} OBJECT ${GENERATED_SOURCES_FULL} ${MOC_SOURCES})
  119. add_dependencies(${GENERATED_TARGET_NAME} ${GEN_TARGET})
  120. set_target_properties(${GENERATED_TARGET_NAME} PROPERTIES PUBLIC_HEADER "${GENERATED_HEADERS_FULL}")
  121. #Add include directories in case if projects are enabled by find_project
  122. target_include_directories(${GENERATED_TARGET_NAME} PUBLIC ${OUT_DIR} PRIVATE
  123. $<TARGET_PROPERTY:${QT_PROTOBUF_PROJECT}::QtProtobuf,INTERFACE_INCLUDE_DIRECTORIES>)
  124. if(TARGET ${QT_PROTOBUF_PROJECT}::QtGrpc)
  125. target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
  126. $<TARGET_PROPERTY:${QT_PROTOBUF_PROJECT}::QtGrpc,INTERFACE_INCLUDE_DIRECTORIES>)
  127. endif()
  128. if(TARGET ${QT_PROTOBUF_PROJECT}::QtProtobufWellKnownTypes)
  129. target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
  130. $<TARGET_PROPERTY:${QT_PROTOBUF_PROJECT}::QtProtobufWellKnownTypes,INTERFACE_INCLUDE_DIRECTORIES>)
  131. endif()
  132. if(TARGET ${QT_PROTOBUF_PROJECT}::QtProtobufQtTypes)
  133. target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
  134. $<TARGET_PROPERTY:${QT_PROTOBUF_PROJECT}::QtProtobufQtTypes,INTERFACE_INCLUDE_DIRECTORIES>)
  135. endif()
  136. #Automatically link whole static library to specified in parameters target
  137. if(DEFINED qtprotobuf_generate_TARGET)
  138. qtprotobuf_link_target(${qtprotobuf_generate_TARGET} ${GENERATED_TARGET_NAME})
  139. endif()
  140. endfunction()