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

NativeAOT publish for DLL does not set automatically RID #29834

Open
kant2002 opened this issue Jan 8, 2023 · 31 comments
Open

NativeAOT publish for DLL does not set automatically RID #29834

kant2002 opened this issue Jan 8, 2023 · 31 comments
Labels
Area-NativeAOT Native AOT compilation

Comments

@kant2002
Copy link

kant2002 commented Jan 8, 2023

I was have following setup. DLL project which I publish as NativeAOT. I have to publish it dotnet publish -r win-x64 --self-contained otherwise project does not pickup nor current RID of my dev machine, not the fact that application is self-contained (NativeAOT). It's most likely issue in SDK

  • dotnet publish want me specify RID
  • dotnet publish -r win-x64 use WinForms references during build, but do not propagate them for publish to ILC
  • dotnet publish -r win-x64 --self-contained works, but self-contained switch is misleading probably and undo a lot of tooling work in recent releases around NativeAOT
@ghost ghost added the untriaged Request triage from a team member label Jan 8, 2023
@ghost
Copy link

ghost commented Jan 8, 2023

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Issue Details

I was have following setup. DLL project which I publish as NativeAOT. I have to publish it dotnet publish -r win-x64 --self-contained otherwise project does not pickup nor current RID of my dev machine, not the fact that application is self-contained (NativeAOT). It's most likely issue in SDK

  • dotnet publish want me specify RID
  • dotnet publish -r win-x64 use WinForms references during build, but do not propagate them for publish to ILC
  • dotnet publish -r win-x64 --self-contained works, but self-contained switch is misleading probably and undo a lot of tooling work in recent releases around NativeAOT
Author: kant2002
Assignees: -
Labels:

untriaged, area-NativeAOT-coreclr

Milestone: -

@am11
Copy link
Member

am11 commented Jan 8, 2023

In .NET 7+, dotnet-publish sets the RID implicitly to the runtime of executing dotnet.exe with Publish{Aot,SingleFile,ReadyToRun}.

You can also pass --use-current-runtime or --ucr in a general-purpose script (e.g. for CI) for cases which aren't covered by implicit RID. I don't remember offhand which are those cases, @nagilson might.

dotnet new mvc -n mvc1 && dotnet publish -p:PublishAot=true mvc1 publishes AOT app for win-x64 on Windows 10 x64 machine; without explicitly specifying the runtime with .NET 7 (and 8 alpha).

@kant2002
Copy link
Author

kant2002 commented Jan 8, 2023

I know about that, but if you create

dotnet new winforms 
# remove OutputType
dotnet publish

then you will have situation like I describe. Probably MVC is special cased somehow.

@am11
Copy link
Member

am11 commented Jan 8, 2023

Well, I tested with two templates: Console and MVC. WinForms is rather an exception.

dotnet new winforms 
# remove OutputType
dotnet publish

I don't see PublishAot specified anywhere.

@kant2002
Copy link
Author

kant2002 commented Jan 8, 2023

You may take a look at this project https://github.com/kant2002/WinFormsComInterop/blob/main/samples/HostedWindowsForms/HostedWindowsForms.csproj

which was led to following error kant2002/WinFormsComInterop#48 (comment) if using dotnet publish -r win-64.

@kant2002
Copy link
Author

kant2002 commented Jan 8, 2023

I think issue is specifically for OutpuType=Library kind of projects. That maybe by design in regular CoreCLR publish, but unexpected for NativeAOT

@am11
Copy link
Member

am11 commented Jan 8, 2023

Yes, classlib requires the runtime argument:

$ dotnet new classlib -n lib1
$ dotnet publish lib1 -p:PublishAot=true --use-current-runtime

@kant2002
Copy link
Author

kant2002 commented Jan 8, 2023

I see two problems here, why PublishAot does not imply --use-current-runtime and second. Why PublishAot does not imply --self-contained. I may probably understand some rationale for first case, but not for second.

@am11
Copy link
Member

am11 commented Jan 8, 2023

Your sample https://github.com/kant2002/WinFormsComInterop/tree/main/samples/HostedWindowsForms is building on my Win10 box with .NET SDK 7.0.101 without --self-contained:

dotnet publish --use-current-runtime
::: or
dotnet publish -r win-x64

...
Generating native code
...

produces bin\Debug\net7.0-windows\win-x64\publish\HostedWindowsForms.dll which is a native library according to ildasm.exe.

@kant2002
Copy link
Author

kant2002 commented Jan 8, 2023

I belive you are did not notice ILC: Method '[HostedWindowsForms]HostedWindowsForms.LibraryFunctions.ShowMessageBox()' will always throw because: Fai led to load assembly 'System.Windows.Forms' . that's because System.Windows.Forms.dll is not part of set of published files. And that's because dotnet SDK think this is not self-contained app.

@am11
Copy link
Member

am11 commented Jan 8, 2023

ILC: Method '[HostedWindowsForms]HostedWindowsForms.LibraryFunctions.ShowMessageBox()' will always throw because: Fai led to load assembly 'System.Windows.Forms'

Sounds like this should be an error.

@kant2002
Copy link
Author

kant2002 commented Jan 8, 2023

ILC reporting is separate issue. I'm worry only about SDK behavior. It seems reasonable that if PublishAot=true then SDK infer RID and --self-contained independently from OutputType of the project.

@MichalStrehovsky
Copy link
Member

This is probably because publishing a library mostly works by accident in the SDK and wasn't fully tested for everything. dotnet/linker#3165 (comment). Looks like it doesn't even work for all NativeAOT scenarios (although WinForms with NativeAOT is definitely not a supported scenario in 7.0).

ILC: Method '[HostedWindowsForms]HostedWindowsForms.LibraryFunctions.ShowMessageBox()' will always throw because: Fai led to load assembly 'System.Windows.Forms'

Sounds like this should be an error.

Nope, people add assemblies their grandmother wrote for .NET Framework 1.0 to their .NET 7 apps and expect the parts that work with a JIT-based runtime to also work on an AOT-based runtime. (I.e. publishing apps with missing or mismatched dependencies is common so the compiler makes a reasonable attempt to emulate the JIT behavior where one would get an exception only once a problematic codepath is reached.)

@kant2002
Copy link
Author

kant2002 commented Jan 9, 2023

So we have one more case in addition to Android where publish self-contained libraries make sense. Is this should be better documented in sample, or SDK work?

@MichalStrehovsky
Copy link
Member

It already mostly works for NativeAOT. Did you hit it in a scenario that doesn't involve WinForms? We don't document/make samples for things that are unsupported.

(I assume the problem is that WinForms adds itself to publish differently than regular NuGet packages and we need a fix in the .NET SDK or WinForms SDK to do it in a way that works with NativeAOT. Basically the SDKs don't expect publishing as libraries and may need extra work.)

@kant2002
Copy link
Author

kant2002 commented Jan 9, 2023

Does failure of embed of ASP.NET Core count as "supported" scenario? I test it and it produce ILC: Method '[webembedded]LibraryFunctions.ShowMessageBox()' will always throw because: Failed to load assembly 'Microsoft.AspNetCore'. Do you need repo with repro?

@MichalStrehovsky
Copy link
Member

ASP.NET Core is also not supported with NativeAOT. It's only a .NET 7 servicing-worthy issue if this doesn't work with regular NuGets. Otherwise this would be "help-wanted", milestoned as "Future".

@kant2002
Copy link
Author

kant2002 commented Jan 9, 2023

I think it affects only cases where library distinguish between self-contained and not self-contained modes. I do not aware of non-MS and popular enough Sdks which do this. So be it -"help wanted" and "Future". Any chance that sdk repo(am I right?) would accept contributions in this area? Once ASP.NET Core make significant progress in NativeAOT I think this issue will re-appear, since I bet some people try to put it in the unmanaged app.

@am11
Copy link
Member

am11 commented Jan 9, 2023

If most (or all) of the PublishAot=true cases must imply SelfContained=true ignoring the project OutputType, then this should be fine: am11@dc23244 (props are still overridable if someone really needs SelfContained=false).

@vitek-karas
Copy link
Member

NativeAOT has the unwanted privilege of being basically the first scenario in which library project needs to be published self-contained. (publishing library project itself is somewhat undefined operation in SDK, making it self-contained is just making it worse). Android apps are like this already, but I think they go well outside the normal SDK integration, so it's not a fair comparison.

Any chance that sdk repo(am I right?) would accept contributions in this area?

I don't see why it wouldn't. I think the toughest part is actually defining what it means to do these things. And then reconciling that with existing behavior which is most likely different and thus it will be a breaking change.

@nagilson
Copy link
Member

nagilson commented Jan 9, 2023

This is definitely an SDK issue, but I don't agree with the idea of turning the automatic RID on for everything... in fact it was like that during part of 7.0.100, and it broke a lot of people.

But @kant2002 is 💯 % right in that it's the fact that it's a library that's the reason there is no implicit RID. The RID only is inferred for executable projects, there are a lot of library projects: EX for a classlib, PublishReadyToRun should not build or publish successfully.

Maybe the suggestion is for winforms project types in particular we allow them to get the implicit RID? Tbh I don't know anything about winforms, but it sounds like something we'd want to do.

@nagilson nagilson transferred this issue from dotnet/runtime Jan 9, 2023
@nagilson nagilson removed the untriaged Request triage from a team member label Jan 9, 2023
@am11
Copy link
Member

am11 commented Jan 9, 2023

in fact it was like that during part of 7.0.100, and it broke a lot of people.

Were those people using PublishAot=true? This issue is specific to NativeAOT, where RID and SelfContained are always required during the publish regardless of OutputType. The proposed fix does not affect anything else.

@vitek-karas
Copy link
Member

The issues were not with publish itself, they were that setting PublishAot=true in a project file affected the behavior of dotnet build and other commands which had nothing to do with publish. That's not to say that it would make sense to default a RID when publishing a library as NativeAOT.

@am11
Copy link
Member

am11 commented Jan 9, 2023

I see, so '$(_IsPublishing)' == 'true' must be checked (if it isn't already).

That's not to say that it would make sense to default a RID when publishing a library as NativeAOT.

Could you explain why it wouldn't make sense? In my understanding, NativeAOT publishing requires RID (mandatory). We are inferring RID for !IsRidAgnostic cases in .NET 7. So I don't see a reason why we should let OutputType affect this inference with dotnet publish -p:PublishAot=true.

@nagilson
Copy link
Member

nagilson commented Jan 9, 2023

The issues were not with publish itself, they were that setting PublishAot=true in a project file affected the behavior of dotnet build

That was an issue but not the one I was referring to. There was a different one where VS was broken because of library projects getting a RID, and builds working that shouldn't have worked. #28628

Were those people using PublishAot=true?

The specific issue was with PublishSingleFile. I'm pretty sure that property and PublishReadyToRun shouldn't get an implicit RID for libraries. PublishAot auto-rid I haven't heard of breaking anyone, but I don't really understand it well enough to say. But if someone from the Aot side is able to comment on this, and confirm we would want a RID if it's in any type of library project, or which types of library projects we'd want a RID for PublishAot, that would be a change we could do.

@vitek-karas
Copy link
Member

That's not to say that it would make sense to default a RID when publishing a library as NativeAOT.

Could you explain why it wouldn't make sense?

Sorry, typo. I meant to say that it does make sense to default a RID when publishing a library as NativeAOT. Lot of the complexity comes from the fact that we want to default the RID typically only when publishing. Building a library because it's a dependency of some other project should not be affected by publish properties. But unfortunately the way SDK/msbuild currently operates the RID defaulting has to happen early on. I'm definitely no expert in that area though - I'll leave it to @nagilson to comment on the feasibility of doing this. Things which I find "interesting":

  • What happens if a PublishAot=true library project is used as a project dependency in some other app. How will that work when I dotnet build that app? What will happen if I dotnet publish the app?
  • What is the RID behavior when I dotnet build the library which has PublishAot=true in its project file.
  • What about dotnet test - next to the library I have a test project which has a dependency on the library (tests for the library), what happens in that case?

@kant2002
Copy link
Author

I would like to split discussion in two parts. Seems to be for --self-contained there no ambiguity, can we just make this change, since that's what give most headache. RID discussion is important, but less impactful on dev experience IMO.

Regarding RID. My understanding that dotnet build,dotnet run and dotnet test are for inner dev loop, where dotnet publish is publish process. If I read conversation correctly, we all want this change only for publish process, without touching dev inner loop. I'm not that familiar with SDK, does RID inference affects dotnet build currently for some scenarios?

@nagilson
Copy link
Member

I'll leave it to @nagilson to comment on the feasibility of doing this

ATM, we can limit the inference only by the dotnet command given: if a library needs to be 'built' but not 'published,' and the library is the dependency of something we invoked dotnet publish on, we don't have the granular control to change the library behavior, it would get the publish behavior. It may be theoretically possible to do it a different way, but it'd probably be an "Epic" in terms of work required and may be impossible.

How will that work when I dotnet build that app? What will happen if I dotnet publish the app

Currently it wouldn't get the inference. As above, we could change the behavior for build and publish on the app. But we'd need a MSBuild property that is available early on to tell the difference between a Library that's NativeAot and one that's not.

What is the RID behavior when I dotnet build the library which has PublishAot=true in its project file.

Currently it shouldn't do anything.

What about dotnet test

This I'm unsure of.

does RID inference affects dotnet build currently for some scenarios?

Before 7.0.200 it did for every property that gets inference, in 7.0.200 only SelfContained.

can we just make this change

Would need to look into self-contained a bit more to make sure nothing is broken.

@marcpopMSFT marcpopMSFT added Area-NativeAOT Native AOT compilation and removed Area-NetSDK labels Jan 10, 2023
@dougkl
Copy link

dougkl commented Aug 4, 2024

I am having the same issue, this error just shows when the project is set the PublishAot = true and FrameworkDependent if I try to set my project as SelfContained I have ILC Compile errors

08:15:35.128   1:7>C:\Users\Superusername\.nuget\packages\microsoft.windowsdesktop.app.runtime.win-x64\8.0.7\runtimes\win-x64\lib\net8.0\System.Windows.Forms.dll : warning IL3053: Assembly 'System.Windows.Forms' produced AOT analysis warnings. [E:\ProjectSr\WebServiceStarter.csproj]
08:15:35.672   1:7>C:\Users\Superusername\.nuget\packages\microsoft.windowsdesktop.app.runtime.win-x64\8.0.7\runtimes\win-x64\lib\net8.0\System.Configuration.ConfigurationManager.dll : warning IL2104: Assembly 'System.Configuration.ConfigurationManager' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries [E:\ProjectSr\WebServiceStarter.csproj]
08:15:36.170   1:7>C:\Users\Superusername\.nuget\packages\microsoft.data.sqlclient\5.1.5\runtimes\win\lib\net6.0\Microsoft.Data.SqlClient.dll : warning IL3053: Assembly 'Microsoft.Data.SqlClient' produced AOT analysis warnings. [E:\ProjectSr\WebServiceStarter.csproj]
08:15:36.734   1:7>C:\Users\Superusername\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\8.0.7\framework\System.Private.DataContractSerialization.dll : warning IL3053: Assembly 'System.Private.DataContractSerialization' produced AOT analysis warnings. [E:\ProjectSr\WebServiceStarter.csproj]
08:15:45.034   1:7>EXEC : error : One or more errors occurred. (Invalid IL or CLR metadata) [E:\ProjectSr\WebServiceStarter.csproj]
                     System.AggregateException: One or more errors occurred. (Invalid IL or CLR metadata) (TaskId:234)
                      ---> Internal.TypeSystem.TypeSystemException+InvalidProgramException: Invalid IL or CLR metadata (TaskId:234)
                        at Internal.TypeSystem.ThrowHelper.ThrowInvalidProgramException() + 0x24 (TaskId:234)
                        at Internal.JitInterface.CorInfoImpl.CompileMethodInternal(IMethodNode, MethodIL) + 0x22a (TaskId:234)
                        at Internal.JitInterface.CorInfoImpl.CompileMethod(MethodCodeNode, MethodIL) + 0x5c (TaskId:234)
                        at ILCompiler.RyuJitCompilation.CompileSingleMethod(CorInfoImpl, MethodCodeNode) + 0xc7 (TaskId:234)
                        at ILCompiler.RyuJitCompilation.CompileSingleMethod(MethodCodeNode methodCodeNodeNeedingCode) + 0x90 (TaskId:234)
                        at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion) + 0x289 (TaskId:234)
                     --- End of stack trace from previous location --- (TaskId:234)
                        at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20 (TaskId:234)
                        at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(Exception) + 0x13 (TaskId:234)
                        at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion) + 0x44a (TaskId:234)
                        at System.Threading.Tasks.TaskReplicator.Replica.Execute() + 0x66 (TaskId:234)
                        --- End of inner exception stack trace --- (TaskId:234)
                        at System.Threading.Tasks.TaskReplicator.Run[TState](TaskReplicator.ReplicatableUserAction`1, ParallelOptions, Boolean) + 0x150 (TaskId:234)
                        at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt, TInt, ParallelOptions, Action`1, Action`2, Func`4, Func`1, Action`1) + 0x394 (TaskId:234)
                     --- End of stack trace from previous location --- (TaskId:234)
                        at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20 (TaskId:234)
                        at System.Threading.Tasks.Parallel.ThrowSingleCancellationExceptionOrOtherException(ICollection, CancellationToken, Exception) + 0x30 (TaskId:234)
                        at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt, TInt, ParallelOptions, Action`1, Action`2, Func`4, Func`1, Action`1) + 0x450 (TaskId:234)
                        at ILCompiler.RyuJitCompilation.CompileMultiThreaded(List`1) + 0x1f0 (TaskId:234)
                        at ILCompiler.RyuJitCompilation.ComputeDependencyNodeDependencies(List`1 obj) + 0x166 (TaskId:234)
                        at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ComputeMarkedNodes() + 0x95 (TaskId:234)
                        at ILCompiler.RyuJitCompilation.CompileInternal(String, ObjectDumper) + 0x1f (TaskId:234)
                        at ILCompiler.Compilation.ILCompiler.ICompilation.Compile(String, ObjectDumper) + 0x2d (TaskId:234)
                        at ILCompiler.Program.Run() + 0x2772 (TaskId:234)
                        at ILCompiler.ILCompilerRootCommand.<>c__DisplayClass227_0.<.ctor>b__0(ParseResult result) + 0x315 (TaskId:234)
08:15:45.177   1:7>C:\Users\Superusername\.nuget\packages\microsoft.dotnet.ilcompiler\8.0.7\build\Microsoft.NETCore.Native.targets(308,5): error MSB3073: The command ""C:\Users\Superusername\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\8.0.7\tools\ilc" @"obj\Release\net8.0-windows\win-x64\native\WebServiceStarter.ilc.rsp"" exited with code 1. [E:\ProjectSr\WebServiceStarter.csproj]
                   Done executing task "Exec" -- FAILED. (TaskId:234)
08:15:45.177   1:7>Done building target "IlcCompile" in project "WebServiceStarter.csproj" -- FAILED.: (TargetId:364)
08:15:45.177   1:7>Done Building Project "E:\ProjectSr\WebServiceStarter.csproj" (Publish target(s)) -- FAILED.

@vitek-karas
Copy link
Member

@dougkl :

this error just shows when the project is set the PublishAot = true and FrameworkDependent

What do you want to achieve by this setup? Currently NativeAOT doesn't support anything but self-contained mode (it will always include the runtime in the final binary).

For the compiler crash (when self-contained is enabled), could you please create a new issue in the dotnet/runtime repo?

/cc @MichalStrehovsky

@dougkl
Copy link

dougkl commented Aug 5, 2024

@vitek-karas just did dotnet/runtime#105947 thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-NativeAOT Native AOT compilation
Projects
None yet
Development

No branches or pull requests

7 participants