gpt4 book ai didi

.net - 指定 PackageReference 依赖 DLL 的构建输出位置

转载 作者:行者123 更新时间:2023-12-01 21:35:38 24 4
gpt4 key购买 nike

我有一个带有一些 NuGet 依赖项的项目,使用 PackageReference:

<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
</ItemGroup>

我不希望依赖直接安装在bin\${buildConfiguration}\${framework}文件夹中(括号中的文件( )):

bin
Debug
net472
(MyLibrary.dll)
(Microsoft.CSharp.dll)
(Microsoft.Xaml.Behaviors.Wpf.dll)

相反,我希望每个构建的依赖项都放在更深的子文件夹中,如下所示:

bin
Debug
net472
(MyLibrary.dll)
MyLibrary
(Microsoft.CSharp.dll)
(Microsoft.Xaml.Behaviors.Wpf.dll)

我知道我可以使用 nuget.config 文件来控制解决方案包的下载位置,但 NuGet 依赖项的构建输出保持不变——bin/release/framework文件夹。

请注意,我想要的不仅仅是移动文件,这可以通过构建后步骤完成,但不会很有用。我需要在构建时更改对相关 DLL 的引用以引用子文件夹而不是根文件夹;所以我可以将根文件夹的全部内容作为一个整体复制到不同的位置,并且仍然可以正常工作。

MyLibrary.dll是使用SDK格式的工程构建的,它使用了PackageReference;它可以是 .NET Framework、.NET Core 或 .NET Standard。

我该怎么做?


一些背景

我编写了一个 Visual Studio debugging visualizer for expressions .调试可视化工具是手动复制的单个 DLL - 连同它们的依赖项 - 到 Documents 下的特定子文件夹 - 例如Visual Studio 2019\Visualizers - 或 VS 安装文件夹的 Visualizers 子文件夹。

如果有两个可视化工具依赖于同一个库的不同版本,那么其中一个很容易崩溃。删除可视化工具是删除不需要的依赖项的偶然事件。

在为 .NET Core 或 .NET Standard 编写可视化工具时需要创建多个 DLL,这使情况更加复杂;这些 DLL 中的每一个都可能有自己的依赖项。

如果可以将依赖项输出到具有相同名称的子文件夹,那将是朝着正确方向迈出的一步。

( Developer community feature request 和(现已关闭)request to document better solutions to this problem )

最佳答案

我只在最基本的情况下对此进行了测试,因此多目标项目可能需要对此进行修改,并且非 sdk 样式项目的工作方式可能与 sdk 样式项目不同,但是:

调查

关于调查任何 MSBuild,您需要了解的最重要的一件事情是 binary log output , 用 MSBuild Structed Log Viewer 查看.

因此,我运行了 dotnet new consoledotnet add package NuGet.Versioning,因为我确实需要在控制台应用程序中进行 SemVer2 比较。现在,我运行 dotnet build -blstart msbuild.binlog

在 MSBuild 日志查看器中,从包中搜索程序集名称,然后搜索单词 copy。在我的例子中,我搜索了“copy nuget.versioning.dll”,它找到了一个结果。单击它,我看到消息是由名为“Copy”的任务输出的,该任务在名为“_CopyFilesMarkedCopyLocal”的目标中运行。单击树中的任务复制,它会在运行复制任务的行上打开 Microsoft.Common.CurrentVersion.targets 的 TextView ,我看到了:

    <Copy
SourceFiles="@(ReferenceCopyLocalPaths)"
DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyLocalIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyLocalIfPossible)"
Condition="'$(UseCommonOutputDirectory)' != 'true'"
>

注意目标 DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"。好的,DestinationSubDirectory 听起来很有希望。检查复制任务的参数,DestinationFiles 项没有任何 DestinationSubDirectory 设置,所以看起来我可以将它设置为我想要的任何相对路径。

让我们搜索定义 ReferenceCopyLocalPaths 项的位置。我看到“AddItem ReferenceCopyLocalPaths”的两个搜索结果,但检查它们的“调用堆栈”时,我发现它们都在名为“ResolveReferences”的目标下。

最后一件事,因为这个问题是关于来自 PackageReference 的程序集,我想格外小心,所以我查看了 ReferenceCopyLocalPaths 项目,并注意到它有一个名为 NuGetPackageId 的元数据项目。

现在:

  • 我想在 ResolveReferences 目标之后运行我自己的目标
  • 我希望它更新 ReferenceCopyLocalPaths 项目
  • 定义 NuGetPackageId 元数据的地方
  • 将 DestinationSubDirectory 设置为某个路径

解决方案

将此目标添加到您的 csproj 中:

  <Target Name="CopyPackageAssembliesToSubFolder" AfterTargets="ResolveReferences">
<ItemGroup>
<ReferenceCopyLocalPaths Condition=" '%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' "
Update="%(ReferenceCopyLocalPaths)"
DestinationSubDirectory="libs\" />
</ItemGroup>
</Target>

现在,当我运行 dotnet clean 时; dotnet build,我看到 bin 目录有一个包含 NuGet.Versioning.dll 的 libs/ 文件夹。

关于.net - 指定 PackageReference 依赖 DLL 的构建输出位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62001105/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com