通过MSBuild目标

时间:2017-11-02 16:26:05

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

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

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

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

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

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

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

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

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

但是,如果我们能解决这个问题,我不确定它是否会奏效。我们在子项目上使用nuget restore命令进行了测试,并始终获得install.conf中所有软件包的安装响应。然而,来自该外部项目的.. \ packages \是空的,packages.conf指定了六个包(VS中的“References”也缺少它们,而且引用'HintPath正确地转到.. \ packages)。

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

2 个答案:

答案 0 :(得分:3)

  

我们如何引用来自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>

enter image description here

答案 1 :(得分:1)

NuGet发现要从解决方案文件恢复的packages.config项目。如果所有项目都在解决方案文件中并运行nuget.exe restore <solution file>,那么无论项目文件中发生了什么,都应该恢复它们。

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

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