From 50cbfab391f50efd2f2270f24c3ca2e48e039510 Mon Sep 17 00:00:00 2001 From: Gil Date: Tue, 10 Jul 2018 07:57:54 -0700 Subject: Reorganize cmake dependencies (#1508) * Add cmake dependencies where required ... instead of relying on a topological sort in the top-level CMakeLists.txt. * Add early exits to external project builds --- CMakeLists.txt | 13 +-- cmake/CompilerSetup.cmake | 2 +- cmake/external/FirebaseCore.cmake | 4 + cmake/external/GoogleUtilities.cmake | 4 + cmake/external/c-ares.cmake | 4 + cmake/external/firestore.cmake | 15 ++- cmake/external/googletest.cmake | 4 + cmake/external/grpc.cmake | 199 ++++++++++++++++++----------------- cmake/external/leveldb.cmake | 72 +++++++------ cmake/external/nanopb.cmake | 5 + cmake/external/protobuf.cmake | 4 + cmake/external/zlib.cmake | 34 +++--- 12 files changed, 200 insertions(+), 160 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 10d8ce2..b5f6970 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,16 +47,5 @@ set( enable_testing() -# These are ordered by a topological sort on DEPENDS attributes. This is -# required because CMake fails the build if you have a DEPENDS on a target that -# does not exist yet. -include(external/GoogleUtilities) -include(external/FirebaseCore) -include(external/googletest) -include(external/zlib) -include(external/leveldb) -include(external/protobuf) -include(external/nanopb) -include(external/c-ares) -include(external/grpc) +include(ExternalProject) include(external/firestore) diff --git a/cmake/CompilerSetup.cmake b/cmake/CompilerSetup.cmake index b560027..c04a26f 100644 --- a/cmake/CompilerSetup.cmake +++ b/cmake/CompilerSetup.cmake @@ -96,4 +96,4 @@ if(APPLE) -F${FIREBASE_INSTALL_DIR}/Frameworks ) -endif(APPLE) +endif() diff --git a/cmake/external/FirebaseCore.cmake b/cmake/external/FirebaseCore.cmake index 8be6969..a14397e 100644 --- a/cmake/external/FirebaseCore.cmake +++ b/cmake/external/FirebaseCore.cmake @@ -14,6 +14,10 @@ include(xcodebuild) +if(TARGET FirebaseCore) + return() +endif() + if(APPLE) # FirebaseCore is only available as a CocoaPod build. xcodebuild(FirebaseCore) diff --git a/cmake/external/GoogleUtilities.cmake b/cmake/external/GoogleUtilities.cmake index af90001..a7a9ce8 100644 --- a/cmake/external/GoogleUtilities.cmake +++ b/cmake/external/GoogleUtilities.cmake @@ -14,6 +14,10 @@ include(xcodebuild) +if(TARGET GoogleUtilities) + return() +endif() + if(APPLE) # GoogleUtilities is only available as a CocoaPod build. xcodebuild(GoogleUtilities) diff --git a/cmake/external/c-ares.cmake b/cmake/external/c-ares.cmake index 4c866c1..965eba9 100644 --- a/cmake/external/c-ares.cmake +++ b/cmake/external/c-ares.cmake @@ -14,6 +14,10 @@ include(ExternalProject) +if(TARGET c-ares) + return() +endif() + ExternalProject_Add( c-ares diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 63ef066..92789ca 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -13,15 +13,28 @@ # limitations under the License. include(ExternalProject) +include(external/FirebaseCore) +include(external/GoogleUtilities) +include(external/googletest) +include(external/grpc) +include(external/leveldb) +include(external/nanopb) +include(external/protobuf) + +if(TARGET Firestore) + return() +endif() ExternalProject_Add( Firestore DEPENDS FirebaseCore + GoogleUtilities googletest - leveldb grpc + leveldb nanopb + protobuf # Lay the binary directory out as if this were a subproject. This makes it # possible to build and test in it directly. diff --git a/cmake/external/googletest.cmake b/cmake/external/googletest.cmake index b80c098..4e922c3 100644 --- a/cmake/external/googletest.cmake +++ b/cmake/external/googletest.cmake @@ -14,6 +14,10 @@ include(ExternalProject) +if(TARGET googletest) + return() +endif() + ExternalProject_Add( googletest diff --git a/cmake/external/grpc.cmake b/cmake/external/grpc.cmake index a789838..e25afe6 100644 --- a/cmake/external/grpc.cmake +++ b/cmake/external/grpc.cmake @@ -14,117 +14,122 @@ include(ExternalProject) include(ExternalProjectFlags) +include(external/c-ares) +include(external/protobuf) +include(external/zlib) + +if(TARGET grpc) + return() +endif() 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 - ) - - set( - CMAKE_ARGS - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DBUILD_SHARED_LIBS:BOOL=OFF - -DgRPC_BUILD_TESTS:BOOL=OFF - - # TODO(rsgowman): We're currently building nanopb twice; once via grpc, and - # once via nanopb. The version from grpc is the one that actually ends up - # being used. We need to fix this such that either: - # a) we instruct grpc to use our nanopb - # b) we rely on grpc's nanopb instead of using our own. - # For now, we'll pass in the necessary nanopb cflags into grpc. (We require - # 16 bit fields. Without explicitly requesting this, nanopb uses 8 bit - # fields.) - -DCMAKE_C_FLAGS=-DPB_FIELD_16BIT - -DCMAKE_CXX_FLAGS=-DPB_FIELD_16BIT - ) - - - ## c-ares - if(NOT c-ares_DIR) - set(c-ares_DIR ${FIREBASE_INSTALL_DIR}/lib/cmake/c-ares) - endif() - - list( - APPEND CMAKE_ARGS - -DgRPC_CARES_PROVIDER:STRING=package - -Dc-ares_DIR:PATH=${c-ares_DIR} - ) - - - ## protobuf - - # Unlike other dependencies of gRPC, we control the protobuf version because we - # have checked-in protoc outputs that must match the runtime. - - # The location where protobuf-config.cmake will be installed varies by platform - if(NOT Protobuf_DIR) - if(WIN32) - set(Protobuf_DIR "${FIREBASE_INSTALL_DIR}/cmake") - else() - set(Protobuf_DIR "${FIREBASE_INSTALL_DIR}/lib/cmake/protobuf") - endif() + return() +endif() + +set( + GIT_SUBMODULES + third_party/boringssl +) + +set( + CMAKE_ARGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DBUILD_SHARED_LIBS:BOOL=OFF + -DgRPC_BUILD_TESTS:BOOL=OFF + + # TODO(rsgowman): We're currently building nanopb twice; once via grpc, and + # once via nanopb. The version from grpc is the one that actually ends up + # being used. We need to fix this such that either: + # a) we instruct grpc to use our nanopb + # b) we rely on grpc's nanopb instead of using our own. + # For now, we'll pass in the necessary nanopb cflags into grpc. (We require + # 16 bit fields. Without explicitly requesting this, nanopb uses 8 bit + # fields.) + -DCMAKE_C_FLAGS=-DPB_FIELD_16BIT + -DCMAKE_CXX_FLAGS=-DPB_FIELD_16BIT +) + + +## c-ares +if(NOT c-ares_DIR) + set(c-ares_DIR ${FIREBASE_INSTALL_DIR}/lib/cmake/c-ares) +endif() + +list( + APPEND CMAKE_ARGS + -DgRPC_CARES_PROVIDER:STRING=package + -Dc-ares_DIR:PATH=${c-ares_DIR} +) + + +## protobuf + +# Unlike other dependencies of gRPC, we control the protobuf version because we +# have checked-in protoc outputs that must match the runtime. + +# The location where protobuf-config.cmake will be installed varies by platform +if(NOT Protobuf_DIR) + if(WIN32) + set(Protobuf_DIR "${FIREBASE_INSTALL_DIR}/cmake") + else() + set(Protobuf_DIR "${FIREBASE_INSTALL_DIR}/lib/cmake/protobuf") endif() - - list( - APPEND CMAKE_ARGS - -DgRPC_PROTOBUF_PROVIDER:STRING=package - -DgRPC_PROTOBUF_PACKAGE_TYPE:STRING=CONFIG - -DProtobuf_DIR:PATH=${Protobuf_DIR} - ) - - - ## zlib - - # cmake/external/zlib.cmake figures out whether or not to build zlib. Either - # way, from the gRPC build's point of view it's a package. +endif() + +list( + APPEND CMAKE_ARGS + -DgRPC_PROTOBUF_PROVIDER:STRING=package + -DgRPC_PROTOBUF_PACKAGE_TYPE:STRING=CONFIG + -DProtobuf_DIR:PATH=${Protobuf_DIR} +) + + +## zlib + +# cmake/external/zlib.cmake figures out whether or not to build zlib. Either +# way, from the gRPC build's point of view it's a package. +list( + APPEND CMAKE_ARGS + -DgRPC_ZLIB_PROVIDER:STRING=package +) +if(ZLIB_FOUND) + # Propagate possible user configuration to FindZLIB.cmake in the sub-build. list( APPEND CMAKE_ARGS - -DgRPC_ZLIB_PROVIDER:STRING=package + -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR} + -DZLIB_LIBRARY=${ZLIB_LIBRARY} ) - if(ZLIB_FOUND) - # Propagate possible user configuration to FindZLIB.cmake in the sub-build. - list( - APPEND CMAKE_ARGS - -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR} - -DZLIB_LIBRARY=${ZLIB_LIBRARY} - ) - endif() +endif() - ExternalProject_GitSource( - GRPC_GIT - GIT_REPOSITORY "https://github.com/grpc/grpc.git" - GIT_TAG "v1.8.3" - GIT_SUBMODULES ${GIT_SUBMODULES} - ) +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 - c-ares - protobuf - zlib +ExternalProject_Add( + grpc + DEPENDS + c-ares + protobuf + zlib - ${GRPC_GIT} + ${GRPC_GIT} - PREFIX ${PROJECT_BINARY_DIR}/external/grpc + PREFIX ${PROJECT_BINARY_DIR}/external/grpc - CMAKE_ARGS - ${CMAKE_ARGS} - - BUILD_COMMAND - ${CMAKE_COMMAND} --build . --target grpc - - UPDATE_COMMAND "" - TEST_COMMAND "" - INSTALL_COMMAND "" - ) + CMAKE_ARGS + ${CMAKE_ARGS} -endif(GRPC_ROOT) + BUILD_COMMAND + ${CMAKE_COMMAND} --build . --target grpc + UPDATE_COMMAND "" + TEST_COMMAND "" + INSTALL_COMMAND "" +) diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake index 9daab02..8b5d7eb 100644 --- a/cmake/external/leveldb.cmake +++ b/cmake/external/leveldb.cmake @@ -14,6 +14,10 @@ include(ExternalProject) +if(TARGET leveldb) + return() +endif() + if(WIN32 OR LEVELDB_ROOT) # If the user has supplied a LEVELDB_ROOT then just use it. Add an empty # custom target so that the superbuild depdendencies don't all have to be @@ -24,50 +28,50 @@ if(WIN32 OR LEVELDB_ROOT) # https://github.com/google/leveldb/issues/363 # https://github.com/google/leveldb/issues/466 add_custom_target(leveldb) + return() +endif() -else() - # Clean up warning output to reduce noise in the build - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") - set( - LEVELDB_CXX_FLAGS "\ - -Wno-deprecated-declarations" - ) - endif() - # Map CMake compiler configuration down onto the leveldb Makefile +# Clean up warning output to reduce noise in the build +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") set( - LEVELDB_OPT "\ - $<$:${CMAKE_CXX_FLAGS_DEBUG}> \ - $<$:${CMAKE_CXX_FLAGS_RELEASE}>" + LEVELDB_CXX_FLAGS "\ + -Wno-deprecated-declarations" ) +endif() - ExternalProject_Add( - leveldb +# Map CMake compiler configuration down onto the leveldb Makefile +set( + LEVELDB_OPT "\ + $<$:${CMAKE_CXX_FLAGS_DEBUG}> \ + $<$:${CMAKE_CXX_FLAGS_RELEASE}>" +) - DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - DOWNLOAD_NAME leveldb-v1.20.tar.gz - URL https://github.com/google/leveldb/archive/v1.20.tar.gz - URL_HASH SHA256=f5abe8b5b209c2f36560b75f32ce61412f39a2922f7045ae764a2c23335b6664 +ExternalProject_Add( + leveldb - PREFIX ${FIREBASE_BINARY_DIR}/external/leveldb + DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} + DOWNLOAD_NAME leveldb-v1.20.tar.gz + URL https://github.com/google/leveldb/archive/v1.20.tar.gz + URL_HASH SHA256=f5abe8b5b209c2f36560b75f32ce61412f39a2922f7045ae764a2c23335b6664 - # LevelDB's configuration is done in the Makefile - CONFIGURE_COMMAND "" + PREFIX ${FIREBASE_BINARY_DIR}/external/leveldb - # The Makefile-based build of leveldb does not support building - # out-of-source. - BUILD_IN_SOURCE ON + # LevelDB's configuration is done in the Makefile + CONFIGURE_COMMAND "" - # 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 out-static/libleveldb.a + # The Makefile-based build of leveldb does not support building + # out-of-source. + BUILD_IN_SOURCE ON - INSTALL_DIR ${FIREBASE_INSTALL_DIR} + # 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 out-static/libleveldb.a - INSTALL_COMMAND "" - TEST_COMMAND "" - ) + INSTALL_DIR ${FIREBASE_INSTALL_DIR} -endif(WIN32 OR LEVELDB_ROOT) + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/cmake/external/nanopb.cmake b/cmake/external/nanopb.cmake index b5c74ce..7f1df78 100644 --- a/cmake/external/nanopb.cmake +++ b/cmake/external/nanopb.cmake @@ -13,6 +13,11 @@ # limitations under the License. include(ExternalProject) +include(external/protobuf) + +if(TARGET nanopb) + return() +endif() set(NANOPB_PROTOC_BIN ${FIREBASE_INSTALL_DIR}/bin/protoc) diff --git a/cmake/external/protobuf.cmake b/cmake/external/protobuf.cmake index e8060b2..a6ad8f0 100644 --- a/cmake/external/protobuf.cmake +++ b/cmake/external/protobuf.cmake @@ -14,6 +14,10 @@ include(ExternalProject) +if(TARGET protobuf) + return() +endif() + # Protubuf has CMake support, but includes it in a `cmake` subdirectory, which # does not work with CMake's ExternalProject by default. CMake 3.7 added # SOURCE_SUBDIR as a means of supporting this but that's too new to require diff --git a/cmake/external/zlib.cmake b/cmake/external/zlib.cmake index a90a511..3206f77 100644 --- a/cmake/external/zlib.cmake +++ b/cmake/external/zlib.cmake @@ -14,27 +14,31 @@ include(ExternalProject) +if(TARGET zlib) + return() +endif() + # Use a system- or user-supplied zlib if available find_package(ZLIB) if(ZLIB_FOUND) add_custom_target(zlib) + return() +endif() -else() - ExternalProject_Add( - zlib +ExternalProject_Add( + zlib - DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - DOWNLOAD_NAME zlib-v1.2.11.tar.gz - URL https://github.com/madler/zlib/archive/v1.2.11.tar.gz - URL_HASH SHA256=629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff + DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} + DOWNLOAD_NAME zlib-v1.2.11.tar.gz + URL https://github.com/madler/zlib/archive/v1.2.11.tar.gz + URL_HASH SHA256=629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff - PREFIX ${PROJECT_BINARY_DIR}/external/zlib + PREFIX ${PROJECT_BINARY_DIR}/external/zlib - CMAKE_ARGS - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX:STRING=${FIREBASE_INSTALL_DIR} - -DBUILD_SHARED_LIBS:BOOL=OFF + CMAKE_ARGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX:STRING=${FIREBASE_INSTALL_DIR} + -DBUILD_SHARED_LIBS:BOOL=OFF - TEST_COMMAND "" - ) -endif() + TEST_COMMAND "" +) -- cgit v1.2.3