@@ -6,13 +6,21 @@ import re
66import  shlex 
77import  subprocess 
88import  sys 
9+ import  urllib 
10+ import  zipfile 
11+ import  hashlib 
12+ import  shutil 
913
1014CC  =  os .environ .get ('CC' , 'cc' )
1115
1216root_dir  =  os .path .dirname (__file__ )
1317sys .path .insert (0 , os .path .join (root_dir , 'tools' , 'gyp' , 'pylib' ))
1418from  gyp .common  import  GetFlavor 
1519
20+ # imports in tools/configure.d 
21+ sys .path .insert (0 , os .path .join (root_dir , 'tools' , 'configure.d' ))
22+ import  nodedownload 
23+ 
1624# parse our options 
1725parser  =  optparse .OptionParser ()
1826
@@ -244,7 +252,7 @@ parser.add_option('--with-icu-path',
244252parser .add_option ('--with-intl' ,
245253    action = 'store' ,
246254    dest = 'with_intl' ,
247-     help = 'Intl mode: none, full-icu, small-icu (default is none )' )
255+     help = 'Intl mode: none, full-icu, small-icu (default is small-icu )' )
248256
249257parser .add_option ('--with-perfctr' ,
250258    action = 'store_true' ,
@@ -712,6 +720,58 @@ def glob_to_var(dir_base, dir_sub):
712720  return  list 
713721
714722def  configure_intl (o ):
723+   icus  =  [
724+     {
725+       'url' : 'http://download.icu-project.org/files/icu4c/54.1/icu4c-54_1-src.zip' ,
726+       # from https://ssl.icu-project.org/files/icu4c/54.1/icu4c-src-54_1.md5: 
727+       'md5' : '6b89d60e2f0e140898ae4d7f72323bca' ,
728+     },
729+   ]
730+   class  ConfigOpener (urllib .FancyURLopener ):
731+     # append to existing version (UA) 
732+     version  =  '%s (node.js/configure)'  %  urllib .URLopener .version 
733+   def  icu_download (path ):
734+     # download ICU, if needed 
735+     def  fmtMb (amt ):
736+       return  "{:.1f}" .format (amt  /  1024000. )
737+     def  reporthook (count , size , total ):
738+       sys .stdout .write (' ICU: %c %sMB total, %sMB downloaded   \r '  % 
739+                        (nodedownload .spin (count ),
740+                         nodedownload .formatSize (total ),
741+                         nodedownload .formatSize (count * size )))
742+     for  icu  in  icus :
743+       url  =  icu ['url' ]
744+       md5  =  icu ['md5' ]
745+       local  =  url .split ('/' )[- 1 ]
746+       targetfile  =  os .path .join (root_dir , 'deps' , local )
747+       if  not  os .path .isfile (targetfile ):
748+         try :
749+           sys .stdout .write (' <%s>\n Connecting...\r '  %  url )
750+           sys .stdout .flush ()
751+           msg  =  urllib .urlretrieve (url , targetfile , reporthook = reporthook )
752+           print  ''   # clear the line 
753+         except :
754+           print  ' ** Error occurred while downloading\n  <%s>'  %  url 
755+           raise 
756+       else :
757+         print  ' Re-using existing %s'  %  targetfile 
758+       if  os .path .isfile (targetfile ):
759+         digest  =  hashlib .md5 ()
760+         count  =  0 
761+         sys .stdout .write (' Checking file integrity with MD5:\r ' )
762+         with  open (targetfile , 'rb' ) as  f :
763+           chunk  =  f .read (1024 )
764+           while  chunk  !=   "" :
765+             digest .update (chunk )
766+             chunk  =  f .read (1024 )
767+         gotmd5  =  digest .hexdigest ()
768+         print  ' MD5:      %s  %s'  %  (gotmd5 , targetfile )
769+         if  (md5  ==  gotmd5 ):
770+           return  targetfile 
771+         else :
772+           print  ' Expected: %s      *MISMATCH*'  %  md5 
773+           print  '\n  ** Corrupted ZIP? Delete %s to retry download.\n '  %  targetfile 
774+     return  None 
715775  icu_config  =  {
716776    'variables' : {}
717777  }
@@ -723,7 +783,6 @@ def configure_intl(o):
723783  write (icu_config_name , do_not_edit  + 
724784        pprint .pformat (icu_config , indent = 2 ) +  '\n ' )
725785
726-   # small ICU is off by default. 
727786  # always set icu_small, node.gyp depends on it being defined. 
728787  o ['variables' ]['icu_small' ] =  b (False )
729788
@@ -739,6 +798,8 @@ def configure_intl(o):
739798    o ['variables' ]['icu_gyp_path' ] =  options .with_icu_path 
740799    return 
741800  # --with-intl=<with_intl> 
801+   if  with_intl  is  None :
802+     with_intl  =  'small-icu'   # The default mode of Intl 
742803  if  with_intl  ==  'none'  or  with_intl  is  None :
743804    o ['variables' ]['v8_enable_i18n_support' ] =  0 
744805    return   # no Intl 
@@ -769,20 +830,47 @@ def configure_intl(o):
769830  # Note: non-ICU implementations could use other 'with_intl' 
770831  # values. 
771832
833+   icu_parent_path  =  os .path .join (root_dir , 'deps' )
834+   icu_full_path  =  os .path .join (icu_parent_path , 'icu' )
835+   icu_small_path  =  os .path .join (icu_parent_path , 'icu-small' )
836+   icu_small_tag  =  os .path .join (icu_full_path , 'is-small-icu.txt' )
837+ 
838+   ## Use (or not) an embedded small-icu. 
839+   if  with_intl  ==  'small-icu' :
840+     if  not  os .path .isdir (icu_full_path ) and  os .path .isdir (icu_small_path ):
841+       # deps/small-icu -> deps/icu 
842+       print  'Copying small ICU %s to %s'  %  (icu_small_path , icu_full_path )
843+       shutil .copytree (icu_small_path , icu_full_path )
844+     #else: 
845+     #  print 'Not copying %s to %s' % (icu_small_path, icu_full_path) 
846+   elif  os .path .isfile (icu_small_tag ):
847+     print  'deleting small-icu %s for --with-intl=%s'  %  (icu_full_path , with_intl )
848+     shutil .rmtree (icu_full_path )
849+ 
772850  # ICU mode. (icu-generic.gyp) 
773851  byteorder  =  sys .byteorder 
774852  o ['variables' ]['icu_gyp_path' ] =  'tools/icu/icu-generic.gyp' 
775853  # ICU source dir relative to root 
776-   icu_full_path  =  os .path .join (root_dir , 'deps/icu' )
777854  o ['variables' ]['icu_path' ] =  icu_full_path 
778855  if  not  os .path .isdir (icu_full_path ):
779-     print  'Error: ICU path is not a directory: %s'  %  (icu_full_path )
856+     print  '* ECMA-402 (Intl) support didn\' t find ICU in %s..'  %  (icu_full_path )
857+     # can we download (or find) a zipfile? 
858+     localzip  =  icu_download (icu_full_path )
859+     if  localzip :
860+       with  zipfile .ZipFile (localzip , 'r' ) as  icuzip :
861+         print  ' Extracting ICU source zip: %s'  %  localzip 
862+         icuzip .extractall (icu_parent_path )
863+   if  not  os .path .isdir (icu_full_path ):
864+     print  ' Cannot build Intl without ICU in %s.'  %  (icu_full_path )
865+     print  ' (Fix, or disable with "--with-intl=none" )' 
780866    sys .exit (1 )
867+   else :
868+     print  '* Using ICU in %s'  %  (icu_full_path )
781869  # Now, what version of ICU is it? We just need the "major", such as 54. 
782870  # uvernum.h contains it as a #define. 
783871  uvernum_h  =  os .path .join (icu_full_path , 'source/common/unicode/uvernum.h' )
784872  if  not  os .path .isfile (uvernum_h ):
785-     print  'Error: could not load %s - is ICU installed?'  %  uvernum_h 
873+     print  '  Error: could not load %s - is ICU installed?'  %  uvernum_h 
786874    sys .exit (1 )
787875  icu_ver_major  =  None 
788876  matchVerExp  =  r'^\s*#define\s+U_ICU_VERSION_SHORT\s+"([^"]*)".*' 
@@ -792,7 +880,7 @@ def configure_intl(o):
792880    if  m :
793881      icu_ver_major  =  m .group (1 )
794882  if  not  icu_ver_major :
795-     print  'Could not read U_ICU_VERSION_SHORT version from %s'  %  uvernum_h 
883+     print  '  Could not read U_ICU_VERSION_SHORT version from %s'  %  uvernum_h 
796884    sys .exit (1 )
797885  icu_endianness  =  sys .byteorder [0 ];  # TODO(srl295): EBCDIC should be 'e' 
798886  o ['variables' ]['icu_ver_major' ] =  icu_ver_major 
@@ -819,8 +907,8 @@ def configure_intl(o):
819907  # this is the icudt*.dat file which node will be using (platform endianness) 
820908  o ['variables' ]['icu_data_file' ] =  icu_data_file 
821909  if  not  os .path .isfile (icu_data_path ):
822-     print  'Error: ICU prebuilt data file %s does not exist.'  %  icu_data_path 
823-     print  'See the README.md.' 
910+     print  '  Error: ICU prebuilt data file %s does not exist.'  %  icu_data_path 
911+     print  '  See the README.md.' 
824912    # .. and we're not about to build it from .gyp! 
825913    sys .exit (1 )
826914  # map from variable name to subdirs 
0 commit comments