QtProtobufGen.cmake 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. function(generate_qtprotobuf)
  2. set(options)
  3. set(oneValueArgs OUT_DIR TARGET MULTI QML GENERATED_HEADERS_VAR)
  4. set(multiValueArgs GENERATED_HEADERS EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
  5. cmake_parse_arguments(generate_qtprotobuf "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  6. set(QtProtobuf_GENERATED ${generate_qtprotobuf_TARGET}_qtprotobuf_gen PARENT_SCOPE)
  7. set(QtProtobuf_GENERATED ${generate_qtprotobuf_TARGET}_qtprotobuf_gen)
  8. set(GEN_TARGET ${generate_qtprotobuf_TARGET}_qtprotobuf_generate)
  9. set(GENERATED_HEADERS ${generate_qtprotobuf_GENERATED_HEADERS})
  10. if(NOT DEFINED QTPROTOBUF_EXECUTABLE)
  11. set(QTPROTOBUF_EXECUTABLE "${QTPROTOBUF_EXECUTABLE_INSTALL}")
  12. endif()
  13. set(GENERATION_TYPE "SINGLE")
  14. if("${generate_qtprotobuf_MULTI}" STREQUAL "TRUE")
  15. set(GENERATION_TYPE "MULTI")
  16. #TODO: add globalenums by default. But it's better to verify if proto file contains any global enum
  17. set(GENERATED_HEADERS ${GENERATED_HEADERS} globalenums.h)
  18. endif()
  19. set(GENERATION_OPTIONS ${GENERATION_TYPE})
  20. if("${generate_qtprotobuf_QML}" STREQUAL "TRUE")
  21. message(STATUS "Enabled QML generation for ${generate_qtprotobuf_TARGET}")
  22. set(GENERATION_OPTIONS "${GENERATION_OPTIONS}:QML")
  23. endif()
  24. find_program(GO_EXECUTABLE "go")
  25. if (GO_EXECUTABLE STREQUAL GO_EXECUTABLE-NOTFOUND)
  26. message(FATAL_ERROR "Golang is mandatory dependency for QtProtobuf. Please install it and ensure that it's accessible by PATH environment variable")
  27. endif()
  28. set(PROTO_INCLUDES ${generate_qtprotobuf_PROTO_INCLUDES})
  29. foreach(PROTO_FILE IN LISTS generate_qtprotobuf_PROTO_FILES)
  30. get_filename_component(BASE_DIR ${PROTO_FILE} DIRECTORY)
  31. set(PROTO_INCLUDES -I"${BASE_DIR}" ${PROTO_INCLUDES})
  32. execute_process(COMMAND ${GO_EXECUTABLE} run ${PROTO_PARSER} ${PROTO_FILE} ${GENERATION_TYPE} OUTPUT_VARIABLE GENERATED_HEADERS_PART ERROR_VARIABLE PARSER_ERROR)
  33. set(GENERATED_HEADERS ${GENERATED_HEADERS} ${GENERATED_HEADERS_PART})
  34. endforeach()
  35. if(NOT "${PARSER_ERROR}" STREQUAL "")
  36. message(FATAL_ERROR "Go parser error ${PARSER_ERROR}")
  37. endif()
  38. if(DEFINED generate_qtprotobuf_GENERATED_HEADERS)
  39. set(GENERATED_HEADERS ${generate_qtprotobuf_GENERATED_HEADERS})
  40. endif()
  41. foreach(EXCLUDE_HEADER IN LISTS generate_qtprotobuf_EXCLUDE_HEADERS)
  42. list(REMOVE_ITEM GENERATED_HEADERS ${EXCLUDE_HEADER})
  43. endforeach()
  44. list(REMOVE_DUPLICATES GENERATED_HEADERS)
  45. if(NOT DEFINED generate_qtprotobuf_OUT_DIR)
  46. set(OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
  47. else()
  48. set(OUT_DIR ${generate_qtprotobuf_OUT_DIR})
  49. endif()
  50. file(MAKE_DIRECTORY ${OUT_DIR})
  51. unset(QTPROTOBUF_GENERATED_SOURCES)
  52. unset(QTPROTOBUF_GENERATED_HEADERS)
  53. foreach(GENERATED_HEADER IN LISTS GENERATED_HEADERS)
  54. get_filename_component(GENERATED_BASENAME ${GENERATED_HEADER} NAME)
  55. string(REGEX REPLACE "\\.[^.]*$" "" GENERATED_BASENAME ${GENERATED_BASENAME})
  56. list(APPEND QTPROTOBUF_GENERATED_SOURCES ${OUT_DIR}/${GENERATED_BASENAME}.cpp)
  57. list(APPEND QTPROTOBUF_GENERATED_HEADERS ${OUT_DIR}/${GENERATED_BASENAME}.h)
  58. set_property(SOURCE ${OUT_DIR}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOMOC ON)
  59. endforeach()
  60. if(WIN32)
  61. set(PROTOC_COMMAND set QT_PROTOBUF_OPTIONS=${GENERATION_OPTIONS}&& $<TARGET_FILE:protobuf::protoc>)
  62. else()
  63. set(PROTOC_COMMAND "QT_PROTOBUF_OPTIONS=${GENERATION_OPTIONS}" $<TARGET_FILE:protobuf::protoc>)
  64. endif()
  65. add_custom_command(
  66. OUTPUT ${QTPROTOBUF_GENERATED_SOURCES} ${QTPROTOBUF_GENERATED_HEADERS}
  67. COMMAND ${PROTOC_COMMAND}
  68. --plugin=protoc-gen-${GENERATOR_TARGET}=${QTPROTOBUF_EXECUTABLE}
  69. --${GENERATOR_TARGET}_out=${OUT_DIR}
  70. ${PROTO_INCLUDES}
  71. ${generate_qtprotobuf_PROTO_FILES}
  72. WORKING_DIRECTORY ${OUT_DIR}
  73. DEPENDS ${generate_qtprotobuf_PROTO_FILES} ${QTPROTOBUF_EXECUTABLE}
  74. COMMENT "Generating QtProtobuf ${generate_qtprotobuf_TARGET} sources..."
  75. )
  76. add_custom_target(${GEN_TARGET} DEPENDS ${QTPROTOBUF_GENERATED_SOURCES} ${QTPROTOBUF_GENERATED_HEADERS} ${generate_qtprotobuf_PROTO_FILES})
  77. if(NOT "${generate_qtprotobuf_GENERATED_HEADERS_VAR}" STREQUAL "")
  78. set(${generate_qtprotobuf_GENERATED_HEADERS_VAR} ${QTPROTOBUF_GENERATED_HEADERS} PARENT_SCOPE)
  79. endif()
  80. qt5_wrap_cpp(MOC_SOURCES ${QTPROTOBUF_GENERATED_HEADERS})
  81. list(APPEND GENERATED_SOURCES ${MOC_SOURCES})
  82. set_source_files_properties(${QTPROTOBUF_GENERATED_SOURCES} PROPERTIES GENERATED TRUE)
  83. add_library(${QtProtobuf_GENERATED} ${QTPROTOBUF_GENERATED_SOURCES} ${MOC_SOURCES})
  84. add_dependencies(${QtProtobuf_GENERATED} ${GEN_TARGET})
  85. target_include_directories(${QtProtobuf_GENERATED} PUBLIC ${OUT_DIR} PRIVATE ${Qt5Core_INCLUDE_DIRS}
  86. $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobuf,INTERFACE_INCLUDE_DIRECTORIES>
  87. $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtGrpc,INTERFACE_INCLUDE_DIRECTORIES> ${OUT_DIR})
  88. if(NOT WIN32)
  89. target_include_directories(${QtProtobuf_GENERATED} PRIVATE
  90. $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobufWellKnownTypes,INTERFACE_INCLUDE_DIRECTORIES>)
  91. endif()
  92. endfunction()