问题 在Linux上构建面向.NET Framework的NuGet包


我想创建一个可以同时和明确定位的NuGet包  .NET Framework 4.6.2和.Net Standard 1.5。这是VS 2017的缩写.csproj文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net462;netstandard1.5</TargetFrameworks>
    ...
  </PropertyGroup>

</Project>

当我从本地Windows机器执行dotnet构建和打包命令时,NuGet包的创建完全符合预期。

然而,当我尝试在Linux上执行相同的dotnet命令时,我收到以下错误:

/opt/dotnet/sdk/1.0.4/Microsoft.Common.CurrentVersion.targets(1111,5):   错误MSB3644:框架的引用程序集   未找到“.NETFramework,Version = v4.6.2”。要解决这个问题,   为此框架版本安装SDK或Targeting Pack   将您的应用程序重新定位到您所使用的框架版本   安装了SDK或Targeting Pack。请注意,程序集将   从全局程序集缓存(GAC)解决并将用于   参考组件的地方。因此你的装配可能不是   正确定位您想要的框架。

然后我突然意识到Linux盒子上没有任何常规的.NET Framework程序集(更不用说了。因此,似乎我将无法使用Linux来构建我的NuGet包。我搜索了一下“ Targeting Pack“,但它仅适用于Windows。

冒着天真的风险,是否有人在Linux上成功构建可以针对.NET Framework的NuGet包?


10560
2018-06-27 00:43


起源

目前他们没有考虑这种情况。所以你必须使用Windows。 - Lex Li
这是由一个跟踪 GitHub上的问题 我几个月前开了。我根据那里发生的讨论发布了答案。 - Martin Ullrich
@MartinUllrich感谢GitHub链接,这非常有用。 - Lee Grissom


答案:


.NET CLI的分发不包含.NET Framework的任何引用程序集,因此其MSBuild版本无法解析所需的编译时资产。这种情况是 跟踪GitHub 虽然并且在迁移到MSBuild之前已经工作(CLI可以使用mono的引用程序集)。

虽然可以使用一些替代方法在非Windows机器上构建您的库:

1.使用mono 5+构建库。

这可能是最稳定的路径。

Mono 5及更高版本包含构建.NET Standar和.NET Core应用程序所需的构建逻辑。在linux上,mono的msbuild可能需要作为单独的软件包安装。因此,而不是以下常用命令

dotnet restore
dotnet build
dotnet publish -c Release

你会使用mono的msbuild来做以下事情:

msbuild /t:Restore
msbuild
msbuild /t:Publish /p:Configuration=Release

单声道<5.2的打包解决方法:

唯一的限制是单声道(<5.2)不能生成开箱即用的NuGet包,但有一个 涉及使用的解决方法 NuGet.Build.Tasks.Pack NuGet包 在允许你这样做的项目中 msbuild /t:Pack /p:Configuration=Release 通过像这样修改项目文件(特别注意删除 Sdk="..." 属性 <Project> 元件):

<Project>
  <PropertyGroup>
    <NuGetBuildTasksPackTargets>junk-value-to-avoid-conflicts</NuGetBuildTasksPackTargets>
  </PropertyGroup>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

  <!-- All your project's other content here -->

  <ItemGroup>
    <PackageReference Include="NuGet.Build.Tasks.Pack" Version="4.0.0" PrivateAssets="All" />
  </ItemGroup>
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

2.使用.NET CLI并告诉MSBuild使用mono的引用程序集。

建设时 net* 目标框架,你可以设置 FrameworkPathOverride 属性作为环境变量或csproj文件中的属性。它需要指向一组参考组件 - 这里可以使用mono的参考组件。但有些文件包含一个特殊文件(redist list),其中包含对.NET CLI中的MSBuild版本无法遵循的其他目录的引用。它在许多场景中都有效:

export FrameworkPathOverride=/usr/lib/mono/4.5/
dotnet build -f net45

这是使用和 由F#团队记录

3.使用包含引用程序集的NuGet包。

在某些MyGet源上,Microsoft发布包含引用程序集的NuGet包。它们不会发布或“官方”,因此这个过程可能会在某个时间点失败。但是他们这样做 计划调查使这条道路正式化

首先在解决方案的目录中创建一个NuGet.Config文件,其中包含以下内容以添加订阅源:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <packageSources>
    <add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
 </packageSources>
</configuration>

然后,您可以添加项目组以添加 PackageReference 到目标包和 PropertyGroup 设置引用程序集的路径,如下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>netcoreapp1.1;net461</TargetFrameworks>
  </PropertyGroup>

  <PropertyGroup Condition=" '$(TargetFramework)' == 'net461' ">
    <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
    <FrameworkPathOverride>$(NuGetPackageFolders)microsoft.targetingpack.netframework.v4.6.1\1.0.1\lib\net461\</FrameworkPathOverride>
  </PropertyGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
    <PackageReference Include="Microsoft.TargetingPack.NETFramework.v4.6.1" Version="1.0.1" ExcludeAssets="All" PrivateAssets="All" />
  </ItemGroup>

</Project>

你可以改变 RuntimeIdentifier 对于不同的平台,如果您使用本机资产(例如,获取 .so Linux的文件)或在构建库时完全删除它。


13
2018-06-27 06:43