在Linux上构建针对.NET Framework的NuGet包

24

我想创建一个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 build和pack命令时,NuGet包按预期完美创建。
然而,当我尝试在Linux上执行相同的dotnet命令时,出现以下错误:
/opt/dotnet/sdk/1.0.4/Microsoft.Common.CurrentVersion.targets(1111,5): error 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包吗?

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

27
.NET CLI的分发版本不包含任何.NET Framework的参考程序集,因此它的MSBuild版本无法解析所需的编译时资源。虽然这种情况在迁移到MSBuild之前已经可以使用(CLI可以使用mono的参考程序集),但是这种情况在GitHub上被跟踪
但是还有几个替代方案可用于在非Windows机器上构建库: 1. 使用mono 5+来构建库。 这可能是最稳定的路径。
Mono 5及更高版本包含了构建.NET Standard和.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

针对 mono < 5.2 的解决方法:

唯一的限制是 mono (< 5.2) 不能直接生成 NuGet 包,但是可以通过在项目中使用 NuGet.Build.Tasks.Pack NuGet 包的方法 来实现 msbuild /t:Pack /p:Configuration=Release,需要修改项目文件(特别注意在 <Project> 元素上移除了 Sdk="..." 属性):

<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 feeds上,Microsoft发布了包含引用程序集的NuGet包。虽然它们没有被发布或"官方"认可,但这个过程在某些时候可能会失败。不过,他们计划调查使此路径官方化

首先,在您的解决方案目录中创建一个NuGet.Config文件,并添加以下内容以添加该feed:

<?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>

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

4
微软已正式宣布,第三个选项现在应该是最终解决方案。https://github.com/Microsoft/dotnet/tree/master/releases/reference-assemblies - Lex Li

9
你可以将以下内容添加到你的项目文件中:
  <ItemGroup Condition="$(TargetFramework.StartsWith('net4')) AND '$(MSBuildRuntimeType)' == 'Core' AND '$(OS)' != 'Windows_NT'">
    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
  </ItemGroup>

这将允许在非Windows系统上为.NET框架构建和打包。 但是,在非Windows系统上,您只能使用dotnet CLI运行.NET Core目标。 因此,您还应该准备好选择一个目标框架在非Windows系统上运行,就像这样:

dotnet run -f netcoreapp2.1

解决方案来源:https://github.com/dotnet/designs/pull/33#issuecomment-489264196。 这是一个临时措施,未来可能会有所更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接