Nexus-Mods / NexusMods.App

Home of the development of the Nexus Mods App
https://nexus-mods.github.io/NexusMods.App/
GNU General Public License v3.0
1.06k stars 47 forks source link

AppImage doesn't support globalization-invariant mode #1866

Open awebeer256 opened 3 months ago

awebeer256 commented 3 months ago

Bug Report

Summary

The initial observed behaviour is that I can't get the AppImage to run on NixOS due to the lack of libicu. The error message explains that without it, the software can still run in "globalization-invariant mode," if that is explicitly requested. When I do that, however, I get another error message that I think means the app's code is trying to force-enable the "generic English language" globalization setting, and then crashing because that's not allowed in globalization-invariant mode.

Steps to reproduce

  1. Be running NixOS 24.05, including the following in your system config:
    programs.appimage.enable = true;
    programs.appimage.binfmt = true;
  2. Download the AppImage of NexusMods.App, version 0.5.3.
  3. Set it to executable, and execute it in a terminal. This results in an instant crash (a window isn't even created), printing the first error message below.
  4. Execute it in a terminal with the environment variable DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1. This results in an instant crash with the second error message.

What is the expected behaviour?

Optionally, the AppImage would have libicu bundled (more info here; I haven't verified it). Regardless of that, though, the AppImage should be able to run in globalization-invariant mode.

Other information

First error message ``` Process terminated. Couldn't find a valid ICU package installed on the system. Please install libicu (or icu-libs) using your package manager and try again. Alternatively you can set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support. Please see https://aka.ms/dotnet-missing-libicu for more information. at System.Environment.FailFast(System.String) at System.Globalization.GlobalizationMode+Settings..cctor() at System.Globalization.CultureData.CreateCultureWithInvariantData() at System.Globalization.CultureData.get_Invariant() at System.Globalization.TextInfo..cctor() at System.Diagnostics.Tracing.EventSource.GetGuid(System.Type) at System.Diagnostics.Tracing.EventSource..ctor(System.Diagnostics.Tracing.EventSourceSettings, System.String[]) at System.Diagnostics.DiagnosticSourceEventSource..cctor() at System.Diagnostics.DiagnosticListener..ctor(System.String) at Microsoft.Extensions.Hosting.HostBuilder.LogHostBuilding(Microsoft.Extensions.Hosting.IHostBuilder) at Microsoft.Extensions.Hosting.HostBuilder.Build() at NexusMods.App.Program.Main(System.String[]) ```
Second error message ``` Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: The type initializer for 'NexusMods.App.UI.Settings.LanguageSettings' threw an exception. ---> System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name') en is an invalid culture identifier. at System.Globalization.CultureInfo..ctor(String name, Boolean useUserOverride) at NexusMods.App.UI.Settings.LanguageSettings..cctor() in /_/src/NexusMods.App.UI/Settings/LanguageSettings.cs:line 19 --- End of inner exception stack trace --- at NexusMods.App.UI.Settings.LanguageSettings..ctor() in /_/src/NexusMods.App.UI/Settings/LanguageSettings.cs:line 12 at System.RuntimeType.CreateInstanceOfT() --- End of inner exception stack trace --- at System.RuntimeType.CreateInstanceOfT() at System.Activator.CreateInstance[T]() at NexusMods.Abstractions.Settings.ServiceExtensions.AddSettings[T](IServiceCollection serviceCollection) in /_/src/Abstractions/NexusMods.Abstractions.Settings/ServiceExtensions.cs:line 18 at NexusMods.App.UI.Settings.ServiceExtensions.AddUISettings(IServiceCollection serviceCollection) in /_/src/NexusMods.App.UI/Settings/ServiceExtensions.cs:line 10 at NexusMods.App.UI.Services.AddUI(IServiceCollection c) in /_/src/NexusMods.App.UI/Services.cs:line 88 at NexusMods.App.Services.AddApp(IServiceCollection services, TelemetrySettings telemetrySettings, Boolean addStandardGameLocators, StartupMode startupMode, ExperimentalSettings experimentalSettings, GameLocatorSettings gameLocatorSettings) in /_/src/NexusMods.App/Services.cs:line 57 at NexusMods.App.Program.<>c__DisplayClass5_0.b__0(IServiceCollection services) in /_/src/NexusMods.App/Program.cs:line 216 at Microsoft.Extensions.Hosting.HostBuilder.InitializeServiceProvider() at Microsoft.Extensions.Hosting.HostBuilder.Build() at NexusMods.App.Program.Main(String[] args) in /_/src/NexusMods.App/Program.cs:line 53 ```

The directory ~/.local/state/NexusMods.App/ does not exist.

Sewer56 commented 3 months ago

Might be a bit of work, don't yet know.

Usually it's kind of hard to have a Linux distro going without libicu these days, it's usually available out the box.

Currently for publishing we run a light fork of PupNet Deploy for creating the AppImages.

Our fork is level with upstream. Upstream is currently busy with life, so there's no release there; but in our case we need a release, so we have a fork. Chances are bundling something like libicu would involve further PupNet changes.

Given the nature of this specific report it's unlikely to happen unless this is the case in a more prominent distro. Especially since Nix already has a package for the App.

(There's a minor bug there. I want to fix it when I get the chance but it's not up to me to decide when that will be)

MattSturgeon commented 3 months ago

Just to clarify, icu is available on nixos, however it's up to packages (or in this case, the appimage-run script) to populate LD_LIBRARY_PATH with their dependencies. On nixos most things aren't on PATH and LD_LIBRARY_PATH globally.

Until the library is bundled with the nexusmods-app appimage or added as a appimage-run dependency, you could add it to your current-system's LD_LIBRARY_PATH by doing something like this in a nixos or home-manager config module:

{lib, pkgs, ...}: {
  # e.g. for home-manager, use home.sessionVariables
  home.sessionVariables = {
    LD_LIBRARY_PATH = lib.makeLibraryPath (with pkgs; [
      icu
    ]);
  };
}

There's probably also a way to override the appimage-run package, and add icu as a runtimeInput or something too...