Skip entry-point trim roots for library outputs#125673
Draft
Conversation
Co-authored-by: sbomer <787361+sbomer@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix new error in .NET 8 Android projects
Skip entry-point trim roots for library outputs
Mar 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Trimmed self-contained library-style app publishes can fail with
IL1034because the SDK always roots the intermediate assembly asRootMode="EntryPoint", even whenOutputType=Library. This updates the trimming target so library projects are not given an entry-point root.SDK target change
Microsoft.NET.ILLink.targets, make the intermediate assemblyTrimmerRootAssemblyitem conditional on$(OutputType) != 'Library'.Regression coverage
ILLink.Taskstest that inspects the shipped target file and asserts the entry-point root is conditioned away for library projects.Behavioral effect
Exeprojects continue to root the main assembly by entry point.Libraryprojects no longer request an entry-point root from the trimmer, avoiding the invalid root configuration that triggersIL1034.Original prompt
This section details on the original issue you should resolve
<issue_title>New error in .NET 8 Android projects</issue_title>
<issue_description>Starting in this Maestro bump: dotnet/android#7630
We started seeing:
Might be caused by: dotnet/linker#3124 (comment)
Android apps are class libraries, because there is no
static void Main()method.To work around this I did:
Filing an issue here, to see if this is what we should actually do -- or something else.</issue_description>
<agent_instructions>Don't set a trimmer root assembly for library projects.</agent_instructions>
Comments on the Issue (you are @copilot in this section)
@vitek-karas @sbomer please take a look. @sbomer I think the workaround ~is doing the right thing~ (edit: see my next comment), and I think it would make sense to put the fix for this into the SDK. In https://github.com/dotnet/linker/pull/3131 we decided against it, but I think this issue shows that we really do already have non-exe projects as a supported scenario - I just didn't know it.I think we should fix this by using
RootMode="library"RootMode="visible" when theOutputTypeisLibrary. From dotnet/android#4604, I think this will work for the Android scenario. Does that sound right to you @jonathanpeppers?Note @vitek-karas @marek-safar @MichalStrehovsky this will make
"library""visible" root mode an officially supported feature for the first time - are we OK with this? If not, the alternative would be to use "all" to get the behavior from before dotnet/linker#3124.</comment_new><comment_new>@sbomer
Sorry, I just remembered that "library" has extra behavior which disables optimizations for when we are only trimming a single library against reference assemblies. I think what we actually want is "visible". @jonathanpeppers you might want to use RootMode="Visible" (or "All", to get the previous behavior) in your workaround instead, until we resolve this issue.</comment_new>
<comment_new>@sbomer
Another option, instead of using the assembly RootMode, would be to let the Android SDK tell the linker via XML descriptor which entry points to keep. Presumably there is an effective entry point (or multiple) for Android apps that is statically known, even if it's not encoded as such in the PE file. This option has slightly cleaner trimming behavior, but I don't like that it relies on the XML.</comment_new>
<comment_new>@MichalStrehovsky
It's not clear to me what "publishing a self-contained library" actually means. (We only support trimming for selfcontained deployments.)
E.g. if we want to support #79377 with IL Linker, we would actually only want to root things with
[UnmanagedCallersOnly(EntryPoint = "Foo")]. This is a definition for "publishing a self-contained library" that makes sense.@jonathanpeppers what are the trimming roots in an Android application?</comment_new>
<comment_new>@marek-safar
I'm not sure that's what we really want. My understanding of the scenario is that this is not library mode trimming but trimming with a custom entry point name that is hardcoded somewhere in XA interop. I think the expectation is that all public methods in such library will be trimmed. </comment_new>
<comment_new>@jonathanpeppers
Android has many roots, where Android/Java will call into managed code, such as:
Android.App.ApplicationAndroid.App.Activity's.xmlI think Android tried really hard to be "decoupled"...
💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.