Skip to content

Commit 7767d46

Browse files
authored
Enable ICU on iOS (dotnet#48606)
1 parent 3fc3a22 commit 7767d46

26 files changed

Lines changed: 248 additions & 88 deletions

File tree

eng/testing/tests.mobile.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
MainLibraryFileName="$(MainLibraryFileName)"
177177
ForceAOT="$(RunAOTCompilation)"
178178
ForceInterpreter="$(MonoForceInterpreter)"
179+
InvariantGlobalization="$(InvariantGlobalization)"
179180
UseConsoleUITemplate="True"
180181
GenerateXcodeProject="True"
181182
BuildAppBundle="True"

src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,6 @@
184184
<PlatformManifestFileEntry Include="icudt_EFIGS.dat" IsNative="true" />
185185
<PlatformManifestFileEntry Include="icudt_optimal.dat" IsNative="true" />
186186
<PlatformManifestFileEntry Include="icudt_optimal_no_CJK.dat" IsNative="true" />
187-
<PlatformManifestFileEntry Include="libicui18n.a" IsNative="true" />
188-
<PlatformManifestFileEntry Include="libicuuc.a" IsNative="true" />
189187
<PlatformManifestFileEntry Include="binding_support.js" IsNative="true" />
190188
<PlatformManifestFileEntry Include="dotnet_support.js" IsNative="true" />
191189
<PlatformManifestFileEntry Include="library_mono.js" IsNative="true" />
@@ -197,6 +195,10 @@
197195
<PlatformManifestFileEntry Include="pinvoke.h" IsNative="true" />
198196
<PlatformManifestFileEntry Include="emcc-flags.txt" IsNative="true" />
199197
<PlatformManifestFileEntry Include="emcc-version.txt" IsNative="true" />
198+
<!-- ICU-specific files -->
199+
<PlatformManifestFileEntry Include="libicudata.a" IsNative="true" />
200+
<PlatformManifestFileEntry Include="libicui18n.a" IsNative="true" />
201+
<PlatformManifestFileEntry Include="libicuuc.a" IsNative="true" />
200202
</ItemGroup>
201203

202204
<ItemGroup>

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ public static partial class PlatformDetection
5050
public static bool IsNotFedoraOrRedHatFamily => !IsFedora && !IsRedHatFamily;
5151
public static bool IsNotDebian10 => !IsDebian10;
5252

53-
// Android
54-
public static bool IsAndroid => RuntimeInformation.IsOSPlatform(OSPlatform.Create("Android"));
55-
5653
public static bool IsSuperUser => IsBrowser || IsWindows ? false : libc.geteuid() == 0;
5754

5855
public static Version OpenSslVersion => !IsOSXLike && !IsWindows ?

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ public static partial class PlatformDetection
2626
public static bool IsMonoInterpreter => GetIsRunningOnMonoInterpreter();
2727
public static bool IsFreeBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD"));
2828
public static bool IsNetBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("NETBSD"));
29+
public static bool IsAndroid => RuntimeInformation.IsOSPlatform(OSPlatform.Create("Android"));
2930
public static bool IsiOS => RuntimeInformation.IsOSPlatform(OSPlatform.Create("IOS"));
3031
public static bool IstvOS => RuntimeInformation.IsOSPlatform(OSPlatform.Create("TVOS"));
3132
public static bool IsMacCatalyst => RuntimeInformation.IsOSPlatform(OSPlatform.Create("MACCATALYST"));
3233
public static bool Isillumos => RuntimeInformation.IsOSPlatform(OSPlatform.Create("ILLUMOS"));
3334
public static bool IsSolaris => RuntimeInformation.IsOSPlatform(OSPlatform.Create("SOLARIS"));
3435
public static bool IsBrowser => RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"));
3536
public static bool IsNotBrowser => !IsBrowser;
37+
public static bool IsNotMobile => IsNotBrowser && !IsMacCatalyst && !IsiOS && !IstvOS && !IsAndroid;
3638
public static bool IsNotNetFramework => !IsNetFramework;
3739

3840
public static bool IsArmProcess => RuntimeInformation.ProcessArchitecture == Architecture.Arm;
@@ -56,6 +58,9 @@ public static partial class PlatformDetection
5658
public static bool IsBrowserDomSupported => GetIsBrowserDomSupported();
5759
public static bool IsNotBrowserDomSupported => !IsBrowserDomSupported;
5860

61+
public static bool IsUsingLimitedCultures => !IsNotMobile;
62+
public static bool IsNotUsingLimitedCultures => IsNotMobile;
63+
5964
// Please make sure that you have the libgdiplus dependency installed.
6065
// For details, see https://docs.microsoft.com/dotnet/core/install/dependencies?pivots=os-macos&tabs=netcore31#libgdiplus
6166
public static bool IsDrawingSupported

src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ PALEXPORT int32_t GlobalizationNative_LoadICU(void);
88
PALEXPORT void GlobalizationNative_InitICUFunctions(void* icuuc, void* icuin, const char* version, const char* suffix);
99

1010
PALEXPORT int32_t GlobalizationNative_GetICUVersion(void);
11+
12+
#if defined(STATIC_ICU)
13+
14+
PALEXPORT int32_t GlobalizationNative_LoadICUData(char* path);
15+
16+
PALEXPORT const char* GlobalizationNative_GetICUDTName(const char* culture);
17+
18+
#endif

src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_static.c

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,99 @@ static void U_CALLCONV icu_trace_data(const void* context, int32_t fnNumber, int
3838
#ifdef __EMSCRIPTEN__
3939
#include <emscripten.h>
4040

41+
static int32_t load_icu_data(void* pData);
42+
4143
EMSCRIPTEN_KEEPALIVE const char* mono_wasm_get_icudt_name(const char* culture);
4244

4345
EMSCRIPTEN_KEEPALIVE const char* mono_wasm_get_icudt_name(const char* culture)
46+
{
47+
return GlobalizationNative_GetICUDTName(culture);
48+
}
49+
50+
EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void* pData);
51+
52+
EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void* pData)
53+
{
54+
return load_icu_data(pData);
55+
}
56+
57+
58+
/*
59+
* driver.c calls this to make sure this file is linked, otherwise
60+
* its not, meaning the EMSCRIPTEN_KEEPALIVE functions above
61+
* are not kept.
62+
*/
63+
void mono_wasm_link_icu_shim(void);
64+
65+
void mono_wasm_link_icu_shim(void)
66+
{
67+
}
68+
69+
#endif
70+
71+
static int32_t load_icu_data(void* pData)
72+
{
73+
74+
UErrorCode status = 0;
75+
udata_setCommonData(pData, &status);
76+
77+
if (U_FAILURE(status)) {
78+
log_icu_error("udata_setCommonData", status);
79+
return 0;
80+
} else {
81+
82+
#if defined(ICU_TRACING)
83+
// see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/tracing.md
84+
utrace_setFunctions(0, 0, 0, icu_trace_data);
85+
utrace_setLevel(UTRACE_VERBOSE);
86+
#endif
87+
isDataSet = 1;
88+
return 1;
89+
}
90+
}
91+
92+
int32_t GlobalizationNative_LoadICUData(char* path)
93+
{
94+
int32_t ret = -1;
95+
char* icu_data;
96+
97+
FILE *fp = fopen (path, "rb");
98+
if (fp == NULL) {
99+
fprintf (stderr, "Unable to load ICU dat file '%s'.", path);
100+
return ret;
101+
}
102+
103+
if (fseek (fp, 0L, SEEK_END) != 0) {
104+
fprintf (stderr, "Unable to determine size of the dat file");
105+
return ret;
106+
}
107+
108+
long bufsize = ftell (fp);
109+
110+
if (bufsize == -1) {
111+
fprintf (stderr, "Unable to determine size of the ICU dat file.");
112+
return ret;
113+
}
114+
115+
icu_data = malloc (sizeof (char) * (bufsize + 1));
116+
117+
if (fseek (fp, 0L, SEEK_SET) != 0) {
118+
fprintf (stderr, "Unable to seek ICU dat file.");
119+
return ret;
120+
}
121+
122+
fread (icu_data, sizeof (char), bufsize, fp);
123+
if (ferror ( fp ) != 0 ) {
124+
fprintf (stderr, "Unable to read ICU dat file");
125+
return ret;
126+
}
127+
128+
fclose (fp);
129+
130+
return load_icu_data (icu_data);
131+
}
132+
133+
const char* GlobalizationNative_GetICUDTName(const char* culture)
44134
{
45135
// Based on https://github.com/dotnet/icu/tree/maint/maint-67/icu-filters
46136

@@ -69,39 +159,6 @@ EMSCRIPTEN_KEEPALIVE const char* mono_wasm_get_icudt_name(const char* culture)
69159
return "icudt_no_CJK.dat";
70160
}
71161

72-
EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void * pData);
73-
74-
EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void * pData)
75-
{
76-
UErrorCode status = 0;
77-
udata_setCommonData(pData, &status);
78-
79-
if (U_FAILURE(status)) {
80-
log_icu_error("udata_setCommonData", status);
81-
return 0;
82-
} else {
83-
//// Uncomment to enable ICU tracing,
84-
//// see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/tracing.md
85-
// utrace_setFunctions(0, 0, 0, icu_trace_data);
86-
// utrace_setLevel(UTRACE_VERBOSE);
87-
isDataSet = 1;
88-
return 1;
89-
}
90-
}
91-
92-
/*
93-
* driver.c calls this to make sure this file is linked, otherwise
94-
* its not, meaning the EMSCRIPTEN_KEEPALIVE functions above
95-
* are not kept.
96-
*/
97-
void mono_wasm_link_icu_shim(void);
98-
99-
void mono_wasm_link_icu_shim(void)
100-
{
101-
}
102-
103-
#endif
104-
105162
int32_t GlobalizationNative_LoadICU(void)
106163
{
107164
if (!isDataSet) {

src/libraries/System.Globalization.Calendars/tests/CalendarTestWithConfigSwitch/CalendarTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace System.Globalization.Tests
1010
public static class CalendarTests
1111
{
1212
[Fact]
13+
[ActiveIssue("https://github.com/dotnet/runtime/issues/36883", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Android)]
1314
public static void TestJapaneseCalendarDateParsing()
1415
{
1516
CultureInfo ciJapanese = new CultureInfo("ja-JP") { DateTimeFormat = { Calendar = new JapaneseCalendar() } };
@@ -18,6 +19,8 @@ public static void TestJapaneseCalendarDateParsing()
1819
string eraName = dt.ToString("gg", ciJapanese);
1920

2021
// Legacy behavior which we used to throw when using a year number exceeding the era max year.
22+
//
23+
// On mobile, this does not throw, but instead produces a DateTime w/ 95/01/01
2124
Assert.ThrowsAny<FormatException>(() => DateTime.Parse(eraName + " 70/1/1 0:00:00", ciJapanese));
2225
}
2326
}

src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public void Normalize()
5151
// Form D
5252
VerifyConformanceInvariant(NormalizationForm.FormD, part0, part1, part2, part3, part4);
5353

54-
// Browser's ICU doesn't support FormKC and FormKD
55-
if (PlatformDetection.IsNotBrowser)
54+
// Mobile / Browser ICU doesn't support FormKC and FormKD
55+
if (PlatformDetection.IsNotUsingLimitedCultures)
5656
{
5757
// Form KC
5858
VerifyConformanceInvariant(NormalizationForm.FormKC, part0, part1, part2, part3, part4);

src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ public static IEnumerable<object[]> NormalizeTestData()
4949
yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormC, "\u1E9b\u0323" };
5050
yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormD, "\u017f\u0323\u0307" };
5151

52-
if (PlatformDetection.IsNotBrowser)
52+
if (PlatformDetection.IsNotUsingLimitedCultures)
5353
{
54-
// Browser's ICU doesn't support FormKC and FormKD
54+
// Mobile / Browser ICU doesn't support FormKC and FormKD
5555
yield return new object[] { "\uFB01", NormalizationForm.FormKC, "fi" };
5656
yield return new object[] { "\uFB01", NormalizationForm.FormKD, "fi" };
5757
yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormKC, "\u1E69" };

src/libraries/System.Globalization/tests/AssemblyInfo.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
using System;
55
using Xunit;
66

7-
[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/36883", TestPlatforms.iOS)]

0 commit comments

Comments
 (0)