Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NativeAOT-LLVM] Implement most of globalization #2490

Merged
merged 6 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion eng/Subsets.props
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
<DefaultCoreClrSubsets Condition="'$(PrimaryRuntimeFlavor)' != 'CoreCLR'">clr.iltools+clr.packages</DefaultCoreClrSubsets>

<DefaultNativeAotSubsets>clr.alljits+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime</DefaultNativeAotSubsets>
<DefaultNativeAotSubsets Condition="'$(TargetArchitecture)' == 'wasm'">clr.nativeaotlibs+clr.nativeaotruntime+nativeaot.build+mono.wasmruntime</DefaultNativeAotSubsets>
<DefaultNativeAotSubsets Condition="'$(TargetsWasm)' == 'true'">clr.nativeaotlibs+clr.nativeaotruntime+nativeaot.build</DefaultNativeAotSubsets>
<DefaultNativeAotSubsets Condition="'$(TargetsBrowser)' == 'true'">$(DefaultNativeAotSubsets)+mono.wasmruntime</DefaultNativeAotSubsets>
SingleAccretion marked this conversation as resolved.
Show resolved Hide resolved

<DefaultMonoSubsets Condition="'$(MonoEnableLLVM)' == 'true' and '$(MonoLLVMDir)' == ''">mono.llvm+</DefaultMonoSubsets>
<DefaultMonoSubsets Condition="'$(MonoAOTEnableLLVM)' == 'true' and '$(MonoLLVMDir)' == ''">mono.llvm+</DefaultMonoSubsets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,9 +506,16 @@ The .NET Foundation licenses this file to you under the MIT license.

<MakeDir Directories="$([System.IO.Path]::GetDirectoryName($(NativeBinary)))" />

<ItemGroup Condition="'$(InvariantGlobalization)' != 'true'">
<NativeLibrary Include="$(IlcFrameworkNativePath)libicuuc.a" />
<NativeLibrary Include="$(IlcFrameworkNativePath)libicui18n.a" />
<NativeLibrary Include="$(IlcFrameworkNativePath)libicudata.a" />
<NativeLibrary Include="$(IlcFrameworkNativePath)libSystem.Globalization.Native.a" />
<NativeLibrary Include="$(IlcFrameworkNativePath)libSystem.Globalization.Native.Icudt.a" />
</ItemGroup>

<ItemGroup>
<NativeLibrary Include="$(IlcFrameworkNativePath)libSystem.Native.a" />
<NativeLibrary Include="$(IlcFrameworkNativePath)libSystem.Globalization.Native.a" />
<NativeLibrary Condition="$(NativeLib) == '' and '$(CustomNativeMain)' != 'true'" Include="$(IlcSdkPath)libbootstrapper.o" />
<NativeLibrary Condition="$(NativeLib) != '' or '$(CustomNativeMain)' == 'true'" Include="$(IlcSdkPath)libbootstrapperdll.o" />
<NativeLibrary Include="$(IlcSdkPath)libPortableRuntime.a" />
Expand Down Expand Up @@ -555,8 +562,8 @@ The .NET Foundation licenses this file to you under the MIT license.
<ItemGroup Condition ="'$(_targetOS)' == 'wasi'" >
<CustomLinkerArg Include="--sysroot=&quot;$(WASI_SDK_PATH.Replace(&quot;\&quot;, &quot;/&quot;))/share/wasi-sysroot&quot;" />
<CustomLinkerArg Include="@(CustomLinkerArgExport->'-Wl,--export=%(Identity)')" />
<!-- Wasi has lots of undefined symbols currently, mostly globalization -->
<CustomLinkerArg Include="-Wl,--unresolved-symbols=ignore-all -Wl,--error-limit=0" />
<!-- We want to put 'warn-unresolved-symbols' here, but wasm-ld crashs on that. Oops. -->
<CustomLinkerArg Include="-Wl,--unresolved-symbols=ignore-all" />
Copy link
Author

@SingleAccretion SingleAccretion Jan 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will have to debug and file a bug on LLVM about this (if it hasn't been fixed already)...

Edit: there is one already - llvm/llvm-project#53987.

<CustomLinkerArg Include="-lstdc++ -lwasi-emulated-process-clocks -lwasi-emulated-signal -lwasi-emulated-getpid" />
<CustomLinkerArg Include="-Wl,--max-memory=2147483648" />
<CustomLinkerArg Include="-Wl,--global-base=$(IlcWasmGlobalBase)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@
<Compile Include="$(CommonPath)Interop\Interop.ICU.cs">
<Link>Common\Interop\Interop.ICU.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Interop.ICU.iOS.cs" Condition="'$(IsiOSLike)' == 'true'">
<Compile Include="$(CommonPath)Interop\Interop.ICU.iOS.cs" Condition="'$(IsiOSLike)' == 'true' or ('$(TargetsWasm)' == 'true' and '$(FeatureNativeAot)' == 'true')">
<Link>Common\Interop\Interop.ICU.iOS.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Interop.Idna.cs">
Expand Down Expand Up @@ -2468,8 +2468,8 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureInfo.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\GlobalizationMode.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\GlobalizationMode.LoadICU.Unix.cs" Condition="'$(IsiOSLike)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\GlobalizationMode.LoadICU.iOS.cs" Condition="'$(IsiOSLike)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\GlobalizationMode.LoadICU.Unix.cs" Condition="'$(IsiOSLike)' != 'true' and ('$(TargetsWasm)' != 'true' or '$(FeatureNativeAot)' != 'true')" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\GlobalizationMode.LoadICU.iOS.cs" Condition="'$(IsiOSLike)' == 'true' or ('$(TargetsWasm)' == 'true' and '$(FeatureNativeAot)' == 'true')" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Guid.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Directory.Unix.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ internal static partial class GlobalizationMode
// validate this implementation detail.
private static partial class Settings
{
#if TARGET_WASM
internal static bool Invariant { get; } = true;
#else
internal static bool Invariant { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
#endif
#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS
internal static bool Hybrid { get; } = true;
#elif TARGET_BROWSER
Expand Down
14 changes: 8 additions & 6 deletions src/native/libs/System.Globalization.Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,6 @@ if(CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_WASI)
set_target_properties(System.Globalization.Native-Static PROPERTIES OUTPUT_NAME System.Globalization.Native CLEAN_DIRECT_OUTPUT 1)
endif()

if (CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI)
add_custom_command(TARGET System.Globalization.Native-Static
POST_BUILD
COMMAND ${CMAKE_AR} qL $<TARGET_FILE:System.Globalization.Native-Static> ${CMAKE_ICU_DIR}/lib/libicuuc.a ${CMAKE_ICU_DIR}/lib/libicui18n.a ${CMAKE_ICU_DIR}/lib/libicudata.a)
endif()

install (TARGETS System.Globalization.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)

if(NOT CLR_CMAKE_TARGET_APPLE AND NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_TARGET_LINUX_MUSL AND NOT CLR_CMAKE_TARGET_HAIKU)
Expand All @@ -180,6 +174,14 @@ if(NOT CLR_CMAKE_TARGET_APPLE AND NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE
endif()
endif()

# Package the ICU data files as static libraries for consumption by NativeAOT targeting WASM.
if (CLR_CMAKE_TARGET_ARCH_WASM)
add_library(System.Globalization.Native.Icudt STATIC icu_data_lib.c)
file(TO_CMAKE_PATH "${CMAKE_ICU_DIR}/lib/icudt.dat" icu_data_file)
target_compile_options(System.Globalization.Native.Icudt PRIVATE -DICU_DATA_FILE=${icu_data_file})
install(TARGETS System.Globalization.Native.Icudt DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)
endif()

if(CLR_CMAKE_TARGET_WIN32)
if(STATIC_LIBS_ONLY)
add_library(System.Globalization.Native.Aot
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Globalization.Native/icu_data_lib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#define STR_IMPL(x) #x
#define STR(x) STR_IMPL(x)

// Ideally, we would use actual assembly (.S), but Cmake doesn't recognize emcc as a valid assembler.
__asm(
" .section .data,\"\",@\n"
" .global static_icu_data\n"
" .align 16\n" // https://unicode-org.github.io/icu/userguide/icu_data/#alignment
"static_icu_data:\n"
" .incbin \"" STR(ICU_DATA_FILE) "\"\n"
"static_icu_data_end:\n"
" .size static_icu_data, static_icu_data_end - static_icu_data\n"
" .size static_icu_data_end, 1\n"
);
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,19 @@ GlobalizationNative_LoadICUData(const char* path)
}
#endif

#ifdef TARGET_WASM
extern char static_icu_data; // Linked-in data packaged via "icu_data_lib".
const char *icu_data = &static_icu_data;
#else // !TARGET_WASM

const char *icu_data = cstdlib_load_icu_data(path);

if (icu_data == NULL)
{
log_shim_error("Failed to load ICU data.");
return 0;
}
#endif // !TARGET_WASM

if (load_icu_data(icu_data) == 0)
{
Expand Down
26 changes: 15 additions & 11 deletions src/native/libs/build-native.proj
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,21 @@
<PackageReference Include="Microsoft.NETCore.Runtime.ICU.Transport" PrivateAssets="all" Version="$(MicrosoftNETCoreRuntimeICUTransportVersion)" GeneratePathProperty="true" />
</ItemGroup>

<Target Name="BuildNativeCommon"
DependsOnTargets="GenerateNativeVersionFile">
<ItemGroup>
<_IcuArtifacts Condition="'$(_IcuDir)' != '' and '$(TargetsAppleMobile)' != 'true'"
Include="$(_IcuDir)/lib/libicuuc.a;
$(_IcuDir)/lib/libicui18n.a;
$(_IcuDir)/lib/libicudata.a;
$(_IcuDir)/lib/*.dat" />
</ItemGroup>

<Copy SourceFiles="@(_IcuArtifacts)" DestinationFolder="$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'native', '$(_BuildNativeOutConfig)'))" SkipUnchangedFiles="true" />
</Target>
Comment on lines +33 to +44
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope to upstream changes to this file, and perhaps remove the duplicate copying done by wasm.proj/wasi.proj.


<Target Name="BuildNativeUnix"
DependsOnTargets="GenerateNativeVersionFile"
DependsOnTargets="BuildNativeCommon"
BeforeTargets="Build"
Condition="!$([MSBuild]::IsOsPlatform(Windows))">
<PropertyGroup>
Expand All @@ -54,21 +67,12 @@
<_BuildNativeUnixArgs>$(_BuildNativeArgs)$(_ProcessorCountArg)$(_PortableBuildArg)$(_CrossBuildArg)$(_BuildNativeCompilerArg)$(_KeepNativeSymbolsBuildArg)$(_CMakeArgs) $(Compiler)</_BuildNativeUnixArgs>
</PropertyGroup>

<ItemGroup>
<_IcuArtifacts Condition="'$(_IcuDir)' != '' and '$(TargetsAppleMobile)' != 'true'"
Include="$(_IcuDir)/lib/libicuuc.a;
$(_IcuDir)/lib/libicui18n.a;
$(_IcuDir)/lib/libicudata.a;
$(_IcuDir)/lib/*.dat" />
</ItemGroup>

<Copy SourceFiles="@(_IcuArtifacts)" DestinationFolder="$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'native', '$(_BuildNativeOutConfig)'))" SkipUnchangedFiles="true" />
<Message Text="$(MSBuildThisFileDirectory)build-native.sh $(_BuildNativeUnixArgs)" Importance="High"/>
<Exec Command="&quot;$(MSBuildThisFileDirectory)build-native.sh&quot; $(_BuildNativeUnixArgs)" />
</Target>

<Target Name="BuildNativeWindows"
DependsOnTargets="GenerateNativeVersionFile"
DependsOnTargets="BuildNativeCommon"
BeforeTargets="Build"
Condition="$([MSBuild]::IsOsPlatform(Windows))">
<PropertyGroup>
Expand Down
25 changes: 25 additions & 0 deletions src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Specialized;
using System.Globalization;

using CpObj;
using CkFinite;

Expand Down Expand Up @@ -399,6 +401,8 @@ private static unsafe int Main(string[] args)

TestPalRandom();

TestGlobalization();

TestDefaultConstructorOf();

TestStructUnboxOverload();
Expand Down Expand Up @@ -3963,6 +3967,27 @@ static void TestPalRandom()
EndTest(Guid.NewGuid() != Guid.NewGuid());
}

static void TestGlobalization()
{
StartTest("Test simple globalization");

CultureInfo jp = CultureInfo.GetCultureInfo("jp");
if (jp.CompareInfo.Compare("さようなら", "サヨウナラ", CompareOptions.IgnoreKanaType) != 0)
{
FailTest("Kana-insensitive comparison failed");
return;
}

CultureInfo ru = CultureInfo.GetCultureInfo("ru");
if (ru.TextInfo.ToTitleCase("до свидания") != "До Свидания")
{
FailTest("ToTitleCase(ru) comparison failed");
return;
}

PassTest();
}

static void TestDefaultConstructorOf()
{
StartTest("Test DefaultConstructorOf");
Expand Down