Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Globalization invariant mode not working on Linux with .NET 8 Preview 6 native AOT #34091

Closed
cfbao opened this issue Jul 19, 2023 · 10 comments
Closed
Assignees
Labels
Area-NetSDK untriaged Request triage from a team member

Comments

@cfbao
Copy link

cfbao commented Jul 19, 2023

Describe the bug

When building a project that

  • includes globalization resources (comes from referenced packages)
  • uses native AOT
  • with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true set
  • on Linux
  • using .NET 8 Preview 6

the build fails.

To Reproduce

Build a project in container with the following files:

(purposefully including a reference to System.CommandLine to include some globalization resources)

cstest.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <PublishAot>true</PublishAot>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <InvariantGlobalization>true</InvariantGlobalization>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
  </ItemGroup>

</Project>

Program.cs:

using System.CommandLine;
var rootCommand = new RootCommand("Sample app for System.CommandLine");
rootCommand.SetHandler(() => Console.WriteLine("Hello, World!"));
return await rootCommand.InvokeAsync(args);

Dockerfile:

FROM alpine:latest AS build

RUN apk update \
    && apk add clang build-base bash zlib-dev

RUN mkdir -p /usr/share/dotnet && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet

RUN wget https://dot.net/v1/dotnet-install.sh \
    && chmod +x ./dotnet-install.sh \
    && ./dotnet-install.sh \
        --channel 8.0 \
        --install-dir /usr/share/dotnet

WORKDIR /source

ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

COPY . .
RUN dotnet publish -r linux-musl-x64 -o /app

FROM scratch as export
COPY --from=build /app /

Exceptions (if any)

#0 137.7   cstest -> /source/bin/Release/net8.0/linux-musl-x64/cstest.dll
#0 137.9   Generating native code
#0 138.2 EXEC : error : Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name') [/source/cstest.csproj]
#0 138.2   zh-Hant is an invalid culture identifier.
#0 138.2   System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
#0 138.2   zh-Hant is an invalid culture identifier.
#0 138.2      at System.Reflection.AssemblyName.set_CultureName(String) + 0xad
#0 138.2      at Internal.TypeSystem.Ecma.EcmaAssembly.GetName() + 0x32d
#0 138.2      at ILCompiler.UsageBasedMetadataManager.<GetSatelliteAssemblies>d__25.MoveNext() + 0x44
#0 138.2      at ILCompiler.DependencyAnalysis.ModuleMetadataNode.GetStaticDependencies(NodeFactory) + 0x1e8
#0 138.2      at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependenciesImpl(DependencyNodeCore`1) + 0x35
#0 138.2      at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependencies(DependencyNodeCore`1) + 0x33
#0 138.2      at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ProcessMarkStack() + 0xb1
#0 138.2      at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ComputeMarkedNodes() + 0x4f
#0 138.2      at ILCompiler.ILScanner.ILCompiler.IILScanner.Scan() + 0x19
#0 138.2      at ILCompiler.Program.<Run>g__RunScanner|4_0(Program.<>c__DisplayClass4_0&) + 0x1a9
#0 138.2      at ILCompiler.Program.Run() + 0x206e
#0 138.2      at ILCompiler.ILCompilerRootCommand.<>c__DisplayClass215_0.<.ctor>b__0(InvocationContext context) + 0x2f3
#0 138.2 /root/.nuget/packages/microsoft.dotnet.ilcompiler/8.0.0-preview.6.23329.7/build/Microsoft.NETCore.Native.targets(290,5): error MSB3073: The command ""/root/.nuget/packages/runtime.linux-musl-x64.microsoft.dotnet.ilcompiler/8.0.0-preview.6.23329.7/tools/ilc" @"obj/Release/net8.0/linux-musl-x64/native/cstest.ilc.rsp"" exited with code 1. [/source/cstest.csproj]

Further technical details

This happens on

  • .NET 8 Preview 6 only, not on Preview 5 or lower.
  • Alpine Linux only, not on other distros like Ubuntu Linux only, not on Windows or Mac
  • native AOT builds only, not on regular builds
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-NetSDK untriaged Request triage from a team member labels Jul 19, 2023
@cfbao cfbao changed the title Globalization invariant mode not working on Alpine with .NET 8 Preview 6 native AOT Globalization invariant mode not working on Linux with .NET 8 Preview 6 native AOT Jul 19, 2023
@vitek-karas
Copy link
Member

Why do you set DOTNET_SYSTEM_GLOBALIZATION_INVARIANT through the environment variable. The env. variable will affect runtime, so in this case it affects the .NET tools which run during build/publish. It will not affect the produced application.
If you want to set this for the app you're building, use the InvariantGlobalization MSBuild property in your csproj file.
https://learn.microsoft.com/en-US/dotnet/core/runtime-config/globalization

@MichalStrehovsky just as an FYI, I don't think we should try to fix here anything - maybe SDK could clean this variable in the CLI to make sure that it can operate correctly as a whole.

@cfbao
Copy link
Author

cfbao commented Jul 20, 2023

@vitek-karas @MichalStrehovsky

Setting DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is required, because affecting the runtime is required.
Note that I'm building in an Alpine container that doesn't have libicu, so the SDK itself needs to run in globalization invariant mode.

In my actual project, I'm already setting <InvariantGlobalization>true</InvariantGlobalization> in the csproj file, and the error occurs there.
I've added this property to the csproj file in this minimal repro in the description. The repro still holds.

@vitek-karas
Copy link
Member

Thanks for clarifying this I didn't realize that you need to set this in order for the SDK to even work.

@MichalStrehovsky
Copy link
Member

I know this failure mode from dotnet/runtime#86689 (comment). This would fail for any assembly with a non-default culture even in .NET 7 (and also for PublishReadyToRun). We're just more likely to run into this now.

I don't actually know if using the SDK with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is a supported configuration. I'll get back once I ask around.

@marcpopMSFT marcpopMSFT removed their assignment Aug 25, 2023
cfbao added a commit to Brightspace/bmx that referenced this issue Sep 22, 2023
Recent .NET 8 releases cause two problems with our existing Linux Docker
builds:

* Our build containers don't have ICU libraries installed and have
`DOTNET_SYSTEM_GLOBALIZATION_INVARIANT` set. The .NET SDK can no longer
deal with localization assets in libraries (e.g. System.CommandLine) in
such scenario. See dotnet/sdk#34091. This may
not be addressed soon (if ever), and we shouldn't give up improvements
coming from recent .NET updates. Adding ICU libraries also don't have
downsides to the BMX binaries themselves. They're only used during the
build process, but aren't added to BMX nor required during BMX runtime.

* Native AOT builds break in Ubuntu 16. .NET 8 runtime targets Ubuntu
16, but apparently Ubuntu 18+ is a requirement for native AOT (see
[docs](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=net8plus%2Clinux-ubuntu#prerequisites)).
The apparent reason is that clang version is too low on Ubuntu 16. (We
can still seek more clarification from the .NET team via GitHub issue.)
Ubuntu 16 support ended more than two years ago, so it's not
unreasonable for BMX to drop support. I'm switching the Linux build to
use Amazon Linux 2 (AL2), because
* AL2 uses an older glibc version than Ubuntu 18, so it should make BMX
compatible with more Linux systems. My anecdotal testing also suggests
that BMX built on AL2 can still run on Ubuntu 16.
* This still ensures that BMX can be run on AL2, which many of D2L's EC2
instances run on.
@Zylvian
Copy link

Zylvian commented Nov 1, 2023

I know this failure mode from dotnet/runtime#86689 (comment). This would fail for any assembly with a non-default culture even in .NET 7 (and also for PublishReadyToRun). We're just more likely to run into this now.

I don't actually know if using the SDK with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is a supported configuration. I'll get back once I ask around.

Hi. This issue still persists in the latest .NET 7 release. Am trying to host a .NET webapp in a docker container on Debian, also running in to the same issue if using InvariantGlobalization.

Has there been any updates in this?

@MichalStrehovsky
Copy link
Member

I know this failure mode from dotnet/runtime#86689 (comment). This would fail for any assembly with a non-default culture even in .NET 7 (and also for PublishReadyToRun). We're just more likely to run into this now.
I don't actually know if using the SDK with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is a supported configuration. I'll get back once I ask around.

Hi. This issue still persists in the latest .NET 7 release. Am trying to host a .NET webapp in a docker container on Debian, also running in to the same issue if using InvariantGlobalization.

Has there been any updates in this?

While DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is a supported switch, setting it on .NET applications that were not built for it or tested with it will break them since the definition of the switch is to do breaking behavior changes. We do not test any part of the SDK with this switch enabled. You're running an untested configuration.

@Zylvian
Copy link

Zylvian commented Nov 14, 2023

I know this failure mode from dotnet/runtime#86689 (comment). This would fail for any assembly with a non-default culture even in .NET 7 (and also for PublishReadyToRun). We're just more likely to run into this now.
I don't actually know if using the SDK with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is a supported configuration. I'll get back once I ask around.

Hi. This issue still persists in the latest .NET 7 release. Am trying to host a .NET webapp in a docker container on Debian, also running in to the same issue if using InvariantGlobalization.
Has there been any updates in this?

While DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is a supported switch, setting it on .NET applications that were not built for it or tested with it will break them since the definition of the switch is to do breaking behavior changes. We do not test any part of the SDK with this switch enabled. You're running an untested configuration.

Affirmative. I am specifically trying to containerize an Umbraco CMS application using this method, but I understand that this might be out of your hand.

The issue I specifically bumped into was the .NET 7 containers not having support for ICU language libraries from the get go, and language invariation would break the application. Had to build my own Dockerfile and add support for it that way.

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
RUN apt update && DEBIAN_FRONTEND=noninteractive && apt install -y tzdata

@orassr
Copy link

orassr commented Nov 26, 2023

I had similar issue while trying to database-update, the work around for me was to change to false on the project file.

@MichalStrehovsky
Copy link
Member

The problematic code path was now removed from the AOT compiler as part of some refactorings. We still do not test or support the SDK with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT but the AOT compiler can now operate like that.

@asleyvm
Copy link

asleyvm commented Jul 16, 2024

export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true
export DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY=false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-NetSDK untriaged Request triage from a team member
Projects
None yet
Development

No branches or pull requests

7 participants