diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
index 64122154d42ee..3b509a7668c48 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
@@ -52,7 +52,7 @@ The .NET Foundation licenses this file to you under the MIT license.
-
+
@@ -67,6 +67,12 @@ The .NET Foundation licenses this file to you under the MIT license.
+
+
+
+
+
+
@@ -74,6 +80,8 @@ The .NET Foundation licenses this file to you under the MIT license.
+
+
@@ -91,6 +99,7 @@ The .NET Foundation licenses this file to you under the MIT license.
+
diff --git a/src/coreclr/nativeaot/docs/compiling.md b/src/coreclr/nativeaot/docs/compiling.md
index f142fa3afecb1..c84d11825aea2 100644
--- a/src/coreclr/nativeaot/docs/compiling.md
+++ b/src/coreclr/nativeaot/docs/compiling.md
@@ -68,3 +68,24 @@ You also need to specify the sysroot directory for Clang using the `SysRoot` pro
```
You may also follow [cross-building instructions](../../../../docs/workflow/building/coreclr/cross-building.md) to create your own sysroot directory.
+
+## Using statically linked ICU
+This feature can statically link libicu libraries (such as libicui18n.a) into your applications at build time.
+NativeAOT binaries built with this feature can run even when libicu libraries are not installed.
+
+You can use this feature by adding the `StaticICULinking` property to your project file as follows:
+
+```xml
+
+ true
+
+```
+
+This feature is only supported on Linux. This feature is not supported when crosscompiling.
+
+### Prerequisites
+
+Ubuntu (20.04+)
+```
+sudo apt-get install libicu-dev cmake
+```
diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj
index 2dc56dde6c172..6624b2f5c275f 100644
--- a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj
+++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj
@@ -16,6 +16,11 @@
+
+
+
+
+
diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt
index a41e66cacd310..5e2fb2948cc43 100644
--- a/src/native/libs/System.Globalization.Native/CMakeLists.txt
+++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt
@@ -57,9 +57,21 @@ set(NATIVEGLOBALIZATION_SOURCES
pal_localeNumberData.c
pal_localeStringData.c
pal_normalization.c
- pal_icushim.c
)
+if (LOCAL_BUILD)
+ set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_icushim_static.c)
+ add_definitions(-DLOCAL_BUILD)
+ add_definitions(-DSTATIC_ICU)
+ add_definitions(-DPALEXPORT=EXTERN_C)
+ add_definitions(-DTARGET_UNIX)
+ # For minipal files
+ include_directories(../../)
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+else()
+ set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_icushim.c)
+endif()
+
if (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m)
endif()
diff --git a/src/native/libs/System.Globalization.Native/local_build.sh b/src/native/libs/System.Globalization.Native/local_build.sh
new file mode 100755
index 0000000000000..0ace96373a36e
--- /dev/null
+++ b/src/native/libs/System.Globalization.Native/local_build.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+#
+
+# This script is used only for building libSystem.Globalization.Native.a
+# in the end-user's computer for NativeAOT purposes (static linking).
+# This file is not used during the dotnet runtime build.
+
+# Currently, only Linux is supported
+
+SHIM_SOURCE_DIR=$1/native/src
+INTERMEDIATE_OUTPUT_PATH=$2
+
+if [ -d "$SHIM_SOURCE_DIR" ]; then
+ LOCAL_SHIM_DIR="$INTERMEDIATE_OUTPUT_PATH"/libs/System.Globalization.Native/build
+ mkdir -p "$LOCAL_SHIM_DIR" && cd "$LOCAL_SHIM_DIR"
+ if [ $? -ne 0 ]; then echo "local_build.sh::ERROR: Cannot use local build directory"; exit 1; fi
+ cmake -S "$SHIM_SOURCE_DIR/libs/System.Globalization.Native/" -DLOCAL_BUILD:STRING=1 -DCLR_CMAKE_TARGET_UNIX:STRING=1
+ if [ $? -ne 0 ]; then echo "local_build.sh::ERROR: cmake failed"; exit 1; fi
+ make -j
+ if [ $? -ne 0 ]; then echo "local_build.sh::ERROR: Build failed"; exit 1; fi
+fi
+
+exit 0
diff --git a/src/native/libs/System.Globalization.Native/pal_icushim_internal.h b/src/native/libs/System.Globalization.Native/pal_icushim_internal.h
index f01ef2384c3c5..e349b47f28802 100644
--- a/src/native/libs/System.Globalization.Native/pal_icushim_internal.h
+++ b/src/native/libs/System.Globalization.Native/pal_icushim_internal.h
@@ -15,7 +15,9 @@
#include "pal_icushim_internal_android.h"
#else
+#if !defined(LOCAL_BUILD)
#define U_DISABLE_RENAMING 1
+#endif
// All ICU headers need to be included here so that all function prototypes are
// available before the function pointers are declared below.
diff --git a/src/native/libs/System.Globalization.Native/pal_icushim_static.c b/src/native/libs/System.Globalization.Native/pal_icushim_static.c
index ff762fc4c6ab2..cd57172b52329 100644
--- a/src/native/libs/System.Globalization.Native/pal_icushim_static.c
+++ b/src/native/libs/System.Globalization.Native/pal_icushim_static.c
@@ -217,12 +217,17 @@ const char* GlobalizationNative_GetICUDTName(const char* culture)
int32_t GlobalizationNative_LoadICU(void)
{
+#if !defined(LOCAL_BUILD)
+// Static NativeAOT compilation does not have
+// GlobalizationNative_LoadICUData() as entrypoint
if (!isDataSet)
{
// don't try to locate icudt.dat automatically if mono_wasm_load_icu_data wasn't called
// and fallback to invariant mode
return 0;
}
+#endif
+
UErrorCode status = 0;
UVersionInfo version;
// Request the CLDR version to perform basic ICU initialization and find out