Skip to content

Commit 7646e76

Browse files
smhmhmdSamiullah MohammedUbuntujkotasMichalStrehovsky
authored
Add local build for System.Globalization shim (#72896)
* Add local build for System.Globalization shim Bundle the System.Globalization.Native shim sources into the native AOT toolchain package and compile them automatically using C/C++ compiler on the target machine. Compiling of the shim sources using C/C++ compiler is done during dotnet publish as follows: dotnet publish /p:LocalSystemGlobalizationNative=1 -bl -r linux-x64 This change is 'opt-in', it is enabled only by using /p:LocalSystemGlobalizationNative=1 * Incorporate review feedback * Copy shim source code into users Obj directory at IntermediateOutputPath and compile ** $ ls -al obj/Debug/net7.0/linux-x64/shim_source_code/libs/System.Globalization.Native/build/libSystem.Globalization.Native-Static.a * Add shell script for readability * Add copyright headers * Fix IlCompilerPackagePath Add change that was part of previous commit * Address review feedback * Include existing pal_icushim_static.c by using STATIC_ICU define * Use IlcSdkPath to copy shim source code * Incorporate review feedback * Remove USE_ICUSHIM_STATIC_BUILD in pal_icushim.c * Rename shim_source_code to source_code in Microsoft.DotNet.ILCompiler.pkgproj and script * Regular config is used, config-standalone.h is removed * IlcPath/.. is replaced to make the ".." go away * Address feedback from 08/04 * Rename option to ICUStaticLinking * Remove <Message .. * Compile without copying sources * Trim list of defines * Emit error when run on Linux in CMakeLists.txt * Move StaticICULibs to near licucore on Mac * Use only IlcHostPackagePath * Fix DirectPInvoke for library built by user * Feedback on 08/25: rename static-build, "source_code" and cleanup compile defs * Remove IlcHostPackagePath check * StaticICULinking property is true/false * Remove -g and -fPIC from definitions * Use minimal warning level * Remove -DHOST_AMD64 * Remove -O0 * Remove -fms-extensions -fwrapv * Standardize on "local build" * Rename build-nativeaot-shim-standalone.sh to build.sh * Script name in the error message should match the actual script name * Rename source_code to native/src Test code: $ cat Program.cs using System.Globalization; namespace CurrentCulture { class Program { static void Main(string[] args) { double val = 1235.56; Console.WriteLine($"Current culture: {CultureInfo.CurrentCulture.Name}"); Console.WriteLine(val); CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); Console.WriteLine($"Current culture: {CultureInfo.CurrentCulture.Name}"); Console.WriteLine(val); } } } $ cat hello-4.csproj <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <RootNamespace>hello_4</RootNamespace> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> $ cat nuget.config <?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <!--To inherit the global NuGet package sources remove the <clear/> line below --> <clear /> <add key="repositoryPath" value="/home/ubuntu/runtime/artifacts/packages/Debug/Shipping" /> <add key="dotnet7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json" /> </packageSources> </configuration> Test code build: rm ./bin/Debug/net7.0/linux-arm64/native/hello-4 ~/dotnet-sdk/dotnet clean ~/dotnet-sdk/dotnet publish /p:PublishAot=true /p:StaticICULinking=true -bl -r linux-arm64 --self-contained -v d 2>&1 > log ./bin/Debug/net7.0/linux-arm64/native/hello-4 Tested on x86-64 and arm64 * Feedback on 09/02 * Incorporated change to use only src/native/libs/System.Globalization.Native/CMakeLists.txt * Conditionalized CMakeLists.txt for local build * Moved the build.sh into parent as local_build.sh and removed local-build directory. * Rename STATIC_SHIM_COMPILE to LOCAL_BUILD * Move file includes to previous itemgroup Move the includes in Microsoft.DotNet.ILCompiler.pkgproj to <ItemGroup Condition="'$(PackageTargetRuntime)' != ''"> * Move file includes to previous itemgroup Move the includes in Microsoft.DotNet.ILCompiler.pkgproj to <ItemGroup Condition="'$(PackageTargetRuntime)' != ''"> * Update section in compiling.md * Add "Using statically linked ICU" to compiling.md * Remove define check for LOCAL_BUILD in CMakeLists.txt * Update src/coreclr/nativeaot/docs/compiling.md * Update src/coreclr/nativeaot/docs/compiling.md * Update src/coreclr/nativeaot/docs/compiling.md * Update src/coreclr/nativeaot/docs/compiling.md Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com> * Update src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com> Co-authored-by: Samiullah Mohammed <ubuntu@ip-172-31-24-113> Co-authored-by: Ubuntu <ubuntu@ip-10-0-0-223.us-west-1.compute.internal> Co-authored-by: Jan Kotas <jkotas@microsoft.com> Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
1 parent 96072f2 commit 7646e76

File tree

7 files changed

+82
-2
lines changed

7 files changed

+82
-2
lines changed

src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ The .NET Foundation licenses this file to you under the MIT license.
5252

5353
<ItemGroup>
5454
<NetCoreAppNativeLibrary Include="System.Native" />
55-
<NetCoreAppNativeLibrary Include="System.Globalization.Native" />
55+
<NetCoreAppNativeLibrary Include="System.Globalization.Native" Condition="'$(StaticICULinking)' != 'true'" />
5656
<NetCoreAppNativeLibrary Include="System.IO.Compression.Native" />
5757
<NetCoreAppNativeLibrary Include="System.Net.Security.Native" />
5858
<NetCoreAppNativeLibrary Include="System.Security.Cryptography.Native.Apple" Condition="'$(TargetOS)' == 'OSX'" />
@@ -67,13 +67,21 @@ The .NET Foundation licenses this file to you under the MIT license.
6767
<NativeLibrary Include="@(NetCoreAppNativeLibrary->'%(EscapedPath)')" />
6868
</ItemGroup>
6969

70+
<ItemGroup Condition="'$(StaticICULinking)' == 'true'">
71+
<NativeLibrary Include="$(IntermediateOutputPath)/libs/System.Globalization.Native/build/libSystem.Globalization.Native.a"/>
72+
<DirectPInvoke Include="libSystem.Globalization.Native" />
73+
<StaticICULibs Include="-Wl,-Bstatic -licuio -licutu -licui18n -licuuc -licudata -Wl,-Bdynamic" />
74+
</ItemGroup>
75+
7076
<ItemGroup Condition="'$(TargetOS)' == 'OSX'">
7177
<NativeFramework Include="CoreFoundation" />
7278
<NativeFramework Include="Foundation" />
7379
<NativeFramework Include="Security" />
7480
<NativeFramework Include="GSS" />
7581
</ItemGroup>
7682

83+
<Exec Command="$(IlcHostPackagePath)/native/src/libs/System.Globalization.Native/local_build.sh $(IlcHostPackagePath)/ $(IntermediateOutputPath)" Condition="'$(StaticICULinking)' == 'true'"/>
84+
7785
<ItemGroup>
7886
<LinkerArg Include="@(NativeLibrary)" />
7987
<LinkerArg Include="--sysroot=$(SysRoot)" Condition="'$(SysRoot)' != ''" />
@@ -91,6 +99,7 @@ The .NET Foundation licenses this file to you under the MIT license.
9199
<LinkerArg Include="-lz" />
92100
<LinkerArg Include="-lrt" Condition="'$(TargetOS)' != 'OSX'" />
93101
<LinkerArg Include="-licucore" Condition="'$(TargetOS)' == 'OSX'" />
102+
<LinkerArg Include="@(StaticICULibs)" Condition="'$(StaticICULinking)' == 'true'" />
94103
<LinkerArg Include="-dynamiclib" Condition="'$(TargetOS)' == 'OSX' and '$(NativeLib)' == 'Shared'" />
95104
<LinkerArg Include="-shared" Condition="'$(TargetOS)' != 'OSX' and '$(NativeLib)' == 'Shared'" />
96105
<!-- binskim warning BA3001 PIE disabled on executable -->

src/coreclr/nativeaot/docs/compiling.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,24 @@ You also need to specify the sysroot directory for Clang using the `SysRoot` pro
6868
```
6969

7070
You may also follow [cross-building instructions](../../../../docs/workflow/building/coreclr/cross-building.md) to create your own sysroot directory.
71+
72+
## Using statically linked ICU
73+
This feature can statically link libicu libraries (such as libicui18n.a) into your applications at build time.
74+
NativeAOT binaries built with this feature can run even when libicu libraries are not installed.
75+
76+
You can use this feature by adding the `StaticICULinking` property to your project file as follows:
77+
78+
```xml
79+
<PropertyGroup>
80+
<StaticICULinking>true</StaticICULinking>
81+
</PropertyGroup>
82+
```
83+
84+
This feature is only supported on Linux. This feature is not supported when crosscompiling.
85+
86+
### Prerequisites
87+
88+
Ubuntu (20.04+)
89+
```
90+
sudo apt-get install libicu-dev cmake
91+
```

src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
<File Include="$(CoreCLRAotSdkDir)*" TargetPath="sdk" />
1717
<File Include="$(MibcOptimizationDataDir)/$(TargetOS)/$(TargetArchitecture)/**/*.mibc" TargetPath="mibc" />
1818
</ItemGroup>
19+
<ItemGroup Condition="'$(PackageTargetRuntime)' != '' and '$(TargetOS)' == 'Linux'">
20+
<File Include="$(MSBuildThisFileDirectory)\..\..\..\..\native\libs\System.Globalization.Native\*" TargetPath="native/src/libs/System.Globalization.Native"/>
21+
<File Include="$(MSBuildThisFileDirectory)\..\..\..\..\native\minipal\*" TargetPath="native/src/minipal"/>
22+
<File Include="$(MSBuildThisFileDirectory)\..\..\..\..\native\libs\Common\*" TargetPath="native/src/libs/Common"/>
23+
</ItemGroup>
1924

2025
<ItemGroup>
2126
<File Include="$(CoreCLRBuildIntegrationDir)*" TargetPath="build" />

src/native/libs/System.Globalization.Native/CMakeLists.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,21 @@ set(NATIVEGLOBALIZATION_SOURCES
5757
pal_localeNumberData.c
5858
pal_localeStringData.c
5959
pal_normalization.c
60-
pal_icushim.c
6160
)
6261

62+
if (LOCAL_BUILD)
63+
set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_icushim_static.c)
64+
add_definitions(-DLOCAL_BUILD)
65+
add_definitions(-DSTATIC_ICU)
66+
add_definitions(-DPALEXPORT=EXTERN_C)
67+
add_definitions(-DTARGET_UNIX)
68+
# For minipal files
69+
include_directories(../../)
70+
include_directories(${CMAKE_CURRENT_BINARY_DIR})
71+
else()
72+
set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_icushim.c)
73+
endif()
74+
6375
if (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
6476
set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m)
6577
endif()
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/sh
2+
3+
# Licensed to the .NET Foundation under one or more agreements.
4+
# The .NET Foundation licenses this file to you under the MIT license.
5+
#
6+
7+
# This script is used only for building libSystem.Globalization.Native.a
8+
# in the end-user's computer for NativeAOT purposes (static linking).
9+
# This file is not used during the dotnet runtime build.
10+
11+
# Currently, only Linux is supported
12+
13+
SHIM_SOURCE_DIR=$1/native/src
14+
INTERMEDIATE_OUTPUT_PATH=$2
15+
16+
if [ -d "$SHIM_SOURCE_DIR" ]; then
17+
LOCAL_SHIM_DIR="$INTERMEDIATE_OUTPUT_PATH"/libs/System.Globalization.Native/build
18+
mkdir -p "$LOCAL_SHIM_DIR" && cd "$LOCAL_SHIM_DIR"
19+
if [ $? -ne 0 ]; then echo "local_build.sh::ERROR: Cannot use local build directory"; exit 1; fi
20+
cmake -S "$SHIM_SOURCE_DIR/libs/System.Globalization.Native/" -DLOCAL_BUILD:STRING=1 -DCLR_CMAKE_TARGET_UNIX:STRING=1
21+
if [ $? -ne 0 ]; then echo "local_build.sh::ERROR: cmake failed"; exit 1; fi
22+
make -j
23+
if [ $? -ne 0 ]; then echo "local_build.sh::ERROR: Build failed"; exit 1; fi
24+
fi
25+
26+
exit 0

src/native/libs/System.Globalization.Native/pal_icushim_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include "pal_icushim_internal_android.h"
1616
#else
1717

18+
#if !defined(LOCAL_BUILD)
1819
#define U_DISABLE_RENAMING 1
20+
#endif
1921

2022
// All ICU headers need to be included here so that all function prototypes are
2123
// available before the function pointers are declared below.

src/native/libs/System.Globalization.Native/pal_icushim_static.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,17 @@ const char* GlobalizationNative_GetICUDTName(const char* culture)
217217

218218
int32_t GlobalizationNative_LoadICU(void)
219219
{
220+
#if !defined(LOCAL_BUILD)
221+
// Static NativeAOT compilation does not have
222+
// GlobalizationNative_LoadICUData() as entrypoint
220223
if (!isDataSet)
221224
{
222225
// don't try to locate icudt.dat automatically if mono_wasm_load_icu_data wasn't called
223226
// and fallback to invariant mode
224227
return 0;
225228
}
229+
#endif
230+
226231
UErrorCode status = 0;
227232
UVersionInfo version;
228233
// Request the CLDR version to perform basic ICU initialization and find out

0 commit comments

Comments
 (0)