QtProtobufInternalHelpers.cmake 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. set(_qtprotobuf_all_known_multi_args SOURCES PUBLIC_HEADER INCLUDE_DIRECTORIES LIBRARIES
  2. PUBLIC_LIBRARIES PUBLIC_INCLUDE_DIRECTORIES DEFINES PUBLIC_DEFINES)
  3. function(qtprotobuf_parse_arguments prefix option single multi)
  4. cmake_parse_arguments(arg "" "" "${_qtprotobuf_all_known_multi_args}" ${ARGN})
  5. foreach(_arg IN LISTS _qtprotobuf_all_known_multi_args)
  6. if(${_arg} IN_LIST multi)
  7. set(${prefix}_${_arg} ${arg_${_arg}} PARENT_SCOPE)
  8. else()
  9. list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${_arg} ${arg_${_arg}})
  10. endif()
  11. endforeach()
  12. set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
  13. endfunction()
  14. function(qt_protobuf_internal_add_test)
  15. set(options MULTI QML FIELDENUM)
  16. set(oneValueArgs QML_DIR TARGET)
  17. set(multiValueArgs SOURCES GENERATED_HEADERS EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
  18. cmake_parse_arguments(add_test_target "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  19. ## test sources build
  20. # policy enables automoc for generated files
  21. if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
  22. cmake_policy(SET CMP0071 NEW)
  23. endif()
  24. set(GENERATED_SOURCES_DIR ${CMAKE_CURRENT_BINARY_DIR}/${add_test_target_TARGET}_generated)
  25. if(DEFINED add_test_target_PROTO_FILES)
  26. file(GLOB PROTO_FILES ABSOLUTE ${add_test_target_PROTO_FILES})
  27. else()
  28. file(GLOB PROTO_FILES ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/proto/*.proto)
  29. endif()
  30. add_executable(${add_test_target_TARGET} ${add_test_target_SOURCES})
  31. set(EXTRA_OPTIONS COMMENTS)
  32. if(add_test_target_MULTI)
  33. set(EXTRA_OPTIONS ${EXTRA_OPTIONS} MULTI)
  34. endif()
  35. if(add_test_target_QML)
  36. set(EXTRA_OPTIONS ${EXTRA_OPTIONS} QML)
  37. endif()
  38. if(add_test_target_FIELDENUM)
  39. set(EXTRA_OPTIONS ${EXTRA_OPTIONS} FIELDENUM)
  40. endif()
  41. qtprotobuf_generate(TARGET ${add_test_target_TARGET}
  42. OUT_DIR ${GENERATED_SOURCES_DIR}
  43. PROTO_FILES ${PROTO_FILES}
  44. GENERATED_HEADERS ${add_test_target_GENERATED_HEADERS}
  45. EXCLUDE_HEADERS ${add_test_target_EXCLUDE_HEADERS}
  46. ${EXTRA_OPTIONS}
  47. PROTO_INCLUDES ${add_test_target_PROTO_INCLUDES})
  48. target_link_libraries(${add_test_target_TARGET} PUBLIC gtest_main
  49. gtest
  50. ${QT_PROTOBUF_NAMESPACE}::Protobuf
  51. ${QT_PROTOBUF_NAMESPACE}::Grpc
  52. ${QT_VERSIONED_PREFIX}::Core
  53. ${QT_VERSIONED_PREFIX}::Test
  54. ${QT_VERSIONED_PREFIX}::Network
  55. ${CMAKE_THREAD_LIBS_INIT})
  56. if(${add_test_target_QML})
  57. target_link_libraries(${add_test_target_TARGET} PUBLIC ${QT_VERSIONED_PREFIX}::Qml)
  58. endif()
  59. endfunction()
  60. function(qt_protobuf_internal_add_example)
  61. set(options)
  62. set(oneValueArgs TARGET QML_DIR)
  63. set(multiValueArgs SOURCES PROTO_FILES RESOURCES)
  64. cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  65. set(CMAKE_INCLUDE_CURRENT_DIR ON)
  66. set(CMAKE_AUTOMOC ON)
  67. set(CMAKE_AUTORCC ON)
  68. file(GLOB PROTO_FILES ABSOLUTE ${arg_PROTO_FILES})
  69. file(GLOB SOURCES ${arg_SOURCES})
  70. add_executable(${TARGET} ${SOURCES} ${arg_RESOURCES})
  71. qtprotobuf_generate(TARGET ${TARGET}
  72. OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
  73. PROTO_FILES ${PROTO_FILES}
  74. QML)
  75. qt_protobuf_internal_add_target_windeployqt(TARGET ${TARGET} QML_DIR ${arg_QML_DIR})
  76. target_link_libraries(${TARGET} PRIVATE examples_common
  77. ${QT_PROTOBUF_NAMESPACE}::Protobuf
  78. ${QT_PROTOBUF_NAMESPACE}::Grpc
  79. ${QT_VERSIONED_PREFIX}::Quick
  80. ${QT_VERSIONED_PREFIX}::Qml)
  81. endfunction()
  82. function(qt_protobuf_internal_check_install)
  83. set(QT_PROTOBUF_INSTALL
  84. TRUE CACHE INTERNAL "Indicates wether QT_PROTOBUF_INSTALL might be installed or not" FORCE
  85. )
  86. if(NOT "${QT_PROTOBUF_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
  87. message(STATUS "QtProtobuf configured as sub-project.")
  88. set(QT_PROTOBUF_INSTALL TRUE CACHE INTERNAL "" FORCE)
  89. message(STATUS "All install rules are disabled.")
  90. endif()
  91. endfunction()
  92. function(qt_protobuf_extract_qt_variable variable)
  93. if(NOT DEFINED QT_QMAKE_EXECUTABLE)
  94. find_program(QT_QMAKE_EXECUTABLE "qmake")
  95. if(QT_QMAKE_EXECUTABLE STREQUAL QT_QMAKE_EXECUTABLE-NOTFOUND)
  96. message(FATAL_ERROR "Could not find qmake executable")
  97. endif()
  98. endif()
  99. execute_process(
  100. COMMAND "${QT_QMAKE_EXECUTABLE}" -query ${variable}
  101. OUTPUT_VARIABLE ${variable}
  102. OUTPUT_STRIP_TRAILING_WHITESPACE
  103. )
  104. set(${variable} ${${variable}} PARENT_SCOPE)
  105. endfunction()
  106. function(qt_protobuf_internal_generate_qt_headers out_var)
  107. set(options)
  108. set(oneValueArgs "TARGET")
  109. set(multiValueArgs "PUBLIC_HEADER")
  110. cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  111. foreach(PUBLIC_HEADER IN LISTS arg_PUBLIC_HEADER)
  112. get_filename_component(PUBLIC_HEADER_BASE_NAME ${PUBLIC_HEADER} NAME FALSE)
  113. file(STRINGS ${PUBLIC_HEADER} CLASS_NAME REGEX "#pragma once //[a-zA-Z]+")
  114. if (NOT "${CLASS_NAME}" STREQUAL "")
  115. string(REPLACE "#pragma once //" "" CLASS_NAME "${CLASS_NAME}")
  116. message(STATUS "Generate Qt header for ${CLASS_NAME}")
  117. configure_file("${QT_PROTOBUF_CMAKE_DIR}/GeneratedHeaderTemplate"
  118. "${QT_PROTOBUF_BINARY_DIR}/include/${arg_TARGET}/${CLASS_NAME}" @ONLY
  119. )
  120. list(APPEND ${out_var}
  121. "${QT_PROTOBUF_BINARY_DIR}/include/${arg_TARGET}/${CLASS_NAME}"
  122. )
  123. endif()
  124. endforeach()
  125. set(${out_var} "${${out_var}}" PARENT_SCOPE)
  126. endfunction()
  127. function(qt_protobuf_internal_add_library target)
  128. qtprotobuf_parse_arguments(arg
  129. ""
  130. ""
  131. "SOURCES;PUBLIC_HEADER"
  132. ${ARGN}
  133. )
  134. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  135. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  136. set(target_include_dir ${CMAKE_INSTALL_INCLUDEDIR}/${prefixed_target})
  137. set(target_lib_dir ${CMAKE_INSTALL_LIBDIR})
  138. set(target_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE})
  139. set(CMAKE_AUTOMOC ON)
  140. set(CMAKE_AUTORCC ON)
  141. if(NOT arg_SOURCES)
  142. message(FATAL_ERROR "SOURCES are not specified for ${target}")
  143. endif()
  144. file(GLOB sources ${arg_SOURCES} ${arg_PUBLIC_HEADER})
  145. add_library(${target} ${sources})
  146. if(NOT BUILD_SHARED_LIBS)
  147. target_compile_definitions(${target} PUBLIC QT_PROTOBUF_STATIC)
  148. endif()
  149. string(TOUPPER "${target}" target_upper)
  150. target_compile_definitions(${target} PRIVATE QT_BUILD_${target_upper}_LIB)
  151. set_target_properties(${target}
  152. PROPERTIES
  153. VERSION ${PROJECT_VERSION}
  154. OUTPUT_NAME ${QT_VERSIONED_PREFIX}${target}
  155. )
  156. target_compile_features(${target}
  157. PUBLIC cxx_std_14
  158. cxx_auto_type
  159. cxx_decltype
  160. cxx_final
  161. cxx_override
  162. cxx_nullptr
  163. cxx_lambdas
  164. cxx_func_identifier
  165. )
  166. target_compile_definitions(${target}
  167. PUBLIC
  168. QT_PROTOBUF_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
  169. QT_PROTOBUF_VERSION_MINOR=${PROJECT_VERSION_MINOR}
  170. )
  171. target_include_directories(${target}
  172. PUBLIC
  173. "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
  174. "$<BUILD_INTERFACE:${QT_PROTOBUF_BINARY_DIR}/include/${target}>"
  175. "$<INSTALL_INTERFACE:${target_include_dir}>"
  176. )
  177. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS}
  178. PUBLIC_HEADER ${arg_PUBLIC_HEADER})
  179. add_library(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  180. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  181. include(CMakePackageConfigHelpers)
  182. configure_package_config_file("Qt${target}Config.cmake.in"
  183. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  184. INSTALL_DESTINATION "${target_cmake_dir}"
  185. )
  186. if(QT_PROTOBUF_INSTALL)
  187. install(TARGETS ${target}
  188. EXPORT ${target_export} COMPONENT dev
  189. ARCHIVE DESTINATION ${target_lib_dir} COMPONENT lib
  190. PUBLIC_HEADER DESTINATION ${target_include_dir} COMPONENT dev
  191. LIBRARY DESTINATION ${target_lib_dir} COMPONENT lib
  192. RUNTIME DESTINATION ${target_cmake_dir} COMPONENT lib)
  193. install(EXPORT ${target_export}
  194. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  195. FILE ${target_export}.cmake
  196. DESTINATION ${target_cmake_dir}
  197. COMPONENT dev)
  198. install(FILES "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  199. DESTINATION "${target_cmake_dir}"
  200. COMPONENT dev)
  201. endif()
  202. export(TARGETS ${target}
  203. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  204. FILE ${target_export}.cmake)
  205. qt_protobuf_internal_add_coverage_target(TARGET ${target})
  206. endfunction()
  207. function(qt_protobuf_internal_extend_target target)
  208. set(multi_arg
  209. SOURCES
  210. PUBLIC_HEADER
  211. INCLUDE_DIRECTORIES
  212. LIBRARIES
  213. PUBLIC_LIBRARIES
  214. PUBLIC_INCLUDE_DIRECTORIES
  215. DEFINES
  216. PUBLIC_DEFINES
  217. )
  218. qtprotobuf_parse_arguments(arg
  219. ""
  220. ""
  221. "${multi_arg}"
  222. ${ARGN}
  223. )
  224. if(NOT TARGET ${target})
  225. message(FATAL_ERROR "${target} is not a target")
  226. endif()
  227. if(arg_SOURCES)
  228. file(GLOB sources ${arg_SOURCES})
  229. target_sources(${target} PRIVATE ${sources})
  230. endif()
  231. if(arg_PUBLIC_HEADER)
  232. file(GLOB PUBLIC_HEADER ${arg_PUBLIC_HEADER})
  233. qt_protobuf_internal_generate_qt_headers(generated_public_header
  234. PUBLIC_HEADER ${PUBLIC_HEADER}
  235. TARGET ${target}
  236. )
  237. set_target_properties(${target} PROPERTIES
  238. PUBLIC_HEADER "${PUBLIC_HEADER};${generated_public_header}")
  239. endif()
  240. if(arg_LIBRARIES)
  241. target_link_libraries(${target} PRIVATE ${arg_LIBRARIES})
  242. endif()
  243. if(arg_PUBLIC_LIBRARIES)
  244. target_link_libraries(${target} PUBLIC ${arg_PUBLIC_LIBRARIES})
  245. endif()
  246. if(arg_INCLUDE_DIRECTORIES)
  247. target_include_directories(${target} PRIVATE ${arg_INCLUDE_DIRECTORIES})
  248. endif()
  249. if(arg_PUBLIC_INCLUDE_DIRECTORIES)
  250. target_include_directories(${target} PUBLIC ${arg_PUBLIC_INCLUDE_DIRECTORIES})
  251. endif()
  252. if(arg_DEFINES)
  253. target_compile_definitions(${target} PRIVATE ${arg_DEFINES})
  254. endif()
  255. if(arg_PUBLIC_DEFINES)
  256. target_compile_definitions(${target} PUBLIC ${arg_PUBLIC_DEFINES})
  257. endif()
  258. endfunction()
  259. function(qt_protobuf_internal_add_executable target)
  260. qtprotobuf_parse_arguments(arg
  261. ""
  262. ""
  263. "SOURCES"
  264. ${ARGN}
  265. )
  266. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  267. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  268. set(target_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE})
  269. set(target_bindir ${CMAKE_INSTALL_BINDIR})
  270. file(GLOB sources ${arg_SOURCES})
  271. add_executable(${target} ${sources})
  272. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS})
  273. add_executable(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  274. include(CMakePackageConfigHelpers)
  275. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  276. include(CMakePackageConfigHelpers)
  277. configure_package_config_file("Qt${target}Config.cmake.in"
  278. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  279. INSTALL_DESTINATION "${target_cmake_dir}"
  280. )
  281. if(QT_PROTOBUF_INSTALL)
  282. install(TARGETS ${target}
  283. EXPORT ${target_export} COMPONENT dev
  284. RUNTIME DESTINATION ${target_bindir}
  285. COMPONENT lib)
  286. install(EXPORT ${target_export}
  287. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  288. FILE ${target_export}.cmake
  289. DESTINATION ${target_cmake_dir}
  290. COMPONENT dev)
  291. install(FILES "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  292. DESTINATION "${target_cmake_dir}"
  293. COMPONENT dev)
  294. endif()
  295. export(TARGETS ${target} NAMESPACE ${QT_PROTOBUF_NAMESPACE}:: FILE ${target_export}.cmake)
  296. endfunction()