Closed rolfbjarne closed 5 months ago
CC @steveisok
This completely breaks the simulator for us, so it's rather urgent to get it fixed (and any fixes would have to be backported to .NET 8)
Tagging subscribers to this area: @dotnet/area-system-globalization See info in area-owners.md if you want to be subscribed.
Author: | rolfbjarne |
---|---|
Assignees: | - |
Labels: | `area-System.Globalization`, `untriaged`, `os-ios` |
Milestone: | - |
CC @akoeplinger
/cc @matouskozak @ivanpovazan
@rolfbjarne @tarekgh @vitek-karas this is net8 so it isn't using hybrid globalization
CC @steveisok
This completely breaks the simulator for us, so it's rather urgent to get it fixed (and any fixes would have to be backported to .NET 8)
Weird, I'm mentioned, but got no notification of this. @rolfbjarne confirming this is off of a .net 8 runtime?
@lewing I didn't claim it is from hybird globalization :smile:
looking at the stack
24 libicucore.A.dylib 0x181dc5838 icu::SimpleDateFormat::SimpleDateFormat(icu::DateFormat::EStyle, icu::DateFormat::EStyle, icu::Locale const&, UErrorCode&) + 160
25 libicucore.A.dylib 0x181dc5720 icu::DateFormat::create(icu::DateFormat::EStyle, icu::DateFormat::EStyle, icu::Locale const&) + 144
26 libicucore.A.dylib 0x181dc5590 udat_open + 392
27 CoreFoundation 0x18049f540 __cficu_udat_open + 68
28 CoreFoundation 0x1803c3d68 __ResetUDateFormat + 484
29 CoreFoundation 0x1803c367c __CreateCFDateFormatter + 320
30 CoreFoundation 0x18049b4c0 -[NSDate descriptionWithLocale:] + 96
31 libxamarin-dotnet-debug.dylib 0x1129fcb8c xamarin_dyn_objc_msgSend + 160
It is the calls to the CoreFoundation. I believe @steveisok is familiar with that stack. Something in the code https://github.com/dotnet/runtime/blob/62304a6d7085e32672ec988835eab41d89b82e25/src/native/libs/System.Globalization.Native/pal_locale.m#L96
looking at the stack
24 libicucore.A.dylib 0x181dc5838 icu::SimpleDateFormat::SimpleDateFormat(icu::DateFormat::EStyle, icu::DateFormat::EStyle, icu::Locale const&, UErrorCode&) + 160 25 libicucore.A.dylib 0x181dc5720 icu::DateFormat::create(icu::DateFormat::EStyle, icu::DateFormat::EStyle, icu::Locale const&) + 144 26 libicucore.A.dylib 0x181dc5590 udat_open + 392 27 CoreFoundation 0x18049f540 __cficu_udat_open + 68 28 CoreFoundation 0x1803c3d68 __ResetUDateFormat + 484 29 CoreFoundation 0x1803c367c __CreateCFDateFormatter + 320 30 CoreFoundation 0x18049b4c0 -[NSDate descriptionWithLocale:] + 96 31 libxamarin-dotnet-debug.dylib 0x1129fcb8c xamarin_dyn_objc_msgSend + 160
It is the calls to the CoreFoundation. I believe @steveisok is familiar with that stack. Something in the code
Calls to CoreFoundation are because of this block in AppDelegate.cs.
var date = NSDate.Now;
var locale = NSLocale.SystemLocale;
var str = date.DescriptionWithLocale (locale);
Most of the functions from runtime/src/native/libs/System.Globalization.Native/pal_locale.m will not be used in described scenario , only some of them like https://github.com/dotnet/runtime/blob/62304a6d7085e32672ec988835eab41d89b82e25/src/native/libs/System.Globalization.Native/pal_locale.m#L17 but from stacktrace these functions are not called.
CC @steveisok This completely breaks the simulator for us, so it's rather urgent to get it fixed (and any fixes would have to be backported to .NET 8)
Weird, I'm mentioned, but got no notification of this. @rolfbjarne confirming this is off of a .net 8 runtime?
Confirmed, this is with stable versions of everything (except Xcode).
This is strange. This seems to be bypassing our globalization PAL. If true, that's unexpected and likely some kind of clash as @rolfbjarne suggested.
@rolfbjarne am I correct in seeing that the objc bindings are bypassing runtime?
This is strange. This seems to be bypassing our globalization PAL. If true, that's unexpected and likely some kind of clash as @rolfbjarne suggested.
@rolfbjarne am I correct in seeing that the objc bindings are bypassing runtime?
I'm not really sure what you mean. Our Objective-C bindings call iOS APIs, in this case in particular, [NSDate descriptionWithLocale:]
. I see no reason for NSDate
to call anything in the runtime's globalization PAL.
I'm not really sure what you mean. Our Objective-C bindings call iOS APIs, in this case in particular,
[NSDate descriptionWithLocale:]
. I see no reason forNSDate
to call anything in the runtime's globalization PAL.
That's good enough. You're confirming what I thought. I'm not sure exactly what to do here. I wonder if it worked previously by luck? Perhaps the icu version on that simulator has changed?
@akoeplinger since you've seen icu clashes like this before, any thoughts?
Xcode 15.3 RC 1 is out and unfortunately we can still repro the issue
Perhaps the icu version on that simulator has changed?
That might be it. Looking at the difference between versions:
diff \
/Applications/Xcode_15.3.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/libicucore.A.tbd \
/Applications/Xcode_15.2.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/libicucore.A.tbd
shows:
< current-version: 74.1
---
> current-version: 72.1
On the other hand, our latest Microsoft.NETCore.Runtime.ICU.Transport 9.0.0-preview.3.24123.1
seems to include: ICU_version = 68.2.0.9
This is pretty weird, according to the stacktrace this called into the system ICU libicucore.A.dylib since we don't ship a .dylib for icu.
If I had to guess it's maybe using our uprv_free
in https://github.com/unicode-org/icu/blob/2d029329c82c7792b985024b2bdab5fc7278fbc8/icu4c/source/common/locid.cpp#L2022-L2039 instead of theirs?
One workaround that I think might be acceptable risk-wise is to rename the exported symbols to have e.g. a dotnet_
prefix. There is some functionality in urename.h that could be used.
One workaround that I think might be acceptable risk-wise is to rename the exported symbols to have e.g. a
dotnet_
prefix. There is some functionality in urename.h that could be used.
We did this numerous times in Mono.
@steveisok .NET 9 seems to be working fine
@steveisok / @vitek-karas any news on this issue?
One workaround that I think might be acceptable risk-wise is to rename the exported symbols to have e.g. a
dotnet_
prefix. There is some functionality in urename.h that could be used.
@dalexsoto looks like we're going to try this approach. Unsure of an ETA at this time.
I managed to repro and @rolfbjarne thank you for providing the workaround:
<PropertyGroup>
<_LibXamarinLinkMode>static</_LibXamarinLinkMode>
<_LibMonoLinkMode>static</_LibMonoLinkMode>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<Target Name="_FixMonoLinkMode" AfterTargets="_MonoReadAvailableComponentsManifest">
<ItemGroup>
<_MonoRuntimeComponentLinking Remove="dynamic" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-arm64" />
</ItemGroup>
</Target>
Although the app seems to work with just forcing static linking (we don't have to additionally disable globalization via <InvariantGlobalization>true</InvariantGlobalization>
as a workaround) which also hints there is a problem with the exported symbols
Xcode 15.3 is now stable, and the crash still happens.
@matouskozak is actively working on this now.
Thanks @rolfbjarne. This bug was a ** to try to work around. I began to suspect bad SDK installations on my machine.
Your workaround fails on my setup, however, unless I remove this line:
<_MonoRuntimeComponentLinking Remove="dynamic" />
Otherwise the build complains with:
/usr/local/share/dotnet/packs/Microsoft.NET.Runtime.MonoTargets.Sdk/7.0.17/Sdk/RuntimeComponentManifest.targets(5,5): Error: Value of _MonoRuntimeComponentLinking for 'iossimulator-x64' must be 'dynamic' or 'static' it is ''. Malformed runtime pack?
Anyway, what is the impact of this workaround on non-simulator builds for iOS devices? Should I add conditions to the targets?
EDIT: This isn't working for me when we need to include Xamarin.TestCloud.Agent and we use iossimulator-x64. I get this error:
dyld[80652]: Library not loaded: @rpath/libmono-component-debugger.dylib
EDIT 2: Ok, so the workaround works on NET8, but not for NET7, which also suffers from this crash. It would be nice if there was a similar workaround for NET7 as well
Anyway, what is the impact of this workaround on non-simulator builds for iOS devices? Should I add conditions to the targets?
It shouldn't change anything for device builds (static linking is the default for device builds).
Anyway, what is the impact of this workaround on non-simulator builds for iOS devices? Should I add conditions to the targets?
It shouldn't change anything for device builds (static linking is the default for device builds).
Thank you, that is useful to know. I have settled on this update for NET8, which works with Xamarin.TestCloud.Agent (iossimulator-x64), but it does not work with NET7. Any ideas? I think maybe target names changed between 7 & 8
<PropertyGroup>
<_LibXamarinLinkMode>static</_LibXamarinLinkMode>
<_LibMonoLinkMode>static</_LibMonoLinkMode>
</PropertyGroup>
<Target Name="_FixMonoLinkMode" AfterTargets="_MonoReadAvailableComponentsManifest">
<ItemGroup>
<_MonoRuntimeComponentLinking Remove="dynamic" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="ios-arm64" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-arm64" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-x64" />
</ItemGroup>
</Target>
NET7 will be necessary because the Xamarin.UITest package has trouble with NET8 simulator builds
but it does not work with NET7. Any ideas?
Any particular reason you can't use Xcode 15.2, or the iOS 17.2 simulator in Xcode 15.3?
This is only an issue with the iOS 17.4 simulator that comes with Xcode 15.3.
Anyway, what is the impact of this workaround on non-simulator builds for iOS devices? Should I add conditions to the targets?
It shouldn't change anything for device builds (static linking is the default for device builds).
Actually wait, this like will change things for device builds:
<InvariantGlobalization>true</InvariantGlobalization>
so you should condition that on the simulator (or see if removing it altogether still works).
Would you have any suggestions as to why this is happening?
You can probably remove this line:
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="ios-arm64" />
Would you have any suggestions as to why this is happening?
You can probably remove this line:
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="ios-arm64" />
Somehow I deleted my post, my code was failing during packaing showing:
error : Value of _MonoRuntimeComponentLinking for 'ios-arm64' must be 'dynamic' or 'static' it is 'static;static'.
Thank you, that makes sense, no need to apply it to ios-arm64 since I just want to deploy to simulator.
We are also seeing similar with our iOS app deployed in production on macOS 14.4. Stack trace below. Do you think it's the same thing @rolfbjarne ? Interestingly, it's happening when we try to show a date/time picker UI element.
Thread 0 Crashed:: tid_103 Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x189d4aa60 pthread_kill + 8
1 libsystem_pthread.dylib 0x189d82c20 pthread_kill + 288
2 libsystem_c.dylib 0x189c8fa20 abort + 180
3 AppName 0x1067e5748 0x104eb4000 + 26416968
4 AppName 0x1067839b0 0x104eb4000 + 26016176
5 libsystem_platform.dylib 0x189db3584 _sigtramp + 56
6 libsystem_pthread.dylib 0x189d82c20 pthread_kill + 288
7 libsystem_c.dylib 0x189c8fa20 abort + 180
8 libsystem_malloc.dylib 0x189b9faa8 malloc_vreport + 896
9 libsystem_malloc.dylib 0x189ba3114 malloc_report + 64
10 libsystem_malloc.dylib 0x189bbd494 find_zone_and_free + 528
11 libicucore.A.dylib 0x18cef7edc icu::Locale::setToBogus() + 52
12 libicucore.A.dylib 0x18cef8240 icu::Locale::operator=(icu::Locale const&) + 40
13 libicucore.A.dylib 0x18d05dd08 icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(icu::number::impl::MacroProps&&, icu::Locale const&) + 216
14 libicucore.A.dylib 0x18cfff7c0 icu::DecimalFormat::touch(UErrorCode&) + 240
15 libicucore.A.dylib 0x18d000024 icu::DecimalFormat::DecimalFormat(icu::UnicodeString const&, icu::DecimalFormatSymbols, UNumberFormatStyle, UErrorCode&) + 380
16 libicucore.A.dylib 0x18d07b718 icu::NumberFormat::makeInstance(icu::Locale const&, UNumberFormatStyle, signed char, UErrorCode&) + 1668
17 libicucore.A.dylib 0x18d07aec8 icu::LocaleCacheKey
We are also seeing similar with our iOS app deployed in production on macOS 14.4. Stack trace below. Do you think it's the same thing @rolfbjarne ? Interestingly, it's happening when we try to show a date/time picker UI element.
Yes, this looks like the same issue, but I've never seen it happen on device. Although what exactly do you mean by "iOS app deployed in production on macOS 14.4"?
Although what exactly do you mean by "iOS app deployed in production on macOS 14.4"?
Not the OP but you can upload iOS apps to the App Store / TestFlight and check a checkbox that allows their distribution to ARM64 Mac devices. I assume it's that scenario.
Yes, that's right. Our iOS app is available on the Mac App Store and with a few tweaks for running in that environment, it works really well.
Yes, that's right. Our iOS app is available on the Mac App Store and with a few tweaks for running in that environment, it works really well.
That's interesting, because:
I guess this means the fix is more urgent than we thought, because that means there's no known workaround for this new scenario.
We've had more than one customer complaining of the problem now (I presume macOS 14.4 is quite new) so it should be fairly straightforward to reproduce. Just instantiate and display a UIDatePicker.
// Not sure if the TimeZone has anything to do with it datePicker = new UIDatePicker() { TimeZone = Foundation.NSTimeZone.FromAbbreviation(@"UTC") };
but it does not work with NET7. Any ideas?
Any particular reason you can't use Xcode 15.2, or the iOS 17.2 simulator in Xcode 15.3?
This is only an issue with the iOS 17.4 simulator that comes with Xcode 15.3.
So I downloaded Xcode 15.2 and installed the iOS 17.2 simulator, then built the app with NET7 and your workaround. It still crashes with the same bogus locale error, yet with NET8 works fine. I have a suspicion that maybe the fact that I have macOS 14.4 installed might be causing the error with NET7 and not necessarily the 17.2 or 17.4 simulator...
Any ideas how to get the workaround to work on NET7 as well?
Thanks
Our app is popular and widespread, and we cannot switch to net8.0 because a great many of our customers are stuck with iOS 10 due to their hardware. Why the decision was made to require iOS 11 with net8.0, I've no idea, but it seems arbitrary and it's quite limiting. A fix for this will definitely need to be backported to net7.0.
Why the decision was made to require iOS 11 with net8.0, I've no idea, but it seems arbitrary
It's not arbitrary at all. It's tied to Apple support policy. Last update for iOS 10 was released in 2019 and that was a special security update that was released after the OS was already deemed unsupported. It was also the last generation of iOS that supported 32-bit devices, so supporting it meant supporting an additional processor architecture (ARM32).
Per the official .NET lifecycle support policy .NET only supports platforms that are still officially supported by their respective vendors. Anything older may still be supported (as in "it runs") for some time but it's not guaranteed to receive fixes (and likely won't receive them).
From practical standpoint, supporting newer iOS versions requires new SDKs and Xcode versions. Old iOS version support gets dropped from Xcode, so in many cases it's not possible to support them. App Store uploads also enforce minimum SDK versions.
You haven't said anything to counter my assertion that it's arbitrary. With net7 I can target iOS 10, with net8 I can't. It's therefore a difference on the Microsoft side, not on the Apple side. When Apple no longer allow building or uploading apps that target iOS 10, fair enough, but this is Microsoft.
When, as in our case, a lot of customers buy the hardware specifically to run our app, we need to build the app for the operating system for as long as the manufacturer allows it.
Having been shipping this app since 2012 and the early days of Monotouch, I am well aware of the cycle of SDKs and Xcode versions.
When Apple no longer allow building or uploading apps that target iOS 10, fair enough, but this is Microsoft.
Xcode stopped supporting iOS 10 in 2022: https://developer.apple.com/news/upcoming-requirements/?id=06062022a.
I understand that they don't offer support for it. However we are happily releasing updates to our app every month or two, to this day, so the App Store still clearly supports it.
I understand that they don't offer support for it.
You don’t seem to understand that both Apple and Microsoft have support policies. These policies are in alignment. If you choose to ignore them then the burden is on you.
Furthermore, current minimum SDK requirement for App Store upload is iOS 16.1 SDK which shipped with Xcode 14.1 (https://developer.apple.com/news/upcoming-requirements/?id=04252023a). As Rolf pointed out, Xcode 14 doesn’t support 32-bit apps and as a consequence doesn’t support iOS 10 and the old devices. The requirement for SDK version is going to increase next month even further (https://developer.apple.com/news/upcoming-requirements/?id=04292024a):
ITMS-90725: SDK version issue - This app was built with the iOS 16.4 SDK. Starting April 29, 2024, all iOS and iPadOS apps must be built with the iOS 17 SDK or later, included in Xcode 15 or later, in order to be uploaded to App Store Connect or submitted for distribution.
I don't think they are alignment if Apple still allows products to be built for iOS 10 (supported or not) but Microsoft does not. I don't think it's fair to say we are ignoring any policies either; we simply support the oldest operating system that we are able to. I presume you are in the fortunate position of not needing to support so many customers using older hardware.
I am aware of the forthcoming change next month that will require apps to be built against the iOS 17 SDK. Are you saying that we will no longer be able to build for iOS 10, even with net7.0, at that point? The message is not clear.
I don't think they are alignment if Apple still allows products to be built for iOS 10 (supported or not) but Microsoft does not.
Once again, supported in this context means official support, ie. if something goes wrong you can go complain to Apple or Microsoft to fix it.
Supported as in "best of luck; we don't actively test these version but we also don't actively try to break them" is a different metric and you are on your own if you choose this path. As previously mentioned, maintaining iOS 10 support means maintaining build support for one more CPU architecture. Removing that is NOT an arbitrary decision. Likewise, the next minimum version bump to iOS 12.2 (.NET 9) is driven by the minimum iOS version that comes with a built-in Swift runtime.
I am not sure how you were able to upload apps with 32-bit iOS support to Apple App Store. Per the linked policy above, Apple was enforcing Xcode 14.1+ build tools since April 25, 2023 for any App Store uploads. I know from my own experience that they actually check this and reject uploads that don't match this policy. Since Xcode 14 dropped 32-bit support completely, uploading of 32-bit apps should not have worked for close to a year now.
Not only were, still are. We are still actively deploying to the App Store and to our many iOS 10 users. This is using Xcode 14.3. I haven't mentioned bitness (that was you) and I haven't said that we are still building for 32bit (we are not). However we have customers using iOS 10 on 64bit devices, who are unable to update to a newer version of iOS due to what Apple have made available for their hardware.
It isn't clear whether the soon-to-be-forced update to Xcode 15 will change the minimum version of iOS that we can target from 10. However, attempting to build our project targeting net8.0-ios results in an actual build error. That's not our familiar "you're on your own, best of luck" path, that's a "we have prevented this" path.
However we have customers using iOS 10 on 64bit devices, who are unable to update to a newer version of iOS due to what Apple have made available for their hardware.
Literally all devices with 64-bit processors that are supported on iOS 10 are also supported on iOS 11, including iPhone 5S and iPad Touch.
Then I have no explanation for why these customers appear unable to upgrade to iOS 11.
@dsmitchell one thing you can try is to expand the proposed workaround by adding two additional MSBuild targets in the following way:
<PropertyGroup>
<_LibXamarinLinkMode>static</_LibXamarinLinkMode>
<_LibMonoLinkMode>static</_LibMonoLinkMode>
</PropertyGroup>
<Target Name="_FixMonoLinkMode" AfterTargets="_MonoReadAvailableComponentsManifest">
<ItemGroup>
<_MonoRuntimeComponentLinking Remove="dynamic" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="ios-arm64" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-arm64" />
<_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-x64" />
</ItemGroup>
</Target>
<Target Name="_OverwriteReferencesLinkerFlags" BeforeTargets="_LinkNativeExecutable">
<!-- Remove the `-u` prefix from `_ReferencesLinkerFlags` so we can give the output file to the platform linker -->
<!-- NOTE: This step is actually also done after LinkNativeCode task, but we cannot intercept it differently -->
<WriteLinesToFile SessionId="$(BuildSessionId)" File="$(_MtouchSymbolsList)" Lines="@(_ReferencesLinkerFlags->'%(Identity)'->Substring (2))" Overwrite="true" />
<ItemGroup>
<!-- Backup collected required symbols -->
<_ReferencesLinkerFlagsBackup Include="@(_ReferencesLinkerFlags)" />
<!-- Clear `_ReferencesLinkerFlags` to prevent required symbols to be passed in -u_symbolName format -->
<_ReferencesLinkerFlags Remove="@(_ReferencesLinkerFlags)" />
<!-- Instruct platform linker to only export required symbols -->
<_ReferencesLinkerFlags Include="-exported_symbols_list" />
<_ReferencesLinkerFlags Include="$(_MtouchSymbolsList)" />
</ItemGroup>
</Target>
<Target Name="_RestoreReferencesLinkerFlags" AfterTargets="_LinkNativeExecutable">
<ItemGroup>
<_ReferencesLinkerFlags Remove="@(_ReferencesLinkerFlags)" />
<_ReferencesLinkerFlags Include="@(_ReferencesLinkerFlagsBackup)" />
</ItemGroup>
</Target>
I tested this workaround on iossimulator with .net7 build and it solves the problem. It is not really a clean solution but seems to work.
The difference between .net7 and .net8 comes from the fact we are invoking the platform linker differently on .net7 compared to the newer releases. With https://github.com/xamarin/xamarin-macios/pull/18408 we started only exporting required symbols from the executable by utilizing -exported_symbols_list
platform linker flag which will hide the clashing global ICU symbols from the mono runtime and make the initially proposed workaround valid for .net8.
However, in .net7 this isn't the case, as we are only instructing the platform linker to preserve the required symbols collected in _ReferencesLinkerFlags
(via -u_symbolName
) resulting with ICU symbols still being preserved/exported from the app which causes the symbol clash again.
@rolfbjarne @dalexsoto as this seems solvable on xamarin SDK side, we might want to consider backporting https://github.com/xamarin/xamarin-macios/pull/18408 to net7 instead, as the backport of the dotnet/runtime fix to net7 got rejected.
@dsmitchell one thing you can try is to expand the proposed workaround by adding two additional MSBuild targets in the following way:
<PropertyGroup> <_LibXamarinLinkMode>static</_LibXamarinLinkMode> <_LibMonoLinkMode>static</_LibMonoLinkMode> </PropertyGroup> <Target Name="_FixMonoLinkMode" AfterTargets="_MonoReadAvailableComponentsManifest"> <ItemGroup> <_MonoRuntimeComponentLinking Remove="dynamic" /> <_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="ios-arm64" /> <_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-arm64" /> <_MonoRuntimeComponentLinking Include="static" RuntimeIdentifier="iossimulator-x64" /> </ItemGroup> </Target> <Target Name="_OverwriteReferencesLinkerFlags" BeforeTargets="_LinkNativeExecutable"> <!-- Remove the `-u` prefix from `_ReferencesLinkerFlags` so we can give the output file to the platform linker --> <!-- NOTE: This step is actually also done after LinkNativeCode task, but we cannot intercept it differently --> <WriteLinesToFile SessionId="$(BuildSessionId)" File="$(_MtouchSymbolsList)" Lines="@(_ReferencesLinkerFlags->'%(Identity)'->Substring (2))" Overwrite="true" /> <ItemGroup> <!-- Backup collected required symbols --> <_ReferencesLinkerFlagsBackup Include="@(_ReferencesLinkerFlags)" /> <!-- Clear `_ReferencesLinkerFlags` to prevent required symbols to be passed in -u_symbolName format --> <_ReferencesLinkerFlags Remove="@(_ReferencesLinkerFlags)" /> <!-- Instruct platform linker to only export required symbols --> <_ReferencesLinkerFlags Include="-exported_symbols_list" /> <_ReferencesLinkerFlags Include="$(_MtouchSymbolsList)" /> </ItemGroup> </Target> <Target Name="_RestoreReferencesLinkerFlags" AfterTargets="_LinkNativeExecutable"> <ItemGroup> <_ReferencesLinkerFlags Remove="@(_ReferencesLinkerFlags)" /> <_ReferencesLinkerFlags Include="@(_ReferencesLinkerFlagsBackup)" /> </ItemGroup> </Target>
I tested this workaround on iossimulator with .net7 build and it solves the problem. It is not really a clean solution but seems to work.
The difference between .net7 and .net8 comes from the fact we are invoking the platform linker differently on .net7 compared to the newer releases. With xamarin/xamarin-macios#18408 we started only exporting required symbols from the executable by utilizing
-exported_symbols_list
platform linker flag which will hide the clashing global ICU symbols from the mono runtime and make the initially proposed workaround valid for .net8.However, in .net7 this isn't the case, as we are only instructing the platform linker to preserve the required symbols collected in
_ReferencesLinkerFlags
(via-u_symbolName
) resulting with ICU symbols still being preserved/exported from the app which causes the symbol clash again.@rolfbjarne @dalexsoto as this seems solvable on xamarin SDK side, we might want to consider backporting xamarin/xamarin-macios#18408 to net7 instead, as the backport of the dotnet/runtime fix to net7 got rejected.
@ivanpovazan Thank you so much for this detailed explanation. It sounds promising, and I will try this out on my local setup. The reason why I am forced to also use NET7 for simulator is because of Xamarin.UITest v4.3.4 not supporting NET8 nor on-device testing at the moment
@ivanpovazan
@rolfbjarne @dalexsoto as this seems solvable on xamarin SDK side, we might want to consider backporting xamarin/xamarin-macios#18408 to net7 instead, as the backport of the dotnet/runtime fix to net7 got rejected.
That change caused some problems (https://github.com/xamarin/xamarin-macios/issues?q=is%3Aissue+sort%3Aupdated-desc+_ExportSymbolsExplicitly+), so it will probably not be backported (at least not with the new behavior on by default).
Description
App crashes when iOS starts using its own ICU code.
I'm guessing it's because of a symbol clash with Mono's ICU symbols.
Reproduction Steps
dotnet new ios
Note: an iOS 17.2 simulator works just fine.
Expected behavior
No crash.
Actual behavior
Crash:
Full crash report: https://gist.github.com/rolfbjarne/9fcedeb59d0521c4c9bb931056bba15c
Regression?
Yes. Fortunately it seems to only affect the simulator, and not device.
Known Workarounds
Disable globalization and make the app link mono statically works:
Configuration
Other information
No response