@@ -6,13 +6,20 @@ import re
66import  shlex 
77import  subprocess 
88import  sys 
9+ import  urllib 
10+ import  zipfile 
11+ import  hashlib 
912
1013CC  =  os .environ .get ('CC' , 'cc' )
1114
1215root_dir  =  os .path .dirname (__file__ )
1316sys .path .insert (0 , os .path .join (root_dir , 'tools' , 'gyp' , 'pylib' ))
1417from  gyp .common  import  GetFlavor 
1518
19+ # imports in tools/configure.d 
20+ sys .path .insert (0 , os .path .join (root_dir , 'tools' , 'configure.d' ))
21+ import  nodedownload 
22+ 
1623# parse our options 
1724parser  =  optparse .OptionParser ()
1825
@@ -244,7 +251,7 @@ parser.add_option('--with-icu-path',
244251parser .add_option ('--with-intl' ,
245252    action = 'store' ,
246253    dest = 'with_intl' ,
247-     help = 'Intl mode: none, full-icu, small-icu (default is none )' )
254+     help = 'Intl mode: none, full-icu, small-icu (default is small-icu )' )
248255
249256parser .add_option ('--with-perfctr' ,
250257    action = 'store_true' ,
@@ -712,6 +719,58 @@ def glob_to_var(dir_base, dir_sub):
712719  return  list 
713720
714721def  configure_intl (o ):
722+   icus  =  [
723+     {
724+       'url' : 'http://download.icu-project.org/files/icu4c/54.1/icu4c-54_1-src.zip' ,
725+       # from https://ssl.icu-project.org/files/icu4c/54.1/icu4c-src-54_1.md5: 
726+       'md5' : '6b89d60e2f0e140898ae4d7f72323bca' ,
727+     },
728+   ]
729+   class  ConfigOpener (urllib .FancyURLopener ):
730+     # append to existing version (UA) 
731+     version  =  '%s (node.js/configure)'  %  urllib .URLopener .version 
732+   def  icu_download (path ):
733+     # download ICU, if needed 
734+     def  fmtMb (amt ):
735+       return  "{:.1f}" .format (amt  /  1024000. )
736+     def  reporthook (count , size , total ):
737+       sys .stdout .write (' ICU: %c %sMB total, %sMB downloaded   \r '  % 
738+                        (nodedownload .spin (count ),
739+                         nodedownload .formatSize (total ),
740+                         nodedownload .formatSize (count * size )))
741+     for  icu  in  icus :
742+       url  =  icu ['url' ]
743+       md5  =  icu ['md5' ]
744+       local  =  url .split ('/' )[- 1 ]
745+       targetfile  =  os .path .join (root_dir , 'deps' , local )
746+       if  not  os .path .isfile (targetfile ):
747+         try :
748+           sys .stdout .write (' <%s>\n Connecting...\r '  %  url )
749+           sys .stdout .flush ()
750+           msg  =  urllib .urlretrieve (url , targetfile , reporthook = reporthook )
751+           print  ''   # clear the line 
752+         except :
753+           print  ' ** Error occurred while downloading\n  <%s>'  %  url 
754+           raise 
755+       else :
756+         print  ' Re-using existing %s'  %  targetfile 
757+       if  os .path .isfile (targetfile ):
758+         digest  =  hashlib .md5 ()
759+         count  =  0 
760+         sys .stdout .write (' Checking file integrity with MD5:\r ' )
761+         with  open (targetfile , 'rb' ) as  f :
762+           chunk  =  f .read (1024 )
763+           while  chunk  !=   "" :
764+             digest .update (chunk )
765+             chunk  =  f .read (1024 )
766+         gotmd5  =  digest .hexdigest ()
767+         print  ' MD5:      %s  %s'  %  (gotmd5 , targetfile )
768+         if  (md5  ==  gotmd5 ):
769+           return  targetfile 
770+         else :
771+           print  ' Expected: %s      *MISMATCH*'  %  md5 
772+           print  '\n  ** Corrupted ZIP? Delete %s to retry download.\n '  %  targetfile 
773+     return  None 
715774  icu_config  =  {
716775    'variables' : {}
717776  }
@@ -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 
742803  if  with_intl  ==  'none'  or  with_intl  is  None :
743804    o ['variables' ]['v8_enable_i18n_support' ] =  0 
744805    return   # no Intl 
@@ -773,16 +834,28 @@ def configure_intl(o):
773834  byteorder  =  sys .byteorder 
774835  o ['variables' ]['icu_gyp_path' ] =  'tools/icu/icu-generic.gyp' 
775836  # ICU source dir relative to root 
776-   icu_full_path  =  os .path .join (root_dir , 'deps/icu' )
837+   icu_parent_path  =  os .path .join (root_dir , 'deps' )
838+   icu_full_path  =  os .path .join (icu_parent_path , 'icu' )
777839  o ['variables' ]['icu_path' ] =  icu_full_path 
778840  if  not  os .path .isdir (icu_full_path ):
779-     print  'Error: ICU path is not a directory: %s'  %  (icu_full_path )
841+     print  '* ECMA-402 (Intl) support didn\' t find ICU in %s..'  %  (icu_full_path )
842+     # can we download (or find) a zipfile? 
843+     localzip  =  icu_download (icu_full_path )
844+     if  localzip :
845+       with  zipfile .ZipFile (localzip , 'r' ) as  icuzip :
846+         print  ' Extracting ICU source zip: %s'  %  localzip 
847+         icuzip .extractall (icu_parent_path )
848+   if  not  os .path .isdir (icu_full_path ):
849+     print  ' Cannot build Intl without ICU in %s.'  %  (icu_full_path )
850+     print  ' (Fix, or disable with "--with-intl=none" )' 
780851    sys .exit (1 )
852+   else :
853+     print  '* Using ICU in %s'  %  (icu_full_path )
781854  # Now, what version of ICU is it? We just need the "major", such as 54. 
782855  # uvernum.h contains it as a #define. 
783856  uvernum_h  =  os .path .join (icu_full_path , 'source/common/unicode/uvernum.h' )
784857  if  not  os .path .isfile (uvernum_h ):
785-     print  'Error: could not load %s - is ICU installed?'  %  uvernum_h 
858+     print  '  Error: could not load %s - is ICU installed?'  %  uvernum_h 
786859    sys .exit (1 )
787860  icu_ver_major  =  None 
788861  matchVerExp  =  r'^\s*#define\s+U_ICU_VERSION_SHORT\s+"([^"]*)".*' 
@@ -792,7 +865,7 @@ def configure_intl(o):
792865    if  m :
793866      icu_ver_major  =  m .group (1 )
794867  if  not  icu_ver_major :
795-     print  'Could not read U_ICU_VERSION_SHORT version from %s'  %  uvernum_h 
868+     print  '  Could not read U_ICU_VERSION_SHORT version from %s'  %  uvernum_h 
796869    sys .exit (1 )
797870  icu_endianness  =  sys .byteorder [0 ];  # TODO(srl295): EBCDIC should be 'e' 
798871  o ['variables' ]['icu_ver_major' ] =  icu_ver_major 
@@ -819,8 +892,8 @@ def configure_intl(o):
819892  # this is the icudt*.dat file which node will be using (platform endianness) 
820893  o ['variables' ]['icu_data_file' ] =  icu_data_file 
821894  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.' 
895+     print  '  Error: ICU prebuilt data file %s does not exist.'  %  icu_data_path 
896+     print  '  See the README.md.' 
824897    # .. and we're not about to build it from .gyp! 
825898    sys .exit (1 )
826899  # map from variable name to subdirs 
0 commit comments