@@ -6,13 +6,21 @@ import re
6
6
import shlex
7
7
import subprocess
8
8
import sys
9
+ import urllib
10
+ import zipfile
11
+ import hashlib
12
+ import shutil
9
13
10
14
CC = os .environ .get ('CC' , 'cc' )
11
15
12
16
root_dir = os .path .dirname (__file__ )
13
17
sys .path .insert (0 , os .path .join (root_dir , 'tools' , 'gyp' , 'pylib' ))
14
18
from gyp .common import GetFlavor
15
19
20
+ # imports in tools/configure.d
21
+ sys .path .insert (0 , os .path .join (root_dir , 'tools' , 'configure.d' ))
22
+ import nodedownload
23
+
16
24
# parse our options
17
25
parser = optparse .OptionParser ()
18
26
@@ -712,6 +720,56 @@ def glob_to_var(dir_base, dir_sub):
712
720
return list
713
721
714
722
def 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
715
773
icu_config = {
716
774
'variables' : {}
717
775
}
@@ -723,7 +781,6 @@ def configure_intl(o):
723
781
write (icu_config_name , do_not_edit +
724
782
pprint .pformat (icu_config , indent = 2 ) + '\n ' )
725
783
726
- # small ICU is off by default.
727
784
# always set icu_small, node.gyp depends on it being defined.
728
785
o ['variables' ]['icu_small' ] = b (False )
729
786
@@ -739,6 +796,8 @@ def configure_intl(o):
739
796
o ['variables' ]['icu_gyp_path' ] = options .with_icu_path
740
797
return
741
798
# --with-intl=<with_intl>
799
+ if with_intl is None :
800
+ with_intl = 'none' # The default mode of Intl
742
801
if with_intl == 'none' or with_intl is None :
743
802
o ['variables' ]['v8_enable_i18n_support' ] = 0
744
803
return # no Intl
@@ -769,20 +828,47 @@ def configure_intl(o):
769
828
# Note: non-ICU implementations could use other 'with_intl'
770
829
# values.
771
830
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
+
772
848
# ICU mode. (icu-generic.gyp)
773
849
byteorder = sys .byteorder
774
850
o ['variables' ]['icu_gyp_path' ] = 'tools/icu/icu-generic.gyp'
775
851
# ICU source dir relative to root
776
- icu_full_path = os .path .join (root_dir , 'deps/icu' )
777
852
o ['variables' ]['icu_path' ] = icu_full_path
778
853
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" )'
780
864
sys .exit (1 )
865
+ else :
866
+ print '* Using ICU in %s' % (icu_full_path )
781
867
# Now, what version of ICU is it? We just need the "major", such as 54.
782
868
# uvernum.h contains it as a #define.
783
869
uvernum_h = os .path .join (icu_full_path , 'source/common/unicode/uvernum.h' )
784
870
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
786
872
sys .exit (1 )
787
873
icu_ver_major = None
788
874
matchVerExp = r'^\s*#define\s+U_ICU_VERSION_SHORT\s+"([^"]*)".*'
@@ -792,7 +878,7 @@ def configure_intl(o):
792
878
if m :
793
879
icu_ver_major = m .group (1 )
794
880
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
796
882
sys .exit (1 )
797
883
icu_endianness = sys .byteorder [0 ]; # TODO(srl295): EBCDIC should be 'e'
798
884
o ['variables' ]['icu_ver_major' ] = icu_ver_major
@@ -819,8 +905,8 @@ def configure_intl(o):
819
905
# this is the icudt*.dat file which node will be using (platform endianness)
820
906
o ['variables' ]['icu_data_file' ] = icu_data_file
821
907
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.'
824
910
# .. and we're not about to build it from .gyp!
825
911
sys .exit (1 )
826
912
# map from variable name to subdirs
0 commit comments