dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.58k stars 4.55k forks source link

Duplicate AOT/Trimmer warnings for console apps #104374

Closed jonathanpeppers closed 2 days ago

jonathanpeppers commented 1 week ago

Description

Building a console app with dotnet publish -c Release -r win-x64 --no-build, I get double warnings from the Roslyn analyzer and ILC:

"D:\src\nativeaotwarnings\nativeaotwarnings.sln" (Publish target) (1) ->
"D:\src\nativeaotwarnings\nativeaotwarnings.csproj" (Publish target) (2) ->
(CoreCompile target) ->
  D:\src\nativeaotwarnings\Program.cs(1,20): warning IL3050: Using member 'System.Type.MakeGenericType(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [D:\src\nativeaotwarnings\nativeaotwarnings.csproj]
  D:\src\nativeaotwarnings\Program.cs(1,20): warning IL2055: Call to 'System.Type.MakeGenericType(params Type[])' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. [D:\src\nativeaotwarnings\nativeaotwarnings.csproj]

"D:\src\nativeaotwarnings\nativeaotwarnings.sln" (Publish target) (1) ->
"D:\src\nativeaotwarnings\nativeaotwarnings.csproj" (Publish target) (2) ->
(IlcCompile target) ->
  D:\src\nativeaotwarnings\Program.cs(1): Trim analysis warning IL2055: Program.<Main>$(String[]): Call to 'System.Type.MakeGenericType(Type[])' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. [D:\src\nativeaotwarnings\nativeaotwarnings.csproj]
  D:\src\nativeaotwarnings\Program.cs(1): AOT analysis warning IL3050: Program.<Main>$(String[]): Using member 'System.Type.MakeGenericType(Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [D:\src\nativeaotwarnings\nativeaotwarnings.csproj]

4 Warning(s)
0 Error(s)

I would like to address this problem in the Android workload as well, but asking about console apps first. We have some cases on Android that can trigger duplicate warnings.

Reproduction Steps

I attached the repro, but you could do:

  1. dotnet new console
  2. Add PublishAot=true in the .csproj
  3. Add a trimmer/AOT warning on purpose:
Console.WriteLine (Foo.type.MakeGenericType (typeof (object)));

class Foo
{
    public static Type type = typeof (List<>);
}
  1. dotnet build -c Release -bl:build.binlog
  2. dotnet restore -r win-x64 -bl:restore.binlog
  3. dotnet publish -c Release -r win-x64 --no-build -bl:publish.binlog

Expected behavior

I should get two warnings: IL2055 and IL3050.

Actual behavior

I get four warnings: IL2055 x 2 and IL3050 x 2.

Regression?

No

Known Workarounds

No response

Configuration

I assume this probably does the same thing in .NET 9, but I didn't try.

Other information

Here is a repro project: nativeaotwarnings.zip

ivanpovazan commented 6 days ago

I don't think dotnet publish --no-build with NativeAOT has any effect. We always need to execute the build first.

If we take for example targeting iOS with NativeAOT, during the publishing process it's necessary for the SDK to retrieve a different version of the runtime pack (NativeAOT) than what was used for the build (Mono). Retrieving and handling of the runtime packs is part of the Build phase, which means it cannot be done during Publish with --no-build.

My two cents on warnings: I think that when publishing an app with NativeAOT the duplicated warnings is the expected behaviour. On the other hand, when building the app with PublishAot=true the warnings will come from Roslyn analyzers only, as ILC will not run in this scenario, so there will be no duplicates. Finally, the "downside" of dotnet build with PublishAot=true is that the user won't see any trim/AOT/singlefile warnings coming from NuGets. For that dotnet publish is required. The last bit is probably making the biggest difference between Mono and NativeAOT on mobile, as with Mono we are running the trimmer (getting full program view) even during the build which makes the difference between building and publishing minimal with Mono.

jonathanpeppers commented 2 days ago

Ok, I found steps that fix this are:

In this case, a build was performed with the RID, and I don't get double warnings. So, you would only get double warnings if build + publish both run.

This is basically what happens on mobile with dotnet build, as we have to run illink and some subset of the publish targets to get a runnable app.

agocke commented 2 days ago

This is currently by-design for console apps. I don't see a good reason to change it there. If the mobile experience is different, we should address it there.

jonathanpeppers commented 2 days ago

@agocke can you recommend what we should do?

On Android it seems like we should somehow disable the Roslyn analyzers if a build would run the trimmer, does that sound correct?

We want to see warnings from NuGet packages but not 2x of the project’s source code.

agocke commented 2 days ago

Yeah, I think that might be the best option. You can disable the analyzers with <EnableTrimAnalyzer>false</> and <EnableAotAnalyzer>false</>

ivanpovazan commented 1 day ago

Disabling Roslyn analyzers would prevent our IDEs from showing squiggly lines in places where the code is not trim compatible.