Flush 'Build for ...' messages before each build
[platform/upstream/iotivity.git] / auto_build.py
1 #!/usr/bin/python
2
3 import os
4 import sys
5 import platform
6 import subprocess
7 import multiprocessing
8
9 # help message
10 def helpmsg(script):
11     helpstr = '''
12 Usage:
13     build:
14         python %s <targetbuild>
15         Allowed values for <target_build>: all, linux_unsecured, linux_secured, linux_unsecured_with_ra, linux_secured_with_ra, linux_unsecured_with_rd, linux_secured_with_rd, android, arduino, tizen, simulator, darwin, windows, msys
16         Note: \"linux\" will build \"linux_unsecured\", \"linux_secured\", \"linux_unsecured_with_ra\", \"linux_secured_with_ra\", \"linux_secured_with_rd\", \"linux_unsecured_with_mq\", \"linux_unsecured_with_tcp\" & \"linux_unsecured_with_rd\".
17         Any selection will build both debug and release versions of all available targets in the scope you've selected.
18         To choose any specific command, please use the SCons commandline directly. Please refer to [IOTIVITY_REPO]/Readme.scons.txt.
19     clean:
20         python %s -c
21     '''
22     print (helpstr % (script, script))
23     sys.exit()
24
25 def call_scons(build_options, extra_option_str):
26     """
27     This function formats and runs a scons command
28     Arguments:
29     build_options    -- {Dictionary} build flags (keys) associated with values;
30     extra_option_str -- {String} extra options to append to scons command
31     """
32     cmd_line = "scons VERBOSE=" + VERBOSE
33     for key in build_options:
34         cmd_line += " " + key + "=" + str(build_options[key])
35
36     cmd_line += " " + str(extra_option_str)
37
38     print ("Running : " + cmd_line)
39     sys.stdout.flush()
40     exit_code = subprocess.Popen([cmd_line], shell=True).wait()
41     if exit_code != 0:
42         exit(exit_code)
43
44 def build_all(flag, extra_option_str):
45     if platform.system() == "Linux":
46         build_linux_unsecured(flag, extra_option_str)
47         build_linux_secured(flag, extra_option_str)
48         build_linux_unsecured_with_ra(flag, extra_option_str)
49         build_linux_secured_with_ra(flag, extra_option_str)
50         build_linux_unsecured_with_rm(flag, extra_option_str)
51         build_linux_unsecured_with_rd(flag, extra_option_str)
52         build_linux_secured_with_rd(flag, extra_option_str)
53         build_linux_unsecured_with_mq(flag, extra_option_str)
54         build_linux_unsecured_with_tcp(flag, extra_option_str)
55         build_simulator(flag, extra_option_str)
56
57     build_android(flag, extra_option_str)
58     build_arduino(flag, extra_option_str)
59     build_tizen(flag, extra_option_str)
60
61     if platform.system() == "Windows":
62         build_windows(flag, extra_option_str)
63
64     if platform.system() == "Darwin":
65         build_darwin(flag, extra_option_str)
66
67 def build_linux(flag, extra_option_str):
68     build_linux_unsecured(flag, extra_option_str)
69     build_linux_secured(flag, extra_option_str)
70
71 def build_linux_unsecured(flag, extra_option_str):
72     print ("*********** Build for linux ************")
73     build_options = {
74                         'RELEASE':flag,
75                     }
76     call_scons(build_options, extra_option_str)
77
78 def build_linux_unsecured_with_tcp(flag, extra_option_str):
79     print ("*********** Build for linux with TCP ************")
80     build_options = {
81                         'RELEASE':flag,
82                         'WITH_TCP': 1,
83                         'TARGET_TRANSPORT': 'IP',
84                     }
85     call_scons(build_options, extra_option_str)
86
87 def build_linux_unsecured_with_rm(flag, extra_option_str):
88     print ("*********** Build for linux with RoutingManager************")
89     build_options = {
90                         'ROUTING':'GW',
91                         'RELEASE':flag,
92                     }
93     call_scons(build_options, extra_option_str)
94
95 def build_linux_secured(flag, extra_option_str):
96     print ("*********** Build for linux with Security *************")
97     build_options = {
98                         'RELEASE':flag,
99                         'SECURED':1,
100                     }
101     call_scons(build_options, extra_option_str)
102
103 def build_linux_unsecured_with_ra(flag, extra_option_str):
104     print ("*********** Build for linux With Remote Access *************")
105     build_options = {
106                         'RELEASE':flag,
107                         'WITH_RA':1,
108                         'WITH_RA_IBB':1,
109                     }
110     call_scons(build_options, extra_option_str)
111
112 def build_linux_secured_with_ra(flag, extra_option_str):
113     print ("*********** Build for linux With Remote Access & Security ************")
114     build_options = {
115                         'RELEASE':flag,
116                         'WITH_RA':1,
117                         'WITH_RA_IBB':1,
118                         'SECURED':1,
119                     }
120     call_scons(build_options, extra_option_str)
121
122 def build_linux_unsecured_with_rd(flag, extra_option_str):
123     print ("*********** Build for linux With Resource Directory *************")
124     build_options = {
125                         'RELEASE':flag,
126                         'WITH_RD':1,
127                     }
128     call_scons(build_options, extra_option_str)
129
130 def build_linux_secured_with_rd(flag, extra_option_str):
131     print ("*********** Build for linux With Resource Directory & Security ************")
132     build_options = {
133                         'RELEASE':flag,
134                         'WITH_RD':1,
135                         'SECURED':1,
136                     }
137     call_scons(build_options, extra_option_str)
138
139 def build_linux_unsecured_with_mq(flag, extra_option_str):
140     print ("*********** Build for linux With Message Queue ************")
141     build_options = {
142                         'RELEASE':flag,
143                         'WITH_MQ':'PUB,SUB,BROKER',
144                     }
145     call_scons(build_options, extra_option_str)
146
147 def build_linux_unsecured_with_tcp(flag, extra_option_str):
148     print ("*********** Build for linux With tcp ************")
149     build_options = {
150                         'RELEASE':flag,
151                         'WITH_TCP':'1',
152                     }
153     call_scons(build_options, extra_option_str)
154
155 def build_android(flag, extra_option_str):
156     # Note: for android, as oic-resource uses C++11 feature stoi and to_string,
157     # it requires gcc-4.9, currently only android-ndk-r10(for linux)
158     # and windows android-ndk-r10(64bit target version) support these features.
159
160     build_android_x86(flag, extra_option_str)
161     build_android_x86_with_rm(flag, extra_option_str)
162     build_android_armeabi(flag, extra_option_str)
163     build_android_armeabi_with_rm(flag, extra_option_str)
164
165 def build_android_x86(flag, extra_option_str):
166     """ Build Android x86 Suite """
167     build_android_x86_with_ip(flag, extra_option_str)
168     build_android_x86_with_bt(flag, extra_option_str)
169     build_android_x86_with_ble(flag, extra_option_str)
170
171 def build_android_x86_with_ip(flag, extra_option_str):
172     print ("*********** Build for android x86 *************")
173     build_options = {
174                         'TARGET_OS':'android',
175                         'TARGET_ARCH':'x86',
176                         'RELEASE':flag,
177                         'TARGET_TRANSPORT':'IP',
178                     }
179     call_scons(build_options, extra_option_str)
180
181 def build_android_x86_with_bt(flag, extra_option_str):
182     print ("*********** Build for android x86 with Bluetooth *************")
183     build_options = {
184                         'TARGET_OS':'android',
185                         'TARGET_ARCH':'x86',
186                         'RELEASE':flag,
187                         'TARGET_TRANSPORT':'BT',
188                     }
189     call_scons(build_options, extra_option_str)
190
191 def build_android_x86_with_ble(flag, extra_option_str):
192     print ("*********** Build for android x86 with Bluetooth Low Energy *************")
193     build_options = {
194                         'TARGET_OS':'android',
195                         'TARGET_ARCH':'x86',
196                         'RELEASE':flag,
197                         'TARGET_TRANSPORT':'BLE',
198                     }
199     call_scons(build_options, extra_option_str)
200
201 def build_android_x86_with_rm(flag, extra_option_str):
202     """ Build Android x86 Routing Manager Suite """
203     build_android_x86_with_rm_and_ip(flag, extra_option_str)
204     build_android_x86_with_rm_and_bt(flag, extra_option_str)
205     build_android_x86_with_rm_and_ble(flag, extra_option_str)
206
207 def build_android_x86_with_rm_and_ip(flag, extra_option_str):
208     print ("*********** Build for android x86 with Routing Manager *************")
209     build_options = {
210                         'TARGET_OS':'android',
211                         'TARGET_ARCH':'x86',
212                         'ROUTING':'GW',
213                         'RELEASE':flag,
214                         'TARGET_TRANSPORT':'IP',
215                     }
216     call_scons(build_options, extra_option_str)
217
218 def build_android_x86_with_rm_and_bt(flag, extra_option_str):
219     print ("*********** Build for android x86 with Routing Manager and Bluetooth *************")
220     build_options = {
221                         'TARGET_OS':'android',
222                         'TARGET_ARCH':'x86',
223                         'ROUTING':'GW',
224                         'RELEASE':flag,
225                         'TARGET_TRANSPORT':'BT',
226                     }
227     call_scons(build_options, extra_option_str)
228
229 def build_android_x86_with_rm_and_ble(flag, extra_option_str):
230     print ("*********** Build for android x86 with Routing Manager and Bluetooth Low Energy *************")
231     build_options = {
232                         'TARGET_OS':'android',
233                         'TARGET_ARCH':'x86',
234                         'ROUTING':'GW',
235                         'RELEASE':flag,
236                         'TARGET_TRANSPORT':'BLE',
237                     }
238     call_scons(build_options, extra_option_str)
239
240 def build_android_armeabi(flag, extra_option_str):
241     """ Build Android Armeabi Suite """
242     build_android_armeabi_with_ip(flag, extra_option_str)
243     build_android_armeabi_with_bt(flag, extra_option_str)
244     build_android_armeabi_with_ble(flag, extra_option_str)
245
246 def build_android_armeabi_with_ip(flag, extra_option_str):
247     print ("*********** Build for android armeabi *************")
248     build_options = {
249                         'TARGET_OS':'android',
250                         'TARGET_ARCH':'armeabi',
251                         'RELEASE':flag,
252                         'TARGET_TRANSPORT':'IP',
253                     }
254     call_scons(build_options, extra_option_str)
255
256 def build_android_armeabi_with_bt(flag, extra_option_str):
257     print ("*********** Build for android armeabi with Bluetooth *************")
258     build_options = {
259                         'TARGET_OS':'android',
260                         'TARGET_ARCH':'armeabi',
261                         'RELEASE':flag,
262                         'TARGET_TRANSPORT':'BT',
263                     }
264     call_scons(build_options, extra_option_str)
265
266 def build_android_armeabi_with_ble(flag, extra_option_str):
267     print ("*********** Build for android armeabi with Bluetooth Low Energy *************")
268     build_options = {
269                         'TARGET_OS':'android',
270                         'TARGET_ARCH':'armeabi',
271                         'RELEASE':flag,
272                         'TARGET_TRANSPORT':'BLE',
273                     }
274     call_scons(build_options, extra_option_str)
275
276 def build_android_armeabi_with_rm(flag, extra_option_str):
277     """ Build Android Armeabi Routing Manager Suite """
278     build_android_armeabi_with_rm_and_ip(flag, extra_option_str)
279     build_android_armeabi_with_rm_and_bt(flag, extra_option_str)
280     build_android_armeabi_with_rm_and_ble(flag, extra_option_str)
281
282 def build_android_armeabi_with_rm_and_ip(flag, extra_option_str):
283     print ("*********** Build for android armeabi with Routing Manager *************")
284     build_options = {
285                         'TARGET_OS':'android',
286                         'TARGET_ARCH':'armeabi',
287                         'ROUTING':'GW',
288                         'RELEASE':flag,
289                         'TARGET_TRANSPORT':'IP',
290                     }
291     call_scons(build_options, extra_option_str)
292
293 def build_android_armeabi_with_rm_and_bt(flag, extra_option_str):
294     print ("*********** Build for android armeabi with Routing Manager and Bluetooth *************")
295     build_options = {
296                         'TARGET_OS':'android',
297                         'TARGET_ARCH':'armeabi',
298                         'ROUTING':'GW',
299                         'RELEASE':flag,
300                         'TARGET_TRANSPORT':'BT',
301                     }
302     call_scons(build_options, extra_option_str)
303
304 def build_android_armeabi_with_rm_and_ble(flag, extra_option_str):
305     print ("*********** Build for android armeabi with Routing Manager and Bluetooth Low Energy *************")
306     build_options = {
307                         'TARGET_OS':'android',
308                         'TARGET_ARCH':'armeabi',
309                         'ROUTING':'GW',
310                         'RELEASE':flag,
311                         'TARGET_TRANSPORT':'BLE',
312                     }
313     call_scons(build_options, extra_option_str)
314
315 def build_arduino(flag, extra_option_str):
316     print ("*********** Build for arduino avr *************")
317     extra_option_str = "resource " + extra_option_str
318     build_options = {
319                         'TARGET_OS':'arduino',
320                         'UPLOAD':'false',
321                         'BOARD':'mega',
322                         'TARGET_ARCH':'avr',
323                         'TARGET_TRANSPORT':'IP',
324                         'SHIELD':'ETH',
325                         'RELEASE':flag,
326                     }
327     call_scons(build_options, extra_option_str)
328
329     build_options['SHIELD'] = 'WIFI'
330     call_scons(build_options, extra_option_str)
331
332     build_options['TARGET_TRANSPORT'] = 'BLE'
333     build_options['SHIELD']           = 'RBL_NRF8001'
334     call_scons(build_options, extra_option_str)
335
336     print ("*********** Build for arduino arm *************")
337     build_options['BOARD']            = 'arduino_due_x'
338     build_options['TARGET_ARCH']      = 'arm'
339     build_options['TARGET_TRANSPORT'] = 'IP'
340     build_options['SHIELD']           = 'ETH'
341     call_scons(build_options, extra_option_str)
342
343     build_options['SHIELD'] = 'WIFI'
344     call_scons(build_options, extra_option_str)
345
346     # BLE support for the Arduino Due is currently unavailable.
347
348 def build_tizen(flag, extra_option_str):
349     print ("*********** Build for Tizen *************")
350     cmd_line = "/bin/sh " + os.getcwd() + "/gbsbuild.sh"
351     print ("Running : " + cmd_line)
352     subprocess.Popen([cmd_line], shell=True).wait()
353
354     print ("*********** Build for Tizen octbstack lib and sample *************")
355     extra_option_str = "-f resource/csdk/stack/samples/tizen/build/SConscript " + extra_option_str
356     build_options = {
357                         'TARGET_OS':'tizen',
358                         'TARGET_TRANSPORT':'IP',
359                         'LOGGING':'true',
360                         'RELEASE':flag,
361                     }
362     call_scons(build_options, extra_option_str)
363
364     print ("*********** Build for Tizen octbstack lib and sample with Security*************")
365     build_options['SECURED'] = 1
366     call_scons(build_options, extra_option_str)
367
368     print ("*********** Build for Tizen octbstack lib and sample with Routing Manager*************")
369     del build_options['SECURED']
370     build_options['ROUTING'] = 'GW'
371     call_scons(build_options, extra_option_str)
372
373 # Mac OS and iOS
374 def build_darwin(flag, extra_option_str):
375     print ("*********** Build for OSX *************")
376     build_options = {
377                         'TARGET_OS':'darwin',
378                         'SYS_VERSION':'10.9',
379                         'RELEASE':flag,
380                     }
381     call_scons(build_options, extra_option_str)
382
383     print ("*********** Build for IOS i386 *************")
384     build_options = {
385                         'TARGET_OS':'ios',
386                         'TARGET_ARCH':'i386',
387                         'SYS_VERSION':'7.0',
388                         'RELEASE':flag,
389                     }
390     call_scons(build_options, extra_option_str)
391
392     print ("*********** Build for IOS x86_64 *************")
393     build_options['TARGET_ARCH'] = 'x86_64'
394     call_scons(build_options, extra_option_str)
395
396     print ("*********** Build for IOS armv7 *************")
397     build_options['TARGET_ARCH'] = 'armv7'
398     call_scons(build_options, extra_option_str)
399
400     print ("*********** Build for IOS armv7s *************")
401     build_options['TARGET_ARCH'] = 'armv7s'
402     call_scons(build_options, extra_option_str)
403
404     print ("*********** Build for IOS arm64 *************")
405     build_options['TARGET_ARCH'] = 'arm64'
406     call_scons(build_options, extra_option_str)
407
408 # Windows
409 def build_windows(flag, extra_option_str):
410     print ("*********** Build for Windows *************")
411     os.environ["SCONSFLAGS"] = ""
412     build_options = {
413                         'TARGET_OS':'windows',
414                         'TARGET_ARCH':'amd64',
415                         'RELEASE':flag,
416                         'WITH_RA':0,
417                         'TARGET_TRANSPORT':'IP',
418                         'SECURED':1,
419                         'WITH_TCP':0,
420                         'BUILD_SAMPLE':'ON',
421                         'LOGGING':'off',
422                         'TEST':1,
423                         'WITH_RD':1,
424                     }
425     call_scons(build_options, extra_option_str)
426
427 # Windows msys
428 def build_msys(flag, extra_option_str):
429     print ("*********** Build for msys_nt *************")
430     os.environ["SCONSFLAGS"] = ""
431     build_options = {
432                         'TARGET_OS':'msys_nt',
433                         'TARGET_ARCH':'x86_64',
434                         'RELEASE':flag,
435                         'WITH_RA':0,
436                         'TARGET_TRANSPORT':'IP',
437                         'SECURED':1,
438                         'WITH_TCP':0,
439                         'BUILD_SAMPLE':'ON',
440                         'LOGGING':'off',
441                         'TEST':1,
442                         'WITH_RD':1,
443                     }
444     call_scons(build_options, extra_option_str)
445
446 def build_simulator(flag, extra_option_str):
447     print ("*********** Build for simulator plugin *************")
448     build_options = {
449                         'SIMULATOR':1,
450                         'RELEASE':flag,
451                     }
452     call_scons(build_options, extra_option_str)
453
454 def unit_tests():
455     print ("*********** Unit test Start *************")
456     build_options = {
457                         'RELEASE':'false',
458                     }
459     extra_option_str = "resource -c"
460     call_scons(build_options, extra_option_str)
461
462     build_options = {
463                         'LOGGING':'false',
464                         'RELEASE':'false',
465                     }
466     extra_option_str = "resource"
467     call_scons(build_options, extra_option_str)
468
469     build_options = {
470                         'TEST':1,
471                         'RELEASE':'false',
472                     }
473     extra_option_str = "resource"
474     call_scons(build_options, extra_option_str)
475
476     print ("*********** Unit test Stop *************")
477
478 # Main module starts here
479 if os.getenv("SCONSFLAGS", "") == "":
480     os.environ["SCONSFLAGS"] = "-Q -j " + str(multiprocessing.cpu_count())
481
482 arg_num     = len(sys.argv)
483 script_name = sys.argv[0]
484
485 # May be overridden in user's shell
486 VERBOSE = os.getenv("VERBOSE", "1")
487
488 if arg_num == 1:
489     build_all("true", "")
490     build_all("false", "")
491     unit_tests()
492
493 elif arg_num == 2:
494     if str(sys.argv[1]) == '-c':
495         build_all("true", "-c")
496         build_all("false", "-c")
497
498     elif str(sys.argv[1]) == "all":
499         build_all("true", "")
500         build_all("false", "")
501         unit_tests()
502
503     elif str(sys.argv[1]) == "linux":
504         build_linux("true", "")
505         build_linux("false", "")
506
507     elif str(sys.argv[1]) == "linux_unsecured":
508         build_linux_unsecured("true", "")
509         build_linux_unsecured("false", "")
510         build_linux_unsecured_with_rm("true", "")
511         build_linux_unsecured_with_rm("false", "")
512
513     elif str(sys.argv[1]) == "linux_secured":
514         build_linux_secured("true", "")
515         build_linux_secured("false", "")
516
517     elif str(sys.argv[1]) == "linux_unsecured_with_ra":
518         build_linux_unsecured_with_ra("true", "")
519         build_linux_unsecured_with_ra("false", "")
520
521     elif str(sys.argv[1]) == "linux_secured_with_ra":
522         build_linux_secured_with_ra("true", "")
523         build_linux_secured_with_ra("false", "")
524
525     elif str(sys.argv[1]) == "linux_unsecured_with_rd":
526         build_linux_unsecured_with_rd("true", "")
527         build_linux_unsecured_with_rd("false", "")
528
529     elif str(sys.argv[1]) == "linux_secured_with_rd":
530         build_linux_secured_with_rd("true", "")
531         build_linux_secured_with_rd("false", "")
532
533     elif str(sys.argv[1]) == "linux_unsecured_with_mq":
534         build_linux_unsecured_with_mq("true", "")
535         build_linux_unsecured_with_mq("false", "")
536
537     elif str(sys.argv[1]) == "linux_unsecured_with_tcp":
538         build_linux_unsecured_with_tcp("true", "")
539         build_linux_unsecured_with_tcp("false", "")
540
541     elif str(sys.argv[1]) == "android":
542         build_android("true", "")
543         build_android("false", "")
544
545     elif str(sys.argv[1]) == "android_x86":
546         build_android_x86("true", "")
547         build_android_x86("false", "")
548         build_android_x86_with_rm("true", "")
549         build_android_x86_with_rm("false", "")
550
551     elif str(sys.argv[1]) == "android_x86_with_ip":
552         build_android_x86_with_ip("true", "")
553         build_android_x86_with_ip("false", "")
554
555     elif str(sys.argv[1]) == "android_x86_with_bt":
556         build_android_x86_with_bt("true", "")
557         build_android_x86_with_bt("false", "")
558
559     elif str(sys.argv[1]) == "android_x86_with_ble":
560         build_android_x86_with_ble("true", "")
561         build_android_x86_with_ble("false", "")
562
563     elif str(sys.argv[1]) == "android_x86_with_rm_and_ip":
564         build_android_x86_with_rm_and_ip("true", "")
565         build_android_x86_with_rm_and_ip("false", "")
566
567     elif str(sys.argv[1]) == "android_x86_with_rm_and_bt":
568         build_android_x86_with_rm_and_bt("true", "")
569         build_android_x86_with_rm_and_bt("false", "")
570
571     elif str(sys.argv[1]) == "android_x86_with_rm_and_ble":
572         build_android_x86_with_rm_and_ble("true", "")
573         build_android_x86_with_rm_and_ble("false", "")
574
575     elif str(sys.argv[1]) == "android_armeabi":
576         build_android_armeabi("true", "")
577         build_android_armeabi("false", "")
578         build_android_armeabi_with_rm("true", "")
579         build_android_armeabi_with_rm("false", "")
580
581     elif str(sys.argv[1]) == "android_armeabi_with_ip":
582         build_android_armeabi_with_ip("true", "")
583         build_android_armeabi_with_ip("false", "")
584
585     elif str(sys.argv[1]) == "android_armeabi_with_bt":
586         build_android_armeabi_with_bt("true", "")
587         build_android_armeabi_with_bt("false", "")
588
589     elif str(sys.argv[1]) == "android_armeabi_with_ble":
590         build_android_armeabi_with_ble("true", "")
591         build_android_armeabi_with_ble("false", "")
592
593     elif str(sys.argv[1]) == "android_armeabi_with_rm_and_ip":
594         build_android_armeabi_with_rm_and_ip("true", "")
595         build_android_armeabi_with_rm_and_ip("false", "")
596
597     elif str(sys.argv[1]) == "android_armeabi_with_rm_and_bt":
598         build_android_armeabi_with_rm_and_bt("true", "")
599         build_android_armeabi_with_rm_and_bt("false", "")
600
601     elif str(sys.argv[1]) == "android_armeabi_with_rm_and_ble":
602         build_android_armeabi_with_rm_and_ble("true", "")
603         build_android_armeabi_with_rm_and_ble("false", "")
604
605     elif str(sys.argv[1]) == "arduino":
606         build_arduino("true", "")
607         build_arduino("false", "")
608
609     elif str(sys.argv[1]) == "windows":
610         build_windows("true", "")
611         build_windows("false", "")
612
613     elif str(sys.argv[1]) == "msys":
614         build_msys("true", "")
615         build_msys("false", "")
616
617     elif str(sys.argv[1]) == "tizen":
618         build_tizen("true", "")
619         build_tizen("false", "")
620
621     elif str(sys.argv[1]) == "simulator":
622         build_simulator("true", "")
623         build_simulator("false", "")
624
625     elif str(sys.argv[1]) == "darwin":
626         build_darwin("true", "")
627         build_darwin("false", "")
628
629     elif str(sys.argv[1]) == "unit_tests":
630         unit_tests()
631
632     else:
633         helpmsg(script_name)
634 else:
635         helpmsg(script_name)
636
637 print ("===================== done =====================")