-
Notifications
You must be signed in to change notification settings - Fork 89
Make the MSBuild runtime assembly check more correct #360
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Microsoft.Build.Locator | ||
|
|
||
| Microsoft.Build.Locator helps you locate and register MSBuild assemblies provided with Visual Studio or the .NET SDK. This is essential when you need to use MSBuild APIs in your application to evaluate or build projects. | ||
|
|
||
| ## Why do I need this? | ||
|
|
||
| When using MSBuild's .NET API to load and build projects, you need access to the SDKs and build logic distributed with Visual Studio or the .NET SDK, not just the MSBuild APIs. MSBuildLocator helps you find these installations and set up your application to use them, ensuring your code gets the same view of projects as `MSBuild.exe`, `dotnet build`, or Visual Studio. | ||
|
|
||
| ## Quick Start | ||
|
|
||
| Before using any MSBuild APIs, register MSBuild assemblies: | ||
|
|
||
| ```csharp | ||
| using Microsoft.Build.Locator; | ||
| using Microsoft.Build.Evaluation; | ||
|
|
||
| // Register defaults before using any MSBuild types | ||
| MSBuildLocator.RegisterDefaults(); | ||
|
|
||
| // Now you can safely use MSBuild APIs. | ||
| // NOTE: due the the way that the CLR loads assemblies, you MUST | ||
| // register MSBuild through Locator before any types from | ||
| // the MSBuild assemblies are used in your application. | ||
| // The safest way to ensure this is to put any MSBuild API | ||
| // access into a separate method. | ||
| LoadProject(); | ||
|
|
||
| void LoadProject() | ||
| { | ||
| var project = new Project("MyProject.csproj"); | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
| For more control over which MSBuild instance to use: | ||
|
|
||
| ```csharp | ||
| using Microsoft.Build.Locator; | ||
|
|
||
| // Query available MSBuild instances | ||
| var instances = MSBuildLocator.QueryVisualStudioInstances().ToArray(); | ||
|
|
||
| // Register a specific instance | ||
| var instance = instances.OrderByDescending(i => i.Version).First(); | ||
| MSBuildLocator.RegisterInstance(instance); | ||
| ``` | ||
|
|
||
| ## Documentation | ||
|
|
||
| For complete documentation, see [Use Microsoft.Build.Locator](https://learn.microsoft.com/visualstudio/msbuild/updating-an-existing-application#use-microsoftbuildlocator) on Microsoft Learn. | ||
|
|
||
| ## Samples | ||
|
|
||
| See the [BuilderApp](https://github.com/microsoft/MSBuildLocator/blob/a349ee7ffd889cd7634d3fd8b413bf9f29244b50/samples/BuilderApp) sample for a full | ||
| exploration of the MSBuildLocator library and capabilities. | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,24 @@ | ||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <Target Name="EnsureMSBuildAssembliesNotCopied" AfterTargets="Build" Condition="'$(DisableMSBuildAssemblyCopyCheck)' != 'true'"> | ||
| <Target Name="EnsureMSBuildAssembliesNotCopied" AfterTargets="ResolvePackageAssets" Condition="'$(DisableMSBuildAssemblyCopyCheck)' != 'true'"> | ||
| <ItemGroup> | ||
| <MSBuildPackagesWithoutPrivateAssets | ||
| Include="@(PackageReference)" | ||
| Condition="!$([MSBuild]::ValueOrDefault('%(PackageReference.ExcludeAssets)', '').ToLower().Contains('runtime')) and | ||
| ( | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Framework' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Utilities.Core' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Tasks.Core' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Engine' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Conversion.Core' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Runtime' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Localization' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.Build.Engine' or | ||
| '%(PackageReference.Identity)' == 'Microsoft.NET.StringTools' or | ||
| '%(PackageReference.Identity)' == 'NuGet.Frameworks' | ||
| )"/> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Framework'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Utilities.Core'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Tasks.Core'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Engine'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Conversion.Core'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Runtime'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Localization'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.Build.Engine'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'Microsoft.NET.StringTools'))" /> | ||
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'NuGet.Frameworks'))" /> | ||
| <MSBuildAssembliesCopyLocalItems Include="@(_MSBuildAssembliesCopyLocalItems->WithMetadataValue('CopyLocal', 'true')->WithMetadataValue('AssetType', 'runtime'))" /> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once we have the candidate set, we can find just the ones that are runtime assets and were copylocal'd. |
||
| <_DistinctMSBuildPackagesReferencedPoorly Include="@(MSBuildAssembliesCopyLocalItems->Metadata('NuGetPackageId')->Distinct())" /> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. such assets will have the nuget package id and version metadata on them, so we can distinct the IDs easily and make nice error messages. |
||
| <_DistinctPackagesWithVersions Include="@(_DistinctMSBuildPackagesReferencedPoorly->'%(NuGetPackageId)@%(NuGetPackageVersion)')" /> | ||
| </ItemGroup> | ||
|
|
||
| <Error | ||
| Condition="'@(MSBuildPackagesWithoutPrivateAssets)' != ''" | ||
| Text="A PackageReference to Microsoft.Build.* without ExcludeAssets="runtime" exists in your project. This will cause MSBuild assemblies to be copied to your output directory, causing your application to load them at runtime. To use the copy of MSBuild registered by MSBuildLocator, set ExcludeAssets="runtime" on the MSBuild PackageReferences. To disable this check, set the property DisableMSBuildAssemblyCopyCheck=true in your project file (not recommended as you must distributed all of MSBuild + associated toolset). Package(s) referenced: @(MSBuildPackagesWithoutPrivateAssets)" /> | ||
| Condition="@(_DistinctPackagesWithVersions->Count()) > 0" | ||
baronfel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Text="A PackageReference to an MSBuild run-time package without ExcludeAssets="runtime" exists in your project. This will cause MSBuild run-time assemblies to be copied to your output directory, causing your application to load them at runtime. To use the copy of MSBuild registered by MSBuildLocator, set ExcludeAssets="runtime" on the MSBuild PackageReferences. To disable this check, set the property DisableMSBuildAssemblyCopyCheck=true in your project file (not recommended as you must distributed all of MSBuild + associated toolset). Package(s) referenced: @(_DistinctPackagesWithVersions, ', ')" /> | ||
| </Target> | ||
| </Project> | ||
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.
ResolvePackageAssets creates RuntimeCopyLocalItems for all dependencies, so we have to filter those down to just the ones that came from the MSbuild-related dependencies we want to flag.