Insert a Directory.Build target into project dependency pipeline

问题描述 投票:0回答:1

我的项目分布在两个解决方案中,称它们为

Mine.sln
Theirs.sln
(它们位于不同的存储库中)。
Theirs
中的项目都是对
Mine
的依赖。这两个解决方案目前是按顺序构建的。我想更改此设置,以便将依赖项构建为
Mine
的一部分,从而无需使用两个解决方案(它们也在单独的存储库中)。问题是在
Theirs
中,项目在 nuget 包引用上设置了
HintPath
属性(不幸的是,这是 pre-sdk 项目)。

为了更具体一点:

Mine.sln (14 projects)
 +=> MP0
 +=> MP1
 +=> ...
 +=> MP13
Theirs.sln (21 projects)
 +=> TP0
 +=> TP1
 +=> ...
 +=> TP20

Theirs
Mine
我添加了大概10个左右,还有
MP0 => TP1, TP2
等项目依赖

问题:当

Theirs
被构建为
Mine
的依赖项时,那些与
HintPath
解决方案相关的
Theirs
属性不再正确并且依赖项项目无法构建。有一个处理这个问题的 GitHub 问题,虽然没有真正的解决方案:https://github.com/NuGet/Home/issues/738

Theirs
中修改项目并不是一个真正的选择,所以我正在探索做一些事情的可能性,比如在构建过程中重写内存中的那些属性。有一个项目可以逐个项目地执行此操作,我查看了他们使用的目标文件(https://github.com/jstangroome/NuGetReferenceHintPathRewrite/blob/master/content/NuGetReferenceHintPathRewrite.targets ),但它是针对每个项目的,需要在
Theirs
中修改项目,这又不是一个真正的选择。

我的希望是在

Directory.Build.targets
的根部使用
Mine.sln
来为由该解决方案构建的每个项目设置一个在
ResolveAssemblyReferences
之前运行的目标。我的
Directory.Build.targets
文件如下所示:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="ReferenceHintPathUpdate" BeforeTargets="BeforeResolveAssemblyReference">
        <Message Text="ReferenceHintPathUpdate: Building $(MSBuildProjectName) in $(SolutionDir)" Importance="High" />
    </Target>
</Project>

我这里只有

Message
任务来测试构建顺序和依赖项。我期待在终端中看到每个项目名称输出,但我只从 some 项目中获得输出(一些由
Mine
引用,一些由
Theirs
引用,但与所有项目都不一样)。我还不能确定为什么这个目标只针对某些项目运行;似乎没有明显的共同模式。

示例(过滤后的)输出:

ReferenceHintPathUpdate: Building MP0 in C:\Users\Me\MySolution
ReferenceHintPathUpdate: Building MP1 in C:\Users\Me\MySolution
...
ReferenceHintPathUpdate: Building MP7 in C:\Users\Me\MySolution
ReferenceHintPathUpdate: Building TP0 in C:\Users\Me\MySolution
ReferenceHintPathUpdate: Building TP4 in C:\Users\Me\MySolution

我需要做什么才能使

Directory.Build.targets
中定义的目标运行此解决方案构建的每个项目,特别是 来自
Theirs.sln
的依赖项项目?

.net msbuild nuget
1个回答
1
投票

将项目(或尽可能多的项目)从使用

packages.config
迁移到使用
PackageReference
PackageReference
可用于遗留风格项目和 SDK 风格项目。如果您有任何.Net Framework ASP.NET 项目,这些项目无法迁移,需要继续使用
packages.config
.

随着

PackageReference
没有提示路径。

你是如何解决两个repos的问题的?版本控制系统 git 和

Theirs
是否作为子目录中的子模块被拉入?

我假设您无法映射或移动

TP*
项目目录,以便相对
HintPath
工作。 (有些版本控制系统支持“覆盖”存储库,但 git 子模块不能那样工作。)

我假设有些项目不能更改为

PackageReference
要么因为项目是 .Net Framework ASP.NET 要么因为它是
Theirs
.

对于遗留样式和 SDK 样式项目,

Directory.Build.props
Directory.Build.targets
文件如果找到会自动导入。 MSBuild 向上搜索父目录以查找文件。请参阅按文件夹自定义构建并注意有关搜索范围的部分。

我发现“链接”

Directory.Build.*
文件非常有用,但必须将其明确添加到每个文件中。请参阅有关多级合并的部分。

如果

Theirs
存储库使用
Directory.Build.targets
文件而没有链接,您的
Directory.Build.targets
文件将不会被导入。当不同的项目似乎有不同的行为时,我希望这是问题所在。

以下内容可以添加到所有

Directory.Build.props
Directory.Build.targets
文件中。

<Import Project="$([MSBuild]::GetPathOfFileAbove('$(MSBuildThisFile)', '$(MSBuildThisFileDirectory)../'))" Condition="'$([MSBuild]::GetPathOfFileAbove('$(MSBuildThisFile)', '$(MSBuildThisFileDirectory)../'))' != ''" />

这是在

multi-level merging
中的例子Import的一个变体。

使用

$(MSBuildThisFile)
属性而不是硬编码文件名。

如果找不到文件,

GetPathOfFileAbove
返回一个空字符串。拥有
Condition
很重要,因为当
Import
属性计算为空字符串时,
Project
会导致错误。使用
Condition
,您无需关心哪个文件在目录结构中最高。这也意味着链条在顶部是可扩展的。

我喜欢在

Import
文件的开头始终有这个
Directory.Build.*
。如果
Import
位于不同文件的不同位置,则链接很难理解和排除故障。同样将导入放在文件的开头意味着当前文件可以使用和/或覆盖导入文件中的内容。

如果你能在

Theirs
中进行一些更改,这可能是最好的:使用
PackageReference
并为
Directory.Build.*
文件添加链接。

© www.soinside.com 2019 - 2024. All rights reserved.