Build: app-local ICU is now configurable at runtime#23009
Conversation
|
Claude finished @Migaroez's task in 6m 2s —— View job PR Review Complete
SummaryVerdict: Approved with Suggestions The core implementation is solid — Two minor documentation inconsistencies were flagged in inline comments:
|
|
@JasonElkin If you could take this one out for a spin and see if it satisfies your needs that would be great. If needed, I can run a "nightly" build on this branch so it ends up on myget. |
There was a problem hiding this comment.
PR Review - Target: origin/v17/dev - Classified as: Config-only. See inline comments for suggestions. Two minor documentation issues found: (1) misleading env var override bullet in all three comment blocks - the env var cannot override a runtimeconfig.json entry already present; (2) self-referential cross-reference in UmbracoProject.csproj lines 30 and 63. Core implementation is correct. Approved with Suggestions.
Prerequisites
Fixes #22758. Non funtional breaking approach to #22771.
Description
#22758 reports that an Umbraco app built on Linux or Windows crashes on macOS with
Failed to load app-local ICU: libicuuc.68.2.0.9.dylib. Root cause:RuntimeIdentifieris build-time, so theRuntimeHostConfigurationOptionforSystem.Globalization.AppLocalIcugets baked intoruntimeconfig.jsonwhenever the build host is not macOS — even for cross-platform deployment artifacts.PR #22771 fixes this by removing app-local ICU entirely. That works, but it also throws out the original cross-platform consistency guarantee added in #11276 and silently changes globalization behavior on Windows Server 2016 / Windows 10 1703–1809 (which fall back to NLS without app-local ICU — see Microsoft Learn).
This PR instead keeps the default outcome but introduces an MSBuild property knob (
UmbracoUseAppLocalIcu) plus a documented post-publish escape hatch. The default still enables app-local ICU 72.1.0.3 for Linux/Windows builds; deployers who need different behavior on a particular target (macOS, or anywhere else) can override without rebuilding.Override paths
dotnet publish -p:UmbracoUseAppLocalIcu=false(or set the property in.csproj/Directory.Build.props)System.Globalization.AppLocalIcuunderruntimeOptions.configPropertiesin the published*.runtimeconfig.jsonDOTNET_SYSTEM_GLOBALIZATION_APPLOCALICUis honored only when the runtimeconfig has no AppLocalIcu key — i.e. as a fallback, not as a runtime override of a JSON value already present. The general .NET 9 env-var-precedence rule does not apply here (verified on .NET 10); This is probably because AppLocalIcu is resolved by the native host before the CLR boots. Use the build-time or post-publish path for an actual override.How to test
dotnet publish src/Umbraco.Web.UI/Umbraco.Web.UI.csproj -c Release -o ./out
Expected:
out/Umbraco.Web.UI.runtimeconfig.jsoncontains"System.Globalization.AppLocalIcu": "72.1.0.3"andout/runtimes/linux-x64/native/libicuuc.so.72.1.0.3+out/runtimes/win-x64/native/icuuc72.dllare present.dotnet publish src/Umbraco.Web.UI/Umbraco.Web.UI.csproj -c Release -p:UmbracoUseAppLocalIcu=false -o ./out
Expected:
AppLocalIcukey absent fromruntimeconfig.json; noruntimes/<rid>/native/*icu*files; publish output ~3 MB smaller (ICU natives gone).*.runtimeconfig.jsonand delete theSystem.Globalization.AppLocalIculine (or change its value).Failed to load app-local ICUcrash; falls back to system ICU.runtimeconfig.jsoncontains the entry; the runtime loadsicuuc72.dll/libicuuc.so.72.1.0.3from the publish output as before.