【问题标题】:Resolve .NET 4.7 external project NuGet dependencies via MSBuild targets通过 MSBuild 目标解决 .NET 4.7 外部项目 NuGet 依赖项
【发布时间】:2018-04-15 06:19:02
【问题描述】:

我们需要构建这些项目,它们有一些奇怪的做法。它们依赖于作为另一个项目的构建过程的结果生成的链接代码文件。这些项目位于一个子文件夹中。

因此,在构建我们的项目之前,我们需要构建子项目。这是通过向每个项目的 BeforeBuild 目标添加自定义构建目标来完成的,并且似乎有效。但是,如果没有恢复其 NuGet 依赖项,子项目将无法构建。

澄清一下:我们知道这种模式完全是疯狂的,但我们没有人力来重构每个使用这种模式的项目。我们只是想让它们一步可靠地编译。

每个外部项目依赖项都列在自定义 ItemGroup 中,如下所示:

<ItemGroup> <ExternalDependantProjects Include= "..\<subfolder>\<project>\<project>.csproj" /> </ItemGroup>

我们一直在尝试通过添加由每个项目的 BeforeBuild 目标调用的自定义构建目标来解决这个问题。我们首先尝试使用 ResolveNuGetPackageAssets 作为构建目标,但发现这仅在 netcore 中受支持,而我们的目标是 net47。

现在我们正在尝试编写一个自定义构建目标,该目标将恢复外部项目中的 NuGet 依赖项。我们尝试了直截了当的方法,如下所示:&lt;Exec Command="nuget restore @(ExternalDependantProjects)" /&gt; 以及更复杂和更复杂的 PowerShell 尝试:&lt;Exec Command="powershell.exe -command &amp;quot;&amp;apos;@(ExternalDependantProjects, '&amp;apos; &amp;apos;')&amp;apos; | foreach { nuget restore $_ }&amp;quot;" /&gt;

在这两种情况下,它只是尝试恢复主项目的包,而不是外部项目。 @(ExternalDependantProjects) 似乎等于空白,因此没有添加新参数。使用表明 @(ExternalDependantProjects) 不返回任何内容。但是,当我们调用 MSBuild“构建”目标时,它确实可以用作“项目”参数。所以,我怀疑我们以错误的方式使用 Item 参数?也许有一些语法可以访问 Item 的 Include 属性?

但是,如果我们能够解决该问题,我不确定它是否会起作用。我们在子项目上使用 nuget restore 命令进行了测试,总是得到packages.conf中所有包都安装的响应。然而,来自该外部项目的 ..\packages\ 是空的,并且 packages.conf 指定了六个包(它们也从 VS 的“引用”中丢失,并且引用的 HintPath 正确地转到了 ..\packages)。

所以我们在三个方面感到困惑:我们如何引用来自 MSBuild 目标的 ExternalDependentProjects 项包含路径,为什么 NuGet 恢复 CLI 不起作用,这甚至是解决此问题的正确方法吗?我们是不是完全走错了路?

【问题讨论】:

  • 为什么这需要被黑客入侵并不明显。就像其他任何项目一样,让它成为一个正常的项目。您所要做的就是确保它先于其他构建。 MSBuild 可能无法自行解决此问题,因此您必须提供帮助。右键单击解决方案节点并选择项目依赖项。
  • @Jansky,这个问题呢?这个问题解决了吗?如果没有,请告诉我有关此问题的最新信息吗?
  • 嘿@Leo-MSFT,我非常感谢您在回复中付出的所有努力。它给了我一些很好的解决方案。但是我已经被转移到另一个项目,不确定何时/是否有时间解决这个问题。无论如何,我暂时将您的答案标记为答案。

标签: visual-studio msbuild nuget msbuild-task nuget-cli


【解决方案1】:

我们如何引用来自 MSBuild 目标的 ExternalDependentProjects 项包含路径,为什么 NuGet 恢复 CLI 不起作用,这甚至是解决此问题的正确方法吗?我们是不是完全走错了路?

您应该使用选项-OutputDirectory 编写自定义构建目标,因此自定义构建目标应如下所示:

  <Target Name="BeforeBuild">
      <Exec Command="nuget restore @(ExternalDependantProjects) -OutputDirectory ..\<subfolder>\packages" />
  </Target>

使用此目标,外部项目的 NuGet 包将成功恢复。

此外,@(ExternalDependantProjects) 的值不等于空白,您可以使用目标回显该值。

以下是我的测试样例,您可以参考一些详细信息:

ExternalpProject 是子文件夹名称,TestExternalProject 是外部项目名称。

<ItemGroup>
  <ExternalDependantProjects Include= "..\ExternalpProject\TestExternalProject\TestExternalProject.csproj" />
</ItemGroup> 

<Target Name="BeforeBuild">
  <Message Text="Restore package for Externalp Project" Importance="high"></Message>
  <Exec Command="nuget restore @(ExternalDependantProjects) -OutputDirectory ..\ExternalpProject\packages" />
</Target>

<Target Name="AfterBuild">
  <Message Text="Display the value of ExternalDependantProjects" Importance="high"></Message>
  <Message Text="@(ExternalDependantProjects)"></Message>
</Target>

【讨论】:

    【解决方案2】:

    NuGet 发现 packages.config 项目以从解决方案文件中恢复。如果所有项目都在解决方案文件中,并且您运行 nuget.exe restore &lt;solution file&gt;,则无论项目文件中发生了什么,它们都应该得到恢复。

    作为任何自定义方案的解决方法,您可以编写一个脚本来发现文件夹中的所有 packages.config 文件,然后直接在文件上调用 nuget.exe restore &lt;packages.config&gt; -SolutionDirectory &lt;solution root&gt;。对于 packages.config 恢复,唯一需要的部分是从 packages.config 文件中发现 id/versions 列表,以便可以将它们下载并解压缩到解决方案级别的 packages 文件夹。

    我还建议将项目引用与ReferenceOutputAssembly=false 一起使用,以确保项目按照您想要的顺序构建,并且不会相互引用。见:https://blogs.msdn.microsoft.com/kirillosenkov/2015/04/04/how-to-have-a-project-reference-without-referencing-the-actual-binary/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-19
      • 2018-11-15
      • 2020-01-02
      • 2019-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多