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

[iOS] Introduce support for linking ICU libs #97216

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3681a84
Create separate lib System.HybridGlobalization.Native
mkhamoyan Jan 19, 2024
6fd58f0
Fix build on Apple platforms
mkhamoyan Jan 22, 2024
d0a6820
HYBRID_GLOBALIZATION_DLL_NAME define only for Apple
mkhamoyan Jan 22, 2024
9d91003
Fix build failure
mkhamoyan Jan 22, 2024
29a248e
Fix non-Apple build
mkhamoyan Jan 22, 2024
8bc9d03
Fix syntax error
mkhamoyan Jan 22, 2024
50f4ce8
Fix linux builds
mkhamoyan Jan 22, 2024
b082055
Fix duplicate symbol issue
mkhamoyan Jan 23, 2024
e1ac526
Filter in Xcode libs depending on hybrid mode, pinvoke changes
mkhamoyan Jan 23, 2024
1566200
Revert not needed changes
mkhamoyan Jan 23, 2024
f660f6d
Revert changes
mkhamoyan Jan 23, 2024
4d009b1
Fix ICU lib flow
mkhamoyan Jan 23, 2024
f5d2926
Change hybrid casing and idn functions
mkhamoyan Jan 23, 2024
9f00a46
Merge branch 'main' into support_icu_libs
mkhamoyan Jan 25, 2024
a7cc352
temporary solution for library mode not include hybrid libs
mkhamoyan Jan 25, 2024
0587d2d
Merge branch 'main' into support_icu_libs
mkhamoyan Jan 25, 2024
01f9da0
Merge branch 'support_icu_libs' of https://github.com/mkhamoyan/runti…
mkhamoyan Jan 25, 2024
376dcb0
Refactoring and running tests on hybrid mode
mkhamoyan Jan 26, 2024
7534dc6
When hybrid mode don't include icu libs
mkhamoyan Jan 29, 2024
4db5989
Merge branch 'main' into support_icu_libs
mkhamoyan Jan 29, 2024
0ede71f
Fix syntax error
mkhamoyan Jan 29, 2024
6e3dc61
Fix OSX build failure
mkhamoyan Jan 29, 2024
23d91d9
Remove unused code
mkhamoyan Jan 30, 2024
2263998
Remove PKG_CONFIG_PATH info
mkhamoyan Jan 30, 2024
fc5d2c5
Move libe code under System.Globalization.Native
mkhamoyan Jan 31, 2024
7f436a7
Fix build
mkhamoyan Jan 31, 2024
910d640
Fix windows build
mkhamoyan Jan 31, 2024
7342955
clean up the code
mkhamoyan Jan 31, 2024
23f15fb
clean up the code, test both ICU and hybrid on CI
mkhamoyan Jan 31, 2024
9bef7b5
Merge branch 'main' into support_icu_libs
mkhamoyan Jan 31, 2024
aaacddb
Fix build
mkhamoyan Jan 31, 2024
e0fb75c
Make hybrid mode enabled by default
mkhamoyan Jan 31, 2024
9294637
Change setting Hybrid property
mkhamoyan Feb 1, 2024
f869884
Remove redundant test suites and add System.Globalization.Tests for iOS
mkhamoyan Feb 1, 2024
bbfed76
Fix HybridGlobalization value check
mkhamoyan Feb 9, 2024
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
2 changes: 2 additions & 0 deletions eng/pipelines/common/evaluate-default-paths.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ jobs:
- src/libraries/System.Private.CoreLib/*
- src/native/libs/Common/*
- src/native/libs/System.Globalization.Native/*
- src/native/libs/System.HybridGlobalization.Native/*
- src/native/libs/System.IO.Compression.Native/*
exclude:
- eng/Version.Details.xml
Expand All @@ -109,6 +110,7 @@ jobs:
- src/libraries/System.Private.CoreLib/*
- src/native/libs/Common/*
- src/native/libs/System.Globalization.Native/*
- src/native/libs/System.HybridGlobalization.Native/*
- src/native/libs/System.IO.Compression.Native/*
exclude:
- ${{ parameters._const_paths._wasm_specific_only }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ The .NET Foundation licenses this file to you under the MIT license.

<ItemGroup>
<NetCoreAppNativeLibrary Include="System.Native" />
<NetCoreAppNativeLibrary Include="System.Globalization.Native" Condition="'$(StaticICULinking)' != 'true' and '$(InvariantGlobalization)' != 'true'" />
<NetCoreAppNativeLibrary Include="System.Globalization.Native" Condition="'$(StaticICULinking)' != 'true' and '$(InvariantGlobalization)' != 'true' and (('$(_IsiOSLikePlatform)' == 'true' and '$(HybridGlobalization)' != 'true') or '$(_IsiOSLikePlatform)' != 'true')" />
<NetCoreAppNativeLibrary Include="System.HybridGlobalization.Native" Condition="'$(_IsiOSLikePlatform)' == 'true' and '$(StaticICULinking)' != 'true' and '$(InvariantGlobalization)' != 'true' and '$(HybridGlobalization)' == 'true'" />
Copy link
Member

Choose a reason for hiding this comment

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

If I understood the motivation for this PR correctly, hybrid globalization is the new default for iOS-like platforms. However, these lines will include System.HybridGlobalization.Native library only if HybridGlobalization=true.

What are the expectations on where HybridGlobalization MSBuild property would be set?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Motivation of this PR is to support our ICU libs on Apple platforms (as currently that is not possible).
By these changes we are creating 2 separate libraries

  • System.Globalization.Native - this will include our ICU libs
  • System.HybridGlobalization.Native - this is only for Hybrid mode, using native implementations for globalization

Hence System.HybridGlobalization.Native library will be included only if HybridGlobalization=true.
If HybridGlobalization=false we will include System.Globalization.Native which is getting globalization data using our ICU libs.

Copy link
Member

Choose a reason for hiding this comment

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

I see, thank you for the explanation.

However, I am still confused with:

we only support hybrid mode on Apple platforms

Does that mean that in this new default setting, we should start linking against System.HybridGlobalization.Native by default?
And if that is the case, then HybridGlobalization=true would have to be set somewhere early in SDK

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Default mode is implemented such that if the user does not enable Invariant mode, the Hybrid mode is automatically enabled. (see https://github.com/dotnet/runtime/pull/97216/files#diff-2884e8c39a88d26cb57ef06adca164f61238c4ad1c593d8e38bcb167212faa38R18 and https://github.com/dotnet/runtime/pull/97216/files#diff-45555715c5a7b53d8311327e5515c313f9e1c316f612af23fb84b5859a5c48ccR479).

If user wants to use ICU libs then they need to disable HybridGlobalization.

Copy link
Member

Choose a reason for hiding this comment

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

the Hybrid mode is automatically enabled

It is not how this build logic works. If the user does not set Hybrid mode explicitly by setting the HybridGlobalization to true, this build logic is going to default to ICU.

Copy link
Member

Choose a reason for hiding this comment

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

Right, it is how it should work; but it is not what https://github.com/dotnet/runtime/pull/97216/files#diff-a8c821001409a0c4d6589a59e663d4d07e53b0127b345f17640410828c580b37R118-R119 does.

When the HybridGlobalization property is not set, '$(HybridGlobalization)' == 'true' is going to be false and it is going to default to ICU.

Copy link
Member

@ilonatommy ilonatommy Feb 9, 2024

Choose a reason for hiding this comment

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

For clarification: MsBuild properties have 3 states, true, false, undefined. When the property is not set then it's not false, it's undefined.

Copy link
Member

Choose a reason for hiding this comment

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

The intent is to default to hybrid. That may mean setting the value explicitly to true or defining another setting to enable icu in the sdk.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, it is how it should work; but it is not what https://github.com/dotnet/runtime/pull/97216/files#diff-a8c821001409a0c4d6589a59e663d4d07e53b0127b345f17640410828c580b37R118-R119 does.

When the HybridGlobalization property is not set, '$(HybridGlobalization)' == 'true' is going to be false and it is going to default to ICU.

I see, I will change this part to check if '$(HybridGlobalization)' == 'false' or '$(HybridGlobalization)' != 'false'.

Copy link
Member

Choose a reason for hiding this comment

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

I would like to say that the improvements which hybrid globalization is bringing to both Mono and NativeAOT on iOS are amazing, and thanks @mkhamoyan and the whole team for your hard work and making this possible!

The remark I made on these lines of code seem to match the intended behaviour with the latest commit. However, I think this is only one piece of the puzzle which solves only the NativeAOT builds.

HybridGlobalization as a feature switch

As I mentioned in my comment, I think that for changes like these, when we are potentially breaking our internal and/or external customers, a better approach would be to first introduce a MSBuild property "feature switch" (for example in https://github.com/dotnet/sdk) which would be HybridGlobalization=false at first.
After that, do the implementation and make all the required changes in all our relevant repositories (dotnet/runtime, xamarin/xamarin-macios, dotnet/maui) taking into account this new features switch and test internally with HybridGlobalization=true as the changes flow in (this would potentially get better with dotnet/dotnet, but we are not there yet).
If everything works, throughout our whole stack (E2E testing passes), then simply flip the switch in the dotnet/sdk to true and announce it is the new default.
This could still break our external customers, but at least internally we made sure that we provided ways to integrate and adapt to the new change.

On the other hand, regarding questions around Mono components and their build integration #97216 (comment), this seems to be a different use case.
For Mono native components like: hot_reload, debugger, diagnostics_tracing, marshal-ilgen Mono provides both: an empty native lib version - "stub" (when the component is not needed/used) and the actual native lib with the implementation.
To toggle between what needs to be linked with the final app and to enable other build systems to specify which components should be included in the build Mono provides -> RuntimeComponentManifest.targets
and item groups: _MonoRuntimeComponentDontLink and _MonoRuntimeComponentLink.
Xamarin already implements this through: https://github.com/xamarin/xamarin-macios/blob/282d107a02d80e04a1eca780f022966d52c50215/dotnet/targets/Xamarin.Shared.Sdk.targets#L442-L461

This is a great approach, but the changes introduced here do not seem to fit. We will have two globalization libraries that we ship, but we need to link only against one of them, and according to: https://github.com/xamarin/xamarin-macios/blob/282d107a02d80e04a1eca780f022966d52c50215/dotnet/targets/Xamarin.Shared.Sdk.targets#L1134-L1141
with this PR, we would probably end up in build failures, as we would be linking against both: System.Globalization.Native and System.HybridGlobalization.Native.
This is where a global sdk-level feature switch would play a role, as the build systems (internal or external) would have a single source of truth and know which library to link against.

Another way to provide native dependencies

One thing to note is that NativeAOT also supports native components and switching them on and off (libeventpipe-enabled/disabled, libstandalonegc-enabled/disabled), but the NativeAOT build system resolves this on its own, and can provide native linker switches and dependencies for integrators to utilize and expand upon:

<ItemGroup>
<NativeLibrary Condition="'$(IlcMultiModule)' == 'true'" Include="$(SharedLibrary)" />
<NativeLibrary Condition="'$(NativeLib)' == '' and '$(CustomNativeMain)' != 'true'" Include="$(IlcSdkPath)libbootstrapper.o" />
<NativeLibrary Condition="'$(NativeLib)' != '' or '$(CustomNativeMain)' == 'true'" Include="$(IlcSdkPath)libbootstrapperdll.o" />
<NativeLibrary Include="$(IlcSdkPath)$(FullRuntimeName).a" />
<NativeLibrary Include="$(IlcSdkPath)$(EventPipeName)$(LibFileExt)" />
<NativeLibrary Include="$(IlcSdkPath)$(StandaloneGCSupportName)$(LibFileExt)" />
<NativeLibrary Condition="'$(LinkStandardCPlusPlusLibrary)' != 'true' and '$(StaticICULinking)' != 'true'" Include="$(IlcSdkPath)libstdc++compat.a" />
</ItemGroup>

This approach is also supported by the Xamarin build system: https://github.com/xamarin/xamarin-macios/blob/282d107a02d80e04a1eca780f022966d52c50215/dotnet/targets/Xamarin.Shared.Sdk.targets#L1357-L1362

As the hybrid globalization change is a bit unique (and maybe in the future we will figure their would be a new implementation of say: System.Security.Cryptography.Native.Apple) we might want to provide the way for Mono to also resolve the native dependencies on its own (similarly to how NativeAOT does it) for example in: Microsoft.NET.Runtime.MonoTargets.Sdk https://github.com/dotnet/runtime/blob/64204a583ec9563b67b4e9d06538bbf46dcb29ca/src/mono/nuget/Microsoft.NET.Runtime.MonoTargets.Sdk/Microsoft.NET.Runtime.MonoTargets.Sdk.pkgproj package where RuntimeComponentManifest.targets already lives and is provided with workload installation. This way we would simplify the build integrations process altogether and make a first step towards having a runtime-agnostic integration.


These are my two cents, and please let me know if I can help in this effort to unblock the feature getting into the upcoming releases, as it brings great size saving for our customers targeting iOS platforms.

<NetCoreAppNativeLibrary Include="System.IO.Compression.Native" />
<NetCoreAppNativeLibrary Include="System.Net.Security.Native" Condition="!$(_targetOS.StartsWith('tvos')) and '$(_linuxLibcFlavor)' != 'bionic'" />
<NetCoreAppNativeLibrary Include="System.Security.Cryptography.Native.Apple" Condition="'$(_IsApplePlatform)' == 'true'" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
<ItemGroup>
<_pastShimFiles Include="System.Globalization.Native.dylib" />
<_pastShimFiles Include="System.Globalization.Native.so" />
<_pastShimFiles Include="System.HybridGlobalization.Native.dylib" />
<_pastShimFiles Include="System.HybridGlobalization.Native.so" />
<_pastShimFiles Include="System.IO.Compression.Native.a" />
<_pastShimFiles Include="System.IO.Compression.Native.dylib" />
<_pastShimFiles Include="System.IO.Compression.Native.so" />
Expand Down Expand Up @@ -80,6 +82,9 @@
<PlatformManifestFileEntry Include="libSystem.Globalization.Native.a" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Globalization.Native.dylib" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Globalization.Native.so" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.HybridGlobalization.Native.a" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.HybridGlobalization.Native.dylib" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.HybridGlobalization.Native.so" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.IO.Compression.Native.a" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.IO.Compression.Native.dylib" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.IO.Compression.Native.so" IsNative="true" />
Expand Down
8 changes: 4 additions & 4 deletions src/libraries/Common/src/Interop/Interop.Calendar.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ internal static partial class Interop
{
internal static partial class Globalization
{
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetCalendarsNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetCalendarsNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int GetCalendarsNative(string localeName, CalendarId[] calendars, int calendarsCapacity);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetCalendarInfoNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetCalendarInfoNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial string GetCalendarInfoNative(string localeName, CalendarId calendarId, CalendarDataType calendarDataType);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLatestJapaneseEraNative")]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLatestJapaneseEraNative")]
internal static partial int GetLatestJapaneseEraNative();

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetJapaneseEraStartDateNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetJapaneseEraStartDateNative", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool GetJapaneseEraStartDateNative(int era, out int startYear, out int startMonth, out int startDay);

Expand Down
7 changes: 5 additions & 2 deletions src/libraries/Common/src/Interop/Interop.Casing.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ internal static partial class Interop
{
internal static partial class Globalization
{
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int ChangeCaseNative(string localeName, int lNameLen, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, [MarshalAs(UnmanagedType.Bool)] bool bToUpper);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseInvariantNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseInvariantNative", StringMarshalling = StringMarshalling.Utf8)]
internal static unsafe partial int ChangeCaseInvariantNative(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, [MarshalAs(UnmanagedType.Bool)] bool bToUpper);

[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_InitOrdinalCasingPage", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial void InitOrdinalCasingPageNative(int pageNumber, char* pTarget);
}
}
10 changes: 5 additions & 5 deletions src/libraries/Common/src/Interop/Interop.Collation.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ internal struct Range

internal static partial class Globalization
{
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_CompareStringNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_CompareStringNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int CompareStringNative(string localeName, int lNameLen, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_EndsWithNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_EndsWithNative", StringMarshalling = StringMarshalling.Utf16)]
[MethodImpl(MethodImplOptions.NoInlining)]
internal static unsafe partial int EndsWithNative(string localeName, int lNameLen, char* target, int cwTargetLength, char* source, int cwSourceLength, CompareOptions options);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_IndexOfNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_IndexOfNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial Range IndexOfNative(string localeName, int lNameLen, char* target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, [MarshalAs(UnmanagedType.Bool)] bool fromBeginning);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_StartsWithNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_StartsWithNative", StringMarshalling = StringMarshalling.Utf16)]
[MethodImpl(MethodImplOptions.NoInlining)]
internal static unsafe partial int StartsWithNative(string localeName, int lNameLen, char* target, int cwTargetLength, char* source, int cwSourceLength, CompareOptions options);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetSortKeyNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetSortKeyNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int GetSortKeyNative(string localeName, int lNameLen, char* str, int strLength, byte* sortKey, int sortKeyLength, CompareOptions options);
}
}
17 changes: 17 additions & 0 deletions src/libraries/Common/src/Interop/Interop.Idna.iOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Globalization
{

[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_ToAscii", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int ToAsciiNative(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);

[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_ToUnicode", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int ToUnicodeNative(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
}
}
18 changes: 9 additions & 9 deletions src/libraries/Common/src/Interop/Interop.Locale.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@ internal static partial class Interop
{
internal static partial class Globalization
{
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetDefaultLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetDefaultLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial string GetDefaultLocaleNameNative();

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoStringNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoStringNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial string GetLocaleInfoStringNative(string localeName, uint localeStringData, string? uiLocaleName = null);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoIntNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoIntNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int GetLocaleInfoIntNative(string localeName, uint localeNumberData);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int GetLocaleInfoPrimaryGroupingSizeNative(string localeName, uint localeGroupingData);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int GetLocaleInfoSecondaryGroupingSizeNative(string localeName, uint localeGroupingData);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial string GetLocaleNameNative(string localeName);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocalesNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocalesNative", StringMarshalling = StringMarshalling.Utf16)]
internal static partial int GetLocalesNative([Out] char[]? value, int valueLength);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleTimeFormatNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleTimeFormatNative", StringMarshalling = StringMarshalling.Utf8)]
internal static partial string GetLocaleTimeFormatNative(string localeName, [MarshalAs(UnmanagedType.Bool)] bool shortFormat);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_IsPredefinedLocaleNative", StringMarshalling = StringMarshalling.Utf8)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_IsPredefinedLocaleNative", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool IsPredefinedLocaleNative(string localeName);
}
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/Common/src/Interop/Interop.Normalization.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ internal static partial class Interop
{
internal static partial class Globalization
{
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_IsNormalizedNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_IsNormalizedNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int IsNormalizedNative(NormalizationForm normalizationForm, char* src, int srcLen);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_NormalizeStringNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_NormalizeStringNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int NormalizeStringNative(NormalizationForm normalizationForm, char* src, int srcLen, char* buffer, int bufferLength);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Globalization
{
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetTimeZoneDisplayNameNative", StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(Libraries.HybridGlobalizationNative, EntryPoint = "GlobalizationNative_GetTimeZoneDisplayNameNative", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial ResultCode GetTimeZoneDisplayNameNative(
string localeName,
int lNameLength,
Expand Down
1 change: 1 addition & 0 deletions src/libraries/Common/src/Interop/Unix/Interop.Libraries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal static partial class Libraries
internal const string CryptoNative = "libSystem.Security.Cryptography.Native.OpenSsl";
internal const string CompressionNative = "libSystem.IO.Compression.Native";
internal const string GlobalizationNative = "libSystem.Globalization.Native";
internal const string HybridGlobalizationNative = "libSystem.HybridGlobalization.Native";
internal const string IOPortsNative = "libSystem.IO.Ports.Native";
internal const string HostPolicy = "libhostpolicy";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,9 @@
<Compile Include="$(CommonPath)Interop\Interop.Idna.cs">
<Link>Common\Interop\Interop.Idna.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Interop.Idna.iOS.cs" Condition="'$(IsiOSLike)' == 'true'">
<Link>Common\Interop\Interop.Idna.iOS.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Interop.Locale.cs">
<Link>Common\Interop\Interop.Locale.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ private static partial class Settings
/// the GlobalizationMode.Invariant check. Globalization P/Invokes, e.g. in CompareInfo.GetSortKey,
/// rely on ICU already being loaded before they are called.
/// </summary>
#if !TARGET_MACCATALYST && !TARGET_IOS && !TARGET_TVOS
static Settings()
{
#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS
if (GlobalizationMode.Hybrid)
return;
#endif
// Use GlobalizationMode.Invariant to allow ICU initialization to be trimmed when Invariant=true
// and PredefinedCulturesOnly is unspecified.
if (!GlobalizationMode.Invariant)
Expand All @@ -33,7 +36,6 @@ static Settings()
}
}
}
#endif

private static string GetIcuLoadFailureMessage()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ internal static partial class GlobalizationMode
private static partial class Settings
{
internal static bool Invariant { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS
internal static bool Hybrid { get; } = true;
#elif TARGET_BROWSER

#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER
internal static bool Hybrid { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.Hybrid", "DOTNET_SYSTEM_GLOBALIZATION_HYBRID");
#endif
internal static bool PredefinedCulturesOnly { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", GlobalizationMode.Invariant);
Expand Down
Loading
Loading