FindProtobuf.cmake 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. #[=======================================================================[.rst:
  4. FindProtobuf
  5. ------------
  6. Locate and configure the Google Protocol Buffers library.
  7. .. versionadded:: 3.6
  8. Support for :command:`find_package` version checks.
  9. .. versionchanged:: 3.6
  10. All input and output variables use the ``Protobuf_`` prefix.
  11. Variables with ``PROTOBUF_`` prefix are still supported for compatibility.
  12. The following variables can be set and are optional:
  13. ``Protobuf_SRC_ROOT_FOLDER``
  14. When compiling with MSVC, if this cache variable is set
  15. the protobuf-default VS project build locations
  16. (vsprojects/Debug and vsprojects/Release
  17. or vsprojects/x64/Debug and vsprojects/x64/Release)
  18. will be searched for libraries and binaries.
  19. ``Protobuf_IMPORT_DIRS``
  20. List of additional directories to be searched for
  21. imported .proto files.
  22. ``Protobuf_DEBUG``
  23. .. versionadded:: 3.6
  24. Show debug messages.
  25. ``Protobuf_USE_STATIC_LIBS``
  26. .. versionadded:: 3.9
  27. Set to ON to force the use of the static libraries.
  28. Default is OFF.
  29. Defines the following variables:
  30. ``Protobuf_FOUND``
  31. Found the Google Protocol Buffers library
  32. (libprotobuf & header files)
  33. ``Protobuf_VERSION``
  34. .. versionadded:: 3.6
  35. Version of package found.
  36. ``Protobuf_INCLUDE_DIRS``
  37. Include directories for Google Protocol Buffers
  38. ``Protobuf_LIBRARIES``
  39. The protobuf libraries
  40. ``Protobuf_PROTOC_LIBRARIES``
  41. The protoc libraries
  42. ``Protobuf_LITE_LIBRARIES``
  43. The protobuf-lite libraries
  44. .. versionadded:: 3.9
  45. The following :prop_tgt:`IMPORTED` targets are also defined:
  46. ``protobuf::libprotobuf``
  47. The protobuf library.
  48. ``protobuf::libprotobuf-lite``
  49. The protobuf lite library.
  50. ``protobuf::libprotoc``
  51. The protoc library.
  52. ``protobuf::protoc``
  53. .. versionadded:: 3.10
  54. The protoc compiler.
  55. The following cache variables are also available to set or use:
  56. ``Protobuf_LIBRARY``
  57. The protobuf library
  58. ``Protobuf_PROTOC_LIBRARY``
  59. The protoc library
  60. ``Protobuf_INCLUDE_DIR``
  61. The include directory for protocol buffers
  62. ``Protobuf_PROTOC_EXECUTABLE``
  63. The protoc compiler
  64. ``Protobuf_LIBRARY_DEBUG``
  65. The protobuf library (debug)
  66. ``Protobuf_PROTOC_LIBRARY_DEBUG``
  67. The protoc library (debug)
  68. ``Protobuf_LITE_LIBRARY``
  69. The protobuf lite library
  70. ``Protobuf_LITE_LIBRARY_DEBUG``
  71. The protobuf lite library (debug)
  72. Example:
  73. .. code-block:: cmake
  74. find_package(Protobuf REQUIRED)
  75. include_directories(${Protobuf_INCLUDE_DIRS})
  76. include_directories(${CMAKE_CURRENT_BINARY_DIR})
  77. protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
  78. protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
  79. protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS DESCRIPTORS PROTO_DESCS foo.proto)
  80. protobuf_generate_python(PROTO_PY foo.proto)
  81. add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
  82. target_link_libraries(bar ${Protobuf_LIBRARIES})
  83. .. note::
  84. The ``protobuf_generate_cpp`` and ``protobuf_generate_python``
  85. functions and :command:`add_executable` or :command:`add_library`
  86. calls only work properly within the same directory.
  87. .. command:: protobuf_generate_cpp
  88. Add custom commands to process ``.proto`` files to C++:
  89. .. code-block:: cmake
  90. protobuf_generate_cpp (
  91. <srcs-var> <hdrs-var>
  92. [DESCRIPTORS <var>]
  93. [EXPORT_MACRO <macro>]
  94. [<proto-file>...])
  95. ``<srcs-var>``
  96. Variable to define with autogenerated source files
  97. ``<hdrs-var>``
  98. Variable to define with autogenerated header files
  99. ``DESCRIPTORS <var>``
  100. .. versionadded:: 3.10
  101. Variable to define with autogenerated descriptor files, if requested.
  102. ``EXPORT_MACRO <macro>``
  103. is a macro which should expand to ``__declspec(dllexport)`` or
  104. ``__declspec(dllimport)`` depending on what is being compiled.
  105. ``<proto-file>...``
  106. ``.proto`` files
  107. .. command:: protobuf_generate_python
  108. .. versionadded:: 3.4
  109. Add custom commands to process ``.proto`` files to Python:
  110. .. code-block:: cmake
  111. protobuf_generate_python (<py-srcs-var> [<proto-file>...])
  112. ``<py-srcs-var>``
  113. Variable to define with autogenerated Python files
  114. ``<proto-file>...``
  115. ``.proto`` files
  116. .. command:: protobuf_generate
  117. .. versionadded:: 3.13
  118. Automatically generate source files from ``.proto`` schema files at build time:
  119. .. code-block:: cmake
  120. protobuf_generate (
  121. TARGET <target>
  122. [LANGUAGE <lang>]
  123. [OUT_VAR <var>]
  124. [EXPORT_MACRO <macro>]
  125. [PROTOC_OUT_DIR <dir>]
  126. [PLUGIN <plugin>]
  127. [PLUGIN_OPTIONS <plugin-options>]
  128. [DEPENDENCIES <dependencies>]
  129. [PROTOS <proto-file>...]
  130. [IMPORT_DIRS <dir>...]
  131. [GENERATE_EXTENSIONS <extension>...]
  132. [PROTOC_OPTIONS <option>...]
  133. [PROTOC_EXE <executable>]
  134. [APPEND_PATH])
  135. ``APPEND_PATH``
  136. A flag that causes the base path of all proto schema files to be added to
  137. ``IMPORT_DIRS``.
  138. ``LANGUAGE <lang>``
  139. A single value: cpp or python. Determines what kind of source files are
  140. being generated. Defaults to cpp.
  141. ``OUT_VAR <var>``
  142. Name of a CMake variable that will be filled with the paths to the generated
  143. source files.
  144. ``EXPORT_MACRO <macro>``
  145. Name of a macro that is applied to all generated Protobuf message classes
  146. and extern variables. It can, for example, be used to declare DLL exports.
  147. ``PROTOC_OUT_DIR <dir>``
  148. Output directory of generated source files. Defaults to ``CMAKE_CURRENT_BINARY_DIR``.
  149. ``PLUGIN <plugin>``
  150. .. versionadded:: 3.21
  151. An optional plugin executable. This could, for example, be the path to
  152. ``grpc_cpp_plugin``.
  153. ``PLUGIN_OPTIONS <plugin-options>``
  154. .. versionadded:: 3.28
  155. Additional options provided to the plugin, such as ``generate_mock_code=true``
  156. for the gRPC cpp plugin.
  157. ``DEPENDENCIES <dependencies>``
  158. .. versionadded:: 3.28
  159. Arguments forwarded to the ``DEPENDS`` of the underlying ``add_custom_command``
  160. invocation.
  161. ``TARGET <target>``
  162. CMake target that will have the generated files added as sources.
  163. ``PROTOS <proto-file>...``
  164. List of proto schema files. If omitted, then every source file ending in *proto* of ``TARGET`` will be used.
  165. ``IMPORT_DIRS <dir>...``
  166. A common parent directory for the schema files. For example, if the schema file is
  167. ``proto/helloworld/helloworld.proto`` and the import directory ``proto/`` then the
  168. generated files are ``${PROTOC_OUT_DIR}/helloworld/helloworld.pb.h`` and
  169. ``${PROTOC_OUT_DIR}/helloworld/helloworld.pb.cc``.
  170. ``GENERATE_EXTENSIONS <extension>...``
  171. If LANGUAGE is omitted then this must be set to the extensions that protoc generates.
  172. ``PROTOC_OPTIONS <option>...``
  173. .. versionadded:: 3.28
  174. Additional arguments that are forwarded to protoc.
  175. ``PROTOC_EXE <executable>``
  176. .. versionadded:: 4.0
  177. Command name, path, or CMake executable used to generate protobuf bindings.
  178. If omitted, ``protobuf::protoc`` is used.
  179. Example:
  180. .. code-block:: cmake
  181. find_package(gRPC CONFIG REQUIRED)
  182. find_package(Protobuf REQUIRED)
  183. add_library(ProtoTest Test.proto)
  184. target_link_libraries(ProtoTest PUBLIC gRPC::grpc++)
  185. protobuf_generate(TARGET ProtoTest)
  186. protobuf_generate(
  187. TARGET ProtoTest
  188. LANGUAGE grpc
  189. PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
  190. PLUGIN_OPTIONS generate_mock_code=true
  191. GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc)
  192. #]=======================================================================]
  193. cmake_policy(PUSH)
  194. cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
  195. function(protobuf_generate)
  196. set(_options APPEND_PATH DESCRIPTORS)
  197. set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS DEPENDENCIES PROTOC_EXE)
  198. if(COMMAND target_sources)
  199. list(APPEND _singleargs TARGET)
  200. endif()
  201. set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS)
  202. cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
  203. if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
  204. message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
  205. return()
  206. endif()
  207. if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
  208. message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
  209. return()
  210. endif()
  211. if(NOT protobuf_generate_LANGUAGE)
  212. set(protobuf_generate_LANGUAGE cpp)
  213. endif()
  214. string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
  215. if(NOT protobuf_generate_PROTOC_OUT_DIR)
  216. set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
  217. endif()
  218. if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp)
  219. set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}")
  220. endif()
  221. foreach(_option ${_dll_export_decl} ${protobuf_generate_PLUGIN_OPTIONS})
  222. # append comma - not using CMake lists and string replacement as users
  223. # might have semicolons in options
  224. if(_plugin_options)
  225. set( _plugin_options "${_plugin_options},")
  226. endif()
  227. set(_plugin_options "${_plugin_options}${_option}")
  228. endforeach()
  229. if(protobuf_generate_PLUGIN)
  230. set(_plugin "--plugin=${protobuf_generate_PLUGIN}")
  231. endif()
  232. if(NOT protobuf_generate_GENERATE_EXTENSIONS)
  233. if(protobuf_generate_LANGUAGE STREQUAL cpp)
  234. set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
  235. elseif(protobuf_generate_LANGUAGE STREQUAL python)
  236. set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py)
  237. else()
  238. message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
  239. return()
  240. endif()
  241. endif()
  242. if(protobuf_generate_TARGET)
  243. get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
  244. foreach(_file ${_source_list})
  245. if(_file MATCHES "proto$")
  246. list(APPEND protobuf_generate_PROTOS ${_file})
  247. endif()
  248. endforeach()
  249. endif()
  250. if(NOT protobuf_generate_PROTOS)
  251. message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
  252. return()
  253. endif()
  254. if(NOT protobuf_generate_PROTOC_EXE)
  255. if(NOT TARGET protobuf::protoc)
  256. message(SEND_ERROR "protoc executable not found. "
  257. "Please define the Protobuf_PROTOC_EXECUTABLE variable, or pass PROTOC_EXE to protobuf_generate, or ensure that protoc is in CMake's search path.")
  258. return()
  259. endif()
  260. # Default to using the CMake executable
  261. set(protobuf_generate_PROTOC_EXE protobuf::protoc)
  262. endif()
  263. if(protobuf_generate_APPEND_PATH)
  264. # Create an include path for each file specified
  265. foreach(_file ${protobuf_generate_PROTOS})
  266. get_filename_component(_abs_file ${_file} ABSOLUTE)
  267. get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
  268. list(FIND _protobuf_include_path ${_abs_dir} _contains_already)
  269. if(${_contains_already} EQUAL -1)
  270. list(APPEND _protobuf_include_path -I ${_abs_dir})
  271. endif()
  272. endforeach()
  273. endif()
  274. foreach(DIR ${protobuf_generate_IMPORT_DIRS})
  275. get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
  276. list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
  277. if(${_contains_already} EQUAL -1)
  278. list(APPEND _protobuf_include_path -I ${ABS_PATH})
  279. endif()
  280. endforeach()
  281. if(NOT protobuf_generate_APPEND_PATH)
  282. list(APPEND _protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
  283. endif()
  284. set(_generated_srcs_all)
  285. foreach(_proto ${protobuf_generate_PROTOS})
  286. get_filename_component(_abs_file ${_proto} ABSOLUTE)
  287. get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
  288. get_filename_component(_basename ${_proto} NAME_WLE)
  289. file(RELATIVE_PATH _rel_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_abs_dir})
  290. set(_possible_rel_dir)
  291. if (NOT protobuf_generate_APPEND_PATH)
  292. foreach(DIR ${_protobuf_include_path})
  293. if(NOT DIR STREQUAL "-I")
  294. file(RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir})
  295. if(_rel_dir STREQUAL _abs_dir)
  296. continue()
  297. endif()
  298. string(FIND "${_rel_dir}" "../" _is_in_parent_folder)
  299. if (NOT ${_is_in_parent_folder} EQUAL 0)
  300. break()
  301. endif()
  302. endif()
  303. endforeach()
  304. set(_possible_rel_dir ${_rel_dir}/)
  305. endif()
  306. set(_generated_srcs)
  307. foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS})
  308. list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_possible_rel_dir}${_basename}${_ext}")
  309. endforeach()
  310. if(protobuf_generate_DESCRIPTORS AND protobuf_generate_LANGUAGE STREQUAL cpp)
  311. set(_descriptor_file "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.desc")
  312. set(_dll_desc_out "--descriptor_set_out=${_descriptor_file}")
  313. list(APPEND _generated_srcs ${_descriptor_file})
  314. endif()
  315. list(APPEND _generated_srcs_all ${_generated_srcs})
  316. set(_comment "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}")
  317. if(protobuf_generate_PROTOC_OPTIONS)
  318. set(_comment "${_comment}, protoc-options: ${protobuf_generate_PROTOC_OPTIONS}")
  319. endif()
  320. if(_plugin_options)
  321. set(_comment "${_comment}, plugin-options: ${_plugin_options}")
  322. endif()
  323. add_custom_command(
  324. OUTPUT ${_generated_srcs}
  325. COMMAND ${protobuf_generate_PROTOC_EXE}
  326. ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_dll_desc_out} ${_protobuf_include_path} ${_abs_file}
  327. DEPENDS ${_abs_file} protobuf::protoc ${protobuf_generate_DEPENDENCIES}
  328. COMMENT ${_comment}
  329. VERBATIM )
  330. endforeach()
  331. set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
  332. if(protobuf_generate_OUT_VAR)
  333. set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
  334. endif()
  335. if(protobuf_generate_TARGET)
  336. target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all})
  337. endif()
  338. endfunction()
  339. function(PROTOBUF_GENERATE_CPP SRCS HDRS)
  340. cmake_parse_arguments(protobuf_generate_cpp "" "EXPORT_MACRO;DESCRIPTORS" "" ${ARGN})
  341. set(_proto_files "${protobuf_generate_cpp_UNPARSED_ARGUMENTS}")
  342. if(NOT _proto_files)
  343. message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
  344. return()
  345. endif()
  346. if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
  347. set(_append_arg APPEND_PATH)
  348. endif()
  349. if(protobuf_generate_cpp_DESCRIPTORS)
  350. set(_descriptors DESCRIPTORS)
  351. endif()
  352. if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
  353. set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
  354. endif()
  355. if(DEFINED Protobuf_IMPORT_DIRS)
  356. set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
  357. endif()
  358. set(_outvar)
  359. protobuf_generate(${_append_arg} ${_descriptors} LANGUAGE cpp EXPORT_MACRO ${protobuf_generate_cpp_EXPORT_MACRO} OUT_VAR _outvar ${_import_arg} PROTOS ${_proto_files})
  360. set(${SRCS})
  361. set(${HDRS})
  362. if(protobuf_generate_cpp_DESCRIPTORS)
  363. set(${protobuf_generate_cpp_DESCRIPTORS})
  364. endif()
  365. foreach(_file ${_outvar})
  366. if(_file MATCHES "cc$")
  367. list(APPEND ${SRCS} ${_file})
  368. elseif(_file MATCHES "desc$")
  369. list(APPEND ${protobuf_generate_cpp_DESCRIPTORS} ${_file})
  370. else()
  371. list(APPEND ${HDRS} ${_file})
  372. endif()
  373. endforeach()
  374. set(${SRCS} ${${SRCS}} PARENT_SCOPE)
  375. set(${HDRS} ${${HDRS}} PARENT_SCOPE)
  376. if(protobuf_generate_cpp_DESCRIPTORS)
  377. set(${protobuf_generate_cpp_DESCRIPTORS} "${${protobuf_generate_cpp_DESCRIPTORS}}" PARENT_SCOPE)
  378. endif()
  379. endfunction()
  380. function(PROTOBUF_GENERATE_PYTHON SRCS)
  381. if(NOT ARGN)
  382. message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
  383. return()
  384. endif()
  385. if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
  386. set(_append_arg APPEND_PATH)
  387. endif()
  388. if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
  389. set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
  390. endif()
  391. if(DEFINED Protobuf_IMPORT_DIRS)
  392. set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
  393. endif()
  394. set(_outvar)
  395. protobuf_generate(${_append_arg} LANGUAGE python OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN})
  396. set(${SRCS} ${_outvar} PARENT_SCOPE)
  397. endfunction()
  398. if(Protobuf_DEBUG)
  399. # Output some of their choices
  400. message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
  401. "Protobuf_USE_STATIC_LIBS = ${Protobuf_USE_STATIC_LIBS}")
  402. endif()
  403. # Backwards compatibility
  404. # Define camel case versions of input variables
  405. foreach(UPPER
  406. PROTOBUF_SRC_ROOT_FOLDER
  407. PROTOBUF_IMPORT_DIRS
  408. PROTOBUF_DEBUG
  409. PROTOBUF_LIBRARY
  410. PROTOBUF_PROTOC_LIBRARY
  411. PROTOBUF_INCLUDE_DIR
  412. PROTOBUF_PROTOC_EXECUTABLE
  413. PROTOBUF_LIBRARY_DEBUG
  414. PROTOBUF_PROTOC_LIBRARY_DEBUG
  415. PROTOBUF_LITE_LIBRARY
  416. PROTOBUF_LITE_LIBRARY_DEBUG
  417. )
  418. if (DEFINED ${UPPER})
  419. string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
  420. if (NOT DEFINED ${Camel})
  421. set(${Camel} ${${UPPER}})
  422. endif()
  423. endif()
  424. endforeach()
  425. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  426. set(_PROTOBUF_ARCH_DIR x64/)
  427. endif()
  428. # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
  429. if( Protobuf_USE_STATIC_LIBS )
  430. set( _protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
  431. if(WIN32)
  432. set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
  433. else()
  434. set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
  435. endif()
  436. endif()
  437. include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
  438. # Internal function: search for normal library as well as a debug one
  439. # if the debug one is specified also include debug/optimized keywords
  440. # in *_LIBRARIES variable
  441. function(_protobuf_find_libraries name filename)
  442. if(${name}_LIBRARIES)
  443. # Use result recorded by a previous call.
  444. return()
  445. elseif(${name}_LIBRARY)
  446. # Honor cache entry used by CMake 3.5 and lower.
  447. set(${name}_LIBRARIES "${${name}_LIBRARY}" PARENT_SCOPE)
  448. else()
  449. find_library(${name}_LIBRARY_RELEASE
  450. NAMES ${filename}
  451. NAMES_PER_DIR
  452. PATHS ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Release)
  453. mark_as_advanced(${name}_LIBRARY_RELEASE)
  454. find_library(${name}_LIBRARY_DEBUG
  455. NAMES ${filename}d ${filename}
  456. NAMES_PER_DIR
  457. PATHS ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Debug)
  458. mark_as_advanced(${name}_LIBRARY_DEBUG)
  459. select_library_configurations(${name})
  460. if(UNIX AND Threads_FOUND AND ${name}_LIBRARY)
  461. list(APPEND ${name}_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
  462. endif()
  463. set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
  464. set(${name}_LIBRARIES "${${name}_LIBRARIES}" PARENT_SCOPE)
  465. endif()
  466. endfunction()
  467. #
  468. # Main.
  469. #
  470. # By default have PROTOBUF_GENERATE_CPP macro pass -I to protoc
  471. # for each directory where a proto file is referenced.
  472. if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
  473. set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE)
  474. endif()
  475. # Google's provided vcproj files generate libraries with a "lib"
  476. # prefix on Windows
  477. if(MSVC)
  478. set(Protobuf_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
  479. set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
  480. find_path(Protobuf_SRC_ROOT_FOLDER protobuf.pc.in)
  481. endif()
  482. if(UNIX)
  483. # Protobuf headers may depend on threading.
  484. find_package(Threads QUIET)
  485. endif()
  486. # The Protobuf library
  487. _protobuf_find_libraries(Protobuf protobuf)
  488. #DOC "The Google Protocol Buffers RELEASE Library"
  489. _protobuf_find_libraries(Protobuf_LITE protobuf-lite)
  490. # The Protobuf Protoc Library
  491. _protobuf_find_libraries(Protobuf_PROTOC protoc)
  492. # Restore original find library prefixes
  493. if(MSVC)
  494. set(CMAKE_FIND_LIBRARY_PREFIXES "${Protobuf_ORIG_FIND_LIBRARY_PREFIXES}")
  495. endif()
  496. # Find the include directory
  497. find_path(Protobuf_INCLUDE_DIR
  498. google/protobuf/service.h
  499. PATHS ${Protobuf_SRC_ROOT_FOLDER}/src
  500. )
  501. mark_as_advanced(Protobuf_INCLUDE_DIR)
  502. # Find the protoc Executable
  503. find_program(Protobuf_PROTOC_EXECUTABLE
  504. NAMES protoc
  505. DOC "The Google Protocol Buffers Compiler"
  506. PATHS
  507. ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Release
  508. ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Debug
  509. )
  510. mark_as_advanced(Protobuf_PROTOC_EXECUTABLE)
  511. if(Protobuf_DEBUG)
  512. message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
  513. "requested version of Google Protobuf is ${Protobuf_FIND_VERSION}")
  514. endif()
  515. if(Protobuf_INCLUDE_DIR)
  516. set(_PROTOBUF_COMMON_HEADER ${Protobuf_INCLUDE_DIR}/google/protobuf/stubs/common.h)
  517. if(Protobuf_DEBUG)
  518. message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
  519. "location of common.h: ${_PROTOBUF_COMMON_HEADER}")
  520. endif()
  521. set(Protobuf_VERSION "")
  522. set(Protobuf_LIB_VERSION "")
  523. file(STRINGS ${_PROTOBUF_COMMON_HEADER} _PROTOBUF_COMMON_H_CONTENTS REGEX "#define[ \t]+GOOGLE_PROTOBUF_VERSION[ \t]+")
  524. if(_PROTOBUF_COMMON_H_CONTENTS MATCHES "#define[ \t]+GOOGLE_PROTOBUF_VERSION[ \t]+([0-9]+)")
  525. set(Protobuf_LIB_VERSION "${CMAKE_MATCH_1}")
  526. endif()
  527. unset(_PROTOBUF_COMMON_H_CONTENTS)
  528. math(EXPR _PROTOBUF_MAJOR_VERSION "${Protobuf_LIB_VERSION} / 1000000")
  529. math(EXPR _PROTOBUF_MINOR_VERSION "${Protobuf_LIB_VERSION} / 1000 % 1000")
  530. math(EXPR _PROTOBUF_SUBMINOR_VERSION "${Protobuf_LIB_VERSION} % 1000")
  531. set(Protobuf_VERSION "${_PROTOBUF_MAJOR_VERSION}.${_PROTOBUF_MINOR_VERSION}.${_PROTOBUF_SUBMINOR_VERSION}")
  532. if(Protobuf_DEBUG)
  533. message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
  534. "${_PROTOBUF_COMMON_HEADER} reveals protobuf ${Protobuf_VERSION}")
  535. endif()
  536. if(Protobuf_PROTOC_EXECUTABLE)
  537. # Check Protobuf compiler version to be aligned with libraries version
  538. execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} --version
  539. OUTPUT_VARIABLE _PROTOBUF_PROTOC_EXECUTABLE_VERSION)
  540. if("${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" MATCHES "libprotoc ([0-9.]+)")
  541. set(_PROTOBUF_PROTOC_EXECUTABLE_VERSION "${CMAKE_MATCH_1}")
  542. endif()
  543. if(Protobuf_DEBUG)
  544. message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
  545. "${Protobuf_PROTOC_EXECUTABLE} reveals version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}")
  546. endif()
  547. # protoc version 22 and up don't print the major version any more
  548. if(NOT "${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" VERSION_EQUAL "${Protobuf_VERSION}" AND
  549. NOT "${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" VERSION_EQUAL "${_PROTOBUF_MINOR_VERSION}.${_PROTOBUF_SUBMINOR_VERSION}")
  550. message(WARNING "Protobuf compiler version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}"
  551. " doesn't match library version ${Protobuf_VERSION}")
  552. endif()
  553. endif()
  554. if(Protobuf_LIBRARY)
  555. if(NOT TARGET protobuf::libprotobuf)
  556. add_library(protobuf::libprotobuf UNKNOWN IMPORTED)
  557. set_target_properties(protobuf::libprotobuf PROPERTIES
  558. INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
  559. if(EXISTS "${Protobuf_LIBRARY}")
  560. set_target_properties(protobuf::libprotobuf PROPERTIES
  561. IMPORTED_LOCATION "${Protobuf_LIBRARY}")
  562. endif()
  563. if(EXISTS "${Protobuf_LIBRARY_RELEASE}")
  564. set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
  565. IMPORTED_CONFIGURATIONS RELEASE)
  566. set_target_properties(protobuf::libprotobuf PROPERTIES
  567. IMPORTED_LOCATION_RELEASE "${Protobuf_LIBRARY_RELEASE}")
  568. endif()
  569. if(EXISTS "${Protobuf_LIBRARY_DEBUG}")
  570. set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
  571. IMPORTED_CONFIGURATIONS DEBUG)
  572. set_target_properties(protobuf::libprotobuf PROPERTIES
  573. IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}")
  574. endif()
  575. if (Protobuf_VERSION VERSION_GREATER_EQUAL "3.6")
  576. set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
  577. INTERFACE_COMPILE_FEATURES cxx_std_11
  578. )
  579. endif()
  580. if (WIN32 AND NOT Protobuf_USE_STATIC_LIBS)
  581. set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
  582. INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS"
  583. )
  584. endif()
  585. if(UNIX AND TARGET Threads::Threads)
  586. set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
  587. INTERFACE_LINK_LIBRARIES Threads::Threads)
  588. endif()
  589. endif()
  590. endif()
  591. if(Protobuf_LITE_LIBRARY)
  592. if(NOT TARGET protobuf::libprotobuf-lite)
  593. add_library(protobuf::libprotobuf-lite UNKNOWN IMPORTED)
  594. set_target_properties(protobuf::libprotobuf-lite PROPERTIES
  595. INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
  596. if(EXISTS "${Protobuf_LITE_LIBRARY}")
  597. set_target_properties(protobuf::libprotobuf-lite PROPERTIES
  598. IMPORTED_LOCATION "${Protobuf_LITE_LIBRARY}")
  599. endif()
  600. if(EXISTS "${Protobuf_LITE_LIBRARY_RELEASE}")
  601. set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
  602. IMPORTED_CONFIGURATIONS RELEASE)
  603. set_target_properties(protobuf::libprotobuf-lite PROPERTIES
  604. IMPORTED_LOCATION_RELEASE "${Protobuf_LITE_LIBRARY_RELEASE}")
  605. endif()
  606. if(EXISTS "${Protobuf_LITE_LIBRARY_DEBUG}")
  607. set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
  608. IMPORTED_CONFIGURATIONS DEBUG)
  609. set_target_properties(protobuf::libprotobuf-lite PROPERTIES
  610. IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}")
  611. endif()
  612. if (WIN32 AND NOT Protobuf_USE_STATIC_LIBS)
  613. set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
  614. INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS"
  615. )
  616. endif()
  617. if(UNIX AND TARGET Threads::Threads)
  618. set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
  619. INTERFACE_LINK_LIBRARIES Threads::Threads)
  620. endif()
  621. endif()
  622. endif()
  623. if(Protobuf_PROTOC_LIBRARY)
  624. if(NOT TARGET protobuf::libprotoc)
  625. add_library(protobuf::libprotoc UNKNOWN IMPORTED)
  626. set_target_properties(protobuf::libprotoc PROPERTIES
  627. INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
  628. if(EXISTS "${Protobuf_PROTOC_LIBRARY}")
  629. set_target_properties(protobuf::libprotoc PROPERTIES
  630. IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}")
  631. endif()
  632. if(EXISTS "${Protobuf_PROTOC_LIBRARY_RELEASE}")
  633. set_property(TARGET protobuf::libprotoc APPEND PROPERTY
  634. IMPORTED_CONFIGURATIONS RELEASE)
  635. set_target_properties(protobuf::libprotoc PROPERTIES
  636. IMPORTED_LOCATION_RELEASE "${Protobuf_PROTOC_LIBRARY_RELEASE}")
  637. endif()
  638. if(EXISTS "${Protobuf_PROTOC_LIBRARY_DEBUG}")
  639. set_property(TARGET protobuf::libprotoc APPEND PROPERTY
  640. IMPORTED_CONFIGURATIONS DEBUG)
  641. set_target_properties(protobuf::libprotoc PROPERTIES
  642. IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}")
  643. endif()
  644. if (Protobuf_VERSION VERSION_GREATER_EQUAL "3.6")
  645. set_property(TARGET protobuf::libprotoc APPEND PROPERTY
  646. INTERFACE_COMPILE_FEATURES cxx_std_11
  647. )
  648. endif()
  649. if (WIN32 AND NOT Protobuf_USE_STATIC_LIBS)
  650. set_property(TARGET protobuf::libprotoc APPEND PROPERTY
  651. INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS"
  652. )
  653. endif()
  654. if(UNIX AND TARGET Threads::Threads)
  655. set_property(TARGET protobuf::libprotoc APPEND PROPERTY
  656. INTERFACE_LINK_LIBRARIES Threads::Threads)
  657. endif()
  658. endif()
  659. endif()
  660. if(Protobuf_PROTOC_EXECUTABLE)
  661. if(NOT TARGET protobuf::protoc)
  662. add_executable(protobuf::protoc IMPORTED)
  663. if(EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
  664. set_target_properties(protobuf::protoc PROPERTIES
  665. IMPORTED_LOCATION "${Protobuf_PROTOC_EXECUTABLE}")
  666. endif()
  667. endif()
  668. endif()
  669. endif()
  670. include(FindPackageHandleStandardArgs)
  671. find_package_handle_standard_args(Protobuf
  672. REQUIRED_VARS Protobuf_LIBRARIES Protobuf_INCLUDE_DIR
  673. VERSION_VAR Protobuf_VERSION
  674. )
  675. if(Protobuf_FOUND)
  676. set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR})
  677. endif()
  678. # Restore the original find library ordering
  679. if( Protobuf_USE_STATIC_LIBS )
  680. set(CMAKE_FIND_LIBRARY_SUFFIXES ${_protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
  681. endif()
  682. # Backwards compatibility
  683. # Define upper case versions of output variables
  684. foreach(Camel
  685. Protobuf_SRC_ROOT_FOLDER
  686. Protobuf_IMPORT_DIRS
  687. Protobuf_DEBUG
  688. Protobuf_INCLUDE_DIRS
  689. Protobuf_LIBRARIES
  690. Protobuf_PROTOC_LIBRARIES
  691. Protobuf_LITE_LIBRARIES
  692. Protobuf_LIBRARY
  693. Protobuf_PROTOC_LIBRARY
  694. Protobuf_INCLUDE_DIR
  695. Protobuf_PROTOC_EXECUTABLE
  696. Protobuf_LIBRARY_DEBUG
  697. Protobuf_PROTOC_LIBRARY_DEBUG
  698. Protobuf_LITE_LIBRARY
  699. Protobuf_LITE_LIBRARY_DEBUG
  700. )
  701. string(TOUPPER ${Camel} UPPER)
  702. set(${UPPER} ${${Camel}})
  703. endforeach()
  704. cmake_policy(POP)