mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
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>
This commit is contained in:
parent
6a03fce16e
commit
a30839576c
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -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
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
91
README.md
|
|
@ -83,30 +83,103 @@ 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).
|
||||
|
||||
#### 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
|
||||
./configure --with-intl=full-icu --download=all
|
||||
```
|
||||
|
||||
Windows:
|
||||
|
||||
```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=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 ICU from source:
|
||||
#### Build with a specific ICU:
|
||||
|
||||
First: Unpack latest ICU
|
||||
[icu4c-**##.#**-src.tgz](http://icu-project.org/download) (or `.zip`)
|
||||
as `deps/icu` (You'll have: `deps/icu/source/...`)
|
||||
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:
|
||||
Unix/Macintosh: from an already-unpacked ICU
|
||||
|
||||
```sh
|
||||
./configure --with-intl=full-icu
|
||||
./configure --with-intl=[small-icu,full-icu] --with-icu-source=/path/to/icu
|
||||
```
|
||||
|
||||
Windows:
|
||||
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
vendored
137
configure
vendored
|
|
@ -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
Normal file
103
test/simple/test-intl.js
Normal file
|
|
@ -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
Normal file
127
tools/configure.d/nodedownload.py
Normal file
|
|
@ -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
|
||||
|
|
@ -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)'
|
||||
'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' ],
|
||||
}],
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../deps/icu/source/i18n',
|
||||
],
|
||||
'defines': [
|
||||
'U_I18N_IMPLEMENTATION=1',
|
||||
],
|
||||
'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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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…
Reference in New Issue
Block a user