Skip to content

Commit 67a2a47

Browse files
sgallaghertargos
authored andcommitted
build: auto-load ICU data from --with-icu-default-data-dir
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]>
1 parent 1c6e2ec commit 67a2a47

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

configure.py

+9
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@
443443
'the icu4c source archive. '
444444
'v%d.x or later recommended.' % icu_versions['minimum_icu'])
445445

446+
intl_optgroup.add_option('--with-icu-default-data-dir',
447+
action='store',
448+
dest='with_icu_default_data_dir',
449+
help='Path to the icuXXdt{lb}.dat file. If unspecified, ICU data will '
450+
'only be read if the NODE_ICU_DATA environment variable or the '
451+
'--icu-data-dir runtime argument is used. This option has effect '
452+
'only when Node.js is built with --with-intl=small-icu.')
453+
446454
parser.add_option('--with-ltcg',
447455
action='store_true',
448456
dest='with_ltcg',
@@ -1370,6 +1378,7 @@ def write_config(data, name):
13701378
locs.add('root') # must have root
13711379
o['variables']['icu_locales'] = ','.join(str(loc) for loc in locs)
13721380
# We will check a bit later if we can use the canned deps/icu-small
1381+
o['variables']['icu_default_data'] = options.with_icu_default_data_dir or ''
13731382
elif with_intl == 'full-icu':
13741383
# full ICU
13751384
o['variables']['v8_enable_i18n_support'] = 1

node.gypi

+7
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@
103103
'conditions': [
104104
[ 'icu_small=="true"', {
105105
'defines': [ 'NODE_HAVE_SMALL_ICU=1' ],
106+
'conditions': [
107+
[ 'icu_default_data!=""', {
108+
'defines': [
109+
'NODE_ICU_DEFAULT_DATA_DIR="<(icu_default_data)"',
110+
],
111+
}],
112+
],
106113
}]],
107114
}],
108115
[ 'node_no_browser_globals=="true"', {

src/node.cc

+20
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979

8080
#if defined(NODE_HAVE_I18N_SUPPORT)
8181
#include <unicode/uvernum.h>
82+
#include <unicode/utypes.h>
8283
#endif
8384

8485

@@ -831,6 +832,25 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
831832
if (per_process::cli_options->icu_data_dir.empty())
832833
credentials::SafeGetenv("NODE_ICU_DATA",
833834
&per_process::cli_options->icu_data_dir);
835+
836+
#ifdef NODE_ICU_DEFAULT_DATA_DIR
837+
// If neither the CLI option nor the environment variable was specified,
838+
// fall back to the configured default
839+
if (per_process::cli_options->icu_data_dir.empty()) {
840+
// Check whether the NODE_ICU_DEFAULT_DATA_DIR contains the right data
841+
// file and can be read.
842+
static const char full_path[] =
843+
NODE_ICU_DEFAULT_DATA_DIR "/" U_ICUDATA_NAME ".dat";
844+
845+
FILE* f = fopen(full_path, "rb");
846+
847+
if (f != nullptr) {
848+
fclose(f);
849+
per_process::cli_options->icu_data_dir = NODE_ICU_DEFAULT_DATA_DIR;
850+
}
851+
}
852+
#endif // NODE_ICU_DEFAULT_DATA_DIR
853+
834854
// Initialize ICU.
835855
// If icu_data_dir is empty here, it will load the 'minimal' data.
836856
if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {

0 commit comments

Comments
 (0)