Browse Source

build: i18n: add icu config options

Make "--with-intl=none" the default and add "intl-none" option to
vcbuild.bat.

If icu data is missing print a warning unless either --download=all or
--download=icu is set. If set then automatically download, verify (MD5)
and unpack the ICU data if not already available.

There's a "list" of URLs being used, but right now only the first is
picked up. The logic works something like this:

* If there is no directory deps/icu,
  * If no zip file (currently icu4c-54_1-src.zip),
    * Download zip file (icu-project.org -> sf.net)
  * Verify the MD5 sum of the zipfile
    * If bad, print error and exit
  * Unpack the zipfile into deps/icu
* If deps/icu now exists, use it, else fail with help text

Add the configuration option "--with-icu-source=..."

Usage:
  * --with-icu-source=/path/to/my/other/icu
  * --with-icu-source=/path/to/icu54.zip
  * --with-icu-source=/path/to/icu54.tgz
  * --with-icu-source=http://example.com/icu54.tar.bz2

Add the configuration option "--with-icu-locals=...".  Allows choosing
which locales are used in the "small-icu" case.

Example:
    configure --with-intl=small-icu --with-icu-locales=tlh,grc,nl

(Also note that as of this writing, neither Klingon nor Ancient Greek
are in upstream CLDR data. Serving suggestion only.)

Don't use hard coded ../../out paths on windows. This was suggested by
@misterdjules as it causes test failures.  With this fix, "out" is no
longer created on windows and the following can run properly:

    python tools/test.py simple

Reduce space by about 1MB with ICU 54 (over without this patch). Also
trims a few other source files, but only conditional on the exact ICU
version used. This is to future-proof - a file that is unneeded now may
be needed in future ICUs.

Also:
  * Update distclean to remove icu related files
  * Refactor some code into tools/configure.d/nodedownload.py
  * Update docs
  * Add test

PR-URL: https://github.com/joyent/node/pull/8719
Fixes: https://github.com/joyent/node/issues/7676#issuecomment-64704230
[trev.norris@gmail.com small change to test's whitespace and logic]
Signed-off-by: Trevor Norris <trev.norris@gmail.com>
v0.11.15-release
Steven R. Loomis 10 years ago
committed by Trevor Norris
parent
commit
a30839576c
  1. 3
      .gitignore
  2. 4
      Makefile
  3. 91
      README.md
  4. 137
      configure
  5. 103
      test/simple/test-intl.js
  6. 127
      tools/configure.d/nodedownload.py
  7. 174
      tools/icu/icu-generic.gyp
  8. 15
      tools/icu/icu_small.json
  9. 13
      tools/icu/icutrim.py
  10. 8
      vcbuild.bat

3
.gitignore

@ -46,6 +46,9 @@ ipch/
email.md
deps/v8-*
deps/icu
deps/icu*.zip
deps/icu*.tgz
deps/icu-tmp
./node_modules
.svn/

4
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

91
README.md

@ -83,31 +83,104 @@ 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
```

137
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

103
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');
}

127
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

174
tools/icu/icu-generic.gyp

@ -11,6 +11,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.
@ -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

15
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",

13
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

8
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

Loading…
Cancel
Save