diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c index 7fa6dd6fd8ac16..4a0d693d43b2a9 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c @@ -6,6 +6,7 @@ #include #include "pal_icushim_internal.h" +#if !defined(STATIC_ICU) #if defined(TARGET_UNIX) #include #elif defined(TARGET_WINDOWS) @@ -482,3 +483,34 @@ int32_t GlobalizationNative_GetICUVersion() return (versionInfo[0] << 24) + (versionInfo[1] << 16) + (versionInfo[2] << 8) + versionInfo[3]; } + +#else // !defined(STATIC_ICU) + +#include +#include + +int32_t GlobalizationNative_LoadICU(void) +{ + const char* icudir = getenv("DOTNET_ICU_DIR"); + if (!icudir) + return 0; + + // path to a directory with icudt___.dat (e.g. icudt67l.dat) + // we can also use `udata_setCommonData(const void *data, UErrorCode *err)` API here + u_setDataDirectory(icudir); + return 1; +} + +void GlobalizationNative_InitICUFunctions(void* icuuc, void* icuin, const char* version, const char* suffix) +{ + // no-op for static +} + +int32_t GlobalizationNative_GetICUVersion(void) +{ + UVersionInfo versionInfo; + u_getVersion(versionInfo); + + return (versionInfo[0] << 24) + (versionInfo[1] << 16) + (versionInfo[2] << 8) + versionInfo[3]; +} +#endif // defined(STATIC_ICU) diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h index 33617e7f5d039d..666b4700088e7e 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h @@ -56,6 +56,7 @@ #include "pal_compiler.h" +#if !defined(STATIC_ICU) // List of all functions from the ICU libraries that are used in the System.Globalization.Native.so #define FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ PER_FUNCTION_BLOCK(u_charsToUChars, libicuuc) \ @@ -280,3 +281,4 @@ FOR_ALL_ICU_FUNCTIONS #define usearch_getMatchedLength(...) usearch_getMatchedLength_ptr(__VA_ARGS__) #define usearch_last(...) usearch_last_ptr(__VA_ARGS__) #define usearch_openFromCollator(...) usearch_openFromCollator_ptr(__VA_ARGS__) +#endif // !defined(STATIC_ICU) diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index e89b59c5f71009..8f013c5f0c6774 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -210,6 +210,9 @@ /* Use static zlib */ #cmakedefine HAVE_STATIC_ZLIB 1 +/* Use static ICU */ +#cmakedefine STATIC_ICU 1 + /* Use OS-provided zlib */ #cmakedefine HAVE_SYS_ZLIB 1 diff --git a/src/mono/configure.ac b/src/mono/configure.ac index bd3e76d216c509..19b48ba7c61342 100644 --- a/src/mono/configure.ac +++ b/src/mono/configure.ac @@ -1309,6 +1309,12 @@ AC_ARG_WITH(spectre-mitigation, [ --with-spectre-mitigation=yes,no AC_ARG_WITH(spectre-indirect-branch-choice, [ --with-spectre-indirect-branch-choice=keep,thunk,inline,extern Convert indirect branches to the specified kind of thunk (defaults to inline)], [], [with_spectre_indirect_branch_choice=inline]) AC_ARG_WITH(spectre-function-return-choice, [ --with-spectre-function-return-choice=keep,thunk,inline,extern Convert function return instructions to the specified kind of thunk (defaults to inline)], [], [with_spectre_function_return_choice=inline]) +AC_ARG_WITH(static_icu, [ --with-static-icu=yes|no Integrate ICU statically into the runtime (defaults to no)],[ + if test x$with_static_icu = xyes ; then + AC_DEFINE(STATIC_ICU,1,[Integrate ICU statically into the runtime.]) + fi +], [with_static_icu=no]) + dnl dnl Spectre compiler mitigation flag checks dnl @@ -1696,6 +1702,7 @@ AM_CONDITIONAL(INSTALL_MONOTOUCH, [test "x$with_monotouch" != "xno"]) AM_CONDITIONAL(INSTALL_MONOTOUCH_WATCH, [test "x$with_monotouch_watch" != "xno"]) AM_CONDITIONAL(INSTALL_MONOTOUCH_TV, [test "x$with_monotouch_tv" != "xno"]) AM_CONDITIONAL(BITCODE, test "x$with_bitcode" = "xyes") +AM_CONDITIONAL(STATIC_ICU, test "x$with_static_icu" = "xyes") AM_CONDITIONAL(INSTALL_XAMMAC, [test "x$with_xammac" != "xno"]) AM_CONDITIONAL(INSTALL_TESTING_AOT_FULL_INTERP, [test "x$with_testing_aot_full_interp" != "xno"]) AM_CONDITIONAL(INSTALL_TESTING_AOT_HYBRID, [test "x$with_testing_aot_hybrid" != "xno"]) @@ -6836,7 +6843,10 @@ if test x$with_core = xonly; then fi if test x$have_shim_globalization = xyes || test x$cross_compiling = xyes; then ICU_SHIM_PATH=../../../libraries/Native/Unix/System.Globalization.Native - if test x$target_osx = xyes; then + if test x$target_wasm = xyes && test x$with_static_icu = xyes; then + ICU_CFLAGS="-DTARGET_UNIX -DU_DISABLE_RENAMING" + have_sys_icu=yes + elif test x$target_osx = xyes; then ORIG_CPPFLAGS=$CPPFLAGS # adding icu path to pkg_config_path PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig diff --git a/src/mono/mono.proj b/src/mono/mono.proj index be67580a2e204e..f50a4f77ac4b52 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -635,6 +635,7 @@ <_MonoConfigureParams Include="--disable-icall-tables"/> <_MonoConfigureParams Include="--disable-crash-reporting"/> <_MonoConfigureParams Include="--with-bitcode=yes"/> + <_MonoConfigureParams Condition="'$(ICU_REPO)' != ''" Include="--with-static-icu=yes"/> <_MonoConfigureParams Include="--enable-minimal=ssa,com,jit,reflection_emit_save,portability,assembly_remapping,attach,verifier,full_messages,appdomains,shadowcopy,security,sgen_marksweep_conc,sgen_split_nursery,sgen_gc_bridge,logging,remoting,shared_perfcounters,sgen_debug_helpers,soft_debug,interpreter,assert_messages,cleanup,mdb,gac,threads,$(_MonoEnableMinimal)"/> <_MonoCFLAGS Include="-fexceptions" /> <_MonoCXXFLAGS Include="-fexceptions -s DISABLE_EXCEPTION_CATCHING=0" /> diff --git a/src/mono/mono/metadata/Makefile.am b/src/mono/mono/metadata/Makefile.am index 7949999d565b7f..012751c8cdc243 100644 --- a/src/mono/mono/metadata/Makefile.am +++ b/src/mono/mono/metadata/Makefile.am @@ -158,6 +158,13 @@ nodist_libmonoruntime_shimglobalization_la_SOURCES = \ @ICU_SHIM_PATH@/entrypoints.c libmonoruntime_shimglobalization_la_CFLAGS = @ICU_CFLAGS@ -I$(top_srcdir)/../libraries/Native/Unix/System.Globalization.Native/ -I$(top_srcdir)/../libraries/Native/Unix/Common/ + +if STATIC_ICU +libmonoruntime_shimglobalization_la_CFLAGS += -I$(ICU_REPO)/icu4c/source/wasm-usr/include/ \ +-L$(ICU_REPO)/icu4c/source/wasm-build/lib/ -licui18n -licuuc -licutu -licuio \ +-L$(ICU_REPO)/icu4c/source/wasm-build/stubdata -licudata +endif + endif endif diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 0897b64af08840..99808fcb0fce10 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -56,6 +56,17 @@ MONO_LIBS = \ $(MONO_BIN_DIR)/libmono-icall-table.a \ ${SYS_NATIVE_DIR}/libSystem.Native.a +ifeq ($(ICU_REPO),) + @echo "ICU_REPO is not set." +else + MONO_LIBS := $(MONO_LIBS) \ + $(ICU_REPO)/icu4c/source/wasm-build/lib/libicui18n.a \ + $(ICU_REPO)/icu4c/source/wasm-build/lib/libicuio.a \ + $(ICU_REPO)/icu4c/source/wasm-build/lib/libicuuc.a \ + $(ICU_REPO)/icu4c/source/wasm-build/lib/libicutu.a \ + $(ICU_REPO)/icu4c/source/wasm-build/stubdata/libicudata.a +endif + EMCC_FLAGS=--profiling-funcs -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN=1 -s ALIASING_FUNCTION_POINTERS=0 -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'FS_createPath', 'FS_createDataFile', 'cwrap', 'setValue', 'getValue', 'UTF8ToString', 'addFunction']" -s "EXPORTED_FUNCTIONS=['_putchar']" --source-map-base http://example.com -s WASM_OBJECT_FILES=0 -s FORCE_FILESYSTEM=1 -s USE_ZLIB=1 EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1 EMCC_RELEASE_FLAGS=-Oz --llvm-opts 2 --llvm-lto 1 -DENABLE_NETCORE=1 diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index 197d7f140cbf33..cdb38a9cea66cc 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -322,7 +322,7 @@ mono_wasm_load_runtime (const char *managed_path, int enable_debugging) monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0); #endif #ifdef ENABLE_NETCORE - monoeg_g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", 0); + monoeg_g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", getenv("DOTNET_ICU_DIR") ? "0" : "1", 0); #endif mini_parse_debug_option ("top-runtime-invoke-unhandled"); diff --git a/src/mono/wasm/wasm.targets b/src/mono/wasm/wasm.targets index 7372daaa444d27..8fa68f40d76ac9 100644 --- a/src/mono/wasm/wasm.targets +++ b/src/mono/wasm/wasm.targets @@ -9,6 +9,7 @@ +