【问题标题】:MSBuild Conditional PackageReference based on .Net TargetFramework基于 .Net TargetFramework 的 MSBuild Conditional PackageReference
【发布时间】:2023-01-29 21:24:30
【问题描述】:

介绍

我正在构建一个类库,它可以被一些以 .Net Framework 4.0 为目标的旧应用程序和以 .Net Framework 4.6.1 为目标的新应用程序使用

我在需要 .Net Framework 4.6.1 的类库中添加一些数据库/Hibernate 新代码。此新代码与 .Net Framework 4.0 不兼容,因为 nuGet 包 FluentNHibernate 3.1.0 需要 .Net Framework 4.6.1 及更高版本。遗留应用程序不需要此功能。

我想要达到的目标

我正在尝试有条件地构建类库,以便可以使用一个代码库和 master git 分支来构建一个与一个或另一个应用程序兼容的版本。

到目前为止,我已经能够:

  • 定义一个常量指示目标框架(FWK40)
    • 用于在 .cs 代码中调整代码以适应目标框架
  • 有条件地定义目标框架 (TargetFrameworkVersion)
  • 不在正确的 TargetFrameworkVersion 下时从构建中排除文件

这是 .CSPROJ 到目前为止的样子(强调相关调整):

 <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug.Net40|AnyCPU'">

    <!-- Set target framework here -->

    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\Debug.Net40\</OutputPath>

    <!-- Define Build-time constant here -->

    <DefineConstants Condition=" '$(TargetFrameworkVersion)' == 'v4.0'" >FWK40</DefineConstants>

 </PropertyGroup>

 <ItemGroup>

    <-- Conditionally include .cs files here -->

    <Compile Include="Database\GeneralSQL.cs" Condition="'$(TargetFrameworkVersion)' != 'v4.0'" />
    <Compile Include="Database\NamingStrategy.cs" Condition="'$(TargetFrameworkVersion)' != 'v4.0'" />
 <ItemGroup>

 <ItemGroup>

    <-- In THEORY conditionally include PackageReference here -->

    <PackageReference Include="FluentNHibernate" Condition="'$(TargetFramework)' != 'net40'" >
        <Version>3.1.0</Version>
    </PackageReference>
 </ItemGroup>

到目前为止的结果

发生了什么,如果我收到 nuGet 错误提示:

NU1202: Package FluentNHibernate 3.1.0 is not compatible with net40 (.NETFramework,Version=v4.0). Package FluentNHibernate 3.1.0 supports:
Failed to restore C:\_projets\repos\TestSolution\TestLibrary\TestLibrary.csproj (in 19 ms).
NuGet package restore failed. Please see Error List window for detailed warnings and errors.

尽管有这个错误,所有程序集都正确生成,DLL 类库本身,以及使用该类库的 EXE 控制台应用程序到目前为止,它们运行正常。

问题

我无法条件性地包含 nuGet PackageReference。

并且 nuGet 错误仍然导致 MSBuild.exe 失败,从而阻止 CI/CD 管道正常工作。

我试过什么

我尝试了很多方法来摆脱 nuget NU1202 错误消息。

#1 我最初尝试过基于 $(TargetFrameworkVersion) 的其他条件,它在 .csproj 中有效,但无济于事。

#2 根据官方文档,nuGet ReferencePackage 仅支持基于 $(TargetFramework) adding-a-packagereference-condition 的条件,如上面的示例 .csproj 所示。然而,这仍然不起作用。

  • 到目前为止,我还没弄清楚 Property TargetFramework 到底是什么样子的。我在 Verbosity 级别诊断中运行了 MSBUILD.EXE,它转储了所有属性,但未列出 TargetFramework(而其他是)

  • 我试图“反转”条件== 'net461',这样如果预期值不正确,它就不会被包含在内,错误就会消失=>没有效果,错误仍然存​​在

#3 我试图为自己定义 TargetFramework 属性

    <!-- Set target framework here -->
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <TargetFramework>net40</TargetFramework>
  • 结果会更糟!
  • Visual Studio 不喜欢它,“配置管理器”崩溃了
    • 不允许为项目设置特定配置。
    • 从 Debug.Net40 更改为任何其他配置(或加载项目)会显示讨厌的错误消息
Current solution contains incorrect configuration mappings. It may cause projects to not work properly

而且 csproj 肯定也没有正确加载,项目将跳过构建步骤。

我现在在哪里

我真的卡住了!似乎无法找到一种方法来完成这项工作。

  • 我不想有一个分支 master40 和一个分支 master 来处理这个。
  • 我不想拥有两个不同的 csproj 文件,除非我能以某种方式设法将一个文件共享/包含到另一个文件中并且 Visual Studio 不会抱怨

真正正确的做法是使 ReferencePackage 上的条件按预期实际工作。

【问题讨论】:

    标签: c# msbuild packagereference


    【解决方案1】:

    你想要的是多目标。 您链接的文档似乎仅适用于 SDK 样式的项目。 AFAIK,多目标不适用于旧式项目格式。

    我建议迁移到SDK-style project format。 那里有很多事情要简单得多,更不用说更好的记录了。 您可以使用工具来执行此操作,例如this one。不要被它的名字和错误的术语使用所迷惑。 (因为这也一直在 SO 上混淆:是的,您可以将 SDK 样式的格式与 .NET Framework TFM 一起使用;SDK 样式与 TFM 或 Visual Studio 版本无关,但仅与最低要求的 MSBuild版本)。

    一旦你为你的特定项目完成了这些,the documentation for multi-targeting 应用并且你可以在 $(TargetFramework) 上使用 Condition 就像你已经做过的那样,在你的 PackageReferenceCompile 项目组以及几乎任何你想。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 2018-07-10
      • 1970-01-01
      • 2012-04-30
      • 1970-01-01
      相关资源
      最近更新 更多