xref: /aosp_15_r20/external/grpc-grpc/templates/CMakeLists.txt.template (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1%YAML 1.2
2--- |
3  # GRPC global cmake file
4  # This currently builds C and C++ code.
5  # This file has been automatically generated from a template file.
6  # Please look at the templates directory instead.
7  # This file can be regenerated from the template by running
8  # tools/buildgen/generate_projects.sh
9  #
10  # Copyright 2015 gRPC authors.
11  #
12  # Licensed under the Apache License, Version 2.0 (the "License");
13  # you may not use this file except in compliance with the License.
14  # You may obtain a copy of the License at
15  #
16  #     http://www.apache.org/licenses/LICENSE-2.0
17  #
18  # Unless required by applicable law or agreed to in writing, software
19  # distributed under the License is distributed on an "AS IS" BASIS,
20  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  # See the License for the specific language governing permissions and
22  # limitations under the License.
23
24  <%
25  import re
26
27  proto_re = re.compile('(.*)\\.proto')
28  lib_map = {lib.name: lib for lib in libs}
29
30  third_party_proto_prefixes = {lib.proto_prefix for lib in external_proto_libraries}
31
32  gpr_libs = ['gpr']
33  grpc_libs = ['grpc', 'grpc_unsecure']
34  grpcxx_libs = ['grpc++', 'grpc++_unsecure']
35  protoc_libs = ['benchmark_helpers', 'grpc++_reflection', 'grpcpp_channelz']
36
37  def third_party_proto_import_path(path):
38    """Removes third_party prefix to match ProtoBuf's relative import path."""
39    for prefix in third_party_proto_prefixes:
40      if path.startswith(prefix):
41        return path[len(prefix):]
42    return path
43
44  def proto_replace_ext(filename, ext):
45    """Replace the .proto extension with given extension."""
46    m = proto_re.match(filename)
47    if not m:
48      return filename
49    return '${_gRPC_PROTO_GENS_DIR}/' + third_party_proto_import_path(m.group(1)) + ext
50
51  def is_absl_lib(lib_name):
52    """Returns True if the library is one of the abseil libraries."""
53    return lib_name.startswith("absl/")
54
55  def get_absl_dep(lib_name):
56    """Gets the corresponding cmake target for given absl library."""
57    # The "cmake_target" field originates from src/abseil-cpp/preprocessed_builds.yaml.gen.py
58    return lib_map[lib_name].cmake_target
59
60  def get_transitive_deps(lib_name):
61    """Get list of transitive deps for given library."""
62    transitive_deps = []
63    lib_metadata = lib_map.get(lib_name, None)
64    if lib_metadata:
65      transitive_deps = lib_metadata.transitive_deps
66    return list(transitive_deps)
67
68  def list_abseil_pkg_targets(lib):
69    # TODO(jtattermusch): this function is odd, try to eliminate it.
70    # This returns a list of abseil pkg targets which the given lib and
71    # its non-abseil transitive dependencies depend on.
72    # As a result, internal abseil libraries are excluded from the result.
73    absl_specs = set()
74    transitive_deps_and_self = [lib] + get_transitive_deps(lib)
75    for lib_name in transitive_deps_and_self:
76      if is_absl_lib(lib_name): continue
77      lib_metadata = lib_map.get(lib_name, None)
78      if lib_metadata:
79        for dep in lib_metadata.deps:
80          if is_absl_lib(dep):
81            absl_specs.add(get_absl_dep(dep).replace("::", "_"))
82    return list(sorted(absl_specs))
83
84  def lib_name_to_pkgconfig_requires_private_name(lib_name):
85    """If library belongs to pkgconfig Requires.private section, return the name under which to include it."""
86    # TODO(jtattermusch): extract the metadata to a centralized location.
87    deps_to_pkgconfig_requires_private = {
88      "cares": "libcares",
89      "libssl": "openssl",
90      "re2": "re2",
91      "z": "zlib",
92    }
93    return deps_to_pkgconfig_requires_private.get(lib_name, None)
94
95  def is_pkgconfig_package(lib_name):
96    """Returns True if a pkgconfig package exists for a given library."""
97    # TODO(jtattermusch): extract the metadata to a centralized location.
98    if lib_name in ["address_sorting", "utf8_range_lib"]:
99      return False
100    if lib_name == "upb" or lib_name.startswith("upb_"):
101      # TODO(jtattermusch): Add better detection for what are the "upb" libs.
102      return False
103    return True
104
105  def get_pkgconfig_requires(lib):
106    """Returns "Requires" list for generating the pkgconfig .pc file for given library."""
107    requires = set()
108    requires.update(list_abseil_pkg_targets(lib))
109    for lib_name in get_transitive_deps(lib):
110      if not is_pkgconfig_package(lib_name):
111        # these deps go into Libs or Libs.Private
112        continue
113      if is_absl_lib(lib_name):
114        # absl libs have special handling
115        continue
116      if lib_name_to_pkgconfig_requires_private_name(lib_name) is not None:
117        # these deps go into Requires.private
118        continue
119      if lib_name == 'protobuf':
120        # TODO(jtattermusch): add better way of excluding explicit protobuf dependency.
121        continue
122      if lib_name == 'opentelemetry-cpp::api':
123        requires.add('opentelemetry_api')
124      else:
125        requires.add(lib_name)
126    return list(sorted(requires))
127
128  def get_pkgconfig_requires_private(lib):
129    """Returns the "Requires.private" list for generating the pkgconfig .pc file for given library."""
130    private_requires = set()
131    for lib_name in get_transitive_deps(lib):
132      if is_absl_lib(lib_name):
133        # absl deps to into Requires
134        continue
135      require_name = lib_name_to_pkgconfig_requires_private_name(lib_name)
136      if require_name:
137        private_requires.add(require_name)
138    return list(sorted(private_requires))
139
140  def get_pkgconfig_libs(lib):
141    """The "Libs" list for generating the pkgconfig .pc file for given library."""
142    libs = set()
143    # add self
144    libs.add("-l" + lib)
145    return list(sorted(libs))
146
147  def get_pkgconfig_libs_private(lib):
148    """The "Libs.private" list for generating the pkgconfig .pc file for given library."""
149    private_libs = []
150    for lib_name in get_transitive_deps(lib):
151      if is_absl_lib(lib_name):
152        # absl deps to into Requires
153        continue
154      if is_pkgconfig_package(lib_name):
155        continue
156      # Transitive deps are pre-sorted in topological order.
157      # We must maintain that order to prevent linkage errors.
158      private_libs.append("-l" + lib_name)
159    return private_libs
160
161  def lib_type_for_lib(lib_name):
162    """Returns STATIC/SHARED to force a static or shared lib build depending on the library."""
163    # grpc_csharp_ext is loaded by C# runtime and it
164    # only makes sense as a shared lib.
165    if lib_name in ['grpc_csharp_ext']:
166      return ' SHARED'
167
168    # upb always compiles as a static library on Windows
169    elif lib_name in ['upb','upb_collections_lib','upb_json_lib','upb_textformat_lib'] + protoc_libs:
170      return ' ${_gRPC_STATIC_WIN32}'
171
172    else:
173      return ''
174
175  def get_deps(target_dict):
176    # TODO(jtattermusch): remove special cases based on target names
177    deps = []
178    deps.append("${_gRPC_ALLTARGETS_LIBRARIES}")
179    for d in target_dict.get('deps', []):
180      if d == 'z':
181        deps.append("${_gRPC_ZLIB_LIBRARIES}")
182      elif d == 'address_sorting':
183        deps.append("${_gRPC_ADDRESS_SORTING_LIBRARIES}")
184      elif d == 'benchmark':
185        deps.append("${_gRPC_BENCHMARK_LIBRARIES}")
186      elif d == 'libssl':
187        deps.append("${_gRPC_SSL_LIBRARIES}")
188      elif d == 're2':
189        deps.append("${_gRPC_RE2_LIBRARIES}")
190      elif d == 'cares':
191        deps.append("${_gRPC_CARES_LIBRARIES}")
192      elif d == 'protobuf':
193        deps.append("${_gRPC_PROTOBUF_LIBRARIES}")
194      elif d == 'protoc':
195        deps.append("${_gRPC_PROTOBUF_PROTOC_LIBRARIES}")
196      elif is_absl_lib(d):
197        deps.append(get_absl_dep(d))
198      # TODO(jtattermusch): add handling for upb libraries
199      else:
200        deps.append(d)
201    return deps
202
203  def is_generate_cmake_target(lib_or_target):
204    """Returns True if a cmake target should be generated for given library/target."""
205    # TODO(jtattermusch): extract the metadata to a centralized location.
206    if lib_or_target.build not in ["all", "plugin", "plugin_test", "protoc", "tool", "test", "private"]:
207      return False
208    if lib_or_target.boringssl:
209      # Don't generate target for boringssl libs or tests
210      return False
211    if lib_or_target.name in ['cares', 'benchmark', 're2', 'xxhash', 'z']:
212      # we rely on these target to be created by external cmake builds.
213      return False
214    if is_absl_lib(lib_or_target.name):
215      # we rely on absl targets to be created by an external cmake build.
216      return False
217    return True
218
219  def get_platforms_condition_begin(platforms):
220    if all(platform in platforms for platform in ['linux', 'mac', 'posix', 'windows']):
221      return ''
222    cond = ' OR '.join(['_gRPC_PLATFORM_%s' % platform.upper() for platform in platforms])
223    return 'if(%s)' % cond
224
225  def get_platforms_condition_end(platforms):
226    if not get_platforms_condition_begin(platforms):
227      return ''
228    return 'endif()'
229
230  def platforms_condition_block(platforms):
231    def _func(text):
232      lines = text.split('\n')
233      cond = get_platforms_condition_begin(platforms)
234      if cond:
235        # Remove empty line following <%block>
236        del lines[0]
237
238        # Indent each line after
239        for i, line in enumerate(lines[:-1]):
240          if line:
241            lines[i] = '  ' + line
242
243        # Add the condition block
244        lines.insert(0, cond)
245
246        # Add endif() to the last line
247        lines[-1] += 'endif()'
248      else:
249        # Remove empty line following <%block>
250        del lines[0]
251
252        # Strip leading whitespace from first line
253        lines[0] = lines[0].lstrip(' ')
254
255        # Remove empty line before </%block>
256        del lines[-1]
257
258      return '\n'.join(lines)
259    return _func
260
261  %>
262  <%
263  # These files are added to a set so that they are not duplicated if multiple
264  # targets use them. Generating the same file multiple times with
265  # add_custom_command() is not allowed in CMake.
266
267  protobuf_gen_files = set()
268  for tgt in targets:
269    for src in tgt.src:
270      if proto_re.match(src):
271        protobuf_gen_files.add(src)
272  for lib in libs:
273    for src in lib.src:
274      if proto_re.match(src):
275        protobuf_gen_files.add(src)
276  %>
277
278  cmake_minimum_required(VERSION 3.13)
279
280  set(PACKAGE_NAME          "grpc")
281  set(PACKAGE_VERSION       "${settings.cpp_version}")
282  set(gRPC_CORE_VERSION     "${settings.core_version}")
283  set(gRPC_CORE_SOVERSION   "${settings.core_version.major}")
284  set(gRPC_CPP_VERSION      "${settings.cpp_version}")
285  set(gRPC_CPP_SOVERSION    "${settings.cpp_version.major}.${settings.cpp_version.minor}")
286  set(PACKAGE_STRING        "<%text>${PACKAGE_NAME} ${PACKAGE_VERSION}</%text>")
287  set(PACKAGE_TARNAME       "<%text>${PACKAGE_NAME}-${PACKAGE_VERSION}</%text>")
288  set(PACKAGE_BUGREPORT     "https://github.com/grpc/grpc/issues/")
289  project(<%text>${PACKAGE_NAME}</%text> LANGUAGES C CXX)
290
291  if(BUILD_SHARED_LIBS AND MSVC)
292    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
293  endif()
294
295  set(gRPC_INSTALL_BINDIR "bin" CACHE STRING "Installation directory for executables")
296  set(gRPC_INSTALL_LIBDIR "lib" CACHE STRING "Installation directory for libraries")
297  set(gRPC_INSTALL_INCLUDEDIR "include" CACHE STRING "Installation directory for headers")
298  set(gRPC_INSTALL_CMAKEDIR "lib/cmake/<%text>${PACKAGE_NAME}</%text>" CACHE STRING "Installation directory for cmake config files")
299  set(gRPC_INSTALL_SHAREDIR "share/grpc" CACHE STRING "Installation directory for root certificates")
300  set(gRPC_BUILD_MSVC_MP_COUNT 0 CACHE STRING "The maximum number of processes for MSVC /MP option")
301
302  # Options
303  option(gRPC_BUILD_TESTS "Build tests" OFF)
304  option(gRPC_BUILD_CODEGEN "Build codegen" ON)
305  option(gRPC_DOWNLOAD_ARCHIVES "Download archives for empty 3rd party directories" ON)
306
307  set(gRPC_INSTALL_default ON)
308  if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
309    # Disable gRPC_INSTALL by default if building as a submodule
310    set(gRPC_INSTALL_default OFF)
311  endif()
312  set(gRPC_INSTALL <%text>${gRPC_INSTALL_default}</%text> CACHE BOOL
313      "Generate installation target")
314
315  # We can install dependencies from submodules if we're running
316  # CMake v3.13 or newer.
317  if(CMAKE_VERSION VERSION_LESS 3.13)
318    set(_gRPC_INSTALL_SUPPORTED_FROM_MODULE OFF)
319  else()
320    set(_gRPC_INSTALL_SUPPORTED_FROM_MODULE ON)
321  endif()
322
323  # Providers for third-party dependencies (gRPC_*_PROVIDER properties):
324  # "module": build the dependency using sources from git submodule (under third_party)
325  # "package": use cmake's find_package functionality to locate a pre-installed dependency
326
327  set(gRPC_ZLIB_PROVIDER "module" CACHE STRING "Provider of zlib library")
328  set_property(CACHE gRPC_ZLIB_PROVIDER PROPERTY STRINGS "module" "package")
329
330  set(gRPC_CARES_PROVIDER "module" CACHE STRING "Provider of c-ares library")
331  set_property(CACHE gRPC_CARES_PROVIDER PROPERTY STRINGS "module" "package")
332
333  set(gRPC_RE2_PROVIDER "module" CACHE STRING "Provider of re2 library")
334  set_property(CACHE gRPC_RE2_PROVIDER PROPERTY STRINGS "module" "package")
335
336  set(gRPC_SSL_PROVIDER "module" CACHE STRING "Provider of ssl library")
337  set_property(CACHE gRPC_SSL_PROVIDER PROPERTY STRINGS "module" "package")
338
339  set(gRPC_PROTOBUF_PROVIDER "module" CACHE STRING "Provider of protobuf library")
340  set_property(CACHE gRPC_PROTOBUF_PROVIDER PROPERTY STRINGS "module" "package")
341
342  if(gRPC_BUILD_TESTS)
343    set(gRPC_BENCHMARK_PROVIDER "module" CACHE STRING "Provider of benchmark library")
344    set_property(CACHE gRPC_BENCHMARK_PROVIDER PROPERTY STRINGS "module" "package")
345  else()
346    set(gRPC_BENCHMARK_PROVIDER "none")
347  endif()
348
349  set(gRPC_ABSL_PROVIDER "module" CACHE STRING "Provider of absl library")
350  set_property(CACHE gRPC_ABSL_PROVIDER PROPERTY STRINGS "module" "package")
351  <%
352    # Collect all abseil rules used by gpr, grpc, so on.
353    used_abseil_rules = set()
354    for lib in libs:
355      if lib.get("baselib"):
356        for dep in lib.transitive_deps:
357          if is_absl_lib(dep):
358            used_abseil_rules.add(lib_map[dep].cmake_target.replace("::", "_"))
359  %>
360  set(gRPC_ABSL_USED_TARGETS
361  % for rule in sorted(used_abseil_rules):
362    ${rule}
363  % endfor
364    absl_meta
365  )
366
367  # The OpenTelemetry plugin supports "package" build only at present.
368  set(gRPC_OPENTELEMETRY_PROVIDER "package")
369  #  set(gRPC_OPENTELEMETRY_PROVIDER "module" CACHE STRING "Provider of opentelemetry library")
370  #  set_property(CACHE gRPC_OPENTELEMETRY_PROVIDER PROPERTY STRINGS "module" "package")
371
372  set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library")
373
374  if(UNIX)
375    if(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Linux")
376      set(_gRPC_PLATFORM_LINUX ON)
377      if(NOT CMAKE_CROSSCOMPILING AND CMAKE_SIZEOF_VOID_P EQUAL 4)
378        message("+++ Enabling SSE2 for <%text>${CMAKE_SYSTEM_PROCESSOR}</%text>")
379        set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> -msse2")
380      endif()
381    elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Darwin")
382      set(_gRPC_PLATFORM_MAC ON)
383    elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "iOS")
384      set(_gRPC_PLATFORM_IOS ON)
385    elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Android")
386      set(_gRPC_PLATFORM_ANDROID ON)
387    else()
388      set(_gRPC_PLATFORM_POSIX ON)
389    endif()
390  endif()
391  if(WIN32)
392    set(_gRPC_PLATFORM_WINDOWS ON)
393  endif()
394
395  if (APPLE AND NOT DEFINED CMAKE_CXX_STANDARD)
396    # AppleClang defaults to C++98, so we bump it to C++14.
397    message("CMAKE_CXX_STANDARD was undefined, defaulting to C++14.")
398    set(CMAKE_CXX_STANDARD 14)
399  endif ()
400
401  ## Some libraries are shared even with BUILD_SHARED_LIBRARIES=OFF
402  if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
403    set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
404  endif()
405  list(APPEND CMAKE_MODULE_PATH "<%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules")
406
407  if(MSVC)
408    include(cmake/msvc_static_runtime.cmake)
409    add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
410    # Set /MP option
411    if (gRPC_BUILD_MSVC_MP_COUNT GREATER 0)
412      set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS} /MP${gRPC_BUILD_MSVC_MP_COUNT}</%text>")
413    elseif (gRPC_BUILD_MSVC_MP_COUNT LESS 0)
414      set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /MP")
415    endif()
416    # needed to compile protobuf
417    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4065 /wd4506")
418    # TODO(jtattermusch): revisit warnings that were silenced as part of upgrade to protobuf3.6.0
419    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4200 /wd4291 /wd4244")
420    # TODO(jtattermusch): revisit C4267 occurrences throughout the code
421    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4267")
422    # TODO(jtattermusch): needed to build boringssl with VS2017, revisit later
423    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4987 /wd4774 /wd4819 /wd4996 /wd4619")
424    # Silences thousands of trucation warnings
425    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4503")
426    # Tell MSVC to build grpc using utf-8
427    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /utf-8")
428    # Inconsistent object sizes can cause stack corruption and should be treated as an error
429    set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /we4789")
430    # To decrease the size of PDB files
431    set(CMAKE_EXE_LINKER_FLAGS "/opt:ref /opt:icf /pdbcompress")
432  endif()
433  if (MINGW)
434    add_definitions(-D_WIN32_WINNT=0x600)
435  endif()
436  set(CMAKE_C_FLAGS "<%text>${CMAKE_C_FLAGS} ${_gRPC_C_CXX_FLAGS}</%text>")
437  set(CMAKE_CXX_FLAGS "<%text>${CMAKE_CXX_FLAGS} ${_gRPC_C_CXX_FLAGS}</%text>")
438
439  if(gRPC_USE_PROTO_LITE)
440    set(_gRPC_PROTOBUF_LIBRARY_NAME "libprotobuf-lite")
441    add_definitions("-DGRPC_USE_PROTO_LITE")
442  else()
443    set(_gRPC_PROTOBUF_LIBRARY_NAME "libprotobuf")
444  endif()
445
446  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_IOS)
447    set(_gRPC_CORE_NOSTDCXX_FLAGS -fno-exceptions -fno-rtti)
448  else()
449    set(_gRPC_CORE_NOSTDCXX_FLAGS "")
450  endif()
451
452  if(UNIX AND NOT HAIKU)
453    # -pthread does more than -lpthread
454    set(THREADS_PREFER_PTHREAD_FLAG ON)
455    find_package(Threads)
456    set(_gRPC_ALLTARGETS_LIBRARIES <%text>${CMAKE_DL_LIBS}</%text> m Threads::Threads)
457    if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
458      find_library(LIBRT rt)
459      if(LIBRT)
460        set(_gRPC_ALLTARGETS_LIBRARIES <%text>${_gRPC_ALLTARGETS_LIBRARIES}</%text> rt)
461      endif()
462    endif()
463  endif()
464
465  include(CheckCXXSourceCompiles)
466
467  if(UNIX OR APPLE)
468    # Some systems require the __STDC_FORMAT_MACROS macro to be defined
469    # to get the fixed-width integer type formatter macros.
470    check_cxx_source_compiles("#include <inttypes.h>
471    #include <cstdio>
472    int main()
473    {
474      int64_t i64{};
475      std::printf(\"%\" PRId64, i64);
476    }"
477    HAVE_STDC_FORMAT_MACROS)
478    if(NOT HAVE_STDC_FORMAT_MACROS)
479      add_definitions(-D__STDC_FORMAT_MACROS)
480    endif()
481  endif()
482
483  # configure ccache if requested
484  include(cmake/ccache.cmake)
485
486  include(cmake/abseil-cpp.cmake)
487  include(cmake/address_sorting.cmake)
488  include(cmake/benchmark.cmake)
489  include(cmake/cares.cmake)
490  include(cmake/protobuf.cmake)
491  include(cmake/re2.cmake)
492  include(cmake/ssl.cmake)
493  include(cmake/upb.cmake)
494  include(cmake/xxhash.cmake)
495  include(cmake/zlib.cmake)
496  include(cmake/download_archive.cmake)
497
498  if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
499    include(cmake/systemd.cmake)
500    set(_gRPC_ALLTARGETS_LIBRARIES <%text>${_gRPC_ALLTARGETS_LIBRARIES}</%text> <%text>${_gRPC_SYSTEMD_LIBRARIES}</%text>)
501  endif()
502
503  option(gRPC_BUILD_GRPCPP_OTEL_PLUGIN "Build grpcpp_otel_plugin" OFF)
504  if(gRPC_BUILD_GRPCPP_OTEL_PLUGIN)
505    include(cmake/opentelemetry-cpp.cmake)
506  endif()
507
508  % for external_proto_library in external_proto_libraries:
509  % if len(external_proto_library.urls) > 1:
510  # Setup external proto library at ${external_proto_library.destination} with ${len(external_proto_library.urls)} download URLs
511  % else:
512  # Setup external proto library at ${external_proto_library.destination} if it doesn't exist
513  % endif
514  % for download_url in external_proto_library.urls:
515  if (NOT EXISTS <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/${external_proto_library.destination} AND gRPC_DOWNLOAD_ARCHIVES)
516    # Download the archive via HTTP, validate the checksum, and extract to ${external_proto_library.destination}.
517    download_archive(
518      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/${external_proto_library.destination}
519      ${download_url}
520      ${external_proto_library.hash}
521      ${external_proto_library.strip_prefix}
522    )
523  endif()
524  % endfor
525  % endfor
526
527  if(WIN32)
528    set(_gRPC_ALLTARGETS_LIBRARIES <%text>${_gRPC_ALLTARGETS_LIBRARIES}</%text> ws2_32 crypt32)
529    set(_gRPC_STATIC_WIN32 STATIC)
530  endif()
531
532  if(BUILD_SHARED_LIBS AND WIN32)
533
534  # Currently for shared lib on Windows (i.e. a DLL) certain bits of source code
535  # are generated from protobuf definitions by upbc. This source code does not include
536  # annotations needed to export these functions from grpc.lib so we have to
537  # re-include a small subset of these.
538  #
539  # This is not an ideal situation because these functions will be unavailable
540  # to clients of grpc and the libraries that need this (e.g. grpc++) will
541  # include redundant duplicate code. Hence, the duplication is only activated
542  # for DLL builds - and should be completely removed when source files are
543  # generated with the necessary __declspec annotations.
544  set(gRPC_UPB_GEN_DUPL_SRC
545    src/core/ext/upb-gen/src/proto/grpc/gcp/altscontext.upb_minitable.c
546    src/core/ext/upb-gen/src/proto/grpc/health/v1/health.upb_minitable.c
547    src/core/ext/upb-gen/src/proto/grpc/gcp/transport_security_common.upb_minitable.c
548  )
549
550  set(gRPC_ADDITIONAL_DLL_SRC
551    src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
552    src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc
553    src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc
554    src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc
555  )
556
557  set(gRPC_ADDITIONAL_DLL_CXX_SRC
558    src/cpp/common/tls_certificate_provider.cc
559    src/cpp/common/tls_certificate_verifier.cc
560    src/cpp/common/tls_credentials_options.cc
561  )
562
563  endif() # BUILD_SHARED_LIBS AND WIN32
564
565  # Create directory for proto source files
566  set(_gRPC_PROTO_SRCS_DIR <%text>${CMAKE_BINARY_DIR}/protos</%text>)
567  file(MAKE_DIRECTORY <%text>${_gRPC_PROTO_SRCS_DIR}</%text>)
568  # Create directory for generated .proto files
569  set(_gRPC_PROTO_GENS_DIR <%text>${CMAKE_BINARY_DIR}/gens</%text>)
570  file(MAKE_DIRECTORY <%text>${_gRPC_PROTO_GENS_DIR}</%text>)
571
572  #  protobuf_generate_grpc_cpp
573  #  --------------------------
574  #
575  #   This method is no longer used by gRPC's CMake build process. However, it
576  #   is used by many open source dependencies, that we might want to keep
577  #   backward compatibility here.
578  #
579  #   Add custom commands to process ``.proto`` files to C++ using protoc and
580  #   GRPC plugin::
581  #
582  #     protobuf_generate_grpc_cpp [<ARGN>...]
583  #
584  #   ``ARGN``
585  #     ``.proto`` files
586  #
587  function(protobuf_generate_grpc_cpp)
588    if(NOT ARGN)
589      message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files")
590      return()
591    endif()
592
593    foreach(FIL <%text>${ARGN}</%text>)
594      protobuf_generate_grpc_cpp_with_import_path_correction(<%text>${FIL}</%text> <%text>${FIL}</%text>)
595    endforeach()
596  endfunction()
597
598  #  protobuf_generate_grpc_cpp_with_import_path_correction
599  #  --------------------------
600  #
601  #   Add custom commands to process ``.proto`` files to C++ using protoc and
602  #   GRPC plugin::
603  #
604  #     protobuf_generate_grpc_cpp_with_import_path_correction <FILE_LOCATION> <IMPORT_PATH>
605  #
606  #   ``FILE_LOCATION``
607  #     The relative path of the ``.proto`` file to the project root
608  #   ``IMPORT_PATH``
609  #     The proto import path that itself expected to be placed in. For
610  #     example, a "bar.proto" file wants to be imported as
611  #     `import "foo/bar.proto"`. Then we should place it under
612  #     "<ProtoBuf_Include_Path>/foo/bar.proto" instead of
613  #     "<ProtoBuf_Include_Path>/third_party/foo/bar.proto". This ensures
614  #     correct symbol being generated and C++ include path being correct.
615  #     More info can be found at https://github.com/grpc/grpc/pull/25272.
616  #
617  function(protobuf_generate_grpc_cpp_with_import_path_correction FILE_LOCATION IMPORT_PATH)
618    if(NOT FILE_LOCATION)
619      message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files")
620      return()
621    endif()
622
623    # Sets the include path for ProtoBuf files
624    set(_protobuf_include_path -I . -I <%text>${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR}</%text>)
625    # The absolute path of the expected place for the input proto file
626    # For example, health proto has package name grpc.health.v1, it's expected to be:
627    #   <%text>${_gRPC_PROTO_SRCS_DIR}/grpc/health/v1/health.proto</%text>
628    get_filename_component(ABS_FIL <%text>${_gRPC_PROTO_SRCS_DIR}/${IMPORT_PATH}</%text> ABSOLUTE)
629    # Get the name of the file, which used to generate output file names for
630    # this command.
631    # Example: "health" for "health.proto"
632    get_filename_component(FIL_WE <%text>${_gRPC_PROTO_SRCS_DIR}/${IMPORT_PATH}</%text> NAME_WE)
633    # Get the relative path between the expected place for the proto and the
634    # working directory. In normal cases, it would be equal IMPORT_PATH, but
635    # it's better to be agnostic to all the global folder locations (like the
636    # centralized location <%text>${_gRPC_PROTO_SRCS_DIR})</%text>.
637    # Example: grpc/health/v1/health.proto
638    file(RELATIVE_PATH REL_FIL <%text>${_gRPC_PROTO_SRCS_DIR}</%text> <%text>${ABS_FIL}</%text>)
639    # Get the directory of the relative path.
640    # Example: grpc/health/v1
641    get_filename_component(REL_DIR <%text>${REL_FIL}</%text> DIRECTORY)
642    # Get the directory and name for output filenames generation.
643    # Example: "grpc/health/v1/health", the file name extension is omitted.
644    set(RELFIL_WE "<%text>${REL_DIR}/${FIL_WE}</%text>")
645    # Copy the proto file to a centralized location, with the correct import
646    # path. For example, health proto has package name grpc.health.v1, the bash
647    # equivalent would be:
648    #   cp src/proto/grpc/health/v1/health.proto <%text>${_gRPC_PROTO_SRCS_DIR}/grpc/health/v1</%text>
649    file(MAKE_DIRECTORY <%text>${_gRPC_PROTO_SRCS_DIR}/${REL_DIR}</%text>)
650    file(COPY <%text>${CMAKE_CURRENT_SOURCE_DIR}/${FILE_LOCATION}</%text> DESTINATION <%text>${_gRPC_PROTO_SRCS_DIR}/${REL_DIR}</%text>)
651
652    #if cross-compiling, find host plugin
653    if(CMAKE_CROSSCOMPILING)
654      find_program(_gRPC_CPP_PLUGIN grpc_cpp_plugin)
655    else()
656      set(_gRPC_CPP_PLUGIN $<TARGET_FILE:grpc_cpp_plugin>)
657    endif()
658
659    add_custom_command(
660      OUTPUT <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"</%text>
661             <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"</%text>
662             <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}_mock.grpc.pb.h"</%text>
663             <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"</%text>
664             <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"</%text>
665      COMMAND <%text>${_gRPC_PROTOBUF_PROTOC_EXECUTABLE}</%text>
666      ARGS --grpc_out=<%text>generate_mock_code=true:${_gRPC_PROTO_GENS_DIR}</%text>
667           --cpp_out=<%text>${_gRPC_PROTO_GENS_DIR}</%text>
668           --plugin=protoc-gen-grpc=<%text>${_gRPC_CPP_PLUGIN}</%text>
669           <%text>${_protobuf_include_path}</%text>
670           <%text>${REL_FIL}</%text>
671      DEPENDS <%text>${CMAKE_CURRENT_SOURCE_DIR}/${FILE_LOCATION}</%text> <%text>${ABS_FIL}</%text> <%text>${_gRPC_PROTOBUF_PROTOC}</%text> <%text>${_gRPC_CPP_PLUGIN}</%text>
672      WORKING_DIRECTORY <%text>${_gRPC_PROTO_SRCS_DIR}</%text>
673      COMMENT "Running gRPC C++ protocol buffer compiler for <%text>${IMPORT_PATH}</%text>"
674      VERBATIM)
675  endfunction()
676
677  # These options allow users to enable or disable the building of the various
678  # protoc plugins. For example, running CMake with
679  # -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF will disable building the C# plugin.
680  set(_gRPC_PLUGIN_LIST)
681  % for tgt in targets:
682  % if tgt.build == 'protoc':
683  option(gRPC_BUILD_${tgt.name.upper()} "Build ${tgt.name}" ON)
684  if (gRPC_BUILD_${tgt.name.upper()})
685    list(APPEND _gRPC_PLUGIN_LIST ${tgt.name})
686  endif ()
687  % endif
688  % endfor
689
690  add_custom_target(plugins
691    DEPENDS <%text>${_gRPC_PLUGIN_LIST}</%text>
692  )
693
694  add_custom_target(tools_c
695    DEPENDS
696  % for tgt in targets:
697  % if tgt.build == 'tool' and not tgt.language == 'c++':
698    ${tgt.name}
699  % endif
700  % endfor
701  )
702
703  add_custom_target(tools_cxx
704    DEPENDS
705  % for tgt in targets:
706  % if tgt.build == 'tool' and tgt.language == 'c++':
707    ${tgt.name}
708  % endif
709  % endfor
710  )
711
712  add_custom_target(tools
713    DEPENDS tools_c tools_cxx)
714
715  % for src in sorted(protobuf_gen_files):
716  protobuf_generate_grpc_cpp_with_import_path_correction(
717    ${src} ${third_party_proto_import_path(src)}
718  )
719  % endfor
720
721  if(gRPC_BUILD_TESTS)
722    add_custom_target(buildtests_c)
723    % for tgt in targets:
724    % if is_generate_cmake_target(tgt) and tgt.build == 'test' and not tgt.language == 'c++':
725    <%block filter='platforms_condition_block(tgt.platforms)'>
726    add_dependencies(buildtests_c ${tgt.name})
727    </%block>
728    % endif
729    % endfor
730
731    add_custom_target(buildtests_cxx)
732    % for tgt in targets:
733    % if is_generate_cmake_target(tgt) and tgt.build == 'test' and tgt.language == 'c++':
734    <%block filter='platforms_condition_block(tgt.platforms)'>
735    add_dependencies(buildtests_cxx ${tgt.name})
736    </%block>
737    % endif
738    % endfor
739
740    add_custom_target(buildtests
741      DEPENDS buildtests_c buildtests_cxx)
742  endif()
743  <%
744    cmake_libs = []
745    for lib in libs:
746      if not is_generate_cmake_target(lib): continue
747      cmake_libs.append(lib)
748  %>
749
750  % for lib in cmake_libs:
751  %   if lib.build in ["test", "private"]:
752  if(gRPC_BUILD_TESTS)
753  ${cc_library(lib)}
754  endif()
755  %   else:
756  %     if lib.build in ["plugin"]:
757  if(gRPC_BUILD_${lib.name.upper()})
758  %     endif
759  ${cc_library(lib)}
760  %     if not lib.build in ["tool"]:
761  %       if any(proto_re.match(src) for src in lib.src):
762  if(gRPC_BUILD_CODEGEN)
763  %       endif
764  ${cc_install(lib)}
765  %       if any(proto_re.match(src) for src in lib.src):
766  endif()
767  %       endif
768  %     endif
769  %     if lib.build in ["plugin"]:
770  endif()
771  %     endif
772  %   endif
773  % endfor
774
775  % for tgt in targets:
776  % if is_generate_cmake_target(tgt):
777  % if tgt.build in ["test", "private"]:
778  if(gRPC_BUILD_TESTS)
779  <%block filter='platforms_condition_block(tgt.platforms)'>
780  ${cc_binary(tgt)}
781  </%block>
782  endif()
783  % elif tgt.build in ["plugin_test"]:
784  if(gRPC_BUILD_TESTS AND ${tgt.plugin_option})
785  <%block filter='platforms_condition_block(tgt.platforms)'>
786  ${cc_binary(tgt)}
787  </%block>
788  endif()
789  % elif tgt.build in ["protoc"]:
790  if(gRPC_BUILD_CODEGEN AND gRPC_BUILD_${tgt.name.upper()})
791  <%block filter='platforms_condition_block(tgt.platforms)'>
792  ${cc_binary(tgt)}
793  ${cc_install(tgt)}
794  </%block>
795  endif()
796  % else:
797  <%block filter='platforms_condition_block(tgt.platforms)'>
798  ${cc_binary(tgt)}
799  % if not tgt.build in ["tool"]:
800  ${cc_install(tgt)}
801  % endif
802  </%block>
803  % endif
804  % endif
805  % endfor
806
807  <%def name="cc_library(lib)">
808  % if any(proto_re.match(src) for src in lib.src):
809  % if lib.name == 'grpcpp_channelz':  # TODO(jtattermusch): remove special case based on target name
810  # grpcpp_channelz doesn't build with protobuf-lite
811  # See https://github.com/grpc/grpc/issues/19473
812  if(gRPC_BUILD_CODEGEN AND NOT gRPC_USE_PROTO_LITE)
813  % else:
814  if(gRPC_BUILD_CODEGEN)
815  % endif
816  % endif
817  add_library(${lib.name}${lib_type_for_lib(lib.name)}
818  % for src in lib.src:
819  % if not proto_re.match(src):
820    ${src}
821  % else:
822    ${proto_replace_ext(src, '.pb.cc')}
823    ${proto_replace_ext(src, '.grpc.pb.cc')}
824    ${proto_replace_ext(src, '.pb.h')}
825    ${proto_replace_ext(src, '.grpc.pb.h')}
826    % if src in ["src/proto/grpc/testing/compiler_test.proto", "src/proto/grpc/testing/echo.proto"]:
827    ${proto_replace_ext(src, '_mock.grpc.pb.h')}
828    % endif
829  % endif
830  % endfor
831  % if lib.name in ['grpc++_alts', 'grpc++_unsecure', 'grpc++']:
832    <%text>${gRPC_UPB_GEN_DUPL_SRC}</%text>
833  % endif
834  % if lib.name in ['grpc_unsecure']:
835    <%text>${gRPC_ADDITIONAL_DLL_SRC}</%text>
836  % endif
837  % if lib.name in ['grpc++_unsecure']:
838    <%text>${gRPC_ADDITIONAL_DLL_CXX_SRC}</%text>
839  % endif
840  )
841
842  target_compile_features(${lib.name} PUBLIC cxx_std_14)
843
844  set_target_properties(${lib.name} PROPERTIES
845  % if lib.language == 'c++':
846    VERSION <%text>${gRPC_CPP_VERSION}</%text>
847    SOVERSION <%text>${gRPC_CPP_SOVERSION}</%text>
848  % else:
849    VERSION <%text>${gRPC_CORE_VERSION}</%text>
850    SOVERSION <%text>${gRPC_CORE_SOVERSION}</%text>
851  % endif
852  )
853
854  if(WIN32 AND MSVC)
855    set_target_properties(${lib.name} PROPERTIES COMPILE_PDB_NAME "${lib.name}"
856      COMPILE_PDB_OUTPUT_DIRECTORY <%text>"${CMAKE_BINARY_DIR}</%text>"
857    )<%
858    dll_annotations = []
859    if lib.name in gpr_libs:
860      dll_annotations.append("GPR_DLL_EXPORTS")
861    if lib.name in grpc_libs:
862      dll_annotations.append("GRPC_DLL_EXPORTS")
863    if lib.name in grpcxx_libs:
864      dll_annotations.append("GRPCXX_DLL_EXPORTS")
865    if set(gpr_libs) & set(lib.transitive_deps):
866      dll_annotations.append("GPR_DLL_IMPORTS")
867    if set(grpc_libs) & set(lib.transitive_deps):
868      dll_annotations.append("GRPC_DLL_IMPORTS")
869    if set(grpcxx_libs) & set(lib.transitive_deps):
870      dll_annotations.append("GRPCXX_DLL_IMPORTS")
871    %>
872    % if dll_annotations:
873    if(BUILD_SHARED_LIBS)
874      target_compile_definitions(${lib.name}
875      PRIVATE
876    % for definition in dll_annotations:
877        "${definition}"
878    % endfor
879      )
880    endif()
881    % endif
882    if(gRPC_INSTALL)
883      install(FILES <%text>${CMAKE_CURRENT_BINARY_DIR}/</%text>${lib.name}.pdb
884        DESTINATION <%text>${gRPC_INSTALL_LIBDIR}</%text> OPTIONAL
885      )
886    endif()
887  endif()
888
889  target_include_directories(${lib.name}
890    PUBLIC <%text>$<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include></%text>
891    PRIVATE
892      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>
893      <%text>${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}</%text>
894      <%text>${_gRPC_RE2_INCLUDE_DIR}</%text>
895      <%text>${_gRPC_SSL_INCLUDE_DIR}</%text>
896      <%text>${_gRPC_UPB_GENERATED_DIR}</%text>
897      <%text>${_gRPC_UPB_GRPC_GENERATED_DIR}</%text>
898      <%text>${_gRPC_UPB_INCLUDE_DIR}</%text>
899      <%text>${_gRPC_XXHASH_INCLUDE_DIR}</%text>
900      <%text>${_gRPC_ZLIB_INCLUDE_DIR}</%text>
901  % if 'gtest' in lib.transitive_deps or lib.name == 'gtest':  # TODO(jtattermusch): avoid special case based on target name
902      third_party/googletest/googletest/include
903      third_party/googletest/googletest
904      third_party/googletest/googlemock/include
905      third_party/googletest/googlemock
906  % endif
907  % if lib.language == 'c++':
908      <%text>${_gRPC_PROTO_GENS_DIR}</%text>
909  % endif
910  )
911  % if len(get_deps(lib)) > 0:
912  target_link_libraries(${lib.name}
913  % for dep in get_deps(lib):
914    ${dep}
915  % endfor
916  )
917  % endif
918  % if lib.name in ["gpr"]:  # TODO(jtattermusch): avoid special case based on target name
919  if(_gRPC_PLATFORM_ANDROID)
920    target_link_libraries(gpr
921      android
922      log
923    )
924  endif()
925  % endif
926  % if lib.name in ["grpc", "grpc_cronet", "grpc_test_util", \
927                    "grpc_test_util_unsecure", "grpc_unsecure", \
928                    "grpc++_cronet"]: # TODO(jtattermusch): remove special cases based on target names
929  if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
930    target_link_libraries(${lib.name} "-framework CoreFoundation")
931  endif()
932  %endif
933
934  % if len(lib.get('public_headers', [])) > 0:
935  foreach(_hdr
936  % for hdr in lib.get('public_headers', []):
937    ${hdr}
938  % endfor
939  )
940    string(REPLACE "include/" "" _path <%text>${_hdr}</%text>)
941    get_filename_component(_path <%text>${_path}</%text> PATH)
942    install(FILES <%text>${_hdr}</%text>
943      DESTINATION "<%text>${gRPC_INSTALL_INCLUDEDIR}/${_path}</%text>"
944    )
945  endforeach()
946  % endif
947  % if any(proto_re.match(src) for src in lib.src):
948  endif()
949  % endif
950  </%def>
951
952  <%def name="cc_binary(tgt)">
953  add_executable(${tgt.name}
954  % for src in tgt.src:
955  % if not proto_re.match(src):
956    ${src}
957  % else:
958    ${proto_replace_ext(src, '.pb.cc')}
959    ${proto_replace_ext(src, '.grpc.pb.cc')}
960    ${proto_replace_ext(src, '.pb.h')}
961    ${proto_replace_ext(src, '.grpc.pb.h')}
962  % endif
963  % endfor
964  )<%
965  dll_annotations = []
966  if set(gpr_libs) & set(tgt.transitive_deps):
967    dll_annotations.append("GPR_DLL_IMPORTS")
968  if set(grpc_libs) & set(tgt.transitive_deps):
969    dll_annotations.append("GRPC_DLL_IMPORTS")
970  if set(grpcxx_libs) & set(tgt.transitive_deps):
971    dll_annotations.append("GRPCXX_DLL_IMPORTS")
972  %>
973  % if dll_annotations:
974  if(WIN32 AND MSVC)
975    if(BUILD_SHARED_LIBS)
976      target_compile_definitions(${tgt.name}
977      PRIVATE
978    % for definition in dll_annotations:
979        "${definition}"
980    % endfor
981      )
982    endif()
983  endif()
984  % endif
985  target_compile_features(${tgt.name} PUBLIC cxx_std_14)
986  target_include_directories(${tgt.name}
987    PRIVATE
988      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>
989      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/include
990      <%text>${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}</%text>
991      <%text>${_gRPC_RE2_INCLUDE_DIR}</%text>
992      <%text>${_gRPC_SSL_INCLUDE_DIR}</%text>
993      <%text>${_gRPC_UPB_GENERATED_DIR}</%text>
994      <%text>${_gRPC_UPB_GRPC_GENERATED_DIR}</%text>
995      <%text>${_gRPC_UPB_INCLUDE_DIR}</%text>
996      <%text>${_gRPC_XXHASH_INCLUDE_DIR}</%text>
997      <%text>${_gRPC_ZLIB_INCLUDE_DIR}</%text>
998  % if 'gtest' in tgt.transitive_deps:
999      third_party/googletest/googletest/include
1000      third_party/googletest/googletest
1001      third_party/googletest/googlemock/include
1002      third_party/googletest/googlemock
1003  % endif
1004  % if tgt.language == 'c++':
1005      <%text>${_gRPC_PROTO_GENS_DIR}</%text>
1006  % endif
1007  )
1008
1009  % if len(get_deps(tgt)) > 0:
1010  target_link_libraries(${tgt.name}
1011  % for dep in get_deps(tgt):
1012    ${dep}
1013  % endfor
1014  )
1015
1016  % endif
1017  </%def>
1018
1019  <%def name="cc_install(tgt)">
1020  % if tgt.name == 'grpcpp_channelz':
1021  # grpcpp_channelz doesn't build with protobuf-lite, so no install required
1022  # See https://github.com/grpc/grpc/issues/22826
1023  if(gRPC_INSTALL AND NOT gRPC_USE_PROTO_LITE)
1024  % else:
1025  if(gRPC_INSTALL)
1026  % endif
1027  % if tgt.build == 'protoc' and 'grpc_plugin_support' in tgt.get('deps', []):
1028    install(TARGETS ${tgt.name} EXPORT gRPCPluginTargets
1029  % else:
1030    install(TARGETS ${tgt.name} EXPORT gRPCTargets
1031  % endif
1032      RUNTIME DESTINATION <%text>${gRPC_INSTALL_BINDIR}</%text>
1033      BUNDLE DESTINATION  <%text>${gRPC_INSTALL_BINDIR}</%text>
1034      LIBRARY DESTINATION <%text>${gRPC_INSTALL_LIBDIR}</%text>
1035      ARCHIVE DESTINATION <%text>${gRPC_INSTALL_LIBDIR}</%text>
1036    )
1037  endif()
1038  </%def>
1039
1040  if(gRPC_INSTALL)
1041    install(EXPORT gRPCTargets
1042      DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>
1043      NAMESPACE gRPC::
1044    )
1045    if(gRPC_BUILD_CODEGEN)
1046      install(EXPORT gRPCPluginTargets
1047        DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>
1048        NAMESPACE gRPC::
1049      )
1050    endif()
1051  endif()
1052
1053  include(CMakePackageConfigHelpers)
1054
1055  configure_file(cmake/gRPCConfig.cmake.in
1056    gRPCConfig.cmake @ONLY)
1057  write_basic_package_version_file(<%text>${CMAKE_CURRENT_BINARY_DIR}/</%text>gRPCConfigVersion.cmake
1058    VERSION <%text>${gRPC_CPP_VERSION}</%text>
1059    COMPATIBILITY AnyNewerVersion)
1060  install(FILES
1061      <%text>${CMAKE_CURRENT_BINARY_DIR}/</%text>gRPCConfig.cmake
1062      <%text>${CMAKE_CURRENT_BINARY_DIR}/</%text>gRPCConfigVersion.cmake
1063    DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>
1064  )
1065  install(FILES
1066      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules/Findc-ares.cmake
1067      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules/Findre2.cmake
1068      <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/cmake/modules/Findsystemd.cmake
1069    DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>/modules
1070  )
1071
1072  install(FILES <%text>${CMAKE_CURRENT_SOURCE_DIR}/etc/roots.pem</%text>
1073    DESTINATION <%text>${gRPC_INSTALL_SHAREDIR}</%text>)
1074
1075  # Function to generate pkg-config files.
1076  function(generate_pkgconfig name description version requires requires_private
1077                              libs libs_private output_filename)
1078    set(PC_NAME "<%text>${name}</%text>")
1079    set(PC_DESCRIPTION "<%text>${description}</%text>")
1080    set(PC_VERSION "<%text>${version}</%text>")
1081    set(PC_REQUIRES "<%text>${requires}</%text>")
1082    set(PC_REQUIRES_PRIVATE "<%text>${requires_private}</%text>")
1083    set(PC_LIB "<%text>${libs}</%text>")
1084    set(PC_LIBS_PRIVATE "<%text>${libs_private}</%text>")
1085    set(output_filepath "<%text>${grpc_BINARY_DIR}/libs/opt/pkgconfig/${output_filename}</%text>")
1086    configure_file(
1087      "<%text>${grpc_SOURCE_DIR}/cmake/pkg-config-template.pc.in</%text>"
1088      "<%text>${output_filepath}</%text>"
1089      @ONLY)
1090    install(FILES "<%text>${output_filepath}</%text>"
1091      DESTINATION "<%text>${gRPC_INSTALL_LIBDIR}/pkgconfig</%text>")
1092  endfunction()
1093
1094  # gpr .pc file
1095  generate_pkgconfig(
1096    "gpr"
1097    "gRPC platform support library"
1098    "<%text>${gRPC_CORE_VERSION}</%text>"
1099    "${" ".join(get_pkgconfig_requires("gpr"))}"
1100    "${" ".join(get_pkgconfig_requires_private("gpr"))}"
1101    "${" ".join(get_pkgconfig_libs("gpr"))}"
1102    "${" ".join(get_pkgconfig_libs_private("gpr"))}"
1103    "gpr.pc")
1104
1105  # grpc .pc file
1106  generate_pkgconfig(
1107    "gRPC"
1108    "high performance general RPC framework"
1109    "<%text>${gRPC_CORE_VERSION}</%text>"
1110    "${" ".join(get_pkgconfig_requires("grpc"))}"
1111    "${" ".join(get_pkgconfig_requires_private("grpc"))}"
1112    "${" ".join(get_pkgconfig_libs("grpc"))}"
1113    "${" ".join(get_pkgconfig_libs_private("grpc"))}"
1114    "grpc.pc")
1115
1116  # grpc_unsecure .pc file
1117  generate_pkgconfig(
1118    "gRPC unsecure"
1119    "high performance general RPC framework without SSL"
1120    "<%text>${gRPC_CORE_VERSION}</%text>"
1121    "${" ".join(get_pkgconfig_requires("grpc_unsecure"))}"
1122    "${" ".join(get_pkgconfig_requires_private("grpc_unsecure"))}"
1123    "${" ".join(get_pkgconfig_libs("grpc_unsecure"))}"
1124    "${" ".join(get_pkgconfig_libs_private("grpc_unsecure"))}"
1125    "grpc_unsecure.pc")
1126
1127  # grpc++ .pc file
1128  generate_pkgconfig(
1129    "gRPC++"
1130    "C++ wrapper for gRPC"
1131    "<%text>${gRPC_CPP_VERSION}</%text>"
1132    "${" ".join(get_pkgconfig_requires("grpc++"))}"
1133    "${" ".join(get_pkgconfig_requires_private("grpc++"))}"
1134    "${" ".join(get_pkgconfig_libs("grpc++"))}"
1135    "${" ".join(get_pkgconfig_libs_private("grpc++"))}"
1136    "grpc++.pc")
1137
1138  # grpc++_unsecure .pc file
1139  generate_pkgconfig(
1140    "gRPC++ unsecure"
1141    "C++ wrapper for gRPC without SSL"
1142    "<%text>${gRPC_CPP_VERSION}</%text>"
1143    "${" ".join(get_pkgconfig_requires("grpc++_unsecure"))}"
1144    "${" ".join(get_pkgconfig_requires_private("grpc++_unsecure"))}"
1145    "${" ".join(get_pkgconfig_libs("grpc++_unsecure"))}"
1146    "${" ".join(get_pkgconfig_libs_private("grpc++_unsecure"))}"
1147    "grpc++_unsecure.pc")
1148
1149  # grpcpp_otel_plugin .pc file
1150  generate_pkgconfig(
1151    "gRPC++ OpenTelemetry Plugin"
1152    "OpenTelemetry Plugin for gRPC C++"
1153    "<%text>${gRPC_CPP_VERSION}</%text>"
1154    "${" ".join(get_pkgconfig_requires("grpcpp_otel_plugin"))}"
1155    "${" ".join(get_pkgconfig_requires_private("grpcpp_otel_plugin"))}"
1156    "${" ".join(get_pkgconfig_libs("grpcpp_otel_plugin"))}"
1157    "${" ".join(get_pkgconfig_libs_private("grpcpp_otel_plugin"))}"
1158    "grpcpp_otel_plugin.pc")
1159