@@ -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