我使用的软件包Xamanimation
具有Xamarin.Forms 4.1.0
(在其nuspec
文件中编写)的依赖项:
<dependencies>
<group targetFramework=".NETStandard2.0">
<dependency id="Xamarin.Forms" version="4.1.0.581479" exclude="Build,Analyzers" />
</group>
</dependencies>
但是我已经为自己构建了Xamarin.Froms,并将输出的dll文件添加到了我的项目参考中:
<Reference Include="Xamarin.Forms.Xaml">
<HintPath>..\thirdparty\xforms\Xamarin.Forms.Xaml.dll</HintPath>
</Reference>
根据nuget's doc,我将ExcludeAssets
属性(和其他测试)添加到PackageReference of Xamanimation
的部分:
<PackageReference Include="Xamanimation">
<IncludeAssets>compile</IncludeAssets>
<!-- <ExcludeAssets>compile</ExcludeAssets> -->
<!-- <PrivateAssets>all</PrivateAssets> -->
<!-- <ExcludeAssets>buildtransitive</ExcludeAssets> -->
<Version>1.3.0</Version>
</PackageReference>
但是它们都不起作用!
MSBuild
将始终使用Trasitive依赖项Xamarin.Forms.4.1.0并忽略我自己的构建类(在其中我添加了新类并在主项目中使用它们,因此链接失败指示已选择是旧的)。
那么排除传递依赖的正确方法是什么?
答案 0 :(得分:0)
我花了一整天的时间研究这个问题,最后得到了一个合理的答案。
所以我想用我可怜的英语在stackoverflow中发布我的第一个长答案。
MSBuild
的{{1}}的{{1}}目标做了邪恶的事情,创建了一个自定义目标以将其还原,并从底部查找任务代码。
毕竟,建立一个Xamarin项目太慢了,
演示源位于github中, 它有四个项目:
nuget plugin
ResolveNuGetPackageAssets
ConflictLib
的{{1}}和ProjectReference
作为DirectLib
。为了测试这种情况,我将ConflictLib和DirectLib推送到PackageReference
,然后对ConflictLib的本地版本进行了修改,以便可以验证使用哪个版本。这些项目及其关系与我的起源问题非常相似,关键点是:当应用程序同时使用具有两个不同版本的库时,本地(ProjectReference或HintPath)(应该)会赢吗?
对于我的原始案例xamarin项目,它是ConflictLib
,所以我来研究它。
对于一个测试用例,一个dotnet核心控制台项目,它是ProjectReference
,因此在构建过程中一定会有一些神秘之处:nuget.org
,这是一个庞大的系统,但是现在我要去进行深入研究。
No
在构建项目时的工作。简单的工具只是在命令行中调用它,它将显示所有执行的Yes
。 MSBuild
类似于MSBuild
,而目标中的targets
与msbuild target
类似,该概念在诸如gradle之类的许多其他系统中以稍有不同的术语存在,因此容易理解。
但是,目标和任务太多了,它们都依赖于其他目标并且通过a target in makefile
和tasks
进行交互,因此很难从文本日志中了解哪个目标违反了我的需求。
幸运的是,有一个用于检查commands in makefile
中所有内容的高级工具:它叫做MSBuild structured log viewer
,我从here中学到了。
现在使用Property
选项构建项目,它将生成一个包含完整信息的二进制日志文件,由上述查看器打开:(我的原始xamarin项目的构建日志)
很明显,Items
目标更改了MSBuild
项,从而决定了最终的链接库程序集。
但是为什么,它在测试用例中没有做出错误的决定?让我们查看其日志:
有区别吗? -没有/bl
目标!
从ResolveNuGetPackageAssets
到Reference
,但在nuget部分有所区别。
在ResolveNuGetPackageAssets
上双击的同时,查看器将打开其中定义目标的ResolveReferences
。
C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Community \ MSBuild \ Current \ Bin \ Microsoft.Common.CurrentVersion.targets
两种情况仍然相同:
ResolveAssemblyReferences
不依赖于ResolveAssemblyReferences
,那么后者在哪里呢?只需单击它,文件就会打开:
C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Community \ MSBuild \ Microsoft \ NuGet \ 16.0 \ Microsoft.NuGet.targets
它会覆盖targets file
,并将ResolveAssemblyReferences
添加到ResolveNuGetPackageAssets
的依存关系中。
最后一个问题:为什么上述ResolveAssemblyReferencesDependsOn
文件没有出现在测试用例中?观看者的ResolveNuGetPackageAssets
部分仍可以回答:
显然,由于属性ResolveAssemblyReferences
设置为true,因此不会导入该文件。经过简单的搜索后,我确认它是测试用例的默认值:已在Microsoft.NET.Sdk.targets中设置。但是在xamarin情况下,它没有设置并且表示NuGet.targets
,所以所有事情都发生了。
首先,我不会将Evaluation
属性添加到xamarin项目中,因为我认为这是一个框架设计,并且可能会对其他方面产生很大的影响,所以我只想解决一个特定的问题。
我决定在SkipImportNuGetBuildTargets
之后立即添加自定义目标,删除false
并添加自己的目标-只需还原SkipImportNuGetBuildTargets
的内容即可。
任务代码很简单(仅在写完之后,实际上花了我很多时间来搜索语法/内置函数/等并进行测试):
注意ResolveAssemblyReferences
(请参阅msbuild doc)的工作方式(但不起作用:注释行),我仍然不太了解它,但是它确实起作用了!