@@ -6,6 +6,9 @@ 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
@@ -244,7 +247,7 @@ parser.add_option('--with-icu-path',
244247parser .add_option ('--with-intl' ,
245248 action = 'store' ,
246249 dest = 'with_intl' ,
247- help = 'Intl mode: none, full-icu, small-icu (default is none )' )
250+ help = 'Intl mode: none, full-icu, small-icu (default is small-icu )' )
248251
249252parser .add_option ('--with-perfctr' ,
250253 action = 'store_true' ,
@@ -712,6 +715,57 @@ def glob_to_var(dir_base, dir_sub):
712715 return list
713716
714717def configure_intl (o ):
718+ class ConfigOpener (urllib .FancyURLopener ):
719+ # append to existing version (UA)
720+ version = '%s (node.js/configure)' % urllib .URLopener .version
721+ def icu_download (path ):
722+ # download ICU, if needed
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+ def fmtMb (amt ):
731+ return "{:.1f}" .format (amt / 1024000. )
732+ spin = "\\ |/-"
733+ def reporthook (count , size , total ):
734+ sys .stdout .write (' ICU: %c %sMB total, %sMB downloaded \r ' %
735+ (spin [count % 4 ], fmtMb (total ), fmtMb (count * size )))
736+ for icu in icus :
737+ url = icu ['url' ]
738+ md5 = icu ['md5' ]
739+ local = url .split ('/' )[- 1 ]
740+ targetfile = os .path .join (root_dir , 'deps' , local )
741+ if not os .path .isfile (targetfile ):
742+ try :
743+ sys .stdout .write (' <%s>\n Connecting...\r ' % url )
744+ sys .stdout .flush ()
745+ msg = urllib .urlretrieve (url , targetfile , reporthook = reporthook )
746+ print '' # clear the line
747+ except :
748+ print ' ** Error occurred while downloading\n <%s>' % url
749+ raise
750+ else :
751+ print ' Re-using existing %s' % targetfile
752+ if os .path .isfile (targetfile ):
753+ digest = hashlib .md5 ()
754+ count = 0
755+ sys .stdout .write (' Checking file integrity with MD5:\r ' )
756+ with open (targetfile , 'rb' ) as f :
757+ chunk = f .read (1024 )
758+ while chunk != "" :
759+ digest .update (chunk )
760+ chunk = f .read (1024 )
761+ gotmd5 = digest .hexdigest ()
762+ print ' MD5: %s %s' % (gotmd5 , targetfile )
763+ if (md5 == gotmd5 ):
764+ return targetfile
765+ else :
766+ print ' Expected: %s *MISMATCH*' % md5
767+ print '\n ** Corrupted ZIP? Delete %s to retry download.\n ' % targetfile
768+ return None
715769 icu_config = {
716770 'variables' : {}
717771 }
@@ -739,6 +793,8 @@ def configure_intl(o):
739793 o ['variables' ]['icu_gyp_path' ] = options .with_icu_path
740794 return
741795 # --with-intl=<with_intl>
796+ if with_intl is None :
797+ with_intl = 'small-icu' # The default mode
742798 if with_intl == 'none' or with_intl is None :
743799 o ['variables' ]['v8_enable_i18n_support' ] = 0
744800 return # no Intl
@@ -773,16 +829,28 @@ def configure_intl(o):
773829 byteorder = sys .byteorder
774830 o ['variables' ]['icu_gyp_path' ] = 'tools/icu/icu-generic.gyp'
775831 # ICU source dir relative to root
776- icu_full_path = os .path .join (root_dir , 'deps/icu' )
832+ icu_parent_path = os .path .join (root_dir , 'deps' )
833+ icu_full_path = os .path .join (icu_parent_path , 'icu' )
777834 o ['variables' ]['icu_path' ] = icu_full_path
778835 if not os .path .isdir (icu_full_path ):
779- print 'Error: ICU path is not a directory: %s' % (icu_full_path )
836+ print '* ECMA-402 (Intl) support didn\' t find ICU in %s..' % (icu_full_path )
837+ # can we download (or find) a zipfile?
838+ localzip = icu_download (icu_full_path )
839+ if localzip :
840+ with zipfile .ZipFile (localzip , 'r' ) as icuzip :
841+ print ' Extracting ICU source zip: %s' % localzip
842+ icuzip .extractall (icu_parent_path )
843+ if not os .path .isdir (icu_full_path ):
844+ print ' Cannot build Intl without ICU in %s.' % (icu_full_path )
845+ print ' (Fix, or disable with "--with-intl=none" )'
780846 sys .exit (1 )
847+ else :
848+ print '* Using ICU in %s' % (icu_full_path )
781849 # Now, what version of ICU is it? We just need the "major", such as 54.
782850 # uvernum.h contains it as a #define.
783851 uvernum_h = os .path .join (icu_full_path , 'source/common/unicode/uvernum.h' )
784852 if not os .path .isfile (uvernum_h ):
785- print 'Error: could not load %s - is ICU installed?' % uvernum_h
853+ print ' Error: could not load %s - is ICU installed?' % uvernum_h
786854 sys .exit (1 )
787855 icu_ver_major = None
788856 matchVerExp = r'^\s*#define\s+U_ICU_VERSION_SHORT\s+"([^"]*)".*'
@@ -792,7 +860,7 @@ def configure_intl(o):
792860 if m :
793861 icu_ver_major = m .group (1 )
794862 if not icu_ver_major :
795- print 'Could not read U_ICU_VERSION_SHORT version from %s' % uvernum_h
863+ print ' Could not read U_ICU_VERSION_SHORT version from %s' % uvernum_h
796864 sys .exit (1 )
797865 icu_endianness = sys .byteorder [0 ]; # TODO(srl295): EBCDIC should be 'e'
798866 o ['variables' ]['icu_ver_major' ] = icu_ver_major
@@ -819,8 +887,8 @@ def configure_intl(o):
819887 # this is the icudt*.dat file which node will be using (platform endianness)
820888 o ['variables' ]['icu_data_file' ] = icu_data_file
821889 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.'
890+ print ' Error: ICU prebuilt data file %s does not exist.' % icu_data_path
891+ print ' See the README.md.'
824892 # .. and we're not about to build it from .gyp!
825893 sys .exit (1 )
826894 # map from variable name to subdirs
0 commit comments