QtProtobufInternalHelpers.cmake 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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 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. OUTPUT_DIRECTORY ${GENERATED_SOURCES_DIR}
  46. PROTO_FILES ${proto_files}
  47. EXCLUDE_HEADERS ${add_test_target_EXCLUDE_HEADERS}
  48. ${EXTRA_OPTIONS}
  49. PROTO_INCLUDES ${add_test_target_PROTO_INCLUDES})
  50. target_link_libraries(${add_test_target_TARGET} PUBLIC gtest_main
  51. gtest
  52. ${QT_PROTOBUF_NAMESPACE}::Protobuf
  53. ${QT_PROTOBUF_NAMESPACE}::Grpc
  54. ${QT_VERSIONED_PREFIX}::Core
  55. ${QT_VERSIONED_PREFIX}::Test
  56. ${QT_VERSIONED_PREFIX}::Network
  57. ${CMAKE_THREAD_LIBS_INIT})
  58. if(${add_test_target_QML})
  59. target_link_libraries(${add_test_target_TARGET} PUBLIC ${QT_VERSIONED_PREFIX}::Qml)
  60. endif()
  61. endfunction()
  62. function(qt_protobuf_internal_add_example)
  63. set(options)
  64. set(oneValueArgs TARGET QML_DIR)
  65. set(multiValueArgs SOURCES PROTO_FILES RESOURCES)
  66. cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  67. set(CMAKE_INCLUDE_CURRENT_DIR ON)
  68. file(GLOB PROTO_FILES ABSOLUTE ${arg_PROTO_FILES})
  69. file(GLOB SOURCES ${arg_SOURCES})
  70. add_executable(${arg_TARGET} ${SOURCES} ${arg_RESOURCES})
  71. qtprotobuf_generate(TARGET ${arg_TARGET}
  72. OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated
  73. PROTO_FILES ${PROTO_FILES}
  74. QML)
  75. qt_protobuf_internal_add_target_windeployqt(TARGET ${arg_TARGET} QML_DIR ${arg_QML_DIR})
  76. target_link_libraries(${arg_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 FALSE 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. "INSTALL_LIBDIR;INSTALL_INCLUDEDIR"
  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. if(arg_INSTALL_INCLUDEDIR)
  137. set(target_install_includedir "${arg_INSTALL_INCLUDEDIR}")
  138. else()
  139. set(target_install_includedir
  140. "${CMAKE_INSTALL_INCLUDEDIR}/${QT_PROTOBUF_NAMESPACE}${target}"
  141. )
  142. endif()
  143. set(target_install_libdir "${CMAKE_INSTALL_LIBDIR}")
  144. set(target_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}")
  145. if(NOT arg_SOURCES)
  146. message(FATAL_ERROR "SOURCES are not specified for ${target}")
  147. endif()
  148. file(GLOB sources ${arg_SOURCES})
  149. add_library(${target} ${sources})
  150. if(NOT BUILD_SHARED_LIBS)
  151. target_compile_definitions(${target} PUBLIC QT_PROTOBUF_STATIC)
  152. endif()
  153. string(TOUPPER "${target}" target_upper)
  154. target_compile_definitions(${target} PRIVATE QT_BUILD_${target_upper}_LIB)
  155. set_target_properties(${target}
  156. PROPERTIES
  157. VERSION ${PROJECT_VERSION}
  158. OUTPUT_NAME ${QT_VERSIONED_PREFIX}${target}
  159. )
  160. target_compile_features(${target}
  161. PUBLIC cxx_std_14
  162. cxx_auto_type
  163. cxx_decltype
  164. cxx_final
  165. cxx_override
  166. cxx_nullptr
  167. cxx_lambdas
  168. cxx_func_identifier
  169. )
  170. target_compile_definitions(${target}
  171. PUBLIC
  172. QT_PROTOBUF_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
  173. QT_PROTOBUF_VERSION_MINOR=${PROJECT_VERSION_MINOR}
  174. )
  175. target_include_directories(${target}
  176. PUBLIC
  177. "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
  178. "$<BUILD_INTERFACE:${QT_PROTOBUF_BINARY_DIR}/include/${target}>"
  179. "$<INSTALL_INTERFACE:${target_install_includedir}>"
  180. )
  181. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS}
  182. PUBLIC_HEADER ${arg_PUBLIC_HEADER})
  183. add_library(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  184. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  185. include(CMakePackageConfigHelpers)
  186. configure_package_config_file("Qt${target}Config.cmake.in"
  187. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  188. INSTALL_DESTINATION "${target_install_cmakedir}"
  189. )
  190. export(TARGETS ${target}
  191. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  192. FILE ${target_export}.cmake
  193. )
  194. if(QT_PROTOBUF_INSTALL)
  195. if(NOT arg_INSTALL_LIBDIR)
  196. unset(arg_INSTALL_LIBDIR)
  197. endif()
  198. if(NOT arg_INSTALL_INCLUDEDIR)
  199. unset(arg_INSTALL_INCLUDEDIR)
  200. endif()
  201. set_target_properties(${target} PROPERTIES
  202. qt_protobuf_install_libdir "${arg_INSTALL_LIBDIR}"
  203. qt_protobuf_install_includedir "${arg_INSTALL_INCLUDEDIR}"
  204. )
  205. set_property(GLOBAL APPEND PROPERTY qt_protobuf_install_targets ${target})
  206. endif()
  207. qt_protobuf_internal_add_coverage_target(TARGET ${target})
  208. endfunction()
  209. function(qt_protobuf_internal_extend_target target)
  210. set(multi_arg
  211. SOURCES
  212. PUBLIC_HEADER
  213. INCLUDE_DIRECTORIES
  214. LIBRARIES
  215. PUBLIC_LIBRARIES
  216. PUBLIC_INCLUDE_DIRECTORIES
  217. DEFINES
  218. PUBLIC_DEFINES
  219. )
  220. qtprotobuf_parse_arguments(arg
  221. ""
  222. ""
  223. "${multi_arg}"
  224. ${ARGN}
  225. )
  226. if(NOT TARGET ${target})
  227. message(FATAL_ERROR "${target} is not a target")
  228. endif()
  229. if(arg_SOURCES)
  230. file(GLOB sources ${arg_SOURCES})
  231. target_sources(${target} PRIVATE ${sources})
  232. endif()
  233. if(arg_PUBLIC_HEADER)
  234. file(GLOB public_header_paths ${arg_PUBLIC_HEADER})
  235. qt_protobuf_internal_generate_qt_headers(generated_public_header
  236. PUBLIC_HEADER ${public_header_paths}
  237. TARGET ${target}
  238. )
  239. set_property(TARGET ${target} APPEND PROPERTY
  240. PUBLIC_HEADER "${public_header_paths};${generated_public_header}")
  241. target_sources(${target} PRIVATE ${public_header_paths})
  242. endif()
  243. if(arg_LIBRARIES)
  244. target_link_libraries(${target} PRIVATE ${arg_LIBRARIES})
  245. endif()
  246. if(arg_PUBLIC_LIBRARIES)
  247. target_link_libraries(${target} PUBLIC ${arg_PUBLIC_LIBRARIES})
  248. endif()
  249. if(arg_INCLUDE_DIRECTORIES)
  250. target_include_directories(${target} PRIVATE ${arg_INCLUDE_DIRECTORIES})
  251. endif()
  252. if(arg_PUBLIC_INCLUDE_DIRECTORIES)
  253. target_include_directories(${target} PUBLIC ${arg_PUBLIC_INCLUDE_DIRECTORIES})
  254. endif()
  255. if(arg_DEFINES)
  256. target_compile_definitions(${target} PRIVATE ${arg_DEFINES})
  257. endif()
  258. if(arg_PUBLIC_DEFINES)
  259. target_compile_definitions(${target} PUBLIC ${arg_PUBLIC_DEFINES})
  260. endif()
  261. endfunction()
  262. function(qt_protobuf_internal_add_executable target)
  263. qtprotobuf_parse_arguments(arg
  264. ""
  265. "INSTALL_BINDIR"
  266. "SOURCES"
  267. ${ARGN}
  268. )
  269. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  270. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  271. set(target_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}")
  272. file(GLOB sources ${arg_SOURCES})
  273. add_executable(${target} ${sources})
  274. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS})
  275. add_executable(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  276. include(CMakePackageConfigHelpers)
  277. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  278. include(CMakePackageConfigHelpers)
  279. configure_package_config_file("Qt${target}Config.cmake.in"
  280. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  281. INSTALL_DESTINATION "${target_install_cmakedir}"
  282. )
  283. export(TARGETS ${target} NAMESPACE ${QT_PROTOBUF_NAMESPACE}:: FILE ${target_export}.cmake)
  284. if(QT_PROTOBUF_INSTALL)
  285. if(arg_INSTALL_BINDIR)
  286. set_target_properties(${target} PROPERTIES
  287. qt_protobuf_install_bindir "${arg_INSTALL_BINDIR}"
  288. )
  289. endif()
  290. set_property(GLOBAL APPEND PROPERTY qt_protobuf_install_targets ${target})
  291. endif()
  292. endfunction()
  293. function(qt_protobuf_internal_install_targets)
  294. if(NOT QT_PROTOBUF_INSTALL)
  295. return()
  296. endif()
  297. get_property(install_targets GLOBAL PROPERTY qt_protobuf_install_targets)
  298. list(REMOVE_DUPLICATES install_targets)
  299. foreach(target ${install_targets})
  300. set(target_config "${QT_PROTOBUF_NAMESPACE}${target}Config")
  301. set(target_export "${QT_PROTOBUF_NAMESPACE}${target}Targets")
  302. set(target_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/${QT_PROTOBUF_NAMESPACE}")
  303. get_target_property(type ${target} TYPE)
  304. if("${type}" STREQUAL "EXECUTABLE")
  305. get_target_property(target_install_bindir ${target} qt_protobuf_install_bindir)
  306. if(NOT target_install_bindir)
  307. set(target_install_bindir "${CMAKE_INSTALL_BINDIR}")
  308. endif()
  309. install(TARGETS ${target}
  310. EXPORT ${target_export} COMPONENT dev
  311. RUNTIME DESTINATION "${target_install_bindir}" COMPONENT lib
  312. )
  313. else()
  314. set(target_install_bindir "${CMAKE_INSTALL_BINDIR}")
  315. get_target_property(target_install_includedir ${target} qt_protobuf_install_includedir)
  316. if(NOT target_install_includedir)
  317. set(target_install_includedir
  318. "${CMAKE_INSTALL_INCLUDEDIR}/${QT_PROTOBUF_NAMESPACE}${target}"
  319. )
  320. endif()
  321. get_target_property(target_install_libdir ${target} qt_protobuf_install_libdir)
  322. if(NOT target_install_libdir)
  323. set(target_install_libdir "${CMAKE_INSTALL_LIBDIR}")
  324. endif()
  325. install(TARGETS ${target}
  326. EXPORT ${target_export} COMPONENT dev
  327. ARCHIVE DESTINATION "${target_install_libdir}" COMPONENT lib
  328. PUBLIC_HEADER DESTINATION "${target_install_includedir}" COMPONENT dev
  329. LIBRARY DESTINATION "${target_install_libdir}" COMPONENT lib
  330. RUNTIME DESTINATION "${target_install_bindir}" COMPONENT lib
  331. )
  332. endif()
  333. install(EXPORT ${target_export}
  334. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  335. FILE ${target_export}.cmake
  336. DESTINATION "${target_install_cmakedir}"
  337. COMPONENT dev
  338. )
  339. install(FILES "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  340. DESTINATION "${target_install_cmakedir}"
  341. COMPONENT dev
  342. )
  343. endforeach()
  344. endfunction()
  345. function(qt_protobuf_internal_generate_pri target)
  346. string(TOLOWER "${target}" target_lower)
  347. set(pri_name "qt_lib_${target_lower}.pri")
  348. get_target_property(QT_PROTOBUF_LIBRARY_OUTPUT_NAME ${target} OUTPUT_NAME)
  349. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${pri_name}.in"
  350. "${QT_PROTOBUF_BINARY_DIR}/${pri_name}" @ONLY
  351. )
  352. if(QT_PROTOBUF_INSTALL)
  353. qt_protobuf_extract_qt_variable(QT_INSTALL_ARCHDATA)
  354. qt_protobuf_extract_qt_variable(QT_INSTALL_PREFIX)
  355. if("${QT_INSTALL_PREFIX}" STREQUAL "${CMAKE_INSTALL_PREFIX}")
  356. set(mkspec_install_dir "${QT_INSTALL_ARCHDATA}/mkspecs/modules")
  357. else()
  358. set(mkspec_install_dir "${CMAKE_INSTALL_PREFIX}/mkspecs/modules")
  359. endif()
  360. install(FILES "${QT_PROTOBUF_BINARY_DIR}/${pri_name}"
  361. DESTINATION "${mkspec_install_dir}"
  362. COMPONENT dev
  363. )
  364. endif()
  365. endfunction()