简体   繁体   English

通过MSBuild目标解决.NET 4.7外部项目NuGet依赖项

[英]Resolve .NET 4.7 external project NuGet dependencies via MSBuild targets

We need to get these projects to build and they have some strange practices. 我们需要构建这些项目,并且它们有一些奇怪的实践。 They rely on linked code files that are generated as the result of another project's build process. 它们依赖于另一个项目的构建过程所生成的链接代码文件。 These projects are situated in a sub-folder. 这些项目位于子文件夹中。

Thus, before building our projects we need to build the sub-project. 因此,在构建项目之前,我们需要构建子项目。 This is done by adding a custom build target to each project's BeforeBuild target, and seems to work. 这是通过将自定义构建目标添加到每个项目的BeforeBuild目标来完成的,并且似乎可行。 However, the sub-project won't build without having it's NuGet dependencies restored. 但是,如果不还原NuGet依赖项,则不会构建子项目。

To clarify: We know that this pattern is totally bonkers, but we don't have anything like the manpower to refactor every project that uses this pattern. 需要说明的是:我们知道这种模式完全是傻瓜,但我们没有像重构使用该模式的每个项目那样的人力。 We're just trying to get them to compile reliably in one step. 我们只是试图让它们一步一步可靠地进行编译。

Each of these external project dependencies is listed in a custom ItemGroup, like so: 这些外部项目依赖项中的每一个都在自定义ItemGroup中列出,如下所示:

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

We've been trying to solve this by adding custom build targets that are called by each project's BeforeBuild target. 我们一直在尝试通过添加每个项目的BeforeBuild目标调用的自定义构建目标来解决此问题。 We first tried using ResolveNuGetPackageAssets as a build target but discovered that this is only supported in netcore, while we are targeting net47. 我们首先尝试使用ResolveNuGetPackageAssets作为构建目标,但是发现我们仅将net47作为目标,这仅在netcore中受支持。

Now we're trying to write a custom build target that will restore the NuGet dependencies in the external project. 现在,我们试图编写一个自定义构建目标,该目标将还原外部项目中的NuGet依赖项。 We've tried the straight-forward approach, like so: <Exec Command="nuget restore @(ExternalDependantProjects)" /> and a somewhat more complex & hacky PowerShell attempt: <Exec Command="powershell.exe -command &quot;&apos;@(ExternalDependantProjects, '&apos; &apos;')&apos; | foreach { nuget restore $_ }&quot;" /> 我们已经尝试了简单的方法,如下所示: <Exec Command="nuget restore @(ExternalDependantProjects)" />以及更复杂且棘手的PowerShell尝试: <Exec Command="powershell.exe -command &quot;&apos;@(ExternalDependantProjects, '&apos; &apos;')&apos; | foreach { nuget restore $_ }&quot;" /> <Exec Command="powershell.exe -command &quot;&apos;@(ExternalDependantProjects, '&apos; &apos;')&apos; | foreach { nuget restore $_ }&quot;" />

In both cases it simply tries to restore the packages of the main project, not the external projects. 在这两种情况下,它都只是尝试还原主项目的软件包,而不是外部项目的软件包。 It seems that @(ExternalDependantProjects) is equal to blank, and so no new argument is added. 似乎@(ExternalDependantProjects)等于空白,因此没有添加新参数。 Using has shown that @(ExternalDependantProjects) returns nothing. 使用表明@(ExternalDependantProjects)不返回任何内容。 However, it does work as the "Projects" parameter when we call an MSBuild "Build" target. 但是,当我们调用MSBuild“ Build”目标时,它确实作为“ Projects”参数起作用。 So, I suspect that we're using the Item parameter in the wrong way? 因此,我怀疑我们是否以错误的方式使用了Item参数? Perhaps there is some syntax to access the Include property of the Item? 也许有一些语法可以访问Item的Include属性?

However, I'm not sure that it will even work if we can resolve that issue. 但是,我不确定如果我们能够解决该问题,它是否也将起作用。 We tested using the nuget restore command on the sub-project and always get the response that all packages in packages.conf are installed. 我们在子项目上使用nuget restore命令进行了测试,并始终获得安装package.conf中所有软件包的响应。 Yet, ..\\packages\\ from that external project is empty and packages.conf specifies half a dozen packages (They're also missing from "References" in VS and the references' HintPath correctly goes to ..\\packages). 但是,该外部项目中的.. \\ packages \\为空,packages.conf指定了六个软件包(VS中的“ References”中也缺少它们,并且引用的HintPath正确地指向了.. \\ packages)。

So we're confounded on three fronts: How do we reference the the ExternalDependentProjects Item include path from MSBuild targets, why won't the NuGet restore CLI work, and is this even the correct way to go about solving this problem? 因此,我们在三个方面感到困惑:如何引用来自MSBuild目标的ExternalDependentProjects项包含路径,为什么NuGet还原CLI不能正常工作,这甚至是解决此问题的正确方法吗? Have we gone down completely the wrong avenue? 我们是否完全走错了道路?

NuGet discovers packages.config projects to restore from the solution file. NuGet发现packages.config项目以从解决方案文件中还原。 If all projects are in the solution file and you run nuget.exe restore <solution file> they should get restored, regardless of what is happening in the project files. 如果所有项目都在解决方案文件中,并且您运行nuget.exe restore <solution file> ,则无论项目文件中发生了什么,都应将其还原。

As a workaround for any custom scenario you could write a script to discover all packages.config files in the folder, and then call nuget.exe restore <packages.config> -SolutionDirectory <solution root> on the files directly. 作为任何自定义方案的解决方法,您可以编写脚本以发现文件夹中的所有packages.config文件,然后直接对文件调用nuget.exe restore <packages.config> -SolutionDirectory <solution root> For packages.config restore the only part needed is to discover the list of id/versions from the packages.config files so that they can be downloaded and extracted to the solution level packages folder. 对于packages.config还原,唯一需要的部分是从packages.config文件中查找id /版本列表,以便可以将它们下载并解压缩到解决方案级别的packages文件夹中。

I also suggest using Project references with ReferenceOutputAssembly=false to ensure that projects build in the order you want, and without referencing each other. 我还建议使用带有ReferenceOutputAssembly=false Project引用,以确保项目按您想要的顺序构建,并且不会互相引用。 See: https://blogs.msdn.microsoft.com/kirillosenkov/2015/04/04/how-to-have-a-project-reference-without-referencing-the-actual-binary/ 请参阅: https : //blogs.msdn.microsoft.com/kirillosenkov/2015/04/04/how-to-have-a-project-reference-without-referencing-the-actual-binary/

How do we reference the the ExternalDependentProjects Item include path from MSBuild targets, why won't the NuGet restore CLI work, and is this even the correct way to go about solving this problem? 我们如何引用来自MSBuild目标的ExternalDependentProjects项包含路径,为什么NuGet还原CLI无法正常工作,这甚至是解决此问题的正确方法吗? Have we gone down completely the wrong avenue? 我们是否完全走错了道路?

You should write your custom build target with the option -OutputDirectory , so the custom build target should be like below: 您应该使用-OutputDirectory选项编写自定义构建目标,因此自定义构建目标应如下所示:

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

With this target, NuGet package for external projects will be restored successfully. 通过此目标,将成功还原用于外部项目的NuGet软件包。

Besides, the value of @(ExternalDependantProjects) is not equal to blank, you can use a target echo this value. 此外, @(ExternalDependantProjects)值不等于空白,可以使用目标回显该值。

Below is my test sample, you can refer to some detail info: 以下是我的测试样本,您可以参考一些详细信息:

ExternalpProject is the sub-folder name, TestExternalProject is the external project name. 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>

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM