-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add ILLink targets and tests #3125
Conversation
--> | ||
<Target Name="ILTransform" | ||
Condition="'$(_TargetFrameworkVersionWithoutV)' >= '3.0' And '$(TargetFrameworkIdentifier)' == '.NETCoreApp'" | ||
DependsOnTargets="$(ILTransformDependsOn)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this only for .NetCoreApp
? How about, if there are whole unused IL files that are not reachable from any public entrypoints in a .netstandard
dll? (ex: partial classes) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right that it would make sense for netstandard, and the linker behavior is probably similar to the portable app case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that since linking happens during publish, the normal workflow of packaging a netstandard library would not run the linker, and it would take some work by library authors to package a linked library. I agree that it makes sense not to block it here.
Condition=" '$(LinkDuringPublish)' == 'true' " | ||
DependsOnTargets="RunILLink"> | ||
|
||
<!-- For now, use ResolvedFileToPublish as input/output. This |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The linker works with ResolvedFileToPublish
as input, and I think that's the way it should be for now.
But I'm curious why crossgen works differently. Crossgen targets run after _ComputeResolvedFilesToPublishTypes
target, and processes/updates the files bifurcated into _ResolvedFileToPublishPreserveNewest
and _ResolvedFileToPublishAlways
items. However, the processing /input-outputs for the two lists there are similar. So, why doesn't crossgen similarly process ResolvedFileToPublish
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question - @fadimounir can you answer this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I started implementing this, i was under the impression that I would need to add some logic to the crossgen task to distinguish between the 2 lists, and only compile things in the PreserveNewest if they were out of date.
Things have evolved since then, and thinking about it now, I believe we should be able to just make crossgen work with the 'ResolvedFileToPublish', before the split that '_ComputeResolvedFilesToPublishTypes' does.
I'll make that change. For the linker, i think this looks correct.
The linker does one operation with multiple input files. Crossgen does multiple operations, each with its own input file, so splitting the 'ResolvedFilesToPublish' by type doesn't make sense here i believe
Looks good. |
4a9b55c
to
3f83d19
Compare
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Show resolved
Hide resolved
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Outdated
Show resolved
Hide resolved
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Show resolved
Hide resolved
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Show resolved
Hide resolved
<ResourceCopyLocalItems Remove="@(_RemovedManagedAssemblies)" /> | ||
<RuntimeCopyLocalItems Remove="@(_RemovedManagedAssemblies)" /> | ||
<RuntimeTargetsCopyLocalItems Remove="@(_RemovedManagedAssemblies)" /> | ||
<RuntimePackAsset Remove="@(_RemovedManagedAssemblies)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the kind of change that would be undesirable if we moved this targets file to the ILLink nuget package, because if the names here change, this would be breaking.
@nguerrera, how can we ensure that name changes here won't break other tools/SDKs that depend on this? CI tests good enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if other sdks to depend on it is expected, it should be public and follow backward compact rules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is exactly why we are putting the targets portion in the SDK. The contract to the linker is pure, no global mutations. Yes, other tools might do this sort of thing, but we specifically cut defining a strict contract for such tools. The linker will be first class and any mutation of the build state will happen in dotnet/sdk. This + sufficient tests will ensure that we don't just break the linker as we used to when it was it's own nuget package. I want to make it possible to write these sort of things outside of the sdk, but it is a hard problem and specifically not one we are going to solve as part of this work.
Looks good overall, modulo the question regarding where the targets file should be, and any related side-effect. |
For dotnet/sdk#3125. This most notably adds a net472 build of ILLink.Tasks, and modifies Sdk.props to import the correct build of the tasks, depending on the MSBuild runtime type. This makes it possible to use the linker tasks on desktop MSBuild once again. Regardless of the MSBuild runtime, illink.dll will run on .NET Core. We set 'rollForwardOnNoCandidateFx' to allow running on .NET Core 3 (even though illink.dl is built targeting netcoreapp2.0). This change removes many workarounds from the old packaging logic, as we can now use NuGet extension points and avoid using a custom .nuspec.
<!-- Remove assemblies from inputs to GenerateDepsFile. See | ||
https://github.com/dotnet/sdk/pull/3086. --> | ||
<ItemGroup> | ||
<_RemovedManagedAssemblies Include="@(_ManagedAssembliesToLink)" Condition="!Exists('$(IntermediateLinkDir)/%(Filename)%(Extension)')" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure $(IntermediateLinkDir) has trailing slash, and don't put the / in the condition or other uses of it plus a file. Look at how this is done for the other output paths.
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Show resolved
Hide resolved
|
||
<ItemGroup> | ||
<_ManagedAssembliesToLink Remove="@(_ManagedResolvedFileToPublish->WithMetadataValue('AssetType', 'resources'))" /> | ||
<_LinkedResolvedFileToPublishCandidates Include="@(_ManagedAssembliesToLink->'$(IntermediateLinkDir)/%(Filename)%(Extension)')" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure trailing slashes and don't use slash. $(IntermediateLinkDir)%(Filename)%(Extension)
where somewhere else there's a !HasTrailingSlash -> add trailing slash. Look at the other ouptut paths that have this pattern
<!-- Also remove them from the old deps file generation logic, | ||
until https://github.com/dotnet/sdk/issues/3098 is | ||
fixed. --> | ||
<_PublishConflictPackageFiles Include="@(_RemovedManagedAssemblies)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch to new logic based on linker being enabled as discussed.
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Outdated
Show resolved
Hide resolved
@@ -175,6 +176,17 @@ Copyright (c) .NET Foundation. All rights reserved. | |||
|
|||
</Target> | |||
|
|||
<!-- | |||
============================================================ | |||
ILTransformForPublish |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not advertise an extension point, and treat that as a separate feature.
It feels weird that this is tied to the TFM as well. Also, publishing for .NETSTandard is very weird (I wish it didn't work), and there is no .NETStandard 3.0, the current version aligned with 3.0 timeframe is 2.1. I think we should limit to NETCoreApp 3.0+ alone. But I think this limit should be applied directly to the linker and not to some generic extensibility point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed this, and made _ILLink
a direct dependency of ComputeAndCopyFilesToPublishDirectory
.
RootAssemblyNames="@(IntermediateAssembly->'%(Filename)')" | ||
RootDescriptorFiles="@(TrimmerRootDescriptors)" | ||
OutputDirectory="$(IntermediateLinkDir)" | ||
ExtraArgs="$(ExtraLinkerArgs) --skip-unresolved true" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be ExtraTrimmerArgs if the other public facing options are "Trimmer"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Named it _ExtraTrimmerArgs
. I don't want to advertise this as a public facing option, and am hoping we can stop using it in the future in favor of defaults that do the right thing. Taking a property here makes it easier to test and makes it easier for us to give users workarounds in case they encounter issues.
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets
Outdated
Show resolved
Hide resolved
@nguerrera I've responded to all of your feedback. Does it look good to merge? I'd like to get it in so that I can make follow-up changes independently. |
Deps file trimming doesn't work on ProjectReferences, so this changes the referenced test project to be a PackageReference. We also disable use of the build dependency file when linking, as the publish dependency file needs to be generated based on what the linker decided to remove.
The current public-facing linker properties are now: - PublishTrimmed - TrimmerRootDescriptors The IL transform extension point has been named ILTransformForPublish, to make it clear that it only runs on publish. This also enables incremental build for project file changes, and lets the linker run on projects targeting .NETStandard.
- Ensure trailing slash in linker output directory - Disable old deps file generation logic - Don't support netstandard - ExtraLinkerArgs -> _ExtraTrimmerArgs - Remove ILTransformForPublish extension point
Looks like the SDK uptake issue has been unblocked: #3153. Removing the workarounds from this PR. |
<_LinkSemaphore>$(IntermediateOutputPath)Link.semaphore</_LinkSemaphore> | ||
<!-- Disable old deps file generation logic until | ||
https://github.com/dotnet/sdk/issues/3098 is fixed. --> | ||
<DepsFileGenerationMode>new</DepsFileGenerationMode> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need this anymore if we can merge #3152 first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nguerrera mind if I do that in a follow-up PR? I'd like to get this change in sooner rather than later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<TrimmerRootDescriptors Include="$(TrimmerRootDescriptors)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these files? It is weird to have a "public" item and property of the same name. Is there a reason why the user wouldn't provide these directly as items?
Also, item names are generally singular (though it is not 100% consistent) so this is more of a nit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are files. In the OOB package we supported this to make it easy to test on the command-line. I'll get rid of this in a follow-up and we can iterate there.
@nguerrera I know you're very busy atm - thank you for finding time to review this! |
@nguerrera please merge when you get a chance! |
….7 (#3125) - Microsoft.DotNet.Cli.Runtime - 5.0.100-alpha1.19506.7
For dotnet/sdk#3125. This most notably adds a net472 build of ILLink.Tasks, and modifies Sdk.props to import the correct build of the tasks, depending on the MSBuild runtime type. This makes it possible to use the linker tasks on desktop MSBuild once again. Regardless of the MSBuild runtime, illink.dll will run on .NET Core. We set 'rollForwardOnNoCandidateFx' to allow running on .NET Core 3 (even though illink.dl is built targeting netcoreapp2.0). This change removes many workarounds from the old packaging logic, as we can now use NuGet extension points and avoid using a custom .nuspec. Commit migrated from dotnet/linker@010f98e
This adds linker targets, mostly adapted from https://github.com/mono/linker/blob/9766e2b2406a3d44cbf05e49ab2bd19b535e3e5a/src/ILLink.Tasks/ILLink.Tasks.targets, to run the linker after
ComputeFilesToPublish
.A few things still need to change (but I wanted to get what I have so far out for review):
Change property names to agreed-upon stringsUpdate deps file generation in response to Rewrite deps file generation #3086. I think this needs Merge release/3.0.1xx to master #3113 or another update PR to be merged.Update the linker:to includeUsingTask
for other tasks in the assembly (namely,ComputeManagedAssemblies
)forReferencePath
supportwith a net472 build of the task dllWhen I run these tests locally with a recent version of the linker, the checks pass up to the deps file asserts.All checks are passing.
@nguerrera, @fadimounir, @swaroop-sridhar PTAL