aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile4
-rw-r--r--README.md91
-rwxr-xr-xconfigure137
-rw-r--r--test/simple/test-intl.js103
-rw-r--r--tools/configure.d/nodedownload.py127
-rw-r--r--tools/icu/icu-generic.gyp174
-rw-r--r--tools/icu/icu_small.json15
-rwxr-xr-xtools/icu/icutrim.py13
-rw-r--r--vcbuild.bat8
10 files changed, 616 insertions, 59 deletions
diff --git a/.gitignore b/.gitignore
index 6581dee9d1..9dda73b2e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,9 @@ ipch/
email.md
deps/v8-*
deps/icu
+deps/icu*.zip
+deps/icu*.tgz
+deps/icu-tmp
./node_modules
.svn/
diff --git a/Makefile b/Makefile
index f84c213449..e463280ac4 100644
--- a/Makefile
+++ b/Makefile
@@ -78,10 +78,12 @@ clean:
distclean:
-rm -rf out
- -rm -f config.gypi
+ -rm -f config.gypi icu_config.gypi
-rm -f config.mk
-rm -rf node node_g blog.html email.md
-rm -rf node_modules
+ -rm -rf deps/icu
+ -rm -rf deps/icu4c*.tgz deps/icu4c*.zip deps/icu-tmp
test: all
$(PYTHON) tools/test.py --mode=release simple message
diff --git a/README.md b/README.md
index 0032c63c07..acaf24b372 100644
--- a/README.md
+++ b/README.md
@@ -83,32 +83,105 @@ make doc
man doc/node.1
```
-### To build `Intl` (ECMA-402) support:
+### `Intl` (ECMA-402) support:
-*Note:* more docs, including how to reduce disk footprint, are on
+[Intl](https://github.com/joyent/node/wiki/Intl) support is not
+enabled by default.
+
+#### "small" (English only) support
+
+This option will build with "small" (English only) support, but
+the full `Intl` (ECMA-402) APIs. With `--download=all` it will
+download the ICU library as needed.
+
+Unix/Macintosh:
+
+```sh
+./configure --with-intl=small-icu --download=all
+```
+
+Windows:
+
+```sh
+vcbuild small-icu download-all
+```
+
+The `small-icu` mode builds
+with English-only data. You can add full data at runtime.
+
+*Note:* more docs are on
[the wiki](https://github.com/joyent/node/wiki/Intl).
-#### Use existing installed ICU (Unix/Macintosh only):
+#### Build with full ICU support (all locales supported by ICU):
+
+With the `--download=all`, this may download ICU if you don't
+have an ICU in `deps/icu`.
+
+Unix/Macintosh:
```sh
-pkg-config --modversion icu-i18n && ./configure --with-intl=system-icu
+./configure --with-intl=full-icu --download=all
```
-#### Build ICU from source:
+Windows:
-First: Unpack latest ICU
- [icu4c-**##.#**-src.tgz](http://icu-project.org/download) (or `.zip`)
- as `deps/icu` (You'll have: `deps/icu/source/...`)
+```sh
+vcbuild full-icu download-all
+```
+
+#### Build with no Intl support `:-(`
+
+The `Intl` object will not be available.
+This is the default at present, so this option is not normally needed.
Unix/Macintosh:
```sh
-./configure --with-intl=full-icu
+./configure --with-intl=none
```
Windows:
```sh
+vcbuild intl-none
+```
+
+#### Use existing installed ICU (Unix/Macintosh only):
+
+```sh
+pkg-config --modversion icu-i18n && ./configure --with-intl=system-icu
+```
+
+#### Build with a specific ICU:
+
+You can find other ICU releases at
+[the ICU homepage](http://icu-project.org/download).
+Download the file named something like `icu4c-**##.#**-src.tgz` (or
+`.zip`).
+
+Unix/Macintosh: from an already-unpacked ICU
+
+```sh
+./configure --with-intl=[small-icu,full-icu] --with-icu-source=/path/to/icu
+```
+
+Unix/Macintosh: from a local ICU tarball
+
+```sh
+./configure --with-intl=[small-icu,full-icu] --with-icu-source=/path/to/icu.tgz
+```
+
+Unix/Macintosh: from a tarball URL
+
+```sh
+./configure --with-intl=full-icu --with-icu-source=http://url/to/icu.tgz
+```
+
+Windows: first unpack latest ICU to `deps/icu`
+ [icu4c-**##.#**-src.tgz](http://icu-project.org/download) (or `.zip`)
+ as `deps/icu` (You'll have: `deps/icu/source/...`)
+
+```sh
vcbuild full-icu
```
diff --git a/configure b/configure
index c558f7f8dd..51475f0357 100755
--- a/configure
+++ b/configure
@@ -6,6 +6,8 @@ import re
import shlex
import subprocess
import sys
+import shutil
+import string
CC = os.environ.get('CC', 'cc')
@@ -13,6 +15,10 @@ root_dir = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(root_dir, 'tools', 'gyp', 'pylib'))
from gyp.common import GetFlavor
+# imports in tools/configure.d
+sys.path.insert(0, os.path.join(root_dir, 'tools', 'configure.d'))
+import nodedownload
+
# parse our options
parser = optparse.OptionParser()
@@ -236,16 +242,31 @@ parser.add_option('--with-etw',
dest='with_etw',
help='build with ETW (default is true on Windows)')
+parser.add_option('--download',
+ action='store',
+ dest='download_list',
+ help=nodedownload.help())
+
parser.add_option('--with-icu-path',
action='store',
dest='with_icu_path',
help='Path to icu.gyp (ICU i18n, Chromium version only.)')
+parser.add_option('--with-icu-locales',
+ action='store',
+ dest='with_icu_locales',
+ help='Comma-separated list of locales for "small-icu". Default: "root,en". "root" is assumed.')
+
parser.add_option('--with-intl',
action='store',
dest='with_intl',
help='Intl mode: none, full-icu, small-icu (default is none)')
+parser.add_option('--with-icu-source',
+ action='store',
+ dest='with_icu_source',
+ help='Intl mode: optional local path to icu/ dir, or path/URL of icu source archive.')
+
parser.add_option('--with-perfctr',
action='store_true',
dest='with_perfctr',
@@ -294,6 +315,8 @@ parser.add_option('--xcode',
(options, args) = parser.parse_args()
+# set up auto-download list
+auto_downloads = nodedownload.parse(options.download_list)
def b(value):
"""Returns the string 'true' if value is truthy, 'false' otherwise."""
@@ -712,6 +735,35 @@ def glob_to_var(dir_base, dir_sub):
return list
def configure_intl(o):
+ icus = [
+ {
+ 'url': 'http://download.icu-project.org/files/icu4c/54.1/icu4c-54_1-src.zip',
+ # from https://ssl.icu-project.org/files/icu4c/54.1/icu4c-src-54_1.md5:
+ 'md5': '6b89d60e2f0e140898ae4d7f72323bca',
+ },
+ ]
+ def icu_download(path):
+ # download ICU, if needed
+ for icu in icus:
+ url = icu['url']
+ md5 = icu['md5']
+ local = url.split('/')[-1]
+ targetfile = os.path.join(root_dir, 'deps', local)
+ if not os.path.isfile(targetfile):
+ if nodedownload.candownload(auto_downloads, "icu"):
+ nodedownload.retrievefile(url, targetfile)
+ else:
+ print ' Re-using existing %s' % targetfile
+ if os.path.isfile(targetfile):
+ sys.stdout.write(' Checking file integrity with MD5:\r')
+ gotmd5 = nodedownload.md5sum(targetfile)
+ print ' MD5: %s %s' % (gotmd5, targetfile)
+ if (md5 == gotmd5):
+ return targetfile
+ else:
+ print ' Expected: %s *MISMATCH*' % md5
+ print '\n ** Corrupted ZIP? Delete %s to retry download.\n' % targetfile
+ return None
icu_config = {
'variables': {}
}
@@ -723,11 +775,11 @@ def configure_intl(o):
write(icu_config_name, do_not_edit +
pprint.pformat(icu_config, indent=2) + '\n')
- # small ICU is off by default.
# always set icu_small, node.gyp depends on it being defined.
o['variables']['icu_small'] = b(False)
with_intl = options.with_intl
+ with_icu_source = options.with_icu_source
have_icu_path = bool(options.with_icu_path)
if have_icu_path and with_intl:
print 'Error: Cannot specify both --with-icu-path and --with-intl'
@@ -739,6 +791,13 @@ def configure_intl(o):
o['variables']['icu_gyp_path'] = options.with_icu_path
return
# --with-intl=<with_intl>
+ # set the default
+ if with_intl is None:
+ with_intl = 'none' # The default mode of Intl
+ # sanity check localelist
+ if options.with_icu_locales and (with_intl != 'small-icu'):
+ print 'Error: --with-icu-locales only makes sense with --with-intl=small-icu'
+ sys.exit(1)
if with_intl == 'none' or with_intl is None:
o['variables']['v8_enable_i18n_support'] = 0
return # no Intl
@@ -746,6 +805,12 @@ def configure_intl(o):
# small ICU (English only)
o['variables']['v8_enable_i18n_support'] = 1
o['variables']['icu_small'] = b(True)
+ with_icu_locales = options.with_icu_locales
+ if not with_icu_locales:
+ with_icu_locales = 'root,en'
+ locs = set(with_icu_locales.split(','))
+ locs.add('root') # must have root
+ o['variables']['icu_locales'] = string.join(locs,',')
elif with_intl == 'full-icu':
# full ICU
o['variables']['v8_enable_i18n_support'] = 1
@@ -769,20 +834,78 @@ def configure_intl(o):
# Note: non-ICU implementations could use other 'with_intl'
# values.
+ # this is just the 'deps' dir. Used for unpacking.
+ icu_parent_path = os.path.join(root_dir, 'deps')
+
+ # The full path to the ICU source directory.
+ icu_full_path = os.path.join(icu_parent_path, 'icu')
+
+ # icu-tmp is used to download and unpack the ICU tarball.
+ icu_tmp_path = os.path.join(icu_parent_path, 'icu-tmp')
+
+ # --with-icu-source processing
+ # first, check that they didn't pass --with-icu-source=deps/icu
+ if with_icu_source and os.path.abspath(icu_full_path) == os.path.abspath(with_icu_source):
+ print 'Ignoring redundant --with-icu-source=%s' % (with_icu_source)
+ with_icu_source = None
+ # if with_icu_source is still set, try to use it.
+ if with_icu_source:
+ if os.path.isdir(icu_full_path):
+ print 'Deleting old ICU source: %s' % (icu_full_path)
+ shutil.rmtree(icu_full_path)
+ # now, what path was given?
+ if os.path.isdir(with_icu_source):
+ # it's a path. Copy it.
+ print '%s -> %s' % (with_icu_source, icu_full_path)
+ shutil.copytree(with_icu_source, icu_full_path)
+ else:
+ # could be file or URL.
+ # Set up temporary area
+ if os.path.isdir(icu_tmp_path):
+ shutil.rmtree(icu_tmp_path)
+ os.mkdir(icu_tmp_path)
+ icu_tarball = None
+ if os.path.isfile(with_icu_source):
+ # it's a file. Try to unpack it.
+ icu_tarball = with_icu_source
+ else:
+ # Can we download it?
+ local = os.path.join(icu_tmp_path, with_icu_source.split('/')[-1]) # local part
+ icu_tarball = nodedownload.retrievefile(with_icu_source, local)
+ # continue with "icu_tarball"
+ nodedownload.unpack(icu_tarball, icu_tmp_path)
+ # Did it unpack correctly? Should contain 'icu'
+ tmp_icu = os.path.join(icu_tmp_path, 'icu')
+ if os.path.isdir(tmp_icu):
+ os.rename(tmp_icu, icu_full_path)
+ shutil.rmtree(icu_tmp_path)
+ else:
+ print ' Error: --with-icu-source=%s did not result in an "icu" dir.' % with_icu_source
+ shutil.rmtree(icu_tmp_path)
+ sys.exit(1)
+
# ICU mode. (icu-generic.gyp)
byteorder = sys.byteorder
o['variables']['icu_gyp_path'] = 'tools/icu/icu-generic.gyp'
# ICU source dir relative to root
- icu_full_path = os.path.join(root_dir, 'deps/icu')
o['variables']['icu_path'] = icu_full_path
if not os.path.isdir(icu_full_path):
- print 'Error: ICU path is not a directory: %s' % (icu_full_path)
+ print '* ECMA-402 (Intl) support didn\'t find ICU in %s..' % (icu_full_path)
+ # can we download (or find) a zipfile?
+ localzip = icu_download(icu_full_path)
+ if localzip:
+ nodedownload.unpack(localzip, icu_parent_path)
+ if not os.path.isdir(icu_full_path):
+ print ' Cannot build Intl without ICU in %s.' % (icu_full_path)
+ print ' (Fix, or disable with "--with-intl=none" )'
sys.exit(1)
+ else:
+ print '* Using ICU in %s' % (icu_full_path)
# Now, what version of ICU is it? We just need the "major", such as 54.
# uvernum.h contains it as a #define.
uvernum_h = os.path.join(icu_full_path, 'source/common/unicode/uvernum.h')
if not os.path.isfile(uvernum_h):
- print 'Error: could not load %s - is ICU installed?' % uvernum_h
+ print ' Error: could not load %s - is ICU installed?' % uvernum_h
sys.exit(1)
icu_ver_major = None
matchVerExp = r'^\s*#define\s+U_ICU_VERSION_SHORT\s+"([^"]*)".*'
@@ -792,7 +915,7 @@ def configure_intl(o):
if m:
icu_ver_major = m.group(1)
if not icu_ver_major:
- print 'Could not read U_ICU_VERSION_SHORT version from %s' % uvernum_h
+ print ' Could not read U_ICU_VERSION_SHORT version from %s' % uvernum_h
sys.exit(1)
icu_endianness = sys.byteorder[0]; # TODO(srl295): EBCDIC should be 'e'
o['variables']['icu_ver_major'] = icu_ver_major
@@ -819,8 +942,8 @@ def configure_intl(o):
# this is the icudt*.dat file which node will be using (platform endianness)
o['variables']['icu_data_file'] = icu_data_file
if not os.path.isfile(icu_data_path):
- print 'Error: ICU prebuilt data file %s does not exist.' % icu_data_path
- print 'See the README.md.'
+ print ' Error: ICU prebuilt data file %s does not exist.' % icu_data_path
+ print ' See the README.md.'
# .. and we're not about to build it from .gyp!
sys.exit(1)
# map from variable name to subdirs
diff --git a/test/simple/test-intl.js b/test/simple/test-intl.js
new file mode 100644
index 0000000000..841239a8d9
--- /dev/null
+++ b/test/simple/test-intl.js
@@ -0,0 +1,103 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+// does node think that i18n was enabled?
+var enablei18n = process.config.variables.v8_enable_i18n_support;
+if (enablei18n === undefined) {
+ enablei18n = false;
+}
+
+// is the Intl object present?
+var haveIntl = (global.Intl != undefined);
+
+// Returns true if no specific locale ids were configured (i.e. "all")
+// Else, returns true if loc is in the configured list
+// Else, returns false
+function haveLocale(loc) {
+ var locs = process.config.variables.icu_locales.split(',');
+ return locs.indexOf(loc) !== -1;
+}
+
+if (!haveIntl) {
+ var erMsg =
+ '"Intl" object is NOT present but v8_enable_i18n_support is ' +
+ enablei18n;
+ assert.equal(enablei18n, false, erMsg);
+ console.log('Skipping Intl tests because Intl object not present.');
+
+} else {
+ var erMsg =
+ '"Intl" object is present but v8_enable_i18n_support is ' +
+ enablei18n +
+ '. Is this test out of date?';
+ assert.equal(enablei18n, true, erMsg);
+
+ // Construct a new date at the beginning of Unix time
+ var date0 = new Date(0);
+
+ // Use the GMT time zone
+ var GMT = 'Etc/GMT';
+
+ // Construct an English formatter. Should format to "Jan 70"
+ var dtf =
+ new Intl.DateTimeFormat(['en'],
+ {timeZone: GMT, month: 'short', year: '2-digit'});
+
+ // If list is specified and doesn't contain 'en' then return.
+ if (process.config.variables.icu_locales && !haveLocale('en')) {
+ console.log('Skipping detailed Intl tests because English is not listed ' +
+ 'as supported.');
+ // Smoke test. Does it format anything, or fail?
+ console.log('Date(0) formatted to: ' + dtf.format(date0));
+ return;
+ }
+
+ // Check with toLocaleString
+ var localeString = dtf.format(date0);
+ assert.equal(localeString, 'Jan 70');
+
+ // Options to request GMT
+ var optsGMT = {timeZone: GMT};
+
+ // Test format
+ localeString = date0.toLocaleString(['en'], optsGMT);
+ assert.equal(localeString, '1/1/1970, 12:00:00 AM');
+
+ // number format
+ assert.equal(new Intl.NumberFormat(['en']).format(12345.67890), '12,345.679');
+
+ var collOpts = { sensitivity: 'base', ignorePunctuation: true };
+ var coll = new Intl.Collator(['en'], collOpts);
+
+ assert.equal(coll.compare('blackbird', 'black-bird'), 0,
+ 'ignore punctuation failed');
+ assert.equal(coll.compare('blackbird', 'red-bird'), -1,
+ 'compare less failed');
+ assert.equal(coll.compare('bluebird', 'blackbird'), 1,
+ 'compare greater failed');
+ assert.equal(coll.compare('Bluebird', 'bluebird'), 0,
+ 'ignore case failed');
+ assert.equal(coll.compare('\ufb03', 'ffi'), 0,
+ 'ffi ligature (contraction) failed');
+}
diff --git a/tools/configure.d/nodedownload.py b/tools/configure.d/nodedownload.py
new file mode 100644
index 0000000000..e24efd865f
--- /dev/null
+++ b/tools/configure.d/nodedownload.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+# Moved some utilities here from ../../configure
+
+import urllib
+import hashlib
+import sys
+import zipfile
+import tarfile
+import fpformat
+import contextlib
+
+def formatSize(amt):
+ """Format a size as a string in MB"""
+ return fpformat.fix(amt / 1024000., 1)
+
+def spin(c):
+ """print out an ASCII 'spinner' based on the value of counter 'c'"""
+ spin = ".:|'"
+ return (spin[c % len(spin)])
+
+class ConfigOpener(urllib.FancyURLopener):
+ """fancy opener used by retrievefile. Set a UA"""
+ # append to existing version (UA)
+ version = '%s node.js/configure' % urllib.URLopener.version
+
+def reporthook(count, size, total):
+ """internal hook used by retrievefile"""
+ sys.stdout.write(' Fetch: %c %sMB total, %sMB downloaded \r' %
+ (spin(count),
+ formatSize(total),
+ formatSize(count*size)))
+
+def retrievefile(url, targetfile):
+ """fetch file 'url' as 'targetfile'. Return targetfile or throw."""
+ try:
+ sys.stdout.write(' <%s>\nConnecting...\r' % url)
+ sys.stdout.flush()
+ msg = ConfigOpener().retrieve(url, targetfile, reporthook=reporthook)
+ print '' # clear the line
+ return targetfile
+ except:
+ print ' ** Error occurred while downloading\n <%s>' % url
+ raise
+
+def md5sum(targetfile):
+ """md5sum a file. Return the hex digest."""
+ digest = hashlib.md5()
+ with open(targetfile, 'rb') as f:
+ chunk = f.read(1024)
+ while chunk != "":
+ digest.update(chunk)
+ chunk = f.read(1024)
+ return digest.hexdigest()
+
+def unpack(packedfile, parent_path):
+ """Unpacks packedfile into parent_path. Assumes .zip. Returns parent_path"""
+ if zipfile.is_zipfile(packedfile):
+ with contextlib.closing(zipfile.ZipFile(packedfile, 'r')) as icuzip:
+ print ' Extracting zipfile: %s' % packedfile
+ icuzip.extractall(parent_path)
+ return parent_path
+ elif tarfile.is_tarfile(packedfile):
+ with tarfile.TarFile.open(packedfile, 'r') as icuzip:
+ print ' Extracting tarfile: %s' % packedfile
+ icuzip.extractall(parent_path)
+ return parent_path
+ else:
+ packedsuffix = packedfile.lower().split('.')[-1] # .zip, .tgz etc
+ raise Exception('Error: Don\'t know how to unpack %s with extension %s' % (packedfile, packedsuffix))
+
+# List of possible "--download=" types.
+download_types = set(['icu'])
+
+# Default options for --download.
+download_default = "none"
+
+def help():
+ """This function calculates the '--help' text for '--download'."""
+ return """Select which packages may be auto-downloaded.
+valid values are: none, all, %s. (default is "%s").""" % (", ".join(download_types), download_default)
+
+def set2dict(keys, value=None):
+ """Convert some keys (iterable) to a dict."""
+ return dict((key, value) for (key) in keys)
+
+def parse(opt):
+ """This function parses the options to --download and returns a set such as { icu: true }, etc. """
+ if not opt:
+ opt = download_default
+
+ theOpts = set(opt.split(','))
+
+ if 'all' in theOpts:
+ # all on
+ return set2dict(download_types, True)
+ elif 'none' in theOpts:
+ # all off
+ return set2dict(download_types, False)
+
+ # OK. Now, process each of the opts.
+ theRet = set2dict(download_types, False)
+ for anOpt in opt.split(','):
+ if not anOpt or anOpt == "":
+ # ignore stray commas, etc.
+ continue
+ elif anOpt is 'all':
+ # all on
+ theRet = dict((key, True) for (key) in download_types)
+ else:
+ # turn this one on
+ if anOpt in download_types:
+ theRet[anOpt] = True
+ else:
+ # future proof: ignore unknown types
+ print 'Warning: ignoring unknown --download= type "%s"' % anOpt
+ # all done
+ return theRet
+
+def candownload(auto_downloads, package):
+ if not (package in auto_downloads.keys()):
+ raise Exception('Internal error: "%s" is not in the --downloads list. Check nodedownload.py' % package)
+ if auto_downloads[package]:
+ return True
+ else:
+ print """Warning: Not downloading package "%s". You could pass "--download=all"
+ (Windows: "download-all") to try auto-downloading it.""" % package
+ return False
diff --git a/tools/icu/icu-generic.gyp b/tools/icu/icu-generic.gyp
index 220d2c16a6..bb2b5e5e4d 100644
--- a/tools/icu/icu-generic.gyp
+++ b/tools/icu/icu-generic.gyp
@@ -12,6 +12,17 @@
'includes': [ '../../icu_config.gypi' ],
'targets': [
{
+ # a target for additional uconfig defines, target only
+ 'target_name': 'icu_uconfig_target',
+ 'type': 'none',
+ 'toolsets': [ 'target' ],
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'UCONFIG_NO_CONVERSION=1',
+ ]
+ },
+ },
+ {
# a target to hold uconfig defines.
# for now these are hard coded, but could be defined.
'target_name': 'icu_uconfig',
@@ -92,24 +103,74 @@
},
{
'target_name': 'icui18n',
- 'type': '<(library)',
- 'toolsets': [ 'target' ],
- 'sources': [
- '<@(icu_src_i18n)'
- ],
- 'include_dirs': [
- '../../deps/icu/source/i18n',
- ],
- 'defines': [
- 'U_I18N_IMPLEMENTATION=1',
+ 'toolsets': [ 'target', 'host' ],
+ 'conditions' : [
+ ['_toolset=="target"', {
+ 'type': '<(library)',
+ 'sources': [
+ '<@(icu_src_i18n)'
+ ],
+ 'conditions': [
+ [ 'icu_ver_major == 54', { 'sources!': [
+ ## Strip out the following for ICU 54 only.
+ ## add more conditions in the future?
+ ## if your compiler can dead-strip, this will
+ ## make ZERO difference to binary size.
+ ## Made ICU-specific for future-proofing.
+
+ # alphabetic index
+ '../../deps/icu/source/i18n/alphaindex.cpp',
+ # BOCSU
+ # misc
+ '../../deps/icu/source/i18n/regexcmp.cpp',
+ '../../deps/icu/source/i18n/regexcmp.h',
+ '../../deps/icu/source/i18n/regexcst.h',
+ '../../deps/icu/source/i18n/regeximp.cpp',
+ '../../deps/icu/source/i18n/regeximp.h',
+ '../../deps/icu/source/i18n/regexst.cpp',
+ '../../deps/icu/source/i18n/regexst.h',
+ '../../deps/icu/source/i18n/regextxt.cpp',
+ '../../deps/icu/source/i18n/regextxt.h',
+ '../../deps/icu/source/i18n/region.cpp',
+ '../../deps/icu/source/i18n/region_impl.h',
+ '../../deps/icu/source/i18n/reldatefmt.cpp',
+ '../../deps/icu/source/i18n/reldatefmt.h'
+ '../../deps/icu/source/i18n/scientificformathelper.cpp',
+ '../../deps/icu/source/i18n/tmunit.cpp',
+ '../../deps/icu/source/i18n/tmutamt.cpp',
+ '../../deps/icu/source/i18n/tmutfmt.cpp',
+ '../../deps/icu/source/i18n/uregex.cpp',
+ '../../deps/icu/source/i18n/uregexc.cpp',
+ '../../deps/icu/source/i18n/uregion.cpp',
+ '../../deps/icu/source/i18n/uspoof.cpp',
+ '../../deps/icu/source/i18n/uspoof_build.cpp',
+ '../../deps/icu/source/i18n/uspoof_conf.cpp',
+ '../../deps/icu/source/i18n/uspoof_conf.h',
+ '../../deps/icu/source/i18n/uspoof_impl.cpp',
+ '../../deps/icu/source/i18n/uspoof_impl.h',
+ '../../deps/icu/source/i18n/uspoof_wsconf.cpp',
+ '../../deps/icu/source/i18n/uspoof_wsconf.h',
+ ]}]],
+ 'include_dirs': [
+ '../../deps/icu/source/i18n',
+ ],
+ 'defines': [
+ 'U_I18N_IMPLEMENTATION=1',
+ ],
+ 'dependencies': [ 'icuucx', 'icu_implementation', 'icu_uconfig', 'icu_uconfig_target' ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../../deps/icu/source/i18n',
+ ],
+ },
+ 'export_dependent_settings': [ 'icuucx', 'icu_uconfig_target' ],
+ }],
+ ['_toolset=="host"', {
+ 'type': 'none',
+ 'dependencies': [ 'icutools' ],
+ 'export_dependent_settings': [ 'icutools' ],
+ }],
],
- 'dependencies': [ 'icuucx', 'icu_implementation', 'icu_uconfig' ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '../../deps/icu/source/i18n',
- ],
- },
- 'export_dependent_settings': [ 'icuucx' ],
},
# This exports actual ICU data
{
@@ -146,32 +207,33 @@
# trim down ICU
'action_name': 'icutrim',
'inputs': [ '<(icu_data_in)', 'icu_small.json' ],
- 'outputs': [ '../../out/icutmp/icudt<(icu_ver_major)<(icu_endianness).dat' ],
+ 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/icutmp/icudt<(icu_ver_major)<(icu_endianness).dat' ],
'action': [ 'python',
'icutrim.py',
'-P', '../../<(CONFIGURATION_NAME)',
'-D', '<(icu_data_in)',
'--delete-tmp',
- '-T', '../../out/icutmp',
+ '-T', '<(SHARED_INTERMEDIATE_DIR)/icutmp',
'-F', 'icu_small.json',
'-O', 'icudt<(icu_ver_major)<(icu_endianness).dat',
- '-v' ],
+ '-v',
+ '-L', '<(icu_locales)'],
},
{
# build final .dat -> .obj
'action_name': 'genccode',
- 'inputs': [ '../../out/icutmp/icudt<(icu_ver_major)<(icu_endianness).dat' ],
- 'outputs': [ '../../out/icudt<(icu_ver_major)<(icu_endianness)_dat.obj' ],
+ 'inputs': [ '<(SHARED_INTERMEDIATE_DIR)/icutmp/icudt<(icu_ver_major)<(icu_endianness).dat' ],
+ 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/icudt<(icu_ver_major)<(icu_endianness)_dat.obj' ],
'action': [ '../../<(CONFIGURATION_NAME)/genccode',
'-o',
- '-d', '../../out/',
+ '-d', '<(SHARED_INTERMEDIATE_DIR)/',
'-n', 'icudata',
'-e', 'icusmdt<(icu_ver_major)',
'<@(_inputs)' ],
},
],
# This file contains the small ICU data.
- 'sources': [ '../../out/icudt<(icu_ver_major)<(icu_endianness)_dat.obj' ],
+ 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/icudt<(icu_ver_major)<(icu_endianness)_dat.obj' ],
} ] ], #end of OS==win and icu_small == true
}, { # OS != win
'conditions': [
@@ -235,7 +297,8 @@
'-T', '<(SHARED_INTERMEDIATE_DIR)/icutmp',
'-F', 'icu_small.json',
'-O', 'icudt<(icu_ver_major)<(icu_endianness).dat',
- '-v' ],
+ '-v',
+ '-L', '<(icu_locales)'],
}, {
# rename to get the final entrypoint name right
'action_name': 'rename',
@@ -284,19 +347,51 @@
{
'target_name': 'icuuc',
'type': 'none',
- 'toolsets': [ 'target' ],
- 'dependencies': [ 'icuucx', 'icudata' ],
- 'export_dependent_settings': [ 'icuucx', 'icudata' ],
+ 'toolsets': [ 'target', 'host' ],
+ 'conditions' : [
+ ['_toolset=="host"', {
+ 'dependencies': [ 'icutools' ],
+ 'export_dependent_settings': [ 'icutools' ],
+ }],
+ ['_toolset=="target"', {
+ 'dependencies': [ 'icuucx', 'icudata' ],
+ 'export_dependent_settings': [ 'icuucx', 'icudata' ],
+ }],
+ ],
},
# This is the 'real' icuuc.
- # tools can depend on 'icuuc + stubdata'
{
'target_name': 'icuucx',
'type': '<(library)',
- 'dependencies': [ 'icu_implementation', 'icu_uconfig' ],
+ 'dependencies': [ 'icu_implementation', 'icu_uconfig', 'icu_uconfig_target' ],
'toolsets': [ 'target' ],
'sources': [
- '<@(icu_src_common)'
+ '<@(icu_src_common)',
+ ],
+ 'conditions': [
+ [ 'icu_ver_major == 54', { 'sources!': [
+ ## Strip out the following for ICU 54 only.
+ ## add more conditions in the future?
+ ## if your compiler can dead-strip, this will
+ ## make ZERO difference to binary size.
+ ## Made ICU-specific for future-proofing.
+
+ # bidi- not needed (yet!)
+ '../../deps/icu/source/common/ubidi.c',
+ '../../deps/icu/source/common/ubidiimp.h',
+ '../../deps/icu/source/common/ubidiln.c',
+ '../../deps/icu/source/common/ubidiwrt.c',
+ #'../../deps/icu/source/common/ubidi_props.c',
+ #'../../deps/icu/source/common/ubidi_props.h',
+ #'../../deps/icu/source/common/ubidi_props_data.h',
+ # and the callers
+ '../../deps/icu/source/common/ushape.cpp',
+ '../../deps/icu/source/common/usprep.cpp',
+ '../../deps/icu/source/common/uts46.cpp',
+ ]}],
+ [ 'OS == "solaris"', { 'defines': [
+ '_XOPEN_SOURCE_EXTENDED=0',
+ ]}],
],
'include_dirs': [
'../../deps/icu/source/common',
@@ -304,7 +399,8 @@
'defines': [
'U_COMMON_IMPLEMENTATION=1',
],
- 'export_dependent_settings': [ 'icu_uconfig' ],
+ 'cflags_c': ['-std=c99'],
+ 'export_dependent_settings': [ 'icu_uconfig', 'icu_uconfig_target' ],
'direct_dependent_settings': {
'include_dirs': [
'../../deps/icu/source/common',
@@ -331,6 +427,12 @@
'<@(icu_src_io)',
'<@(icu_src_stubdata)',
],
+ 'sources!': [
+ '../../deps/icu/source/tools/toolutil/udbgutil.cpp',
+ '../../deps/icu/source/tools/toolutil/udbgutil.h',
+ '../../deps/icu/source/tools/toolutil/dbgutil.cpp',
+ '../../deps/icu/source/tools/toolutil/dbgutil.h',
+ ],
'include_dirs': [
'../../deps/icu/source/common',
'../../deps/icu/source/i18n',
@@ -344,6 +446,12 @@
'U_TOOLUTIL_IMPLEMENTATION=1',
#'DEBUG=0', # http://bugs.icu-project.org/trac/ticket/10977
],
+ 'cflags_c': ['-std=c99'],
+ 'conditions': [
+ ['OS == "solaris"', {
+ 'defines': [ '_XOPEN_SOURCE_EXTENDED=0' ]
+ }]
+ ],
'direct_dependent_settings': {
'include_dirs': [
'../../deps/icu/source/common',
@@ -359,7 +467,7 @@
}],
],
},
- 'export_dependent_settings': [ 'icu_implementation', 'icu_uconfig' ],
+ 'export_dependent_settings': [ 'icu_uconfig' ],
},
# This tool is needed to rebuild .res files from .txt,
# or to build index (res_index.txt) files for small-icu
diff --git a/tools/icu/icu_small.json b/tools/icu/icu_small.json
index ddf7d1204e..e434794e91 100644
--- a/tools/icu/icu_small.json
+++ b/tools/icu/icu_small.json
@@ -1,11 +1,11 @@
{
"copyright": "Copyright (c) 2014 IBM Corporation and Others. All Rights Reserved.",
- "comment": "icutrim.py config: Trim down ICU to just English, needed for node.js use.",
+ "comment": "icutrim.py config: Trim down ICU to just a certain locale set, needed for node.js use.",
"variables": {
"none": {
"only": []
},
- "en_only": {
+ "locales": {
"only": [
"root",
"en"
@@ -15,20 +15,21 @@
}
},
"trees": {
- "ROOT": "en_only",
+ "ROOT": "locales",
"brkitr": "none",
- "coll": "en_only",
- "curr": "en_only",
+ "coll": "locales",
+ "curr": "locales",
"lang": "none",
"rbnf": "none",
"region": "none",
- "zone": "en_only",
+ "zone": "locales",
"converters": "none",
"stringprep": "none",
"translit": "none",
"brkfiles": "none",
"brkdict": "none",
- "confusables": "none"
+ "confusables": "none",
+ "unit": "none"
},
"remove": [
"cnvalias.icu",
diff --git a/tools/icu/icutrim.py b/tools/icu/icutrim.py
index 7f0fb3752e..517bf39bad 100755
--- a/tools/icu/icutrim.py
+++ b/tools/icu/icutrim.py
@@ -65,6 +65,12 @@ parser.add_option("-v","--verbose",
action="count",
default=0)
+parser.add_option('-L',"--locales",
+ action="store",
+ dest="locales",
+ help="sets the 'locales.only' variable",
+ default=None)
+
parser.add_option('-e', '--endian', action='store', dest='endian', help='endian, big, little or host, your default is "%s".' % endian, default=endian, metavar='endianness')
(options, args) = parser.parse_args()
@@ -147,6 +153,13 @@ fi= open(options.filterfile, "rb")
config=json.load(fi)
fi.close()
+if (options.locales):
+ if not config.has_key("variables"):
+ config["variables"] = {}
+ if not config["variables"].has_key("locales"):
+ config["variables"]["locales"] = {}
+ config["variables"]["locales"]["only"] = options.locales.split(',')
+
if (options.verbose > 6):
print config
diff --git a/vcbuild.bat b/vcbuild.bat
index 616b5bb114..39c656f187 100644
--- a/vcbuild.bat
+++ b/vcbuild.bat
@@ -36,6 +36,7 @@ set noperfctr=
set noperfctr_arg=
set noperfctr_msi_arg=
set i18n_arg=
+set download_arg=
:next-arg
if "%1"=="" goto args-done
@@ -65,6 +66,8 @@ if /i "%1"=="upload" set upload=1&goto arg-ok
if /i "%1"=="jslint" set jslint=1&goto arg-ok
if /i "%1"=="small-icu" set i18n_arg=%1&goto arg-ok
if /i "%1"=="full-icu" set i18n_arg=%1&goto arg-ok
+if /i "%1"=="intl-none" set i18n_arg=%1&goto arg-ok
+if /i "%1"=="download-all" set download_arg="--download=all"&goto arg-ok
echo Warning: ignoring invalid command line option `%1`.
@@ -85,6 +88,7 @@ if defined noperfctr set noperfctr_arg=--without-perfctr& set noperfctr_msi_arg=
if "%i18n_arg%"=="full-icu" set i18n_arg=--with-intl=full-icu
if "%i18n_arg%"=="small-icu" set i18n_arg=--with-intl=small-icu
+if "%i18n_arg%"=="intl-none" set i18n_arg=--with-intl=none
:project-gen
@rem Skip project generation if requested.
@@ -95,7 +99,7 @@ if defined NIGHTLY set TAG=nightly-%NIGHTLY%
@rem Generate the VS project.
SETLOCAL
if defined VS100COMNTOOLS call "%VS100COMNTOOLS%\VCVarsQueryRegistry.bat"
- python configure %i18n_arg% %debug_arg% %nosnapshot_arg% %noetw_arg% %noperfctr_arg% --dest-cpu=%target_arch% --tag=%TAG%
+ python configure %download_arg% %i18n_arg% %debug_arg% %nosnapshot_arg% %noetw_arg% %noperfctr_arg% --dest-cpu=%target_arch% --tag=%TAG%
if errorlevel 1 goto create-msvs-files-failed
if not exist node.sln goto create-msvs-files-failed
echo Project files generated.
@@ -232,7 +236,7 @@ python tools/closure_linter/closure_linter/gjslint.py --unix_mode --strict --noj
goto exit
:help
-echo vcbuild.bat [debug/release] [msi] [test-all/test-uv/test-internet/test-pummel/test-simple/test-message] [clean] [noprojgen] [nobuild] [nosign] [x86/x64]
+echo vcbuild.bat [debug/release] [msi] [test-all/test-uv/test-internet/test-pummel/test-simple/test-message] [clean] [noprojgen] [small-icu/full-icu/intl-none] [nobuild] [nosign] [x86/x64] [download-all]
echo Examples:
echo vcbuild.bat : builds release build
echo vcbuild.bat debug : builds debug build