1717
1818
1919Example usage:
20- python build_zips.py --platform=macos --targets =auth --targets=firestore
20+ python build_zips.py --platform=macos --apis =auth --targets=firestore
2121"""
2222import glob
2323import os
3030
3131from absl import app , flags , logging
3232
33- SUPPORT_PLATFORMS = ("linux" , "macos" , "windows" , "ios" , "android" )
33+ SUPPORT_PLATFORMS = ("linux" , "macos" , "windows" , "ios" , "tvos" , " android" )
3434SUPPORT_TARGETS = [
3535 "analytics" , "auth" , "crashlytics" , "database" , "dynamic_links" ,
3636 "firestore" , "functions" , "installations" , "messaging" , "remote_config" ,
3737 "storage"
3838]
39+ TVOS_SUPPORT_TARGETS = [
40+ "analytics" , "auth" , "crashlytics" , "database" , "firestore" , "functions" ,
41+ "installations" , "messaging" , "remote_config" , "storage"
42+ ]
3943SUPPORT_DEVICE = ["device" , "simulator" ]
4044
4145IOS_SUPPORT_ARCHITECTURE = ["arm64" , "armv7" , "x86_64" , "i386" ]
5559 }
5660}
5761
62+ TVOS_CONFIG_DICT = {
63+ "device" : {
64+ "architecture" : ["arm64" ],
65+ "ios_platform_location" : "AppleTvOS.platform" ,
66+ "osx_sysroot" : "appletvos" ,
67+ "toolchain_platform" : "TVOS" ,
68+ },
69+ "simulator" : {
70+ "architecture" : ["x86_64" ],
71+ "ios_platform_location" : "AppleTvSimulator.platform" ,
72+ "osx_sysroot" : "appletvsimulator" ,
73+ "toolchain_platform" : "SIMULATOR_TVOS" ,
74+ }
75+ }
76+
5877ANDROID_SUPPORT_ARCHITECTURE = ["armeabi-v7a" , "arm64-v8a" , "x86" , "x86_64" ]
5978
6079MACOS_SUPPORT_ARCHITECTURE = ["x86_64" , "arm64" ]
86105 "To build on device or simulator. If not set, built on both. Only take affect for ios and android build"
87106)
88107flags .DEFINE_multi_string (
89- "architecture" , None , "Which architectures in build on.\n "
108+ "architecture" , None , "Which architectures in build on. Ignored on tvOS. \n "
90109 "For iOS device ({}).\n "
91110 "For iOS simulator ({}).\n "
92111 "For android ({}).\n "
@@ -167,13 +186,20 @@ def get_targets_args(targets):
167186 camke args included targets.
168187 """
169188 result_args = []
189+
190+ support_targets = SUPPORT_TARGETS
191+ if is_tvos_build ():
192+ support_targets = TVOS_SUPPORT_TARGETS
193+ if not targets :
194+ targets = TVOS_SUPPORT_TARGETS
195+
170196 if targets :
171197 # check if all the entries are valid
172198 for target in targets :
173- if target not in SUPPORT_TARGETS :
199+ if target not in support_targets :
174200 raise app .UsageError (
175201 'Wrong target "{}", please pick from {}' .format (
176- target , "," .join (SUPPORT_TARGETS )))
202+ target , "," .join (support_targets )))
177203 for target in SUPPORT_TARGETS :
178204 if target in targets :
179205 result_args .append ("-DFIREBASE_INCLUDE_" + target .upper () +
@@ -185,6 +211,31 @@ def get_targets_args(targets):
185211 return result_args
186212
187213
214+ def get_tvos_args (source_path ):
215+ """Get the cmake args for tvOS platforms.
216+
217+ Args:
218+ source_path: root source folder to find toolchain file.
219+ Returns:
220+ camke args for iOS platform.
221+ """
222+ result_args = []
223+ toolchain_path = os .path .join (source_path , "cmake" , "unity_tvos.cmake" )
224+ result_args .append ("-DCMAKE_TOOLCHAIN_FILE=" + toolchain_path )
225+ # check device input
226+ global g_target_devices
227+ if FLAGS .device :
228+ for device in FLAGS .device :
229+ if device not in SUPPORT_DEVICE :
230+ raise app .UsageError (
231+ 'Wrong device type {}, please pick from {}' .format (
232+ device , "," .join (SUPPORT_DEVICE )))
233+ g_target_devices = FLAGS .device
234+ else :
235+ g_target_devices = SUPPORT_DEVICE
236+
237+ return result_args
238+
188239def get_ios_args (source_path ):
189240 """Get the cmake args for iOS platform specific.
190241
@@ -490,6 +541,109 @@ def make_macos_multi_arch_build(cmake_args):
490541 logging .info ("Generated Darwin (MacOS) multi-arch (%s) zip %s" ,
491542 "," .join (g_target_architectures ), final_zip_path )
492543
544+
545+ def make_tvos_target (device , arch , cmake_args ):
546+ """Make the tvos build for the given device and architecture.
547+ Assumed to be called from the build directory.
548+
549+ Args:
550+ arch: The architecture to build for.
551+ cmake_args: Additional cmake arguments to use.
552+ """
553+ build_args = cmake_args .copy ()
554+ build_args .append ("-DCMAKE_OSX_ARCHITECTURES=" + arch )
555+ build_args .append ("-DCMAKE_OSX_SYSROOT=" +
556+ TVOS_CONFIG_DICT [device ]["osx_sysroot" ])
557+ build_args .append ("-DCMAKE_XCODE_EFFECTIVE_PLATFORMS=" +
558+ "-" + TVOS_CONFIG_DICT [device ]["osx_sysroot" ])
559+ build_args .append ("-DIOS_PLATFORM_LOCATION=" +
560+ TVOS_CONFIG_DICT [device ]["ios_platform_location" ])
561+ build_args .append ("-DPLATFORM=" +
562+ TVOS_CONFIG_DICT [device ]["toolchain_platform" ])
563+
564+ if not os .path .exists (arch ):
565+ os .makedirs (arch )
566+ build_dir = os .path .join (os .getcwd (), arch )
567+ subprocess .call (build_args , cwd = build_dir )
568+ subprocess .call ('make' , cwd = build_dir )
569+ subprocess .call (['cpack' , '.' ], cwd = build_dir )
570+
571+ def make_tvos_multi_arch_build (cmake_args ):
572+ """Make tvos build for different architectures, and then combine
573+ them together into a fat libraries and a single zip file.
574+
575+ Args:
576+ cmake_args: cmake arguments used to build each architecture.
577+ """
578+ global g_target_devices
579+ current_folder = os .getcwd ()
580+ target_architectures = []
581+
582+ # build multiple architectures
583+ current_folder = os .getcwd ()
584+ threads = []
585+ for device in g_target_devices :
586+ for arch in TVOS_CONFIG_DICT [device ]["architecture" ]:
587+ target_architectures .append (arch )
588+ t = threading .Thread (target = make_tvos_target , args = (device , arch , cmake_args ))
589+ t .start ()
590+ threads .append (t )
591+
592+ for t in threads :
593+ t .join ()
594+
595+ # Merge the different zip files together, using lipo on the library files
596+ zip_base_name = ""
597+ library_list = []
598+ base_temp_dir = tempfile .mkdtemp ()
599+ for arch in target_architectures :
600+ # find *.zip in subfolder architecture
601+ arch_zip_path = glob .glob (os .path .join (arch , "*-tvOS.zip" ))
602+ if not arch_zip_path :
603+ logging .error ("No *-tvOS.zip generated for architecture %s" , arch )
604+ return
605+ if not zip_base_name :
606+ # first architecture, so extract to the final temp folder. The following
607+ # library files will merge to the ones in this folder.
608+ zip_base_name = arch_zip_path [0 ]
609+ with zipfile .ZipFile (zip_base_name ) as zip_file :
610+ zip_file .extractall (base_temp_dir )
611+ library_list .extend (glob .glob (os .path .join (
612+ base_temp_dir , "**" , "*.a" ), recursive = True ))
613+ else :
614+ temporary_dir = tempfile .mkdtemp ()
615+ # from the second *-tvOS.zip, we only need to extract *.a files to operate the merge.
616+ with zipfile .ZipFile (arch_zip_path [0 ]) as zip_file :
617+ for file in zip_file .namelist ():
618+ if file .endswith ('.a' ):
619+ zip_file .extract (file , temporary_dir )
620+
621+ for library_file in library_list :
622+ library_name = os .path .basename (library_file )
623+ matching_files = glob .glob (os .path .join (
624+ temporary_dir , "Plugins" , "tvOS" , "Firebase" , library_name ))
625+ if matching_files :
626+ merge_args = [
627+ "lipo" ,
628+ library_file ,
629+ matching_files [0 ],
630+ "-create" ,
631+ "-output" ,
632+ library_file ,
633+ ]
634+ subprocess .call (merge_args )
635+ logging .info ("merging %s to %s" , matching_files [0 ], library_name )
636+
637+ # archive the temp folder to the final firebase_unity-<version>-tvOS.zip
638+ final_zip_path = os .path .join (current_folder , os .path .basename (zip_base_name ))
639+ with zipfile .ZipFile (final_zip_path , "w" , allowZip64 = True ) as zip_file :
640+ for current_root , _ , filenames in os .walk (base_temp_dir ):
641+ for filename in filenames :
642+ fullpath = os .path .join (current_root , filename )
643+ zip_file .write (fullpath , os .path .relpath (fullpath , base_temp_dir ))
644+ logging .info ("Generated Darwin (tvOS) multi-arch (%s) zip %s" ,
645+ "," .join (g_target_architectures ), final_zip_path )
646+
493647def gen_documentation_zip ():
494648 """If the flag was enabled, builds the zip file containing source files to document.
495649 """
@@ -510,14 +664,20 @@ def is_android_build():
510664 """
511665 return FLAGS .platform == "android"
512666
513-
514667def is_ios_build ():
515668 """
516669 Returns:
517670 If the build platform is ios
518671 """
519672 return FLAGS .platform == "ios"
520673
674+ def is_tvos_build ():
675+ """
676+ Returns:
677+ If the build platform is tvos
678+ """
679+ return FLAGS .platform == "tvos"
680+
521681def is_windows_build ():
522682 """
523683 Returns:
@@ -608,6 +768,8 @@ def main(argv):
608768
609769 if is_ios_build ():
610770 cmake_setup_args .extend (get_ios_args (source_path ))
771+ elif is_tvos_build ():
772+ cmake_setup_args .extend (get_tvos_args (source_path ))
611773 elif is_android_build ():
612774 cmake_setup_args .extend (get_android_args ())
613775 elif is_macos_build ():
@@ -625,6 +787,8 @@ def main(argv):
625787 logging .info ("Build macos with multiple architectures %s" ,
626788 "," .join (g_target_architectures ))
627789 make_macos_multi_arch_build (cmake_setup_args )
790+ elif is_tvos_build ():
791+ make_tvos_multi_arch_build (cmake_setup_args )
628792 else :
629793 subprocess .call (cmake_setup_args )
630794 if is_windows_build ():
0 commit comments