如何在MSBuild中排除(禁用)PackageReference的(传递)依赖性? [英] how to exclude(disable) PackageReference's (transitive)dependency in MSBuild?

查看:257
本文介绍了如何在MSBuild中排除(禁用)PackageReference的(传递)依赖性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用软件包Xamanimation,其依赖性为Xamarin.Forms 4.1.0(写在其nuspec文件中):

I'm using a package Xamanimation which has a dependency of Xamarin.Forms 4.1.0( written in its nuspec file):

    <dependencies>
      <group targetFramework=".NETStandard2.0">
        <dependency id="Xamarin.Forms" version="4.1.0.581479" exclude="Build,Analyzers" />
      </group>
    </dependencies>


但是我已经为自己构建了Xamarin.Froms,并将输出的dll文件添加到了项目的参考中:


but I have built the Xamarin.Froms for my own and added the output dll files into my project's reference:

  <Reference Include="Xamarin.Forms.Xaml">
      <HintPath>..\thirdparty\xforms\Xamarin.Forms.Xaml.dll</HintPath>
    </Reference>

根据 nuget的文档,我将ExcludeAssets属性(和其他测试)添加到PackageReference of Xamanimation部分:

according to the nuget's doc, I add the ExcludeAssets attribute(and other tests) to the section of PackageReference of Xamanimation:

    <PackageReference Include="Xamanimation">
      <IncludeAssets>compile</IncludeAssets>
      <!-- <ExcludeAssets>compile</ExcludeAssets> -->
      <!-- <PrivateAssets>all</PrivateAssets> -->
      <!-- <ExcludeAssets>buildtransitive</ExcludeAssets> -->
      <Version>1.3.0</Version>
    </PackageReference>

但是它们都不起作用!

but none of them work!

MSBuild将始终使用Trasitive依赖项Xamarin.Forms.4.1.0并忽略我自己的构建类(在其中我添加了新类并在主项目中使用它们,因此链接失败表明选择的是旧的).

MSBuild will always use the trasitive dependency Xamarin.Forms.4.1.0 and ignore my own build ones( in which I have add new classes and use them in the main project so the linking failure is indicating the choosen is the old one).

那么排除传递依赖的正确方法是什么?

so what's the correct method to exclude the transitive dependency?

推荐答案

我花了一整天的时间研究这个问题,最终得到了一个合理的答案.

I spend a whole day learning into this question and finally got a reasonable answer.

所以我想用我可怜的英语在stackoverflow中发布我的第一个长答案.

so I'd like to post my first LONG answer in stackoverflow by my poor english.

MSBuildnuget pluginResolveNuGetPackageAssets目标做了邪恶的事情,创建一个自定义目标以将其还原,并找到任务代码的底部.

the MSBuild's nuget plugin's ResolveNuGetPackageAssets target do the evil thing, make a custom target to revert it, go to bottom for the task code.

毕竟,建立一个Xamarin项目太慢了,

after all, building a xamarin project is too slow,

演示源位于 github 中, 它有四个项目:

the demo source is in github, it has four project:

  • ConflictLib:另一个库和主应用程序同时使用的库
  • DirectLib:主应用程序使用的库,并且正在使用ConflictLib
  • MyAppDev:主应用程序,以上两个库为ProjectReference
  • MyAppConsumer:另一个应用程序,使用PackageReferenceDirectLibConflictLib作为ProjectReference.为了测试这种情况,我将ConflictLib和DirectLib推送到nuget.org,然后对ConflictLib的本地版本进行了修改,因此我可以验证使用的是哪个版本.
  • ConflictLib: the library used both by another lib and main application
  • DirectLib: the library used by main application, and is using ConflictLib
  • MyAppDev: the main application, with above two library as ProjectReference
  • MyAppConsumer: the other application, using DirectLib by PackageReference, and ConflictLib as ProjectReference. to test this situation, I pushed the ConflictLib and DirectLib to nuget.org, then made modify to local version of ConflictLib, so I can verify which one is using.

这些项目及其关系与我的起源问题非常相似,关键点是:当应用程序同时使用具有两个不同版本的库时,本地(ProjectReference或HintPath)将(应该)获胜吗?

these projects and their relationship are very similar to my origin problem, the key point is : when application use a library with two different version simutanously, will(should) the local one(ProjectReference or HintPath) win?

对于我的原始案例xamarin项目,它是No,所以我来研究它.

for my origin case, xamarin project, it's No, so I come to study it.

对于一个测试用例,一个dotnet核心控制台项目,它是Yes,因此在构建过程中必须有一些神秘之处:MSBuild,这是一个庞大的系统,但是现在我要深入研究它

for the test case, a dotnet core console project, it's Yes, so there must be something mysterious in the building process: MSBuild, which is a huge system, but now I'm going to dig into it.

简单的工具只是在命令行中调用它,它将显示所有已执行的targets.一个msbuild target类似于a target in makefile,并且目标中的taskscommands in makefile相似,该概念在诸如gradle之类的许多其他系统中以稍有不同的术语存在,因此很容易理解.

the simple tool is just invoke it in command line, it will display all the targets executed. a msbuild target is something like a target in makefile, and the tasks in target are similar to commands in makefile, the concept exist with slightly different term in many other system such as gradle, so it's easy to understand.

但是,目标和任务太多了,它们都依赖于其他目标并且通过PropertyItems进行交互,因此很难从文本日志中了解哪个目标违反了我的需求.

but, there are so many targets and tasks, and all they depend on others and interactive though Property and Items, it's hard to learn which target break my need from the text log.

幸运的是,有一个用于检查MSBuild中所有内容的高级工具:它称为 MSBuild structured log viewer ,来自此处.

fortunately, there's an advanced tool for inspecting everything in MSBuild: it's called MSBuild structured log viewer, I learn it from here.

现在使用/bl选项构建项目,它将生成一个包含完整信息的二进制日志文件,由上述查看器打开:(我的原始xamarin项目的构建日志)

now build the project with /bl option, it will produce a binary log file with full info, open it by the viewer mentioned above:(my origin xamarin project's build log)

很明显,ResolveNuGetPackageAssets目标更改了Reference项,从而决定了最终的链接库程序集.

obvious, the ResolveNuGetPackageAssets target changes the Reference items, which decides the final linked library assembly.

但是为什么,它在测试用例中没有做出错误的决定?让我们查看其日志:

but why it doesn't make the wrong decision in the test case? let's view its log:

有区别吗? -没有ResolveNuGetPackageAssets目标!

got the difference? -- there's no ResolveNuGetPackageAssets target!

ResolveReferencesResolveAssemblyReferences都是一样的,但是在nuget部分有所区别.

it's same from ResolveReferences to ResolveAssemblyReferences, but diff in the nuget part.

ResolveAssemblyReferences上双击时,查看器将打开定义目标的targets file.

while double clicking at ResolveAssemblyReferences, the viewer will open the targets file in which the target be defined.

C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Community \ MSBuild \ Current \ Bin \ Microsoft.Common.CurrentVersion.targets

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets

两种情况仍然相同:

ResolveAssemblyReferences不依赖于ResolveNuGetPackageAssets,那么后者在哪里呢?只需单击它,文件即会打开:

ResolveAssemblyReferences doesn't depend on ResolveNuGetPackageAssets, so where does the later come? just click at it, the file opens:

C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Community \ MSBuild \ Microsoft \ NuGet \ 16.0 \ Microsoft.NuGet.targets

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\NuGet\16.0\Microsoft.NuGet.targets

它会覆盖ResolveAssemblyReferencesDependsOn并将ResolveNuGetPackageAssets添加到ResolveAssemblyReferences的依赖项.

it overrides ResolveAssemblyReferencesDependsOn and add the ResolveNuGetPackageAssets to dependency of ResolveAssemblyReferences.

最后一个问题:为什么上面的NuGet.targets文件没有出现在测试用例中?观看者的Evaluation部分仍可以回答:

the last question: why the above NuGet.targets file not appear in the test case? it could still answered by the viewer's Evaluation section:

显然,由于属性SkipImportNuGetBuildTargets设置为true,因此不会导入该文件.经过简单的搜索后,我确认它是测试用例中的默​​认值:已在

clearly, this file is not imported because a property SkipImportNuGetBuildTargets set to true. after a simple search, I confirmed it's the default value in test case: it's set in Microsoft.NET.Sdk.targets. but in xamarin case, it's not set and means false, so all the things happened.

首先,我不会将SkipImportNuGetBuildTargets属性添加到xamarin项目中,因为我认为这是框架设计,并且可能会对其他方面产生很大影响,我只想解决一些具体问题.

first of all, I won't add the SkipImportNuGetBuildTargets property to xamarin project, because I think it's a framework design and maybe has a great impact on others, I just want to fix a little, specific problem.

我决定在ResolveAssemblyReferences之后立即添加自定义目标,删除Nuget's Xamarin.Forms并添加自己的目标-只需还原ResolveNuGetPackageAssets的作用即可.

I decide to add a custom target immediately after the ResolveAssemblyReferences, remove the Nuget's Xamarin.Forms and add my own ones -- just revert what ResolveNuGetPackageAssets does.

任务代码很简单(仅在写完之后,实际上花了我很多时间来搜索语法/内置函数/等并进行测试):

the task code is simple (only just after I have written, actually it cost me lot of time to search for grammar/builtin function/etc and test):

注意Remove Item的操作方式(请参阅

notice how the Remove Item(see msbuild doc) works (and not work: the commented lines), I still don't understand it exactly, but it did work!

这篇关于如何在MSBuild中排除(禁用)PackageReference的(传递)依赖性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆