QtProtobufInternalHelpers.cmake 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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)
  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(${arg_TARGET} ${SOURCES} ${arg_RESOURCES})
  71. qtprotobuf_generate(TARGET ${arg_TARGET}
  72. OUT_DIR ${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 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. "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. set(CMAKE_AUTOMOC ON)
  146. set(CMAKE_AUTORCC ON)
  147. if(NOT arg_SOURCES)
  148. message(FATAL_ERROR "SOURCES are not specified for ${target}")
  149. endif()
  150. file(GLOB sources ${arg_SOURCES} ${arg_PUBLIC_HEADER})
  151. add_library(${target} ${sources})
  152. if(NOT BUILD_SHARED_LIBS)
  153. target_compile_definitions(${target} PUBLIC QT_PROTOBUF_STATIC)
  154. endif()
  155. string(TOUPPER "${target}" target_upper)
  156. target_compile_definitions(${target} PRIVATE QT_BUILD_${target_upper}_LIB)
  157. set_target_properties(${target}
  158. PROPERTIES
  159. VERSION ${PROJECT_VERSION}
  160. OUTPUT_NAME ${QT_VERSIONED_PREFIX}${target}
  161. )
  162. target_compile_features(${target}
  163. PUBLIC cxx_std_14
  164. cxx_auto_type
  165. cxx_decltype
  166. cxx_final
  167. cxx_override
  168. cxx_nullptr
  169. cxx_lambdas
  170. cxx_func_identifier
  171. )
  172. target_compile_definitions(${target}
  173. PUBLIC
  174. QT_PROTOBUF_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
  175. QT_PROTOBUF_VERSION_MINOR=${PROJECT_VERSION_MINOR}
  176. )
  177. target_include_directories(${target}
  178. PUBLIC
  179. "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
  180. "$<BUILD_INTERFACE:${QT_PROTOBUF_BINARY_DIR}/include/${target}>"
  181. "$<INSTALL_INTERFACE:${target_install_includedir}>"
  182. )
  183. qt_protobuf_internal_extend_target(${target} ${arg_UNPARSED_ARGUMENTS}
  184. PUBLIC_HEADER ${arg_PUBLIC_HEADER})
  185. add_library(${QT_PROTOBUF_NAMESPACE}::${target} ALIAS ${target})
  186. set(target_config_bin_dir "${QT_PROTOBUF_BINARY_DIR}/")
  187. include(CMakePackageConfigHelpers)
  188. configure_package_config_file("Qt${target}Config.cmake.in"
  189. "${QT_PROTOBUF_BINARY_DIR}/${target_config}.cmake"
  190. INSTALL_DESTINATION "${target_install_cmakedir}"
  191. )
  192. export(TARGETS ${target}
  193. NAMESPACE ${QT_PROTOBUF_NAMESPACE}::
  194. FILE ${target_export}.cmake
  195. )
  196. if(QT_PROTOBUF_INSTALL)
  197. if(NOT arg_INSTALL_LIBDIR)
  198. unset(arg_INSTALL_LIBDIR)
  199. endif()
  200. if(NOT arg_INSTALL_INCLUDEDIR)
  201. unset(arg_INSTALL_INCLUDEDIR)
  202. endif()
  203. set_target_properties(${target} PROPERTIES
  204. qt_protobuf_install_libdir "${arg_INSTALL_LIBDIR}"
  205. qt_protobuf_install_includedir "${arg_INSTALL_INCLUDEDIR}"
  206. )
  207. set_property(GLOBAL APPEND PROPERTY qt_protobuf_install_targets ${target})
  208. endif()
  209. qt_protobuf_internal_add_coverage_target(TARGET ${target})
  210. endfunction()
  211. function(qt_protobuf_internal_extend_target target)
  212. set(multi_arg
  213. SOURCES
  214. PUBLIC_HEADER
  215. INCLUDE_DIRECTORIES
  216. LIBRARIES
  217. PUBLIC_LIBRARIES
  218. PUBLIC_INCLUDE_DIRECTORIES
  219. DEFINES
  220. PUBLIC_DEFINES
  221. )
  222. qtprotobuf_parse_arguments(arg
  223. ""
  224. ""
  225. "${multi_arg}"
  226. ${ARGN}
  227. )
  228. if(NOT TARGET ${target})
  229. message(FATAL_ERROR "${target} is not a target")
  230. endif()
  231. if(arg_SOURCES)
  232. file(GLOB sources ${arg_SOURCES})
  233. target_sources(${target} PRIVATE ${sources})
  234. endif()
  235. if(arg_PUBLIC_HEADER)
  236. file(GLOB PUBLIC_HEADER ${arg_PUBLIC_HEADER})
  237. qt_protobuf_internal_generate_qt_headers(generated_public_header
  238. PUBLIC_HEADER ${PUBLIC_HEADER}
  239. TARGET ${target}
  240. )
  241. set_target_properties(${target} PROPERTIES
  242. PUBLIC_HEADER "${PUBLIC_HEADER};${generated_public_header}")
  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()