diff --git a/bazel/BUILD b/bazel/BUILD index 9da2a22a..56e54ba6 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -15,3 +15,8 @@ licenses(["notice"]) # Apache v2 package(default_visibility = ["//:__subpackages__"]) + +exports_files([ + "compiler_id.sh", + "compiler_version.sh", +]) diff --git a/bazel/compiler_id.sh b/bazel/compiler_id.sh new file mode 100755 index 00000000..5e6b8f0e --- /dev/null +++ b/bazel/compiler_id.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# +# Copyright 2019 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. +# +# Given an argument that is the path to a compiler, tries to determine an +# identification string for the compiler according to the CMake-defined IDs: +# https://cmake.org/cmake/help/v3.5/variable/CMAKE_LANG_COMPILER_ID.html + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 " + exit 1 +fi + +version="$("${1}" --version 2> /dev/null \ + | head -1 \ + | tr '[:upper:]' '[:lower:]')" + +case "${version}" in + *gcc* | *g++*) + echo "GNU" + ;; + + *clang*) + echo "Clang" + ;; + + *msvc* | *microsoft*) + # I don't think "--version" above will actually work on Windows, so we + # should figure out how to do that correctly. See #281. + echo "MSVC" + ;; + + *) + echo "unknown" + ;; +esac diff --git a/bazel/compiler_version.sh b/bazel/compiler_version.sh new file mode 100755 index 00000000..846ea05b --- /dev/null +++ b/bazel/compiler_version.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Copyright 2019 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. +# +# Given an argument that is the path to a compiler, tries to determine +# the compiler's version by looking for the first string that looks like +# X.Y with more optional numbers, '.', '-', and '+'. + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 " + exit 1 +fi + +version="$("${1}" --version 2> /dev/null \ + | grep -Eo "[0-9]+\.[0-9.+-]+" \ + | head -1)" + +if [[ -n "${version}" ]]; then + echo "${version}" +else + echo unknown +fi diff --git a/ci/kokoro/docker/build-in-docker-cmake.sh b/ci/kokoro/docker/build-in-docker-cmake.sh index 41c1ed07..8b1952df 100755 --- a/ci/kokoro/docker/build-in-docker-cmake.sh +++ b/ci/kokoro/docker/build-in-docker-cmake.sh @@ -53,15 +53,11 @@ if [[ "${GOOGLE_CLOUD_CPP_CXX_STANDARD:-}" != "" ]]; then "-DGOOGLE_CLOUD_CPP_CXX_STANDARD=${GOOGLE_CLOUD_CPP_CXX_STANDARD}") fi -if [[ "${CODE_COVERAGE:-}" == "yes" ]]; then - cmake_flags+=( - "-DCMAKE_BUILD_TYPE=Coverage") -fi - # We disable the shellcheck warning because we want ${CMAKE_FLAGS} to expand as # separate arguments. # shellcheck disable=SC2086 cmake "-DCMAKE_INSTALL_PREFIX=$HOME/staging" \ + -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ ${CMAKE_FLAGS:-} \ "-H${SOURCE_DIR}" "-B${BINARY_DIR}" "${cmake_flags[@]}" cmake --build "${BINARY_DIR}" -- -j "$(nproc)" diff --git a/ci/kokoro/docker/build.sh b/ci/kokoro/docker/build.sh index 8b5b6901..71be69a6 100755 --- a/ci/kokoro/docker/build.sh +++ b/ci/kokoro/docker/build.sh @@ -52,6 +52,7 @@ if [[ "${BUILD_NAME}" = "clang-tidy" ]]; then export DISTRO_VERSION=30 export CC=clang export CXX=clang++ + export BUILD_TYPE=Debug export CHECK_STYLE=yes export GENERATE_DOCS=yes export CLANG_TIDY=yes @@ -118,7 +119,7 @@ elif [[ "${BUILD_NAME}" = "cxx17" ]]; then export CXX=g++ in_docker_script="ci/kokoro/docker/build-in-docker-cmake.sh" elif [[ "${BUILD_NAME}" = "coverage" ]]; then - export CODE_COVERAGE=yes + export BUILD_TYPE=Coverage export RUN_INTEGRATION_TESTS=yes export DISTRO=fedora-install export DISTRO_VERSION=30 @@ -227,13 +228,12 @@ docker_flags=( # installations. "--env" "TEST_INSTALL=${TEST_INSTALL:-}" - # If set to 'yes', run compile with code coverage flags. Currently only the - # CMake builds use this flag. - "--env" "CODE_COVERAGE=${CODE_COVERAGE:-}" - # If set, pass -DGOOGLE_CLOUD_CPP_CXX_STANDARD= to CMake. "--env" "GOOGLE_CLOUD_CPP_CXX_STANDARD=${GOOGLE_CLOUD_CPP_CXX_STANDARD:-}" + # The type of the build for CMake + "--env" "BUILD_TYPE=${BUILD_TYPE:-Release}" + # Additional flags to enable CMake features. "--env" "CMAKE_FLAGS=${CMAKE_FLAGS:-}" diff --git a/ci/kokoro/docker/upload-coverage.sh b/ci/kokoro/docker/upload-coverage.sh index 82d05af1..542a28bf 100755 --- a/ci/kokoro/docker/upload-coverage.sh +++ b/ci/kokoro/docker/upload-coverage.sh @@ -21,7 +21,7 @@ fi source "${PROJECT_ROOT}/ci/kokoro/define-docker-variables.sh" source "${PROJECT_ROOT}/ci/define-dump-log.sh" -if [[ "${CODE_COVERAGE:-}" != "yes" ]]; then +if [[ "${BUILD_NAME:-}" != "coverage" ]]; then # Not a code coverage build, exit silently. exit 0 fi diff --git a/google/cloud/spanner/BUILD b/google/cloud/spanner/BUILD index 1dd55786..71dbe1ca 100644 --- a/google/cloud/spanner/BUILD +++ b/google/cloud/spanner/BUILD @@ -16,12 +16,42 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 +load(":spanner_client_version.bzl", "GOOGLE_CLOUD_CPP_SPANNER_IS_RELEASE") + +genrule( + name = "generate_build_info", + srcs = ["internal/build_info.cc.in"], + outs = ["internal/build_info.cc"], + cmd = """ +V="unknown"; +CC_VERSION=$$($(location //bazel:compiler_version.sh) $(CC)); +CC_ID=$$($(location //bazel:compiler_id.sh) $(CC)); +sed -e "s;@CMAKE_CXX_COMPILER_ID@;$${CC_ID};" \ + -e "s;@CMAKE_CXX_COMPILER_VERSION@;$${CC_VERSION};" \ + -e "s;@CMAKE_CXX_FLAGS@;$(CC_FLAGS);" \ + -e "s;\\$${CMAKE_CXX_FLAGS_.*};-c $(COMPILATION_MODE);" \ + -e "s;@GOOGLE_CLOUD_CPP_SPANNER_IS_RELEASE@;%s;" \ + -e "s;@GOOGLE_CLOUD_CPP_SPANNER_BUILD_METADATA@;$${V};" < $< > $@ + """ % (GOOGLE_CLOUD_CPP_SPANNER_IS_RELEASE), + toolchains = [ + "@bazel_tools//tools/cpp:current_cc_toolchain", + "@bazel_tools//tools/cpp:cc_flags", + ], + tools = [ + "//bazel:compiler_id.sh", + "//bazel:compiler_version.sh", + ], +) + load(":spanner_client.bzl", "spanner_client_hdrs", "spanner_client_srcs") cc_library( name = "spanner_client", - srcs = spanner_client_srcs, + srcs = spanner_client_srcs + ["internal/build_info.cc"], hdrs = spanner_client_hdrs, + data = [ + ":generate_build_info", + ], deps = [ "@com_github_googleapis_google_cloud_cpp//google/cloud:google_cloud_cpp_common", "@com_github_googleapis_google_cloud_cpp//google/cloud/grpc_utils:google_cloud_cpp_grpc_utils", diff --git a/google/cloud/spanner/CMakeLists.txt b/google/cloud/spanner/CMakeLists.txt index a7a07c88..7d8e360a 100644 --- a/google/cloud/spanner/CMakeLists.txt +++ b/google/cloud/spanner/CMakeLists.txt @@ -25,8 +25,66 @@ set(DOXYGEN_PROJECT_NUMBER "${SPANNER_VERSION}") set(DOXYGEN_EXAMPLE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/samples) include(EnableDoxygen) +# 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_spanner_initialize_git_head var) + set(result "unknown") + # If we cannot find a `.git` directory do not even try to guess the git + # revision. + if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/.git) + # We need `git` to find the revision. + find_program(GOOGLE_CLOUD_CPP_SPANNER_GIT_PROGRAM NAMES git) + mark_as_advanced(GOOGLE_CLOUD_CPP_SPANNER_GIT_PROGRAM) + if (GOOGLE_CLOUD_CPP_SPANNER_GIT_PROGRAM) + # Run `git rev-parse --short HEAD` and capture the output in a + # variable. + execute_process(COMMAND "${GOOGLE_CLOUD_CPP_SPANNER_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_SPANNER_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_SPANNER_METADATA=value in the command line, and when + # GOOGLE_CLOUD_CPP_SPANNER_METADATA has a cached value + set(GOOGLE_CLOUD_CPP_SPANNER_GIT_HEAD "unused") +else () + google_cloud_cpp_spanner_initialize_git_head( + GOOGLE_CLOUD_CPP_SPANNER_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_SPANNER_BUILD_METADATA + "${GOOGLE_CLOUD_CPP_SPANNER_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_SPANNER_BUILD_METADATA) + +message(STATUS "google-cloud-cpp-spanner build metadata set to" + " ${GOOGLE_CLOUD_CPP_SPANNER_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_SPANNER_BUILD_TYPE_UPPER) +configure_file(internal/build_info.cc.in internal/build_info.cc) + configure_file(version_info.h.in ${CMAKE_CURRENT_SOURCE_DIR}/version_info.h) add_library(spanner_client + ${CMAKE_CURRENT_BINARY_DIR}/internal/build_info.cc backoff_policy.h client.cc client.h @@ -38,6 +96,7 @@ add_library(spanner_client date.h internal/base64.cc internal/base64.h + internal/build_info.h internal/database_admin_retry.cc internal/database_admin_retry.h internal/database_admin_stub.cc @@ -102,6 +161,9 @@ add_library(googleapis-c++::spanner_client ALIAS spanner_client) include(CreateBazelConfig) create_bazel_config(spanner_client) +export_variables_to_bazel("spanner_client_version.bzl" + GOOGLE_CLOUD_CPP_SPANNER_IS_RELEASE) + # Define the tests in a function so we have a new scope for variable names. function (spanner_client_define_tests) # The tests require googletest to be installed. Force CMake to use the @@ -133,6 +195,7 @@ function (spanner_client_define_tests) database_admin_client_test.cc date_test.cc internal/base64_test.cc + internal/build_info_test.cc internal/date_test.cc internal/merge_chunk_test.cc internal/polling_loop_test.cc diff --git a/google/cloud/spanner/internal/build_info.cc.in b/google/cloud/spanner/internal/build_info.cc.in new file mode 100644 index 00000000..f1b4a533 --- /dev/null +++ b/google/cloud/spanner/internal/build_info.cc.in @@ -0,0 +1,94 @@ +// Copyright 2017 Google Inc. +// +// 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. + +#include "google/cloud/spanner/internal/build_info.h" +#include "google/cloud/internal/port_platform.h" +#include +#include +#include + +namespace google { +namespace cloud { +namespace spanner { +inline namespace SPANNER_CLIENT_NS { +namespace internal { + +std::string CompilerId() { return R"""(@CMAKE_CXX_COMPILER_ID@)"""; } + +std::string CompilerVersion() { return R"""(@CMAKE_CXX_COMPILER_VERSION@)"""; } + +std::string BuildFlags() { + static auto const* const kFlags = [] { + auto* flags = new std::string(R"""(@CMAKE_CXX_FLAGS@)"""); + if (!flags->empty()) *flags += ' '; + *flags += + R"""(${CMAKE_CXX_FLAGS_${GOOGLE_CLOUD_CPP_SPANNER_BUILD_TYPE_UPPER}})"""; + return flags; + }(); + return *kFlags; +} + +std::string CompilerFeatures() { +#if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS + return "ex"; +#else + return "noex"; +#endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS +} + +std::string LanguageVersion() { + static auto const* const kLanguageVersion = [] { + auto* s = new std::string; + switch (__cplusplus) { + case 199711L: + *s += "98"; + break; + case 201103L: + *s += "2011"; + break; + case 201402L: + *s += "2014"; + break; + case 201703L: + *s += "2017"; + break; + default: + *s += "unknown"; + } + return s; + }(); + return *kLanguageVersion; +} + +bool IsRelease() { + static bool const kIsRelease = []() -> bool { + // NOLINTNEXTLINE(readability-redundant-string-init) + std::string value = R"""(@GOOGLE_CLOUD_CPP_SPANNER_IS_RELEASE@)"""; + for (char& c : value) { + c = static_cast(std::tolower(static_cast(c))); + } + return value == "yes" || value == "1" || value == "true"; + }(); + return kIsRelease; +} + +std::string BuildMetadata() { + return R"""(@GOOGLE_CLOUD_CPP_SPANNER_BUILD_METADATA@)"""; +} + +} // namespace internal +} // namespace GOOGLE_CLOUD_CPP_NS +} // namespace spanner +} // namespace cloud +} // namespace google diff --git a/google/cloud/spanner/internal/build_info.h b/google/cloud/spanner/internal/build_info.h new file mode 100644 index 00000000..c450bd63 --- /dev/null +++ b/google/cloud/spanner/internal/build_info.h @@ -0,0 +1,81 @@ +// Copyright 2017 Google Inc. +// +// 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. + +#ifndef GOOGLE_CLOUD_CPP_SPANNER_GOOGLE_CLOUD_SPANNER_INTERNAL_BUILD_INFO_H_ +#define GOOGLE_CLOUD_CPP_SPANNER_GOOGLE_CLOUD_SPANNER_INTERNAL_BUILD_INFO_H_ + +#include "google/cloud/spanner/version.h" + +namespace google { +namespace cloud { +namespace spanner { +inline namespace SPANNER_CLIENT_NS { +namespace internal { + +/** + * Returns the compiler ID. + * + * The Compiler ID is a string like "GNU" or "Clang", as described by + * https://cmake.org/cmake/help/v3.5/variable/CMAKE_LANG_COMPILER_ID.html + */ +std::string CompilerId(); + +/** + * Returns the compiler version. + * + * This string will be something like "9.1.1". + */ +std::string CompilerVersion(); + +/** + * Returns the build flags. + * + * Examples include "-c fastbuild" or "-O2 -DNDEBUG". + */ +std::string BuildFlags(); + +/** + * Returns certain interesting compiler features. + * + * Currently this returns one of "ex" or "noex" to indicate whether or not + * C++ exceptions are enabled. + */ +std::string CompilerFeatures(); + +/** + * Returns the 4-digit year of the C++ language standard. + */ +std::string LanguageVersion(); + +/** + * Returns true if this is a release branch. + */ +bool IsRelease(); + +/** + * Returns the metadata injected by the build system. + * + * See https://semver.org/#spec-item-10 for more details about the use and + * format of build metadata. Typically, the the value returned here is a hash + * indicating a git commit. + */ +std::string BuildMetadata(); + +} // namespace internal +} // namespace SPANNER_CLIENT_NS +} // namespace spanner +} // namespace cloud +} // namespace google + +#endif // GOOGLE_CLOUD_CPP_SPANNER_GOOGLE_CLOUD_SPANNER_INTERNAL_BUILD_INFO_H_ diff --git a/google/cloud/spanner/internal/build_info_test.cc b/google/cloud/spanner/internal/build_info_test.cc new file mode 100644 index 00000000..bff0784d --- /dev/null +++ b/google/cloud/spanner/internal/build_info_test.cc @@ -0,0 +1,100 @@ +// Copyright 2019 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. + +#include "google/cloud/spanner/internal/build_info.h" +#include + +namespace google { +namespace cloud { +namespace spanner { +inline namespace SPANNER_CLIENT_NS { +namespace internal { +namespace { + +TEST(BuildInfo, CompilerId) { + auto cn = CompilerId(); + EXPECT_FALSE(cn.empty()); + EXPECT_THAT(cn, ::testing::Not(::testing::HasSubstr("@"))); +} + +TEST(BuildInfo, CompilerVersion) { + auto cv = CompilerVersion(); + EXPECT_FALSE(cv.empty()); + EXPECT_THAT(cv, ::testing::Not(::testing::HasSubstr("@"))); +#ifndef _WIN32 // gMock's regex brackets don't work on Windows. + // Look for something that looks vaguely like an X.Y version number. + EXPECT_THAT(cv, ::testing::ContainsRegex(R"([0-9].[0-9])")); +#endif +} + +TEST(BuildInfo, BuildFlags) { + auto bf = BuildFlags(); + EXPECT_THAT(bf, ::testing::Not(::testing::HasSubstr("@"))); +} + +TEST(BuildInfo, CompilerFeatures) { + using ::testing::Eq; + auto cf = CompilerFeatures(); + EXPECT_FALSE(cf.empty()); + EXPECT_THAT(cf, ::testing::AnyOf(Eq("noex"), Eq("ex"))); +} + +TEST(BuildInfo, LanguageVersion) { + using ::testing::HasSubstr; + auto lv = LanguageVersion(); + EXPECT_FALSE(lv.empty()); + EXPECT_THAT(lv, ::testing::Not(::testing::HasSubstr("@"))); +#ifndef _WIN32 // gMock's regex brackets don't work on Windows. + EXPECT_THAT(lv, ::testing::MatchesRegex(R"([0-9A-Za-z_.-]+)")); +#endif +} + +TEST(BuildInfo, IsRelease) { + bool const b = IsRelease(); + // We want to test this, but either value is fine. + EXPECT_TRUE(b || !b); +} + +TEST(BuildInfo, BuildMetadata) { + auto const md = BuildMetadata(); + EXPECT_FALSE(md.empty()); + EXPECT_THAT(md, ::testing::Not(::testing::HasSubstr("@"))); +} + +TEST(BuildInfo, ApiClientHeader) { + // The build info is used to generate the "API Client Header", which is a + // gRPC metadata attribute with the name 'x-goog-api-client'. This test + // generates that whole string as a sanity check that it will contain the + // desired format. + + std::string const api_client_header = "gl-cpp/" + // + CompilerId() + '-' + // + CompilerVersion() + '-' + // + CompilerFeatures() + '-' + // + LanguageVersion(); + EXPECT_THAT(api_client_header, ::testing::Not(::testing::HasSubstr("@"))); + +#ifndef _WIN32 // gMock's regex brackets don't work on Windows. + EXPECT_THAT(api_client_header, + ::testing::MatchesRegex( + R"(gl-cpp/[A-Za-z0-9]+-[0-9.+-]+-(no)?ex-20[1-9][0-9])")); +#endif +} + +} // namespace +} // namespace internal +} // namespace SPANNER_CLIENT_NS +} // namespace spanner +} // namespace cloud +} // namespace google diff --git a/google/cloud/spanner/spanner_client.bzl b/google/cloud/spanner/spanner_client.bzl index 1fd34e70..ba1ffc17 100644 --- a/google/cloud/spanner/spanner_client.bzl +++ b/google/cloud/spanner/spanner_client.bzl @@ -24,6 +24,7 @@ spanner_client_hdrs = [ "database_admin_client.h", "date.h", "internal/base64.h", + "internal/build_info.h", "internal/database_admin_retry.h", "internal/database_admin_stub.h", "internal/date.h", diff --git a/google/cloud/spanner/spanner_client_unit_tests.bzl b/google/cloud/spanner/spanner_client_unit_tests.bzl index 287b0c13..0f1dd994 100644 --- a/google/cloud/spanner/spanner_client_unit_tests.bzl +++ b/google/cloud/spanner/spanner_client_unit_tests.bzl @@ -22,6 +22,7 @@ spanner_client_unit_tests = [ "database_admin_client_test.cc", "date_test.cc", "internal/base64_test.cc", + "internal/build_info_test.cc", "internal/date_test.cc", "internal/merge_chunk_test.cc", "internal/polling_loop_test.cc", diff --git a/google/cloud/spanner/spanner_client_version.bzl b/google/cloud/spanner/spanner_client_version.bzl new file mode 100644 index 00000000..c540cb71 --- /dev/null +++ b/google/cloud/spanner/spanner_client_version.bzl @@ -0,0 +1,19 @@ +# Copyright 2019 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. +# +# DO NOT EDIT -- GENERATED BY CMake -- Change the CMakeLists.txt file if needed + +"""Automatically generated version numbers - DO NOT EDIT.""" + +GOOGLE_CLOUD_CPP_SPANNER_IS_RELEASE = ""