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