Skip to content

Commit

Permalink
build: auto-load ICU data from --with-icu-default-data-dir
Browse files Browse the repository at this point in the history
When compiled with `--with-intl=small` and
`--with-icu-default-data-dir=PATH`, Node.js will use PATH as a
fallback location for the ICU data.

We will first perform an access check using fopen(PATH, 'r') to
ensure that the file is readable. If it is, we'll set the
icu_data_directory and proceed. There's a slight overhead for the
fopen() check, but it should be barely measurable.

This will be useful for Linux distribution packagers who want to
be able to ship a minimal node binary in a container image but
also be able to add on the full i18n support where needed. With
this patch, it becomes possible to ship the interpreter as
/usr/bin/node in one package for the distribution and to ship the
data files in another package (without a strict dependency
between the two). This means that users of the distribution will
not need to explicitly direct Node.js to locate the ICU data. It
also means that in environments where full internationalization is
not required, they do not need to carry the extra content (with
the associated storage costs).

Refs: #3460

Signed-off-by: Stephen Gallagher <[email protected]>

PR-URL: #30825
Reviewed-By: Steven R Loomis <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
  • Loading branch information
sgallagher authored and targos committed Jan 14, 2020
1 parent 1c6e2ec commit 67a2a47
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
9 changes: 9 additions & 0 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,14 @@
'the icu4c source archive. '
'v%d.x or later recommended.' % icu_versions['minimum_icu'])

intl_optgroup.add_option('--with-icu-default-data-dir',
action='store',
dest='with_icu_default_data_dir',
help='Path to the icuXXdt{lb}.dat file. If unspecified, ICU data will '
'only be read if the NODE_ICU_DATA environment variable or the '
'--icu-data-dir runtime argument is used. This option has effect '
'only when Node.js is built with --with-intl=small-icu.')

parser.add_option('--with-ltcg',
action='store_true',
dest='with_ltcg',
Expand Down Expand Up @@ -1370,6 +1378,7 @@ def write_config(data, name):
locs.add('root') # must have root
o['variables']['icu_locales'] = ','.join(str(loc) for loc in locs)
# We will check a bit later if we can use the canned deps/icu-small
o['variables']['icu_default_data'] = options.with_icu_default_data_dir or ''
elif with_intl == 'full-icu':
# full ICU
o['variables']['v8_enable_i18n_support'] = 1
Expand Down
7 changes: 7 additions & 0 deletions node.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@
'conditions': [
[ 'icu_small=="true"', {
'defines': [ 'NODE_HAVE_SMALL_ICU=1' ],
'conditions': [
[ 'icu_default_data!=""', {
'defines': [
'NODE_ICU_DEFAULT_DATA_DIR="<(icu_default_data)"',
],
}],
],
}]],
}],
[ 'node_no_browser_globals=="true"', {
Expand Down
20 changes: 20 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@

#if defined(NODE_HAVE_I18N_SUPPORT)
#include <unicode/uvernum.h>
#include <unicode/utypes.h>
#endif


Expand Down Expand Up @@ -831,6 +832,25 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
if (per_process::cli_options->icu_data_dir.empty())
credentials::SafeGetenv("NODE_ICU_DATA",
&per_process::cli_options->icu_data_dir);

#ifdef NODE_ICU_DEFAULT_DATA_DIR
// If neither the CLI option nor the environment variable was specified,
// fall back to the configured default
if (per_process::cli_options->icu_data_dir.empty()) {
// Check whether the NODE_ICU_DEFAULT_DATA_DIR contains the right data
// file and can be read.
static const char full_path[] =
NODE_ICU_DEFAULT_DATA_DIR "/" U_ICUDATA_NAME ".dat";

FILE* f = fopen(full_path, "rb");

if (f != nullptr) {
fclose(f);
per_process::cli_options->icu_data_dir = NODE_ICU_DEFAULT_DATA_DIR;
}
}
#endif // NODE_ICU_DEFAULT_DATA_DIR

// Initialize ICU.
// If icu_data_dir is empty here, it will load the 'minimal' data.
if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {
Expand Down

0 comments on commit 67a2a47

Please sign in to comment.