doc,deps: document how to maintain ICU in Node.js · nodejs/node@b67759a · GitHub
Skip to content

Commit b67759a

Browse files
srl295addaleax
authored andcommitted
doc,deps: document how to maintain ICU in Node.js
- update v8 guide to mention ICU - move content from the tools/icu/README.md but leave a pointer Fixes: #26108 Co-Authored-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com> PR-URL: #30607 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
1 parent e9f031c commit b67759a

3 files changed

Lines changed: 255 additions & 115 deletions

File tree

doc/guides/maintaining-V8.md

Lines changed: 4 additions & 0 deletions

doc/guides/maintaining-icu.md

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Maintaining ICU in Node.js
2+
3+
## Background
4+
5+
International Components for Unicode ([ICU4C][ICU]) is used both by V8
6+
and also by Node.js directly to provide internationalization
7+
functionality. To quote from icu-project.org:
8+
9+
> ICU is a mature, widely used set of C/C++ and Java libraries providing
10+
> Unicode and Globalization support for software applications. ICU is
11+
> widely portable and gives applications the same results on all platforms
12+
> and between C/C++ and Java software.
13+
14+
## Data dependencies
15+
16+
ICU consumes and includes:
17+
18+
* Extracted locale data from [CLDR][]
19+
* Extracted [Unicode][] data.
20+
* Time zone ([tz][]) data
21+
22+
The current versions of these items can be viewed for node with `node -p process.versions`:
23+
24+
```shell
25+
$ node -p process.versions
26+
27+
{
28+
29+
cldr: '35.1',
30+
icu: '64.2',
31+
tz: '2019a',
32+
unicode: '12.1'
33+
}
34+
```
35+
36+
## Release Schedule
37+
38+
ICU typically has >1 release a year, particularly coinciding with a major
39+
release of [Unicode][]. The current release schedule is available on the [ICU][]
40+
website on the left sidebar.
41+
42+
### V8 depends on ICU
43+
44+
V8 will aggressively upgrade to a new ICU version, due to requirements for
45+
features/bugfixes needed for [Ecma402][] support. The minimum required version
46+
of ICU is specified within the V8 source tree. If the ICU version is too old,
47+
V8 will not compile.
48+
49+
```c
50+
// deps/v8/src/objects/intl-objects.h
51+
#define V8_MINIMUM_ICU_VERSION 64
52+
```
53+
54+
V8 in Node.js depends on the ICU version supplied by Node.js.
55+
56+
The file `tools/icu/icu_versions.json` contains the current minimum
57+
version of ICU that Node.js is known to work with. This should be
58+
_at least_ the same version as V8, so that users will find out
59+
earlier that their ICU is too old. A test case validates this when
60+
Node.js is built.
61+
62+
## How to upgrade ICU
63+
64+
* Make sure your Node.js workspace is clean (`git status`
65+
should be sufficient).
66+
* Configure Node.js with the specific [ICU version](http://icu-project.org/download)
67+
you want to upgrade to, for example:
68+
69+
```shell
70+
./configure \
71+
--with-intl=full-icu \
72+
--with-icu-source=http://download.icu-project.org/files/icu4c/58.1/icu4c-58_1-src.tgz
73+
make
74+
```
75+
76+
> _Note_ in theory, the equivalent `vcbuild.bat` commands should work also,
77+
> but the commands below are makefile-centric.
78+
79+
* If there are ICU version-specific changes needed, you may need to make changes
80+
in `tools/icu/icu-generic.gyp` or add patch files to `tools/icu/patches`.
81+
* Specifically, look for the lists in `sources!` in the `tools/icu/icu-generic.gyp` for
82+
files to exclude.
83+
84+
* Verify the Node.js build works:
85+
86+
```shell
87+
make test-ci
88+
```
89+
90+
Also running
91+
92+
<!-- eslint-disable strict -->
93+
94+
```js
95+
new Intl.DateTimeFormat('es', { month: 'long' }).format(new Date(9E8));
96+
```
97+
98+
…Should return `enero` not `January`.
99+
100+
* Now, copy `deps/icu` over to `deps/icu-small`
101+
102+
> :warning: Do not modify any source code in `deps/icu-small` !
103+
> See section below about floating patches to ICU.
104+
105+
```shell
106+
python tools/icu/shrink-icu-src.py
107+
```
108+
109+
* Now, do a clean rebuild of Node.js to test:
110+
111+
```shell
112+
make -k distclean
113+
./configure
114+
make
115+
```
116+
117+
* Test this newly default-generated Node.js
118+
119+
<!-- eslint-disable strict -->
120+
121+
```js
122+
process.versions.icu;
123+
new Intl.DateTimeFormat('es', { month: 'long' }).format(new Date(9E8));
124+
```
125+
126+
(This should print your updated ICU version number, and also `January` again.)
127+
128+
You are ready to check in the updated `deps/icu-small`. This is a big commit,
129+
so make this a separate commit from the smaller changes.
130+
131+
> :warning: Do not modify any source code in `deps/icu-small` !
132+
> See section below about floating patches to ICU.
133+
134+
* Now, rebuild the Node.js license.
135+
136+
```shell
137+
# clean up - remove deps/icu
138+
make clean
139+
tools/license-builder.sh
140+
```
141+
142+
* Update the URL and hash for the full ICU file in `tools/icu/current_ver.dep`.
143+
It should match the ICU URL used in the first step. When this is done, the
144+
following should build with small ICU.
145+
146+
```shell
147+
# clean up
148+
rm -rf out deps/icu deps/icu4c*
149+
./configure --with-intl=small-icu --download=all
150+
make
151+
make test-ci
152+
```
153+
154+
* commit the change to `tools/icu/current_ver.dep` and `LICENSE` files.
155+
156+
* Note: To simplify review, I often will “pre-land” this patch, meaning that
157+
I run the patch through `curl -L https://github.com/nodejs/node/pull/xxx.patch
158+
| git am -3 --whitespace=fix` per the collaborator’s guide… and then push that
159+
patched branch into my PR's branch. This reduces the whitespace changes that
160+
show up in the PR, since the final land will eliminate those anyway.
161+
162+
## Floating patches to ICU
163+
164+
Floating patches are applied at `configure` time. The "patch" files
165+
are used instead of the original source files. The patch files are
166+
complete `.cpp` files replacing the original contents.
167+
168+
Patches are tied to a specific ICU version. They won’t apply to a
169+
future ICU version. We assume that you filed a bug against [ICU][] and
170+
upstreamed the fix, so the patch won’t be needed in a later ICU
171+
version.
172+
173+
### Example
174+
175+
For example, to patch `source/tools/toolutil/pkg_genc.cpp` for
176+
ICU version 63:
177+
178+
```shell
179+
# go to your Node.js source directory
180+
cd <node>
181+
182+
# create the floating patch directory
183+
mkdir -p tools/icu/patches/63
184+
185+
# create the subdirectory for the file(s) to patch:
186+
mkdir -p tools/icu/patches/63/source/tools/toolutil/
187+
188+
# copy the file to patch
189+
cp deps/icu-small/source/tools/toolutil/pkg_genc.cpp \
190+
tools/icu/patches/63/source/tools/toolutil/pkg_genc.cpp
191+
192+
# Make any changes to this file:
193+
(edit tools/icu/patches/63/source/tools/toolutil/pkg_genc.cpp )
194+
195+
# test
196+
make clean && ./configure && make
197+
```
198+
199+
You should see a message such as:
200+
201+
```shell
202+
INFO: Using floating patch "tools/icu/patches/63/source/tools/toolutil/pkg_genc.cpp" from "tools/icu"
203+
```
204+
205+
### Clean Up
206+
207+
Any patches older than the minimum version given in `tools/icu/icu_versions.json`
208+
ought to be deleted, because they will never be used.
209+
210+
### Why not just modify the ICU source directly?
211+
212+
Especially given the V8 dependencies above, there may be times when a floating
213+
patch to ICU is required. Though it seems expedient to simply change a file in
214+
`deps/icu-small`, this is not the right approach for the following reasons:
215+
216+
1. **Repeatability.** Given the complexity of merging in a new ICU version,
217+
following the steps above in the prior section of this document ought to be
218+
repeatable without concern for overriding a patch.
219+
220+
2. **Verifiability.** Given the number of files modified in an ICU PR,
221+
a floating patch could easily be missed — or dropped altogether next time
222+
something is landed.
223+
224+
3. **Compatibility.** There are a number of ways that ICU can be loaded into
225+
Node.js (see the top level README.md). Only modifying `icu-small` would cause
226+
the patch not to be landed in case the user specifies the ICU source code
227+
another way.
228+
229+
[ICU]: http://icu-project.org
230+
[Unicode]: https://unicode.org
231+
[tz]: https://www.iana.org/time-zones
232+
[CLDR]: https://unicode.org/cldr
233+
[Ecma402]: https://github.com/tc39/ecma402

tools/icu/README.md

Lines changed: 18 additions & 115 deletions

0 commit comments

Comments
 (0)