# ~~~ # Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ~~~ # TODO(#4146) - remove FPHSA_NAME_MISMATCHED manipulation on next absl release set(FPHSA_NAME_MISMATCHED Threads) # Quiet warning caused by Abseil find_package(absl CONFIG REQUIRED) unset(FPHSA_NAME_MISMATCHED) # Generate the version information from the CMake values. configure_file(internal/version_info.h.in ${CMAKE_CURRENT_SOURCE_DIR}/internal/version_info.h) set(DOXYGEN_PROJECT_NAME "Google Cloud C++ Client") set(DOXYGEN_PROJECT_BRIEF "C++ Client Library for Google Cloud Platform") set(DOXYGEN_PROJECT_NUMBER "${GOOGLE_CLOUD_CPP_VERSION}") set(DOXYGEN_PREDEFINED "GOOGLE_CLOUD_CPP_NS=v${GOOGLE_CLOUD_CPP_VERSION_MAJOR}") set(DOXYGEN_EXCLUDE_PATTERNS "*/google/cloud/README.md" "*/google/cloud/internal/*" "*/google/cloud/testing_util/*" "*/google/cloud/bigtable/*" "*/google/cloud/bigquery/*" "*/google/cloud/firestore/*" "*/google/cloud/spanner/*" "*/google/cloud/storage/*" "*/google/cloud/pubsub/*" "*/google/cloud/grpc_utils/*" "*/google/cloud/*_test.cc") set(DOXYGEN_EXCLUDE_SYMBOLS "internal") include(GoogleCloudCppCommon) # Define a function to fetch the current git revision. Using a function creates # a new scope, so the CMake variables do not leak to the global namespace. function (google_cloud_cpp_initialize_git_head var) set(result "") # If we cannot find a `.git` directory do not even try to guess the git # revision. if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/.git) set(result "unknown-commit") # We need `git` to find the revision. find_program(GOOGLE_CLOUD_CPP_GIT_PROGRAM NAMES git) mark_as_advanced(GOOGLE_CLOUD_CPP_GIT_PROGRAM) if (GOOGLE_CLOUD_CPP_GIT_PROGRAM) # Run `git rev-parse --short HEAD` and capture the output in a # variable. execute_process( COMMAND "${GOOGLE_CLOUD_CPP_GIT_PROGRAM}" rev-parse --short HEAD OUTPUT_VARIABLE GIT_HEAD_LOG ERROR_VARIABLE GIT_HEAD_LOG) string(REPLACE "\n" "" result "${GIT_HEAD_LOG}") endif () endif () set(${var} "${result}" PARENT_SCOPE) endfunction () # Capture the compiler version and the git revision into variables, then # generate a config file with the values. if (NOT "${GOOGLE_CLOUD_CPP_BUILD_METADATA}" STREQUAL "") # The build metadata flag is already defined, do not re-compute the # initialization value. This works both when the user supplies # -DGOOGLE_CLOUD_CPP_METADATA=value in the command line, and when # GOOGLE_CLOUD_CPP_METADATA has a cached value set(GOOGLE_CLOUD_CPP_GIT_HEAD "unused") else () google_cloud_cpp_initialize_git_head(GOOGLE_CLOUD_CPP_GIT_HEAD) endif () # Define a CMake configuration option to set the build metadata. By default this # is initialized from `git rev-parse --short HEAD`, but the developer (or the # script building via CMake) can override the value. set(GOOGLE_CLOUD_CPP_BUILD_METADATA "${GOOGLE_CLOUD_CPP_GIT_HEAD}" CACHE STRING "Append build metadata to the library version number") # This option is rarely needed. Mark it as "advanced" to remove it from the # default CMake UIs. mark_as_advanced(GOOGLE_CLOUD_CPP_BUILD_METADATA) message(STATUS "google-cloud-cpp build metadata set to" " ${GOOGLE_CLOUD_CPP_BUILD_METADATA}") # Create the file that captures build information. Having access to the compiler # and build flags at runtime allows us to print better benchmark results. string(TOUPPER "${CMAKE_BUILD_TYPE}" GOOGLE_CLOUD_CPP_BUILD_TYPE_UPPER) configure_file(internal/build_info.cc.in internal/build_info.cc) # the client library add_library( google_cloud_cpp_common # cmake-format: sort ${CMAKE_CURRENT_BINARY_DIR}/internal/build_info.cc backoff_policy.h future.h future_generic.h future_void.h iam_binding.h iam_bindings.cc iam_bindings.h iam_policy.cc iam_policy.h internal/absl_flat_hash_map_quiet.h internal/absl_str_cat_quiet.h internal/absl_str_join_quiet.h internal/absl_str_replace_quiet.h internal/api_client_header.cc internal/api_client_header.h internal/backoff_policy.cc internal/backoff_policy.h internal/big_endian.h internal/build_info.h internal/compiler_info.cc internal/compiler_info.h internal/diagnostics_pop.inc internal/diagnostics_push.inc internal/disable_msvc_crt_secure_warnings.inc internal/filesystem.cc internal/filesystem.h internal/format_time_point.cc internal/format_time_point.h internal/future_base.h internal/future_fwd.h internal/future_impl.cc internal/future_impl.h internal/future_then_impl.h internal/future_then_meta.h internal/getenv.cc internal/getenv.h internal/invoke_result.h internal/ios_flags_saver.h internal/pagination_range.h internal/parse_rfc3339.cc internal/parse_rfc3339.h internal/port_platform.h internal/random.cc internal/random.h internal/retry_policy.h internal/setenv.cc internal/setenv.h internal/stream_range.h internal/strerror.cc internal/strerror.h internal/throw_delegate.cc internal/throw_delegate.h internal/tuple.h internal/user_agent_prefix.cc internal/user_agent_prefix.h internal/utility.h internal/version_info.h kms_key_name.cc kms_key_name.h log.cc log.h optional.h polling_policy.h status.cc status.h status_or.h terminate_handler.cc terminate_handler.h tracing_options.cc tracing_options.h version.cc version.h) target_link_libraries( google_cloud_cpp_common PUBLIC absl::flat_hash_map absl::memory absl::optional absl::time Threads::Threads) google_cloud_cpp_add_common_options(google_cloud_cpp_common) target_include_directories( google_cloud_cpp_common PUBLIC $ $) # We're putting generated code into ${PROJECT_BINARY_DIR} (e.g. compiled # protobufs or build info), so we need it on the include path, however we don't # want it checked by linters so we mark it as SYSTEM. target_include_directories(google_cloud_cpp_common SYSTEM PUBLIC $) target_compile_options(google_cloud_cpp_common PUBLIC ${GOOGLE_CLOUD_CPP_EXCEPTIONS_FLAG}) set_target_properties( google_cloud_cpp_common PROPERTIES VERSION ${GOOGLE_CLOUD_CPP_VERSION} SOVERSION ${GOOGLE_CLOUD_CPP_VERSION_MAJOR}) include(CreateBazelConfig) create_bazel_config(google_cloud_cpp_common YEAR 2018) add_subdirectory(testing_util) # Define the benchmarks in a function so we have a new scope for variable names. function (google_cloud_cpp_common_define_benchmarks) find_package(benchmark CONFIG REQUIRED) set(google_cloud_cpp_common_benchmarks # cmake-format: sort ) # Export the list of benchmarks to a .bzl file so we do not need to maintain # the list in two places. export_list_to_bazel("google_cloud_cpp_common_benchmarks.bzl" "google_cloud_cpp_common_benchmarks" YEAR "2020") # Create a custom target so we can say "build all the benchmarks" add_custom_target(google-cloud-cpp-common-benchmarks) # Generate a target for each benchmark. foreach (fname ${google_cloud_cpp_common_benchmarks}) google_cloud_cpp_add_executable(target "common" "${fname}") add_test(NAME ${target} COMMAND ${target}) target_link_libraries(${target} PRIVATE google_cloud_cpp_common benchmark::benchmark_main) google_cloud_cpp_add_common_options(${target}) add_dependencies(google-cloud-cpp-common-benchmarks ${target}) endforeach () endfunction () if (BUILD_TESTING) google_cloud_cpp_common_define_benchmarks() set(google_cloud_cpp_common_unit_tests # cmake-format: sort future_generic_test.cc future_generic_then_test.cc future_void_test.cc future_void_then_test.cc iam_bindings_test.cc internal/api_client_header_test.cc internal/backoff_policy_test.cc internal/big_endian_test.cc internal/compiler_info_test.cc internal/env_test.cc internal/filesystem_test.cc internal/format_time_point_test.cc internal/future_impl_test.cc internal/invoke_result_test.cc internal/pagination_range_test.cc internal/parse_rfc3339_test.cc internal/random_test.cc internal/retry_policy_test.cc internal/stream_range_test.cc internal/strerror_test.cc internal/throw_delegate_test.cc internal/tuple_test.cc internal/user_agent_prefix_test.cc internal/utility_test.cc kms_key_name_test.cc log_test.cc status_or_test.cc status_test.cc terminate_handler_test.cc tracing_options_test.cc) # Export the list of unit tests so the Bazel BUILD file can pick it up. export_list_to_bazel("google_cloud_cpp_common_unit_tests.bzl" "google_cloud_cpp_common_unit_tests" YEAR 2018) foreach (fname ${google_cloud_cpp_common_unit_tests}) google_cloud_cpp_add_executable(target "common" "${fname}") target_link_libraries( ${target} PRIVATE google_cloud_cpp_testing google_cloud_cpp_common absl::variant GTest::gmock_main GTest::gmock GTest::gtest) google_cloud_cpp_add_common_options(${target}) if (MSVC) target_compile_options(${target} PRIVATE "/bigobj") endif () add_test(NAME ${target} COMMAND ${target}) endforeach () endif () # Export the CMake targets to make it easy to create configuration files. install(EXPORT google_cloud_cpp_common-targets DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_common") # Install the libraries and headers in the locations determined by # GNUInstallDirs install( TARGETS google_cloud_cpp_common EXPORT google_cloud_cpp_common-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT google_cloud_cpp_runtime LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_runtime NAMELINK_SKIP ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_development) # With CMake-3.12 and higher we could avoid this separate command (and the # duplication). install( TARGETS google_cloud_cpp_common LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_development NAMELINK_ONLY ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_development) google_cloud_cpp_install_headers(google_cloud_cpp_common include/google/cloud) # Setup global variables used in the following *.in files. set(GOOGLE_CLOUD_CPP_PC_NAME "Google Cloud C++ Client Library Common Components") set(GOOGLE_CLOUD_CPP_PC_DESCRIPTION "Common Components used by the Google Cloud C++ Client Libraries.") # Abseil doesn't install package config files listing the runtime deps of their # libraries, so we need to explicitly include them here. Here we include the # runtime deps of the absl::optional target (http://github.com/abseil/abseil-cpp # /blob/4a851046a0102cd986a5714a1af8deef28a544c4/absl/types/CMakeLists.txt#L164) google_cloud_cpp_absl_pkg_config(absl_pkg_config google_cloud_cpp_common) string(CONCAT GOOGLE_CLOUD_CPP_PC_LIBS "-lgoogle_cloud_cpp_common" ${absl_pkg_config}) # Create and install the pkg-config files. configure_file("${PROJECT_SOURCE_DIR}/google/cloud/config.pc.in" "google_cloud_cpp_common.pc" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_common.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") # Create and install the CMake configuration files. include(CMakePackageConfigHelpers) configure_file("config.cmake.in" "google_cloud_cpp_common-config.cmake" @ONLY) write_basic_package_version_file( "google_cloud_cpp_common-config-version.cmake" VERSION ${GOOGLE_CLOUD_CPP_VERSION} COMPATIBILITY ExactVersion) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_common-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_common-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_common") if (GOOGLE_CLOUD_CPP_ENABLE_GRPC) find_package(gRPC) # the library add_library( google_cloud_cpp_grpc_utils # cmake-format: sort async_operation.h background_threads.h completion_queue.cc completion_queue.h connection_options.cc connection_options.h grpc_error_delegate.cc grpc_error_delegate.h grpc_utils/async_operation.h grpc_utils/completion_queue.h grpc_utils/grpc_error_delegate.h grpc_utils/version.h internal/async_read_stream_impl.h internal/async_read_write_stream_impl.h internal/async_retry_loop.h internal/async_retry_unary_rpc.h internal/async_rpc_details.h internal/background_threads_impl.cc internal/background_threads_impl.h internal/completion_queue_impl.h internal/default_completion_queue_impl.cc internal/default_completion_queue_impl.h internal/log_wrapper.cc internal/log_wrapper.h internal/polling_loop.h internal/retry_loop.h internal/retry_loop_helpers.cc internal/retry_loop_helpers.h internal/time_utils.cc internal/time_utils.h) target_link_libraries( google_cloud_cpp_grpc_utils PUBLIC absl::function_ref absl::memory absl::time googleapis-c++::rpc_status_protos google_cloud_cpp_common gRPC::grpc++ gRPC::grpc) google_cloud_cpp_add_common_options(google_cloud_cpp_grpc_utils) target_include_directories( google_cloud_cpp_grpc_utils PUBLIC $ $) target_compile_options(google_cloud_cpp_grpc_utils PUBLIC ${GOOGLE_CLOUD_CPP_EXCEPTIONS_FLAG}) set_target_properties( google_cloud_cpp_grpc_utils PROPERTIES VERSION ${GOOGLE_CLOUD_CPP_VERSION} SOVERSION ${GOOGLE_CLOUD_CPP_VERSION_MAJOR}) include(CreateBazelConfig) create_bazel_config(google_cloud_cpp_grpc_utils YEAR 2019) # Define the benchmarks in a function so we have a new scope for variable # names. function (google_cloud_cpp_grpc_utils_define_benchmarks) find_package(benchmark CONFIG REQUIRED) set(google_cloud_cpp_grpc_utils_benchmarks # cmake-format: sortable completion_queue_benchmark.cc) # Export the list of benchmarks to a .bzl file so we do not need to # maintain the list in two places. export_list_to_bazel( "google_cloud_cpp_grpc_utils_benchmarks.bzl" "google_cloud_cpp_grpc_utils_benchmarks" YEAR "2020") # Create a custom target so we can say "build all the benchmarks" add_custom_target(google-cloud-cpp-grpc-utils-benchmarks) # Generate a target for each benchmark. foreach (fname ${google_cloud_cpp_grpc_utils_benchmarks}) google_cloud_cpp_add_executable(target "common" "${fname}") add_test(NAME ${target} COMMAND ${target}) target_link_libraries( ${target} PRIVATE google_cloud_cpp_grpc_utils google_cloud_cpp_common benchmark::benchmark_main) google_cloud_cpp_add_common_options(${target}) add_dependencies(google-cloud-cpp-grpc-utils-benchmarks ${target}) endforeach () endfunction () if (BUILD_TESTING) google_cloud_cpp_grpc_utils_define_benchmarks() # List the unit tests, then setup the targets and dependencies. set(google_cloud_cpp_grpc_utils_unit_tests # cmake-format: sort completion_queue_test.cc connection_options_test.cc grpc_error_delegate_test.cc internal/async_read_write_stream_impl_test.cc internal/async_retry_loop_test.cc internal/async_retry_unary_rpc_test.cc internal/background_threads_impl_test.cc internal/log_wrapper_test.cc internal/polling_loop_test.cc internal/retry_loop_test.cc internal/time_utils_test.cc) # Export the list of unit tests so the Bazel BUILD file can pick it up. export_list_to_bazel("google_cloud_cpp_grpc_utils_unit_tests.bzl" "google_cloud_cpp_grpc_utils_unit_tests" YEAR 2019) foreach (fname ${google_cloud_cpp_grpc_utils_unit_tests}) google_cloud_cpp_add_executable(target "common_grpc_utils" "${fname}") target_link_libraries( ${target} PRIVATE google_cloud_cpp_grpc_utils google_cloud_cpp_testing_grpc google_cloud_cpp_testing google_cloud_cpp_common googleapis-c++::bigtable_protos googleapis-c++::spanner_protos absl::variant GTest::gmock_main GTest::gmock GTest::gtest gRPC::grpc++ gRPC::grpc) google_cloud_cpp_add_common_options(${target}) if (MSVC) target_compile_options(${target} PRIVATE "/bigobj") endif () add_test(NAME ${target} COMMAND ${target}) endforeach () endif () # Install the libraries and headers in the locations determined by # GNUInstallDirs install( TARGETS EXPORT grpc_utils-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) # Export the CMake targets to make it easy to create configuration files. install( EXPORT grpc_utils-targets DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_grpc_utils") install( TARGETS google_cloud_cpp_grpc_utils EXPORT grpc_utils-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT google_cloud_cpp_runtime LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_runtime NAMELINK_SKIP ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_development) # With CMake-3.12 and higher we could avoid this separate command (and the # duplication). install( TARGETS google_cloud_cpp_grpc_utils LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_development NAMELINK_ONLY ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT google_cloud_cpp_development) google_cloud_cpp_install_headers(google_cloud_cpp_grpc_utils include/google/cloud) # Setup global variables used in the following *.in files. set(GOOGLE_CLOUD_CPP_PC_NAME "gRPC Utilities for the Google Cloud C++ Client Library") set(GOOGLE_CLOUD_CPP_PC_DESCRIPTION "Provides gRPC Utilities for the Google Cloud C++ Client Library.") set(GOOGLE_CLOUD_CPP_PC_REQUIRES "google_cloud_cpp_common") google_cloud_cpp_absl_pkg_config(absl_pkg_config google_cloud_cpp_grpc_utils) string(CONCAT GOOGLE_CLOUD_CPP_PC_LIBS "-lgoogle_cloud_cpp_grpc_utils" ${absl_pkg_config}) # Create and install the pkg-config files. configure_file("${PROJECT_SOURCE_DIR}/google/cloud/config.pc.in" "google_cloud_cpp_grpc_utils.pc" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_grpc_utils.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") # Create and install the CMake configuration files. configure_file("grpc_utils/config.cmake.in" "google_cloud_cpp_grpc_utils-config.cmake" @ONLY) write_basic_package_version_file( "google_cloud_cpp_grpc_utils-config-version.cmake" VERSION ${GOOGLE_CLOUD_CPP_VERSION} COMPATIBILITY ExactVersion) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_grpc_utils-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_grpc_utils-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_grpc_utils") add_subdirectory(samples) endif ()