QtProtobufInternalHelpers.cmake 16 KB

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