diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md index 7600b3d7d480b4..c8182f9ff04306 100644 --- a/docs/workflow/trimming/feature-switches.md +++ b/docs/workflow/trimming/feature-switches.md @@ -13,6 +13,7 @@ configurations but their defaults might vary as any SDK can set the defaults dif | EnableUnsafeBinaryFormatterSerialization | System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization | BinaryFormatter serialization support is trimmed when set to false | | EventSourceSupport | System.Diagnostics.Tracing.EventSource.IsSupported | Any EventSource related code or logic is trimmed when set to false | | InvariantGlobalization | System.Globalization.Invariant | All globalization specific code and data is trimmed when set to true | +| HybridGlobalization | System.Globalization.Hybrid | Loading ICU + native implementations | | PredefinedCulturesOnly | System.Globalization.PredefinedCulturesOnly | Don't allow creating a culture for which the platform does not have data | | UseSystemResourceKeys | System.Resources.UseSystemResourceKeys | Any localizable resources for system assemblies is trimmed when set to true | | HttpActivityPropagationSupport | System.Net.Http.EnableActivityPropagation | Any dependency related to diagnostics support for System.Net.Http is trimmed when set to false | diff --git a/eng/testing/tests.ioslike.targets b/eng/testing/tests.ioslike.targets index 140de5099dda6f..905488251c2d7c 100644 --- a/eng/testing/tests.ioslike.targets +++ b/eng/testing/tests.ioslike.targets @@ -100,6 +100,7 @@ library test project. Eg. $(InvariantGlobalization) --> <_ApplePropertyNames Include="InvariantGlobalization" /> + <_ApplePropertyNames Include="HybridGlobalization" /> <_ApplePropertyNames Include="AssemblyName" /> <_ApplePropertyNames Include="MonoEnableLLVM" /> diff --git a/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs b/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs new file mode 100644 index 00000000000000..52882346b63222 --- /dev/null +++ b/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs @@ -0,0 +1,16 @@ +// 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.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)] + internal static unsafe partial string GetLocaleNameNative(string localeName); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoStringNative", StringMarshalling = StringMarshalling.Utf8)] + internal static unsafe partial string GetLocaleInfoStringNative(string localeName, uint localeStringData); + } +} diff --git a/src/libraries/System.Globalization/tests/Hybrid/Hybrid.Tests.csproj b/src/libraries/System.Globalization/tests/Hybrid/Hybrid.Tests.csproj new file mode 100644 index 00000000000000..5854a557a529cf --- /dev/null +++ b/src/libraries/System.Globalization/tests/Hybrid/Hybrid.Tests.csproj @@ -0,0 +1,10 @@ + + + $(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst;$(NetCoreAppCurrent)-osx + true + true + + + + + \ No newline at end of file diff --git a/src/libraries/System.Globalization/tests/Hybrid/HybridMode.cs b/src/libraries/System.Globalization/tests/Hybrid/HybridMode.cs new file mode 100644 index 00000000000000..f5443f8c2c3c01 --- /dev/null +++ b/src/libraries/System.Globalization/tests/Hybrid/HybridMode.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace System.Globalization.Tests +{ + public class HybridModeTests + { + public static IEnumerable EnglishName_TestData() + { + yield return new object[] { "en-US", "English (United States)" }; + yield return new object[] { "fr-FR", "French (France)" }; + } + + public static IEnumerable NativeName_TestData() + { + yield return new object[] { "en-US", "English (United States)" }; + yield return new object[] { "fr-FR", "français (France)" }; + yield return new object[] { "en-CA", "English (Canada)" }; + } + + [Theory] + [MemberData(nameof(EnglishName_TestData))] + public void TestEnglishName(string cultureName, string expected) + { + CultureInfo myTestCulture = new CultureInfo(cultureName); + Assert.Equal(expected, myTestCulture.EnglishName); + } + + [Theory] + [MemberData(nameof(NativeName_TestData))] + public void TestNativeName(string cultureName, string expected) + { + CultureInfo myTestCulture = new CultureInfo(cultureName); + Assert.Equal(expected, myTestCulture.NativeName); + } + + [Theory] + [InlineData("de-DE", "de")] + [InlineData("en-US", "en")] + public void TwoLetterISOLanguageName(string name, string expected) + { + Assert.Equal(expected, new CultureInfo(name).TwoLetterISOLanguageName); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 77ba3fe451347c..d8d5a97bf3c0fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -346,6 +346,7 @@ + @@ -1278,6 +1279,9 @@ Common\Interop\Interop.Locale.cs + + Common\Interop\Interop.Locale.OSX.cs + Common\Interop\Interop.Normalization.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs new file mode 100644 index 00000000000000..870d8504fb9678 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System.Globalization +{ + internal sealed partial class CultureData + { + /// + /// This method uses the sRealName field (which is initialized by the constructor before this is called) to + /// initialize the rest of the state of CultureData based on the underlying OS globalization library. + /// + private bool InitNativeCultureDataCore() + { + Debug.Assert(_sRealName != null); + Debug.Assert(!GlobalizationMode.Invariant); + string realNameBuffer = _sRealName; + + _sWindowsName = GetLocaleNameNative(realNameBuffer); + return true; + } + + internal static unsafe string GetLocaleNameNative(string localeName) + { + return Interop.Globalization.GetLocaleNameNative(localeName); + } + + private string GetLocaleInfoNative(LocaleStringData type) + { + Debug.Assert(!GlobalizationMode.Invariant); + Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfoNative] Expected _sWindowsName to be populated already"); + + return GetLocaleInfoNative(_sWindowsName, type); + } + + // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the + // "windows" name, which can be specific for downlevel (< windows 7) os's. + private static unsafe string GetLocaleInfoNative(string localeName, LocaleStringData type) + { + Debug.Assert(localeName != null, "[CultureData.GetLocaleInfoNative] Expected localeName to be not be null"); + + return Interop.Globalization.GetLocaleInfoStringNative(localeName, (uint)type); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index 079441b08d2e99..92037366b63891 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -2304,7 +2304,11 @@ private string GetLocaleInfoCoreUserOverride(LocaleStringData type) if (GlobalizationMode.Invariant) return null!; +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + return GlobalizationMode.Hybrid ? GetLocaleInfoNative(type) : IcuGetLocaleInfo(type); +#else return ShouldUseUserOverrideNlsData ? NlsGetLocaleInfo(type) : IcuGetLocaleInfo(type); +#endif } private string GetLocaleInfoCore(LocaleStringData type, string? uiCultureName = null) @@ -2313,7 +2317,11 @@ private string GetLocaleInfoCore(LocaleStringData type, string? uiCultureName = if (GlobalizationMode.Invariant) return null!; +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + return GlobalizationMode.Hybrid ? GetLocaleInfoNative(type) : IcuGetLocaleInfo(type, uiCultureName); +#else return GlobalizationMode.UseNls ? NlsGetLocaleInfo(type) : IcuGetLocaleInfo(type, uiCultureName); +#endif } private string GetLocaleInfoCore(string localeName, LocaleStringData type, string? uiCultureName = null) @@ -2322,7 +2330,11 @@ private string GetLocaleInfoCore(string localeName, LocaleStringData type, strin if (GlobalizationMode.Invariant) return null!; +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + return GlobalizationMode.Hybrid ? GetLocaleInfoNative(localeName, type) : IcuGetLocaleInfo(localeName, type, uiCultureName); +#else return GlobalizationMode.UseNls ? NlsGetLocaleInfo(localeName, type) : IcuGetLocaleInfo(localeName, type, uiCultureName); +#endif } private int[] GetLocaleInfoCoreUserOverride(LocaleGroupingData type) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index 4f69f980150412..b04985eedfc1a2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -13,6 +13,9 @@ 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_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + 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); } @@ -20,6 +23,9 @@ private static partial class Settings // This allows for the whole Settings nested class to be trimmed when Invariant=true, and allows for the Settings // static cctor (on Unix) to be preserved when Invariant=false. internal static bool Invariant => Settings.Invariant; +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + internal static bool Hybrid => Settings.Hybrid; +#endif internal static bool PredefinedCulturesOnly => Settings.PredefinedCulturesOnly; private static bool TryGetAppLocalIcuSwitchValue([NotNullWhen(true)] out string? value) => diff --git a/src/mono/msbuild/apple/build/AppleBuild.targets b/src/mono/msbuild/apple/build/AppleBuild.targets index 9e46315fa70f7c..61b656c3590d1e 100644 --- a/src/mono/msbuild/apple/build/AppleBuild.targets +++ b/src/mono/msbuild/apple/build/AppleBuild.targets @@ -249,6 +249,7 @@ GenerateCMakeProject="$(GenerateCMakeProject)" GenerateXcodeProject="$(GenerateXcodeProject)" InvariantGlobalization="$(InvariantGlobalization)" + HybridGlobalization="$(HybridGlobalization)" MainLibraryFileName="$(MainLibraryFileName)" MonoRuntimeHeaders="$(_MonoHeaderPath)" NativeMainSource="$(NativeMainSource)" diff --git a/src/native/libs/System.Globalization.Native/entrypoints.c b/src/native/libs/System.Globalization.Native/entrypoints.c index 8d4901f62dcf6d..10254d6256db4a 100644 --- a/src/native/libs/System.Globalization.Native/entrypoints.c +++ b/src/native/libs/System.Globalization.Native/entrypoints.c @@ -58,6 +58,10 @@ static const Entry s_globalizationNative[] = DllImportEntry(GlobalizationNative_ToAscii) DllImportEntry(GlobalizationNative_ToUnicode) DllImportEntry(GlobalizationNative_WindowsIdToIanaId) +#ifdef __APPLE__ + DllImportEntry(GlobalizationNative_GetLocaleNameNative) + DllImportEntry(GlobalizationNative_GetLocaleInfoStringNative) +#endif }; EXTERN_C const void* GlobalizationResolveDllImport(const char* name); diff --git a/src/native/libs/System.Globalization.Native/pal_locale.h b/src/native/libs/System.Globalization.Native/pal_locale.h index 1180c4919f4028..7ee6d1e7ee56e1 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.h +++ b/src/native/libs/System.Globalization.Native/pal_locale.h @@ -9,6 +9,10 @@ PALEXPORT int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLeng PALEXPORT int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength); +#ifdef __APPLE__ +PALEXPORT const char* GlobalizationNative_GetLocaleNameNative(const char* localeName); +#endif + PALEXPORT int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLength); PALEXPORT int32_t GlobalizationNative_IsPredefinedLocale(const UChar* localeName); diff --git a/src/native/libs/System.Globalization.Native/pal_locale.m b/src/native/libs/System.Globalization.Native/pal_locale.m index 2968735694fc44..7400c48b1c9ba6 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.m +++ b/src/native/libs/System.Globalization.Native/pal_locale.m @@ -3,8 +3,10 @@ #include #include "pal_locale_internal.h" +#include "pal_localeStringData.h" #import +#import char* DetectDefaultAppleLocaleName() { @@ -28,6 +30,129 @@ return strdup([localeName UTF8String]); } +#if defined(TARGET_OSX) || defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) + +const char* GlobalizationNative_GetLocaleNameNative(const char* localeName) +{ + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + const char* value = [currentLocale.localeIdentifier UTF8String]; + return strdup(value); +} + +const char* GlobalizationNative_GetLocaleInfoStringNative(const char* localeName, LocaleStringData localeStringData) +{ + const char* value; + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.locale = currentLocale; + NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:currentLocale]; + NSLocale *gbLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"]; + + + switch (localeStringData) + { + ///// localized name of locale, eg "German (Germany)" in UI language (corresponds to LOCALE_SLOCALIZEDDISPLAYNAME) + case LocaleString_LocalizedDisplayName: + /// Display name (language + country usually) in English, eg "German (Germany)" (corresponds to LOCALE_SENGLISHDISPLAYNAME) + case LocaleString_EnglishDisplayName: + value = [[gbLocale displayNameForKey:NSLocaleIdentifier value:currentLocale.localeIdentifier] UTF8String]; + break; + /// Display name in native locale language, eg "Deutsch (Deutschland) (corresponds to LOCALE_SNATIVEDISPLAYNAME) + case LocaleString_NativeDisplayName: + value = [[currentLocale displayNameForKey:NSLocaleIdentifier value:currentLocale.localeIdentifier] UTF8String]; + break; + /// Language Display Name for a language, eg "German" in UI language (corresponds to LOCALE_SLOCALIZEDLANGUAGENAME) + case LocaleString_LocalizedLanguageName: + /// English name of language, eg "German" (corresponds to LOCALE_SENGLISHLANGUAGENAME) + case LocaleString_EnglishLanguageName: + value = [[gbLocale localizedStringForLanguageCode:currentLocale.languageCode] UTF8String]; + break; + /// native name of language, eg "Deutsch" (corresponds to LOCALE_SNATIVELANGUAGENAME) + case LocaleString_NativeLanguageName: + value = [[currentLocale localizedStringForLanguageCode:currentLocale.languageCode] UTF8String]; + break; + /// English name of country, eg "Germany" (corresponds to LOCALE_SENGLISHCOUNTRYNAME) + case LocaleString_EnglishCountryName: + value = [[gbLocale localizedStringForCountryCode:currentLocale.countryCode] UTF8String]; + break; + /// native name of country, eg "Deutschland" (corresponds to LOCALE_SNATIVECOUNTRYNAME) + case LocaleString_NativeCountryName: + value = [[currentLocale localizedStringForCountryCode:currentLocale.countryCode] UTF8String]; + break; + case LocaleString_ThousandSeparator: + value = [currentLocale.groupingSeparator UTF8String]; + break; + case LocaleString_DecimalSeparator: + value = [currentLocale.decimalSeparator UTF8String]; + // or value = [[currentLocale objectForKey:NSLocaleDecimalSeparator] UTF8String]; + break; + case LocaleString_MonetarySymbol: + value = [currentLocale.currencySymbol UTF8String]; + break; + case LocaleString_Iso4217MonetarySymbol: + // check if this is correct, check currencyISOCode + value = [currentLocale.currencySymbol UTF8String]; + break; + case LocaleString_CurrencyEnglishName: + value = [[gbLocale localizedStringForCurrencyCode:currentLocale.currencyCode] UTF8String]; + break; + case LocaleString_CurrencyNativeName: + value = [[currentLocale localizedStringForCurrencyCode:currentLocale.currencyCode] UTF8String]; + break; + case LocaleString_AMDesignator: + value = [dateFormatter.AMSymbol UTF8String]; + break; + case LocaleString_PMDesignator: + value = [dateFormatter.PMSymbol UTF8String]; + break; + case LocaleString_PositiveSign: + value = [numberFormatter.plusSign UTF8String]; + break; + case LocaleString_NegativeSign: + value = [numberFormatter.minusSign UTF8String]; + break; + case LocaleString_Iso639LanguageTwoLetterName: + // check if this is correct + value = [[currentLocale objectForKey:NSLocaleLanguageCode] UTF8String]; + break; + case LocaleString_Iso3166CountryName: + value = [currentLocale.countryCode UTF8String]; + break; + case LocaleString_NaNSymbol: + value = [numberFormatter.notANumberSymbol UTF8String]; + break; + case LocaleString_PositiveInfinitySymbol: + value = [numberFormatter.positiveInfinitySymbol UTF8String]; + break; + case LocaleString_NegativeInfinitySymbol: + value = [numberFormatter.negativeInfinitySymbol UTF8String]; + break; + case LocaleString_PercentSymbol: + value = [numberFormatter.percentSymbol UTF8String]; + break; + case LocaleString_PerMilleSymbol: + value = [numberFormatter.perMillSymbol UTF8String]; + break; + // TODO find mapping for below cases + // https://github.com/dotnet/runtime/issues/83514 + case LocaleString_Digits: + case LocaleString_MonetaryDecimalSeparator: + case LocaleString_MonetaryThousandSeparator: + case LocaleString_Iso639LanguageThreeLetterName: + case LocaleString_ParentName: + case LocaleString_Iso3166CountryName2: + default: + value = ""; + break; + } + + return strdup(value); +} +#endif + #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) const char* GlobalizationNative_GetICUDataPathFallback(void) { diff --git a/src/native/libs/System.Globalization.Native/pal_localeStringData.h b/src/native/libs/System.Globalization.Native/pal_localeStringData.h index 3d1d26f91b4ebf..e6030d8a4cf86e 100644 --- a/src/native/libs/System.Globalization.Native/pal_localeStringData.h +++ b/src/native/libs/System.Globalization.Native/pal_localeStringData.h @@ -38,6 +38,7 @@ typedef enum LocaleString_Iso3166CountryName2= 0x00000068, LocaleString_NaNSymbol = 0x00000069, LocaleString_PositiveInfinitySymbol = 0x0000006a, + LocaleString_NegativeInfinitySymbol = 0x0000006b, LocaleString_ParentName = 0x0000006d, LocaleString_PercentSymbol = 0x00000076, LocaleString_PerMilleSymbol = 0x00000077 @@ -49,6 +50,10 @@ PALEXPORT int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeNam int32_t valueLength, const UChar* uiLocaleName); +#ifdef __APPLE__ +PALEXPORT const char* GlobalizationNative_GetLocaleInfoStringNative(const char* localeName, LocaleStringData localeStringData); +#endif + PALEXPORT int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, int shortFormat, UChar* value, int32_t valueLength); diff --git a/src/native/libs/System.Globalization.Native/pal_locale_internal.h b/src/native/libs/System.Globalization.Native/pal_locale_internal.h index c754554bbfdd55..1f9edb7640cbfb 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale_internal.h +++ b/src/native/libs/System.Globalization.Native/pal_locale_internal.h @@ -4,6 +4,7 @@ #pragma once #include "pal_icushim_internal.h" +#include "pal_localeStringData.h" /* Function: @@ -60,4 +61,21 @@ DetectDefaultSystemLocaleName Detects the default locale string for Apple platforms */ char* DetectDefaultAppleLocaleName(void); + +/* +Function: +GlobalizationNative_GetLocaleNameNative + +Returns native locale name for Apple platforms +*/ +const char* GlobalizationNative_GetLocaleNameNative(const char* localeName); + +/* +Function: +GlobalizationNative_GetLocaleInfoStringNative + +Returns string locale information if found for the specified locale name for Apple platforms. +Returns empty string if not found. +*/ +const char* GlobalizationNative_GetLocaleInfoStringNative(const char* localeName, LocaleStringData localeStringData); #endif diff --git a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs index f81357930a2e6a..e59e748a37c36d 100644 --- a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs +++ b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs @@ -152,6 +152,11 @@ public string TargetOS /// public bool InvariantGlobalization { get; set; } + /// + /// Forces the runtime to use hybrid(icu files + native functions) mode + /// + public bool HybridGlobalization { get; set; } + /// /// Forces the runtime to use the interpreter /// @@ -318,7 +323,7 @@ public override bool Execute() if (GenerateXcodeProject) { XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles, assemblerDataFiles, assemblerFilesToLink, extraLinkerArgs, - AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource, UseNativeAOTRuntime); + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, HybridGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource, UseNativeAOTRuntime); if (BuildAppBundle) { @@ -344,7 +349,7 @@ public override bool Execute() else if (GenerateCMakeProject) { generator.GenerateCMake(ProjectName, MainLibraryFileName, assemblerFiles, assemblerDataFiles, assemblerFilesToLink, extraLinkerArgs, - AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource, UseNativeAOTRuntime); + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, HybridGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource, UseNativeAOTRuntime); } return true; diff --git a/src/tasks/AppleAppBuilder/Templates/runtime.m b/src/tasks/AppleAppBuilder/Templates/runtime.m index 9cc38793dee6ae..b05389f09f6bda 100644 --- a/src/tasks/AppleAppBuilder/Templates/runtime.m +++ b/src/tasks/AppleAppBuilder/Templates/runtime.m @@ -241,6 +241,10 @@ setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", TRUE); #endif +#if HYBRID_GLOBALIZATION + setenv ("DOTNET_SYSTEM_GLOBALIZATION_HYBRID", "1", TRUE); +#endif + #if ENABLE_RUNTIME_LOGGING setenv ("MONO_LOG_LEVEL", "debug", TRUE); setenv ("MONO_LOG_MASK", "all", TRUE); diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index 6116fad4bceb88..1937e46c10166f 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -182,6 +182,7 @@ public string GenerateXCode( bool forceAOT, bool forceInterpreter, bool invariantGlobalization, + bool hybridGlobalization, bool optimized, bool enableRuntimeLogging, bool enableAppSandbox, @@ -190,7 +191,7 @@ public string GenerateXCode( string? nativeMainSource = null, bool useNativeAOTRuntime = false) { - var cmakeDirectoryPath = GenerateCMake(projectName, entryPointLib, asmFiles, asmDataFiles, asmLinkFiles, extraLinkerArgs, workspace, binDir, monoInclude, preferDylibs, useConsoleUiTemplate, forceAOT, forceInterpreter, invariantGlobalization, optimized, enableRuntimeLogging, enableAppSandbox, diagnosticPorts, runtimeComponents, nativeMainSource, useNativeAOTRuntime); + var cmakeDirectoryPath = GenerateCMake(projectName, entryPointLib, asmFiles, asmDataFiles, asmLinkFiles, extraLinkerArgs, workspace, binDir, monoInclude, preferDylibs, useConsoleUiTemplate, forceAOT, forceInterpreter, invariantGlobalization, hybridGlobalization, optimized, enableRuntimeLogging, enableAppSandbox, diagnosticPorts, runtimeComponents, nativeMainSource, useNativeAOTRuntime); CreateXcodeProject(projectName, cmakeDirectoryPath); return Path.Combine(binDir, projectName, projectName + ".xcodeproj"); } @@ -243,6 +244,7 @@ public string GenerateCMake( bool forceAOT, bool forceInterpreter, bool invariantGlobalization, + bool hybridGlobalization, bool optimized, bool enableRuntimeLogging, bool enableAppSandbox, @@ -436,6 +438,11 @@ public string GenerateCMake( defines.AppendLine("add_definitions(-DINVARIANT_GLOBALIZATION=1)"); } + if (hybridGlobalization) + { + defines.AppendLine("add_definitions(-DHYBRID_GLOBALIZATION=1)"); + } + if (enableRuntimeLogging) { defines.AppendLine("add_definitions(-DENABLE_RUNTIME_LOGGING=1)");