17
17
18
18
19
19
Example usage:
20
- python build_zips.py --platform=macos --targets =auth --targets=firestore
20
+ python build_zips.py --platform=macos --apis =auth --targets=firestore
21
21
"""
22
22
import glob
23
23
import os
30
30
31
31
from absl import app , flags , logging
32
32
33
- SUPPORT_PLATFORMS = ("linux" , "macos" , "windows" , "ios" , "android" )
33
+ SUPPORT_PLATFORMS = ("linux" , "macos" , "windows" , "ios" , "tvos" , " android" )
34
34
SUPPORT_TARGETS = [
35
35
"analytics" , "auth" , "crashlytics" , "database" , "dynamic_links" ,
36
36
"firestore" , "functions" , "installations" , "messaging" , "remote_config" ,
37
37
"storage"
38
38
]
39
+ TVOS_SUPPORT_TARGETS = [
40
+ "analytics" , "auth" , "crashlytics" , "database" , "firestore" , "functions" ,
41
+ "installations" , "messaging" , "remote_config" , "storage"
42
+ ]
39
43
SUPPORT_DEVICE = ["device" , "simulator" ]
40
44
41
45
IOS_SUPPORT_ARCHITECTURE = ["arm64" , "armv7" , "x86_64" , "i386" ]
55
59
}
56
60
}
57
61
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
+
58
77
ANDROID_SUPPORT_ARCHITECTURE = ["armeabi-v7a" , "arm64-v8a" , "x86" , "x86_64" ]
59
78
60
79
MACOS_SUPPORT_ARCHITECTURE = ["x86_64" , "arm64" ]
86
105
"To build on device or simulator. If not set, built on both. Only take affect for ios and android build"
87
106
)
88
107
flags .DEFINE_multi_string (
89
- "architecture" , None , "Which architectures in build on.\n "
108
+ "architecture" , None , "Which architectures in build on. Ignored on tvOS. \n "
90
109
"For iOS device ({}).\n "
91
110
"For iOS simulator ({}).\n "
92
111
"For android ({}).\n "
@@ -167,13 +186,20 @@ def get_targets_args(targets):
167
186
camke args included targets.
168
187
"""
169
188
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
+
170
196
if targets :
171
197
# check if all the entries are valid
172
198
for target in targets :
173
- if target not in SUPPORT_TARGETS :
199
+ if target not in support_targets :
174
200
raise app .UsageError (
175
201
'Wrong target "{}", please pick from {}' .format (
176
- target , "," .join (SUPPORT_TARGETS )))
202
+ target , "," .join (support_targets )))
177
203
for target in SUPPORT_TARGETS :
178
204
if target in targets :
179
205
result_args .append ("-DFIREBASE_INCLUDE_" + target .upper () +
@@ -185,6 +211,31 @@ def get_targets_args(targets):
185
211
return result_args
186
212
187
213
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
+
188
239
def get_ios_args (source_path ):
189
240
"""Get the cmake args for iOS platform specific.
190
241
@@ -490,6 +541,109 @@ def make_macos_multi_arch_build(cmake_args):
490
541
logging .info ("Generated Darwin (MacOS) multi-arch (%s) zip %s" ,
491
542
"," .join (g_target_architectures ), final_zip_path )
492
543
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
+
493
647
def gen_documentation_zip ():
494
648
"""If the flag was enabled, builds the zip file containing source files to document.
495
649
"""
@@ -510,14 +664,20 @@ def is_android_build():
510
664
"""
511
665
return FLAGS .platform == "android"
512
666
513
-
514
667
def is_ios_build ():
515
668
"""
516
669
Returns:
517
670
If the build platform is ios
518
671
"""
519
672
return FLAGS .platform == "ios"
520
673
674
+ def is_tvos_build ():
675
+ """
676
+ Returns:
677
+ If the build platform is tvos
678
+ """
679
+ return FLAGS .platform == "tvos"
680
+
521
681
def is_windows_build ():
522
682
"""
523
683
Returns:
@@ -608,6 +768,8 @@ def main(argv):
608
768
609
769
if is_ios_build ():
610
770
cmake_setup_args .extend (get_ios_args (source_path ))
771
+ elif is_tvos_build ():
772
+ cmake_setup_args .extend (get_tvos_args (source_path ))
611
773
elif is_android_build ():
612
774
cmake_setup_args .extend (get_android_args ())
613
775
elif is_macos_build ():
@@ -625,6 +787,8 @@ def main(argv):
625
787
logging .info ("Build macos with multiple architectures %s" ,
626
788
"," .join (g_target_architectures ))
627
789
make_macos_multi_arch_build (cmake_setup_args )
790
+ elif is_tvos_build ():
791
+ make_tvos_multi_arch_build (cmake_setup_args )
628
792
else :
629
793
subprocess .call (cmake_setup_args )
630
794
if is_windows_build ():
0 commit comments