@@ -617,3 +617,273 @@ index 000000000..28bfb0837
617
617
+ const uint8_t*& ip = *ip_p;
618
618
+ // This section is crucial for the throughput of the decompression loop.
619
619
+ // The latency of an iteration is fundamentally constrained by the
620
+ diff --git a/Firestore/Protos/CMakeLists.txt b/Firestore/Protos/CMakeLists.txt
621
+ index 85589b35f..96da74110 100644
622
+ --- a/Firestore/Protos/CMakeLists.txt
623
+ +++ b/Firestore/Protos/CMakeLists.txt
624
+ @@ -12,7 +12,12 @@
625
+ # See the License for the specific language governing permissions and
626
+ # limitations under the License.
627
+
628
+ -include(FindPythonInterp)
629
+ +include(python_setup)
630
+ +FirebaseSetupPythonInterpreter(
631
+ + OUTVAR MY_PYTHON_EXECUTABLE
632
+ + KEY FirestoreProtos
633
+ + REQUIREMENTS six
634
+ +)
635
+
636
+ # Generate output in-place. So long as the build is idempotent this helps
637
+ # verify that the protoc-generated output isn't changing.
638
+ @@ -200,7 +205,7 @@ if(FIREBASE_IOS_PROTOC_GENERATE_SOURCES)
639
+ COMMENT "Generating nanopb sources"
640
+ OUTPUT ${NANOPB_GENERATED_SOURCES}
641
+ COMMAND
642
+ - ${PYTHON_EXECUTABLE}
643
+ + ${MY_PYTHON_EXECUTABLE}
644
+ ${CMAKE_CURRENT_SOURCE_DIR}/build_protos.py
645
+ --nanopb
646
+ --protoc=$<TARGET_FILE:protoc>
647
+ @@ -232,7 +237,7 @@ if(FIREBASE_IOS_PROTOC_GENERATE_SOURCES)
648
+ COMMENT "Generating C++ protobuf sources"
649
+ OUTPUT ${PROTOBUF_CPP_GENERATED_SOURCES}
650
+ COMMAND
651
+ - ${PYTHON_EXECUTABLE}
652
+ + ${MY_PYTHON_EXECUTABLE}
653
+ ${CMAKE_CURRENT_SOURCE_DIR}/build_protos.py
654
+ --cpp
655
+ --protoc=$<TARGET_FILE:protoc>
656
+ diff --git a/Firestore/core/CMakeLists.txt b/Firestore/core/CMakeLists.txt
657
+ index aeb96431b..a1f477cbe 100644
658
+ --- a/Firestore/core/CMakeLists.txt
659
+ +++ b/Firestore/core/CMakeLists.txt
660
+ @@ -14,8 +14,12 @@
661
+
662
+ include(CheckSymbolExists)
663
+ include(CheckIncludeFiles)
664
+ -include(FindPythonInterp)
665
+
666
+ +include(python_setup)
667
+ +FirebaseSetupPythonInterpreter(
668
+ + OUTVAR MY_PYTHON_EXECUTABLE
669
+ + KEY FirestoreCore
670
+ +)
671
+
672
+ ## firestore_util
673
+
674
+ @@ -286,7 +290,7 @@ add_custom_command(
675
+ OUTPUT
676
+ ${GRPC_ROOT_CERTIFICATE_SOURCES}
677
+ COMMAND
678
+ - ${PYTHON_EXECUTABLE} ${FIREBASE_SOURCE_DIR}/scripts/binary_to_array.py
679
+ + ${MY_PYTHON_EXECUTABLE} ${FIREBASE_SOURCE_DIR}/scripts/binary_to_array.py
680
+ --output_header=${OUTPUT_DIR}/grpc_root_certificates_generated.h
681
+ --output_source=${OUTPUT_DIR}/grpc_root_certificates_generated.cc
682
+ --cpp_namespace=firebase::firestore::remote
683
+ diff --git a/cmake/external/CMakeLists.txt b/cmake/external/CMakeLists.txt
684
+ index 2179633a8..794936fe4 100644
685
+ --- a/cmake/external/CMakeLists.txt
686
+ +++ b/cmake/external/CMakeLists.txt
687
+ @@ -15,7 +15,12 @@
688
+ cmake_minimum_required(VERSION 3.5.1)
689
+ project(Firebase-download C CXX)
690
+
691
+ -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
692
+ +list(
693
+ + APPEND
694
+ + CMAKE_MODULE_PATH
695
+ + ${CMAKE_CURRENT_LIST_DIR}
696
+ + ${CMAKE_CURRENT_LIST_DIR}/..
697
+ +)
698
+
699
+ set(
700
+ FIREBASE_DOWNLOAD_DIR
701
+ diff --git a/cmake/python_setup.cmake b/cmake/python_setup.cmake
702
+ new file mode 100644
703
+ index 000000000..bdb7b9f6a
704
+ --- /dev/null
705
+ +++ b/cmake/python_setup.cmake
706
+ @@ -0,0 +1,183 @@
707
+ +# Copyright 2022 Google LLC
708
+ +#
709
+ +# Licensed under the Apache License, Version 2.0 (the "License");
710
+ +# you may not use this file except in compliance with the License.
711
+ +# You may obtain a copy of the License at
712
+ +#
713
+ +# http://www.apache.org/licenses/LICENSE-2.0
714
+ +#
715
+ +# Unless required by applicable law or agreed to in writing, software
716
+ +# distributed under the License is distributed on an "AS IS" BASIS,
717
+ +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
718
+ +# See the License for the specific language governing permissions and
719
+ +# limitations under the License.
720
+ +
721
+ +# Sets up an isolated Python interpreter, installing required dependencies.
722
+ +#
723
+ +# This function does the following:
724
+ +# 1. Finds a Python interpreter using the best-available built-in cmake
725
+ +# mechanism do do so. This is referred to as the "host" interpreter.
726
+ +# 2. Creates a Python virtualenv in the cmake binary directory using the
727
+ +# host Python interpreter found in the previous step.
728
+ +# 3. Locates the Python interpreter in the virtualenv and sets its path in
729
+ +# the specified OUTVAR variable.
730
+ +# 4. Runs `pip install` to install the specified required dependencies, if any,
731
+ +# in the virtualenv.
732
+ +#
733
+ +# This function also writes "stamp files" into the virtualenv. These files
734
+ +# are used to determine if the virtualenv is up-to-date from a previous cmake
735
+ +# run or if it needs to be recreated from scratch. It will simply be re-used if
736
+ +# possible.
737
+ +#
738
+ +# If any errors occur (e.g. cannot install one of the given requirements) then a
739
+ +# fatal error is logged, causing the cmake processing to terminate.
740
+ +#
741
+ +# See https://docs.python.org/3/library/venv.html for details about virtualenv.
742
+ +#
743
+ +# Arguments:
744
+ +# OUTVAR - The name of the variable into which to store the path of the
745
+ +# Python executable from the virtualenv.
746
+ +# KEY - A unique key to ensure isolation from other Python virtualenv
747
+ +# environments created by this function. This value will be incorporated
748
+ +# into the path of the virtualenv and incorporated into the name of the
749
+ +# cmake cache variable that stores its path.
750
+ +# REQUIREMENTS - (Optional) A list of Python packages to install in the
751
+ +# virtualenv. These will be given as arguments to `pip install`.
752
+ +#
753
+ +# Example:
754
+ +# include(python_setup)
755
+ +# FirebaseSetupPythonInterpreter(
756
+ +# OUTVAR MY_PYTHON_EXECUTABLE
757
+ +# KEY ScanStuff
758
+ +# REQUIREMENTS six absl-py
759
+ +# )
760
+ +# execute_process(COMMAND "${MY_PYTHON_EXECUTABLE}" scan_stuff.py)
761
+ +function(FirebaseSetupPythonInterpreter)
762
+ + cmake_parse_arguments(
763
+ + PARSE_ARGV 0
764
+ + ARG
765
+ + "" # zero-value arguments
766
+ + "OUTVAR;KEY" # single-value arguments
767
+ + "REQUIREMENTS" # multi-value arguments
768
+ + )
769
+ +
770
+ + # Validate this function's arguments.
771
+ + if("${ARG_OUTVAR}" STREQUAL "")
772
+ + message(FATAL_ERROR "OUTVAR must be specified to ${CMAKE_CURRENT_FUNCTION}")
773
+ + elseif("${ARG_KEY}" STREQUAL "")
774
+ + message(FATAL_ERROR "KEY must be specified to ${CMAKE_CURRENT_FUNCTION}")
775
+ + endif()
776
+ +
777
+ + # Calculate the name of the cmake *cache* variable into which to store the
778
+ + # path of the Python interpreter from the virtualenv.
779
+ + set(CACHEVAR "FIREBASE_PYTHON_EXECUTABLE_${ARG_KEY}")
780
+ +
781
+ + set(LOG_PREFIX "${CMAKE_CURRENT_FUNCTION}(${ARG_KEY})")
782
+ +
783
+ + # Find a "host" Python interpreter using the best available mechanism.
784
+ + if(${CMAKE_VERSION} VERSION_LESS "3.12")
785
+ + include(FindPythonInterp)
786
+ + set(DEFAULT_PYTHON_HOST_EXECUTABLE "${PYTHON_EXECUTABLE}")
787
+ + else()
788
+ + find_package(Python3 COMPONENTS Interpreter REQUIRED)
789
+ + set(DEFAULT_PYTHON_HOST_EXECUTABLE "${Python3_EXECUTABLE}")
790
+ + endif()
791
+ +
792
+ + # Get the host Python interpreter on the host system to use.
793
+ + set(
794
+ + FIREBASE_PYTHON_HOST_EXECUTABLE
795
+ + "${DEFAULT_PYTHON_HOST_EXECUTABLE}"
796
+ + CACHE FILEPATH
797
+ + "The Python interpreter on the host system to use"
798
+ + )
799
+ +
800
+ + # Check if the virtualenv is already up-to-date by examining the contents of
801
+ + # its stamp files. The stamp files store the path of the host Python
802
+ + # interpreter and the dependencies that were installed by pip. If both of
803
+ + # these files exist and contain the same Python interpreter and dependencies
804
+ + # then just re-use the virtualenv; otherwise, re-create it.
805
+ + set(PYVENV_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pyvenv/${ARG_KEY}")
806
+ + set(STAMP_FILE1 "${PYVENV_DIRECTORY}/cmake_firebase_python_stamp1.txt")
807
+ + set(STAMP_FILE2 "${PYVENV_DIRECTORY}/cmake_firebase_python_stamp2.txt")
808
+ +
809
+ + if(EXISTS "${STAMP_FILE1}" AND EXISTS "${STAMP_FILE2}")
810
+ + file(READ "${STAMP_FILE1}" STAMP_FILE1_CONTENTS)
811
+ + file(READ "${STAMP_FILE2}" STAMP_FILE2_CONTENTS)
812
+ + if(
813
+ + ("${STAMP_FILE1_CONTENTS}" STREQUAL "${FIREBASE_PYTHON_HOST_EXECUTABLE}")
814
+ + AND
815
+ + ("${STAMP_FILE2_CONTENTS}" STREQUAL "${ARG_REQUIREMENTS}")
816
+ + )
817
+ + set("${ARG_OUTVAR}" "$CACHE{${CACHEVAR}}" PARENT_SCOPE)
818
+ + message(STATUS "${LOG_PREFIX}: Using Python interpreter: $CACHE{${CACHEVAR}}")
819
+ + return()
820
+ + endif()
821
+ + endif()
822
+ +
823
+ + # Create the virtualenv.
824
+ + message(STATUS
825
+ + "${LOG_PREFIX}: Creating Python virtualenv in ${PYVENV_DIRECTORY} "
826
+ + "using ${FIREBASE_PYTHON_HOST_EXECUTABLE}"
827
+ + )
828
+ + file(REMOVE_RECURSE "${PYVENV_DIRECTORY}")
829
+ + execute_process(
830
+ + COMMAND
831
+ + "${FIREBASE_PYTHON_HOST_EXECUTABLE}"
832
+ + -m
833
+ + venv
834
+ + "${PYVENV_DIRECTORY}"
835
+ + RESULT_VARIABLE
836
+ + FIREBASE_PYVENV_CREATE_RESULT
837
+ + )
838
+ + if(NOT FIREBASE_PYVENV_CREATE_RESULT EQUAL 0)
839
+ + message(FATAL_ERROR
840
+ + "Failed to create a Python virtualenv in ${PYVENV_DIRECTORY} "
841
+ + "using ${FIREBASE_PYTHON_HOST_EXECUTABLE}")
842
+ + endif()
843
+ +
844
+ + # Find the Python interpreter in the virtualenv.
845
+ + find_program(
846
+ + "${CACHEVAR}"
847
+ + DOC "The Python interpreter to use for ${ARG_KEY}"
848
+ + NAMES python3 python
849
+ + PATHS "${PYVENV_DIRECTORY}"
850
+ + PATH_SUFFIXES bin Scripts
851
+ + NO_DEFAULT_PATH
852
+ + )
853
+ + if(NOT ${CACHEVAR})
854
+ + message(FATAL_ERROR "Unable to find Python executable in ${PYVENV_DIRECTORY}")
855
+ + else()
856
+ + set(PYTHON_EXECUTABLE "$CACHE{${CACHEVAR}}")
857
+ + message(STATUS "${LOG_PREFIX}: Found Python executable in virtualenv: ${PYTHON_EXECUTABLE}")
858
+ + endif()
859
+ +
860
+ + # Install the dependencies in the virtualenv, if any are requested.
861
+ + if(NOT ("${ARG_REQUIREMENTS}" STREQUAL ""))
862
+ + message(STATUS
863
+ + "${LOG_PREFIX}: Installing Python dependencies into "
864
+ + "${PYVENV_DIRECTORY}: ${ARG_REQUIREMENTS}"
865
+ + )
866
+ + execute_process(
867
+ + COMMAND
868
+ + "${PYTHON_EXECUTABLE}"
869
+ + -m
870
+ + pip
871
+ + install
872
+ + ${ARG_REQUIREMENTS}
873
+ + RESULT_VARIABLE
874
+ + PIP_INSTALL_RESULT
875
+ + )
876
+ + if(NOT PIP_INSTALL_RESULT EQUAL 0)
877
+ + message(FATAL_ERROR
878
+ + "Failed to install Python dependencies into "
879
+ + "${PYVENV_DIRECTORY}: ${ARG_REQUIREMENTS}"
880
+ + )
881
+ + endif()
882
+ + endif()
883
+ +
884
+ + # Write the stamp files.
885
+ + file(WRITE "${STAMP_FILE1}" "${FIREBASE_PYTHON_HOST_EXECUTABLE}")
886
+ + file(WRITE "${STAMP_FILE2}" "${ARG_REQUIREMENTS}")
887
+ +
888
+ + set("${ARG_OUTVAR}" "${PYTHON_EXECUTABLE}" PARENT_SCOPE)
889
+ +endfunction(FirebaseSetupPythonInterpreter)
0 commit comments