Open lemonmojo opened 12 months ago
This shouldn't be NativeAOT specific and happen on Mono as well, guess nobody tried that yet :)
Tagging subscribers to 'os-ios': @steveisok, @akoeplinger, @kotlarmilos See info in area-owners.md if you want to be subscribed.
Author: | lemonmojo |
---|---|
Assignees: | - |
Labels: | `area-CoreLib-mono`, `os-ios` |
Milestone: | - |
@akoeplinger I guess so. Unfortunately I currently have no idea what a proper fix might look like as the location of the file heavily depends on the project/bundle structure.
I mean, even if -[NSBundle mainBundle]
would return the XCTest bundle, the icudt.dat file might instead be included in some framework, potentially deeply nested.
Is there some way/hack to set the path at runtime?
hmm not right now, we have the ICU_DAT_FILE_PATH app context key but NativeAOT compiles that into the app "hardcoded" during the build time.
we could probably add an environment variable override.
another idea might be calling AppContext.SetData("ICU_DAT_FILE_PATH", "<path>")
early on in startup so that it overrides the value that NativeAOT compiled into the app
@akoeplinger I can confirm that using AppContext
to set the file path at runtime does indeed work.
I think it's still a good idea to change the loading code in the runtime to use -[NSBundle bundleForClass:]
and provide a way to overwrite the path using an env var in case the bundle is structured in another way.
@akoeplinger Any chance that the switch to -[NSBundle bundleForClass:]
will make it into .NET 8?
@lemonmojo I was planning to but we recently hit an issue in our so called "library mode" where linking the runtime into two libraries causes an issue because of duplicate Objective-C classes and we got rid of the classes: https://github.com/dotnet/runtime/pull/89956
So the bundleForClass
won't work since we don't have a class to point it to.
I think the env var is the only good option we have left, do you think that'd still help or is the AppContext
solution good enough?
Actually, can you try setting ICU_DAT_FILE_PATH
as an environment variable? it looks like AppContext will read from the environment if it's not set already.
For XCTest we could probably look at XCTestBundlePath
to find the bundle path but we'd hit the same issue when we're embedded inside a .framework.
Alternatively we could make the build pass in the bundle identifier via AppContext and then use +[NSBundle bundleWithIdentifier]
(see the perf optimizations Flutter had to do with that approach: https://github.com/flutter/engine/pull/39975)
I wonder if the easiest solution is embedding the icudt.dat file itself somehow.
@akoeplinger Sorry for the delay. I just tried setting the ICU_DAT_FILE_PATH
as an environment variable instead of writing it to AppContext but that didn't work unfortunately.
At least for my case, just looking at XCTestBundlePath
won't do the trick as I use nested frameworks and the ICU file could be deep inside the framework tree.
I'm not sure I understand your second suggestion regarding passing in the bundle identifier. Could you please elaborate?
Is embedding the icudt.dat file a viable option at that level? If so, that would absolutely be the easiest approach from a .NET user's perspective. To be honest, I didn't even know what that file is and why it's required until I hit some issues because I wasn't embedding it. So yeah, if you can make that work I'd be awesome.
Tagging subscribers to this area: @dotnet/area-system-globalization See info in area-owners.md if you want to be subscribed.
Author: | lemonmojo |
---|---|
Assignees: | akoeplinger |
Labels: | `area-System.Globalization`, `os-ios` |
Milestone: | 9.0.0 |
Description
As commented here the recently introduced change to relatively locate the icudt.dat file inside an app bundle works fine.
However, when a NativeAOT'd library is included and called from an XCTest bundle,
-[NSBundle mainBundle]
returns a path inside Xcode instead of the test bundle:Of course this causes the load to fail because the icudt.dat will never be in Xcode's app bundle. If the XCTest project is however set up to copy this file to it's bundle resources folder, it would be there waiting to be consumed by the .NET runtime but currently fails because the logic of locating it just targets the main bundle.