@@ -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
@@ -712,6 +720,56 @@ 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 reporthook (count , size , total ):
736+ sys .stdout .write (' ICU: %c %sMB total, %sMB downloaded \r ' %
737+ (nodedownload .spin (count ),
738+ nodedownload .formatSize (total ),
739+ nodedownload .formatSize (count * size )))
740+ for icu in icus :
741+ url = icu ['url' ]
742+ md5 = icu ['md5' ]
743+ local = url .split ('/' )[- 1 ]
744+ targetfile = os .path .join (root_dir , 'deps' , local )
745+ if not os .path .isfile (targetfile ):
746+ try :
747+ sys .stdout .write (' <%s>\n Connecting...\r ' % url )
748+ sys .stdout .flush ()
749+ msg = urllib .urlretrieve (url , targetfile , reporthook = reporthook )
750+ print '' # clear the line
751+ except :
752+ print ' ** Error occurred while downloading\n <%s>' % url
753+ raise
754+ else :
755+ print ' Re-using existing %s' % targetfile
756+ if os .path .isfile (targetfile ):
757+ digest = hashlib .md5 ()
758+ count = 0
759+ sys .stdout .write (' Checking file integrity with MD5:\r ' )
760+ with open (targetfile , 'rb' ) as f :
761+ chunk = f .read (1024 )
762+ while chunk != "" :
763+ digest .update (chunk )
764+ chunk = f .read (1024 )
765+ gotmd5 = digest .hexdigest ()
766+ print ' MD5: %s %s' % (gotmd5 , targetfile )
767+ if (md5 == gotmd5 ):
768+ return targetfile
769+ else :
770+ print ' Expected: %s *MISMATCH*' % md5
771+ print '\n ** Corrupted ZIP? Delete %s to retry download.\n ' % targetfile
772+ return None
715773 icu_config = {
716774 'variables' : {}
717775 }
@@ -723,7 +781,6 @@ def configure_intl(o):
723781 write (icu_config_name , do_not_edit +
724782 pprint .pformat (icu_config , indent = 2 ) + '\n ' )
725783
726- # small ICU is off by default.
727784 # always set icu_small, node.gyp depends on it being defined.
728785 o ['variables' ]['icu_small' ] = b (False )
729786
@@ -739,6 +796,8 @@ def configure_intl(o):
739796 o ['variables' ]['icu_gyp_path' ] = options .with_icu_path
740797 return
741798 # --with-intl=<with_intl>
799+ if with_intl is None :
800+ with_intl = 'none' # The default mode of Intl
742801 if with_intl == 'none' or with_intl is None :
743802 o ['variables' ]['v8_enable_i18n_support' ] = 0
744803 return # no Intl
@@ -769,20 +828,47 @@ def configure_intl(o):
769828 # Note: non-ICU implementations could use other 'with_intl'
770829 # values.
771830
831+ icu_parent_path = os .path .join (root_dir , 'deps' )
832+ icu_full_path = os .path .join (icu_parent_path , 'icu' )
833+ icu_small_path = os .path .join (icu_parent_path , 'icu-small' )
834+ icu_small_tag = os .path .join (icu_full_path , 'is-small-icu.txt' )
835+
836+ ## Use (or not) an embedded small-icu.
837+ if with_intl == 'small-icu' :
838+ if not os .path .isdir (icu_full_path ) and os .path .isdir (icu_small_path ):
839+ # deps/small-icu -> deps/icu
840+ print 'Copying small ICU %s to %s' % (icu_small_path , icu_full_path )
841+ shutil .copytree (icu_small_path , icu_full_path )
842+ #else:
843+ # print 'Not copying %s to %s' % (icu_small_path, icu_full_path)
844+ elif os .path .isfile (icu_small_tag ):
845+ print 'deleting small-icu %s for --with-intl=%s' % (icu_full_path , with_intl )
846+ shutil .rmtree (icu_full_path )
847+
772848 # ICU mode. (icu-generic.gyp)
773849 byteorder = sys .byteorder
774850 o ['variables' ]['icu_gyp_path' ] = 'tools/icu/icu-generic.gyp'
775851 # ICU source dir relative to root
776- icu_full_path = os .path .join (root_dir , 'deps/icu' )
777852 o ['variables' ]['icu_path' ] = icu_full_path
778853 if not os .path .isdir (icu_full_path ):
779- print 'Error: ICU path is not a directory: %s' % (icu_full_path )
854+ print '* ECMA-402 (Intl) support didn\' t find ICU in %s..' % (icu_full_path )
855+ # can we download (or find) a zipfile?
856+ localzip = icu_download (icu_full_path )
857+ if localzip :
858+ with zipfile .ZipFile (localzip , 'r' ) as icuzip :
859+ print ' Extracting ICU source zip: %s' % localzip
860+ icuzip .extractall (icu_parent_path )
861+ if not os .path .isdir (icu_full_path ):
862+ print ' Cannot build Intl without ICU in %s.' % (icu_full_path )
863+ print ' (Fix, or disable with "--with-intl=none" )'
780864 sys .exit (1 )
865+ else :
866+ print '* Using ICU in %s' % (icu_full_path )
781867 # Now, what version of ICU is it? We just need the "major", such as 54.
782868 # uvernum.h contains it as a #define.
783869 uvernum_h = os .path .join (icu_full_path , 'source/common/unicode/uvernum.h' )
784870 if not os .path .isfile (uvernum_h ):
785- print 'Error: could not load %s - is ICU installed?' % uvernum_h
871+ print ' Error: could not load %s - is ICU installed?' % uvernum_h
786872 sys .exit (1 )
787873 icu_ver_major = None
788874 matchVerExp = r'^\s*#define\s+U_ICU_VERSION_SHORT\s+"([^"]*)".*'
@@ -792,7 +878,7 @@ def configure_intl(o):
792878 if m :
793879 icu_ver_major = m .group (1 )
794880 if not icu_ver_major :
795- print 'Could not read U_ICU_VERSION_SHORT version from %s' % uvernum_h
881+ print ' Could not read U_ICU_VERSION_SHORT version from %s' % uvernum_h
796882 sys .exit (1 )
797883 icu_endianness = sys .byteorder [0 ]; # TODO(srl295): EBCDIC should be 'e'
798884 o ['variables' ]['icu_ver_major' ] = icu_ver_major
@@ -819,8 +905,8 @@ def configure_intl(o):
819905 # this is the icudt*.dat file which node will be using (platform endianness)
820906 o ['variables' ]['icu_data_file' ] = icu_data_file
821907 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.'
908+ print ' Error: ICU prebuilt data file %s does not exist.' % icu_data_path
909+ print ' See the README.md.'
824910 # .. and we're not about to build it from .gyp!
825911 sys .exit (1 )
826912 # map from variable name to subdirs
0 commit comments