QtProtobufInternalHelpers.cmake 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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 "${option}" "${single}" "${_qtprotobuf_all_known_multi_args}" ${ARGN})
  5. foreach(_arg IN ITEMS ${_qtprotobuf_all_known_multi_args};${single};${option})
  6. if(${_arg} IN_LIST multi OR ${_arg} IN_LIST single OR ${_arg} IN_LIST option)
  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 EXTRA_NAMESPACE)
  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. if(add_test_target_EXTRA_NAMESPACE)
  42. set(EXTRA_OPTIONS ${EXTRA_OPTIONS} EXTRA_NAMESPACE ${add_test_target_EXTRA_NAMESPACE})
  43. endif()
  44. qtprotobuf_generate(TARGET ${add_test_target_TARGET}
  45. OUT_DIR ${GENERATED_SOURCES_DIR}
  46. PROTO_FILES ${proto_files}
  47. GENERATED_HEADERS ${add_test_target_GENERATED_HEADERS}
  48. EXCLUDE_HEADERS ${add_test_target_EXCLUDE_HEADERS}
  49. ${EXTRA_OPTIONS}
  50. PROTO_INCLUDES ${add_test_target_PROTO_INCLUDES})
  51. target_link_libraries(${add_test_target_TARGET} PUBLIC gtest_main
  52. gtest
  53. ${QT_PROTOBUF_NAMESPACE}::Protobuf
  54. ${QT_PROTOBUF_NAMESPACE}::Grpc
  55. ${QT_VERSIONED_PREFIX}::Core
  56. ${QT_VERSIONED_PREFIX}::Test
  57. ${QT_VERSIONED_PREFIX}::Network
  58. ${CMAKE_THREAD_LIBS_INIT})
  59. if(${add_test_target_QML})
  60. target_link_libraries(${add_test_target_TARGET} PUBLIC ${QT_VERSIONED_PREFIX}::Qml)
  61. endif()
  62. endfunction()
  63. function(qt_protobuf_internal_add_example)
  64. set(options)
  65. set(oneValueArgs TARGET QML_DIR)
  66. set(multiValueArgs SOURCES PROTO_FILES RESOURCES)
  67. cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  68. set(CMAKE_INCLUDE_CURRENT_DIR ON)
  69. file(GLOB PROTO_FILES ABSOLUTE ${arg_PROTO_FILES})
  70. file(GLOB SOURCES ${arg_SOURCES})
  71. add_executable(${arg_TARGET} ${SOURCES} ${arg_RESOURCES})
  72. qtprotobuf_generate(TARGET ${arg_TARGET}
  73. OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated
  74. PROTO_FILES ${PROTO_FILES}
  75. QML)
  76. qt_protobuf_internal_add_target_windeployqt(TARGET ${arg_TARGET} QML_DIR ${arg_QML_DIR})
  77. target_link_libraries(${arg_TARGET} PRIVATE examples_common
  78. ${QT_PROTOBUF_NAMESPACE}::Protobuf
  79. ${QT_PROTOBUF_NAMESPACE}::Grpc
  80. ${QT_VERSIONED_PREFIX}::Quick
  81. ${QT_VERSIONED_PREFIX}::Qml)
  82. endfunction()
  83. function(qt_protobuf_internal_check_install)
  84. set(QT_PROTOBUF_INSTALL
  85. TRUE CACHE INTERNAL "Indicates wether QT_PROTOBUF_INSTALL might be installed or not" FORCE
  86. )
  87. if(NOT "${QT_PROTOBUF_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
  88. message(STATUS "QtProtobuf configured as sub-project.")
  89. set(QT_PROTOBUF_INSTALL FALSE CACHE INTERNAL "" FORCE)
  90. message(STATUS "All install rules are disabled.")
  91. endif()
  92. endfunction()
  93. function(qt_protobuf_extract_qt_variable variable)
  94. if(NOT DEFINED QT_QMAKE_EXECUTABLE)
  95. find_program(QT_QMAKE_EXECUTABLE "qmake")
  96. if(QT_QMAKE_EXECUTABLE STREQUAL QT_QMAKE_EXECUTABLE-NOTFOUND)
  97. message(FATAL_ERROR "Could not find qmake executable")
  98. endif()
  99. endif()
  100. execute_process(
  101. COMMAND "${QT_QMAKE_EXECUTABLE}" -query ${variable}
  102. OUTPUT_VARIABLE ${variable}
  103. OUTPUT_STRIP_TRAILING_WHITESPACE
  104. )
  105. set(${variable} ${${variable}} PARENT_SCOPE)
  106. endfunction()
  107. function(qt_protobuf_internal_generate_qt_headers out_var)
  108. set(options)
  109. set(oneValueArgs "TARGET")
  110. set(multiValueArgs "PUBLIC_HEADER")
  111. cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  112. foreach(PUBLIC_HEADER IN LISTS arg_PUBLIC_HEADER)
  113. get_filename_component(PUBLIC_HEADER_BASE_NAME ${PUBLIC_HEADER} NAME FALSE)
  114. file(STRINGS ${PUBLIC_HEADER} CLASS_NAME REGEX "#pragma once //[a-zA-Z]+")
  115. if (NOT "${CLASS_NAME}" STREQUAL "")
  116. string(REPLACE "#pragma once //" "" CLASS_NAME "${CLASS_NAME}")
  117. message(STATUS "Generate Qt header for ${CLASS_NAME}")
  118. configure_file("${QT_PROTOBUF_CMAKE_DIR}/GeneratedHeaderTemplate"
  119. "${QT_PROTOBUF_BINARY_DIR}/include/${arg_TARGET}/${CLASS_NAME}" @ONLY
  120. )
  121. list(APPEND ${out_var}
  122. "${QT_PROTOBUF_BINARY_DIR}/include/${arg_TARGET}/${CLASS_NAME}"
  123. )
  124. endif()
  125. endforeach()
  126. set(${out_var} "${${out_var}}" PARENT_SCOPE)
  127. endfunction()
  128. function(qt_protobuf_internal_add_library target)
  129. qtprotobuf_parse_arguments(arg
  130. ""
  131. "INSTALL_LIBDIR;INSTALL_INCLUDEDIR"
  132. "SOURCES;PUBLIC_HEADER"
  133. ${ARGN}
  134. )
  135. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  136. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  137. if(arg_INSTALL_INCLUDEDIR)
  138. set(target_install_includedir "${arg_INSTALL_INCLUDEDIR}")
  139. else()
  140. set(target_install_includedir
  141. "${CMAKE_INSTALL_INCLUDEDIR}/${QT_PROTOBUF_NAMESPACE}${target}"
  142. )
  143. endif()
  144. set(target_install_libdir "${CMAKE_INSTALL_LIBDIR}")
  145. set(target_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}")
  146. if(NOT arg_SOURCES)
  147. message(FATAL_ERROR "SOURCES are not specified for ${target}")
  148. endif()
  149. file(GLOB sources ${arg_SOURCES})
  150. add_library(${target} ${sources})
  151. if(NOT BUILD_SHARED_LIBS)
  152. target_compile_definitions(${target} PUBLIC QT_PROTOBUF_STATIC)
  153. endif()
  154. string(TOUPPER "${target}" target_upper)
  155. target_compile_definitions(${target} PRIVATE QT_BUILD_${target_upper}_LIB)
  156. set_target_properties(${target}
  157. PROPERTIES
  158. VERSION ${PROJECT_VERSION}
  159. OUTPUT_NAME ${QT_VERSIONED_PREFIX}${target}
  160. )
  161. target_compile_features(${target}
  162. PUBLIC cxx_std_14
  163. cxx_auto_type
  164. cxx_decltype
  165. cxx_final
  166. cxx_override
  167. cxx_nullptr
  168. cxx_lambdas
  169. cxx_func_identifier
  170. )
  171. target_compile_definitions(${target}
  172. PUBLIC
  173. QT_PROTOBUF_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
  174. QT_PROTOBUF_VERSION_MINOR=${PROJECT_VERSION_MINOR}
  175. )
  176. target_include_directories(${target}
  177. PUBLIC
  178. "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
  179. "$<BUILD_INTERFACE:${QT_PROTOBUF_BINARY_DIR}/include/${target}>"
  180. "$<INSTALL_INTERFACE:${target_install_includedir}>"
  181. )
  182. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS}
  183. PUBLIC_HEADER ${arg_PUBLIC_HEADER})
  184. add_library(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  185. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  186. include(CMakePackageConfigHelpers)
  187. configure_package_config_file("Qt${target}Config.cmake.in"
  188. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  189. INSTALL_DESTINATION "${target_install_cmakedir}"
  190. )
  191. export(TARGETS ${target}
  192. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  193. FILE ${target_export}.cmake
  194. )
  195. if(QT_PROTOBUF_INSTALL)
  196. if(NOT arg_INSTALL_LIBDIR)
  197. unset(arg_INSTALL_LIBDIR)
  198. endif()
  199. if(NOT arg_INSTALL_INCLUDEDIR)
  200. unset(arg_INSTALL_INCLUDEDIR)
  201. endif()
  202. set_target_properties(${target} PROPERTIES
  203. qt_protobuf_install_libdir "${arg_INSTALL_LIBDIR}"
  204. qt_protobuf_install_includedir "${arg_INSTALL_INCLUDEDIR}"
  205. )
  206. set_property(GLOBAL APPEND PROPERTY qt_protobuf_install_targets ${target})
  207. endif()
  208. qt_protobuf_internal_add_coverage_target(TARGET ${target})
  209. endfunction()
  210. function(qt_protobuf_internal_extend_target target)
  211. set(multi_arg
  212. SOURCES
  213. PUBLIC_HEADER
  214. INCLUDE_DIRECTORIES
  215. LIBRARIES
  216. PUBLIC_LIBRARIES
  217. PUBLIC_INCLUDE_DIRECTORIES
  218. DEFINES
  219. PUBLIC_DEFINES
  220. )
  221. qtprotobuf_parse_arguments(arg
  222. ""
  223. ""
  224. "${multi_arg}"
  225. ${ARGN}
  226. )
  227. if(NOT TARGET ${target})
  228. message(FATAL_ERROR "${target} is not a target")
  229. endif()
  230. if(arg_SOURCES)
  231. file(GLOB sources ${arg_SOURCES})
  232. target_sources(${target} PRIVATE ${sources})
  233. endif()
  234. if(arg_PUBLIC_HEADER)
  235. file(GLOB public_header_paths ${arg_PUBLIC_HEADER})
  236. qt_protobuf_internal_generate_qt_headers(generated_public_header
  237. PUBLIC_HEADER ${public_header_paths}
  238. TARGET ${target}
  239. )
  240. set_property(TARGET ${target} APPEND PROPERTY
  241. PUBLIC_HEADER "${public_header_paths};${generated_public_header}")
  242. target_sources(${target} PRIVATE ${public_header_paths})
  243. endif()
  244. if(arg_LIBRARIES)
  245. target_link_libraries(${target} PRIVATE ${arg_LIBRARIES})
  246. endif()
  247. if(arg_PUBLIC_LIBRARIES)
  248. target_link_libraries(${target} PUBLIC ${arg_PUBLIC_LIBRARIES})
  249. endif()
  250. if(arg_INCLUDE_DIRECTORIES)
  251. target_include_directories(${target} PRIVATE ${arg_INCLUDE_DIRECTORIES})
  252. endif()
  253. if(arg_PUBLIC_INCLUDE_DIRECTORIES)
  254. target_include_directories(${target} PUBLIC ${arg_PUBLIC_INCLUDE_DIRECTORIES})
  255. endif()
  256. if(arg_DEFINES)
  257. target_compile_definitions(${target} PRIVATE ${arg_DEFINES})
  258. endif()
  259. if(arg_PUBLIC_DEFINES)
  260. target_compile_definitions(${target} PUBLIC ${arg_PUBLIC_DEFINES})
  261. endif()
  262. endfunction()
  263. function(qt_protobuf_internal_add_executable target)
  264. qtprotobuf_parse_arguments(arg
  265. ""
  266. "INSTALL_BINDIR"
  267. "SOURCES"
  268. ${ARGN}
  269. )
  270. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  271. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  272. set(target_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}")
  273. file(GLOB sources ${arg_SOURCES})
  274. add_executable(${target} ${sources})
  275. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS})
  276. add_executable(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  277. include(CMakePackageConfigHelpers)
  278. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  279. include(CMakePackageConfigHelpers)
  280. configure_package_config_file("Qt${target}Config.cmake.in"
  281. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  282. INSTALL_DESTINATION "${target_install_cmakedir}"
  283. )
  284. export(TARGETS ${target} NAMESPACE ${QT_PROTOBUF_NAMESPACE}:: FILE ${target_export}.cmake)
  285. if(QT_PROTOBUF_INSTALL)
  286. if(arg_INSTALL_BINDIR)
  287. set_target_properties(${target} PROPERTIES
  288. qt_protobuf_install_bindir "${arg_INSTALL_BINDIR}"
  289. )
  290. endif()
  291. set_property(GLOBAL APPEND PROPERTY qt_protobuf_install_targets ${target})
  292. endif()
  293. endfunction()
  294. function(qt_protobuf_internal_install_targets)
  295. if(NOT QT_PROTOBUF_INSTALL)
  296. return()
  297. endif()
  298. get_property(install_targets GLOBAL PROPERTY qt_protobuf_install_targets)
  299. list(REMOVE_DUPLICATES install_targets)
  300. foreach(target ${install_targets})
  301. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  302. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  303. set(target_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}")
  304. get_target_property(type ${target} TYPE)
  305. if("${type}" STREQUAL "EXECUTABLE")
  306. get_target_property(target_install_bindir ${target} qt_protobuf_install_bindir)
  307. if(NOT target_install_bindir)
  308. set(target_install_bindir "${CMAKE_INSTALL_BINDIR}")
  309. endif()
  310. install(TARGETS ${target}
  311. EXPORT ${target_export} COMPONENT dev
  312. RUNTIME DESTINATION "${target_install_bindir}" COMPONENT lib
  313. )
  314. else()
  315. set(target_install_bindir "${CMAKE_INSTALL_BINDIR}")
  316. get_target_property(target_install_includedir ${target} qt_protobuf_install_includedir)
  317. if(NOT target_install_includedir)
  318. set(target_install_includedir
  319. "${CMAKE_INSTALL_INCLUDEDIR}/${QT_PROTOBUF_NAMESPACE}${target}"
  320. )
  321. endif()
  322. get_target_property(target_install_libdir ${target} qt_protobuf_install_libdir)
  323. if(NOT target_install_libdir)
  324. set(target_install_libdir "${CMAKE_INSTALL_LIBDIR}")
  325. endif()
  326. install(TARGETS ${target}
  327. EXPORT ${target_export} COMPONENT dev
  328. ARCHIVE DESTINATION "${target_install_libdir}" COMPONENT lib
  329. PUBLIC_HEADER DESTINATION "${target_install_includedir}" COMPONENT dev
  330. LIBRARY DESTINATION "${target_install_libdir}" COMPONENT lib
  331. RUNTIME DESTINATION "${target_install_bindir}" COMPONENT lib
  332. )
  333. endif()
  334. install(EXPORT ${target_export}
  335. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  336. FILE ${target_export}.cmake
  337. DESTINATION "${target_install_cmakedir}"
  338. COMPONENT dev
  339. )
  340. install(FILES "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  341. DESTINATION "${target_install_cmakedir}"
  342. COMPONENT dev
  343. )
  344. endforeach()
  345. endfunction()
  346. function(qt_protobuf_internal_generate_pri target)
  347. string(TOLOWER "${target}" target_lower)
  348. set(pri_name "qt_lib_${target_lower}.pri")
  349. get_target_property(QT_PROTOBUF_LIBRARY_OUTPUT_NAME ${target} OUTPUT_NAME)
  350. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${pri_name}.in"
  351. "${QT_PROTOBUF_BINARY_DIR}/${pri_name}" @ONLY
  352. )
  353. if(QT_PROTOBUF_INSTALL)
  354. qt_protobuf_extract_qt_variable(QT_INSTALL_ARCHDATA)
  355. qt_protobuf_extract_qt_variable(QT_INSTALL_PREFIX)
  356. if("${QT_INSTALL_PREFIX}" STREQUAL "${CMAKE_INSTALL_PREFIX}")
  357. set(mkspec_install_dir "${QT_INSTALL_ARCHDATA}/mkspecs/modules")
  358. else()
  359. set(mkspec_install_dir "${CMAKE_INSTALL_PREFIX}/mkspecs/modules")
  360. endif()
  361. install(FILES "${QT_PROTOBUF_BINARY_DIR}/${pri_name}"
  362. DESTINATION "${mkspec_install_dir}"
  363. COMPONENT dev
  364. )
  365. endif()
  366. endfunction()