aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmake
diff options
context:
space:
mode:
authorGravatar Gil <mcg@google.com>2018-01-13 15:21:01 -0800
committerGravatar GitHub <noreply@github.com>2018-01-13 15:21:01 -0800
commitb15283bd27d6ac5eb784efc52ab13bc40b35a625 (patch)
tree6ab34707ec559c45cddff1583f0c44efff49d1ab /cmake
parentb5454f1a913d246da9e56b4d8e1dd9873d6d65ce (diff)
Build gRPC for Firestore C++ (#652)
* Clean up quoting and other minor issues * Reorganize CMake build output Make it clearer which parts of the output pertain to external projects. * Use a consistent ordering of ExternalProject arguments * Prevent the top-level build from running in parallel This prevents spurious failures when running make -j. * Actually parse arguments in the xcodebuild function * Use ExternalProject features when available * submodule limits from CMake 3.0 * shallow clones from CMake 3.6 * git progress output from CMake 3.8 * Only build the parts of leveldb we need Skip building the tools and other libraries * Avoid installing ExternalProjects Consume build output directly so that we can build just the targets we need. Installing causes all targets to be built. This doesn't matter as much for these targets but the gRPC build includes a ton of stuff we don't need so it's worth adopting this as a general strategy. * Define an external build for grpc * Test that grpc can link successfully. * Add a FindGRPC CMake module * Actually comment ExternalProjext_GitSource
Diffstat (limited to 'cmake')
-rw-r--r--cmake/ExternalProjectFlags.cmake71
-rw-r--r--cmake/FindGRPC.cmake142
-rw-r--r--cmake/FindLevelDB.cmake2
-rw-r--r--cmake/external/firestore.cmake28
-rw-r--r--cmake/external/googletest.cmake39
-rw-r--r--cmake/external/grpc.cmake83
-rw-r--r--cmake/external/leveldb.cmake26
-rw-r--r--cmake/xcodebuild.cmake11
8 files changed, 368 insertions, 34 deletions
diff --git a/cmake/ExternalProjectFlags.cmake b/cmake/ExternalProjectFlags.cmake
new file mode 100644
index 0000000..ed4db2c
--- /dev/null
+++ b/cmake/ExternalProjectFlags.cmake
@@ -0,0 +1,71 @@
+# Copyright 2018 Google
+#
+# 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(CMakeParseArguments)
+
+# Assemble the git-related arguments to an external project making use of the
+# latest features where available but avoiding them when run under CMake
+# versions that don't support them.
+#
+# The complete set of git-related arguments are stored as a list in the
+# variable named by RESULT_VAR in the calling scope.
+#
+# Currently this handles:
+# * GIT_SUBMODULES -- added on CMake 3.0 or later. Earlier CMakes will
+# check out all submodules.
+# * GIT_SHALLOW -- added by default on CMake 3.6 or later. Disable by passing
+# GIT_SHALLOW OFF
+# * GIT_PROGRESS -- added by default on CMake 3.8 or later. Disable by
+# passing GIT_PROGRESS OFF
+function(ExternalProject_GitSource RESULT_VAR)
+ # Parse arguments
+ set(options "")
+ set(single_value GIT_REPOSITORY GIT_TAG GIT_PROGRESS GIT_SHALLOW)
+ set(multi_value GIT_SUBMODULES)
+ cmake_parse_arguments(EP "${options}" "${single_value}" "${multi_value}" ${ARGN})
+
+ set(
+ result
+ GIT_REPOSITORY ${EP_GIT_REPOSITORY}
+ GIT_TAG ${EP_GIT_TAG}
+ ${EP_UNPARSED_ARGUMENTS}
+ )
+
+ # CMake 3.0 added support for constraining the set of submodules to clone
+ if(NOT (CMAKE_VERSION VERSION_LESS "3.0") AND EP_GIT_SUBMODULES)
+ list(APPEND result GIT_SUBMODULES ${EP_GIT_SUBMODULES})
+ endif()
+
+ # CMake 3.6 added support for shallow git clones. Use a shallow clone if
+ # available
+ if(NOT (CMAKE_VERSION VERSION_LESS "3.6"))
+ if(NOT EP_GIT_SHALLOW)
+ set(EP_GIT_SHALLOW ON)
+ endif()
+
+ list(APPEND result GIT_SHALLOW ${EP_GIT_SHALLOW})
+ endif()
+
+ # CMake 3.8 added support for showing progress for large downloads
+ if(NOT (CMAKE_VERSION VERSION_LESS "3.8"))
+ if(NOT EP_GIT_PROGRESS)
+ set(EP_GIT_PROGRESS ON)
+ endif()
+
+ list(APPEND result GIT_PROGRESS ${EP_GIT_PROGRESS})
+ endif()
+
+ set(${RESULT_VAR} ${result} PARENT_SCOPE)
+
+endfunction()
diff --git a/cmake/FindGRPC.cmake b/cmake/FindGRPC.cmake
new file mode 100644
index 0000000..f594b9e
--- /dev/null
+++ b/cmake/FindGRPC.cmake
@@ -0,0 +1,142 @@
+# Copyright 2018 Google
+#
+# 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(FindPackageHandleStandardArgs)
+include(FindZLIB)
+
+set(BINARY_DIR ${FIREBASE_INSTALL_DIR}/external/grpc)
+
+## ZLIB
+
+# the grpc ExternalProject already figures out if zlib should be built or
+# referenced from its installed location. If it elected to allow grpc to build
+# zlib then it will be available at this location.
+find_library(
+ ZLIB_LIBRARY
+ NAMES z
+ HINTS ${BINARY_DIR}/src/grpc-build/third_party/zlib
+)
+
+# If found above, the standard package will honor the ZLIB_LIBRARY variable.
+find_package(ZLIB REQUIRED)
+
+
+## BoringSSL/OpenSSL
+
+find_path(
+ OPENSSL_INCLUDE_DIR openssl/ssl.h
+ HINTS ${BINARY_DIR}/src/grpc/third_party/boringssl/include
+)
+
+find_library(
+ OPENSSL_SSL_LIBRARY
+ NAMES ssl
+ HINTS ${BINARY_DIR}/src/grpc-build/third_party/boringssl/ssl
+)
+
+find_library(
+ OPENSSL_CRYPTO_LIBRARY
+ NAMES crypto
+ HINTS ${BINARY_DIR}/src/grpc-build/third_party/boringssl/crypto
+)
+
+find_package(OpenSSL REQUIRED)
+
+
+## C-Ares
+
+find_library(
+ CARES_LIBRARY
+ NAMES cares
+ HINTS ${BINARY_DIR}/src/grpc-build/third_party/cares/cares/lib
+)
+if(NOT (CARES_LIBRARY STREQUAL "CARES_LIBRARY-NOTFOUND"))
+ if (NOT TARGET c-ares::ares)
+ add_library(c-ares::ares UNKNOWN IMPORTED)
+ set_target_properties(
+ c-ares::ares PROPERTIES
+ IMPORTED_LOCATION ${CARES_LIBRARY}
+ )
+ endif()
+endif()
+
+
+## GRPC
+
+find_path(
+ GRPC_INCLUDE_DIR grpc/grpc.h
+ HINTS
+ $ENV{GRPC_ROOT}/include
+ ${GRPC_ROOT}/include
+ ${BINARY_DIR}/src/grpc/include
+)
+
+find_library(
+ GPR_LIBRARY
+ NAMES gpr
+ HINTS
+ $ENV{GRPC_ROOT}/lib
+ ${GRPC_ROOT}/lib
+ ${BINARY_DIR}/src/grpc-build
+)
+
+find_library(
+ GRPC_LIBRARY
+ NAMES grpc
+ HINTS
+ $ENV{GRPC_ROOT}/lib
+ ${GRPC_ROOT}/lib
+ ${BINARY_DIR}/src/grpc-build
+)
+
+find_package_handle_standard_args(
+ gRPC
+ DEFAULT_MSG
+ GRPC_INCLUDE_DIR
+ GRPC_LIBRARY
+ GPR_LIBRARY
+)
+
+if(GRPC_FOUND)
+ set(GRPC_INCLUDE_DIRS ${GRPC_INCLUDE_DIR})
+ set(GRPC_LIBRARIES ${GRPC_LIBRARY})
+
+ if (NOT TARGET grpc::gpr)
+ add_library(grpc::gpr UNKNOWN IMPORTED)
+ set_target_properties(
+ grpc::gpr PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES ${GRPC_INCLUDE_DIR}
+ IMPORTED_LOCATION ${GPR_LIBRARY}
+ )
+ endif()
+
+ if (NOT TARGET grpc::grpc)
+ set(
+ GRPC_LINK_LIBRARIES
+ c-ares::ares
+ grpc::gpr
+ OpenSSL::SSL
+ OpenSSL::Crypto
+ ZLIB::ZLIB
+ )
+
+ add_library(grpc::grpc UNKNOWN IMPORTED)
+ set_target_properties(
+ grpc::grpc PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES ${GRPC_INCLUDE_DIR}
+ INTERFACE_LINK_LIBRARIES "${GRPC_LINK_LIBRARIES}"
+ IMPORTED_LOCATION ${GRPC_LIBRARY}
+ )
+ endif()
+endif(GRPC_FOUND)
diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake
index 386a298..b664fa8 100644
--- a/cmake/FindLevelDB.cmake
+++ b/cmake/FindLevelDB.cmake
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(binary_dir ${FIREBASE_INSTALL_DIR}/third_party/leveldb/src/leveldb)
+set(binary_dir ${FIREBASE_INSTALL_DIR}/external/leveldb/src/leveldb)
find_path(
LEVELDB_INCLUDE_DIR leveldb/db.h
diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake
index 1abb629..2d0ef02 100644
--- a/cmake/external/firestore.cmake
+++ b/cmake/external/firestore.cmake
@@ -14,27 +14,27 @@
include(ExternalProject)
-set(source_dir ${PROJECT_SOURCE_DIR}/Firestore)
-set(binary_dir ${PROJECT_BINARY_DIR}/Firestore)
-
ExternalProject_Add(
Firestore
- DEPENDS FirebaseCore googletest leveldb
+ DEPENDS
+ FirebaseCore
+ googletest
+ leveldb
+ grpc
# Lay the binary directory out as if this were a subproject. This makes it
# possible to build and test in it directly.
- PREFIX ${binary_dir}
- SOURCE_DIR ${source_dir}
- BINARY_DIR ${binary_dir}
+ PREFIX ${PROJECT_BINARY_DIR}/external/Firestore
+ SOURCE_DIR ${PROJECT_SOURCE_DIR}/Firestore
+ BINARY_DIR ${PROJECT_BINARY_DIR}/Firestore
+
+ CMAKE_ARGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DCMAKE_INSTALL_PREFIX:PATH=${FIREBASE_INSTALL_DIR}
+ ${GTEST_CMAKE_ARGS}
+
BUILD_ALWAYS ON
- # Even though this isn't installed, set up the INSTALL_DIR so that
- # find_package can find dependencies built from source.
- INSTALL_DIR ${FIREBASE_INSTALL_DIR}
INSTALL_COMMAND ""
TEST_BEFORE_INSTALL ON
-
- CMAKE_ARGS
- -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
- -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
diff --git a/cmake/external/googletest.cmake b/cmake/external/googletest.cmake
index 128f849..c467b70 100644
--- a/cmake/external/googletest.cmake
+++ b/cmake/external/googletest.cmake
@@ -13,21 +13,44 @@
# limitations under the License.
include(ExternalProject)
+include(ExternalProjectFlags)
+
+ExternalProject_GitSource(
+ GOOGLETEST_GIT
+ GIT_REPOSITORY "https://github.com/google/googletest.git"
+ GIT_TAG "release-1.8.0"
+)
ExternalProject_Add(
googletest
+ DEPENDS
+ FirebaseCore # for sequencing
- GIT_REPOSITORY "https://github.com/google/googletest.git"
- GIT_TAG "release-1.8.0"
+ ${GOOGLETEST_GIT}
- PREFIX ${PROJECT_BINARY_DIR}/third_party/googletest
+ PREFIX ${PROJECT_BINARY_DIR}/external/googletest
- INSTALL_DIR ${FIREBASE_INSTALL_DIR}
+ CMAKE_ARGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ INSTALL_COMMAND ""
TEST_COMMAND ""
+)
- CMAKE_ARGS
- -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
- -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
- -DBUILD_SHARED_LIBS:BOOL=OFF
+ExternalProject_Get_Property(
+ googletest
+ SOURCE_DIR BINARY_DIR
+)
+
+# Arguments to pass to another CMake invocation so that it can find googletest
+# without installing it using the standard FindGTest module.
+set(GTEST_INCLUDE_DIR ${SOURCE_DIR}/googletest/include)
+set(GTEST_LIBRARY ${BINARY_DIR}/googlemock/gtest/libgtest.a)
+set(GTEST_MAIN_LIBRARY ${BINARY_DIR}/googlemock/gtest/libgtest_main.a)
+set(
+ GTEST_CMAKE_ARGS
+ -DGTEST_INCLUDE_DIR=${GTEST_INCLUDE_DIR}
+ -DGTEST_LIBRARY=${GTEST_LIBRARY}
+ -DGTEST_MAIN_LIBRARY=${GTEST_MAIN_LIBRARY}
)
diff --git a/cmake/external/grpc.cmake b/cmake/external/grpc.cmake
new file mode 100644
index 0000000..fb54960
--- /dev/null
+++ b/cmake/external/grpc.cmake
@@ -0,0 +1,83 @@
+# Copyright 2018 Google
+#
+# 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(ExternalProject)
+include(ExternalProjectFlags)
+include(FindZLIB)
+
+if(GRPC_ROOT)
+ # If the user has supplied a GRPC_ROOT then just use it. Add an empty custom
+ # target so that the superbuild dependencies still work.
+ add_custom_target(grpc)
+
+else()
+ set(
+ GIT_SUBMODULES
+ third_party/boringssl
+ third_party/cares/cares
+ )
+
+ set(
+ CMAKE_ARGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DgRPC_BUILD_TESTS:BOOL=OFF
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ )
+
+ # zlib can be built by grpc but we can avoid it on platforms that provide it
+ # by default.
+ find_package(ZLIB)
+ if(ZLIB_FOUND)
+ list(
+ APPEND CMAKE_ARGS
+ -DgRPC_ZLIB_PROVIDER:STRING=package
+ -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR}
+ -DZLIB_LIBRARY=${ZLIB_LIBRARY}
+ )
+
+ else()
+ list(
+ APPEND GIT_SUBMODULES
+ third_party/zlib
+ )
+
+ endif(ZLIB_FOUND)
+
+ ExternalProject_GitSource(
+ GRPC_GIT
+ GIT_REPOSITORY "https://github.com/grpc/grpc.git"
+ GIT_TAG "v1.8.3"
+ GIT_SUBMODULES ${GIT_SUBMODULES}
+ )
+
+ ExternalProject_Add(
+ grpc
+ DEPENDS
+ leveldb # for sequencing
+
+ ${GRPC_GIT}
+
+ PREFIX ${PROJECT_BINARY_DIR}/external/grpc
+
+ CMAKE_ARGS ${CMAKE_ARGS}
+
+ BUILD_COMMAND
+ ${CMAKE_COMMAND} --build . --target grpc
+
+ TEST_COMMAND ""
+ INSTALL_COMMAND ""
+ )
+
+endif(GRPC_ROOT)
+
diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake
index b3b3fe1..5b2068a 100644
--- a/cmake/external/leveldb.cmake
+++ b/cmake/external/leveldb.cmake
@@ -13,6 +13,7 @@
# limitations under the License.
include(ExternalProject)
+include(ExternalProjectFlags)
if(WIN32 OR LEVELDB_ROOT)
# If the user has supplied a LEVELDB_ROOT then just use it. Add an empty
@@ -41,23 +42,38 @@ else()
$<$<CONFIG:Release>:${CMAKE_CXX_FLAGS_RELEASE}>"
)
+ ExternalProject_GitSource(
+ LEVELDB_GIT
+ GIT_REPOSITORY "https://github.com/google/leveldb.git"
+ GIT_TAG "v1.20"
+ )
+
ExternalProject_Add(
leveldb
+ DEPENDS
+ googletest # for sequencing
- GIT_REPOSITORY "https://github.com/google/leveldb.git"
- GIT_TAG "v1.20"
+ ${LEVELDB_GIT}
- PREFIX ${PROJECT_BINARY_DIR}/third_party/leveldb
+ PREFIX ${PROJECT_BINARY_DIR}/external/leveldb
+ # LevelDB's configuration is done in the Makefile
CONFIGURE_COMMAND ""
- BUILD_ALWAYS ON
+
+ # The Makefile-based build of leveldb does not support building
+ # out-of-source.
BUILD_IN_SOURCE ON
+
+ # Only build the leveldb library skipping the tools and in-memory
+ # implementation we don't use.
BUILD_COMMAND
- env CXXFLAGS=${LEVELDB_CXX_FLAGS} OPT=${LEVELDB_OPT} make -j all
+ env CXXFLAGS=${LEVELDB_CXX_FLAGS} OPT=${LEVELDB_OPT}
+ make -j out-static/libleveldb.a
INSTALL_DIR ${FIREBASE_INSTALL_DIR}
INSTALL_COMMAND ""
TEST_COMMAND ""
)
+
endif(WIN32 OR LEVELDB_ROOT)
diff --git a/cmake/xcodebuild.cmake b/cmake/xcodebuild.cmake
index 8312f6d..01a2961 100644
--- a/cmake/xcodebuild.cmake
+++ b/cmake/xcodebuild.cmake
@@ -33,7 +33,7 @@ function(xcodebuild framework)
set(options "")
set(single_value SCHEME WORKSPACE)
set(multi_value DEPENDS)
- cmake_parse_arguments(xcb "${options}" "${single_value}" "${multi_value}")
+ cmake_parse_arguments(xcb "${options}" "${single_value}" "${multi_value}" ${ARGN})
if(NOT xcb_WORKSPACE)
set(xcb_WORKSPACE ${PROJECT_SOURCE_DIR}/Example/Firebase.xcworkspace)
@@ -46,8 +46,6 @@ function(xcodebuild framework)
set(destination "platform=macOS,arch=x86_64")
set(scheme "${framework}-${platform}")
- set(binary_dir ${PROJECT_BINARY_DIR}/${scheme})
-
# CMake has a variety of release types, but Xcode has just one by default.
if(CMAKE_BUILD_TYPE STREQUAL Debug)
set(configuration Debug)
@@ -65,11 +63,11 @@ function(xcodebuild framework)
${framework}
DEPENDS ${xcb_DEPENDS}
- PREFIX ${binary_dir}
+ PREFIX ${PROJECT_BINARY_DIR}/external/${framework}
# The source directory doesn't actually matter
SOURCE_DIR ${PROJECT_SOURCE_DIR}
- BINARY_DIR ${binary_dir}
+ BINARY_DIR ${PROJECT_BINARY_DIR}/Frameworks
CONFIGURE_COMMAND ""
@@ -79,7 +77,7 @@ function(xcodebuild framework)
-scheme ${scheme}
-configuration ${configuration}
-destination ${destination}
- CONFIGURATION_BUILD_DIR=${FIREBASE_INSTALL_DIR}/Frameworks
+ CONFIGURATION_BUILD_DIR=<BINARY_DIR>
build
${pipe_xcpretty}
BUILD_ALWAYS ${BUILD_PODS}
@@ -87,4 +85,5 @@ function(xcodebuild framework)
INSTALL_COMMAND ""
TEST_COMMAND ""
)
+
endfunction()