使用为 .NET 5 编写的 NuGet 库的 .NET 6 控制台应用程序在 Windows 下运行良好,但在 Mac M1 和 System.BadImageFormatException 上崩溃

.NET 6 console app using NuGet library written for .NET 5 runs fine under Windows but crashes on Mac M1 with System.BadImageFormatException

在 Windows 下,我使用了 SaxonCS 库(在 NuGet https://www.nuget.org/packages/SaxonCS/ 上可用,它是针对 .NET 5 在 .NET 5 和 .NET 6 应用程序中成功编写的。

但是,现在在 Mac M1 上尝试我的一些 .NET 代码,我发现在 .NET 5 应用程序中使用 SaxonCS 可以工作,而在 .NET 6 应用程序中尝试不会出现构建错误,但是尝试 运行 它会给出错误 System.BadImageFormatException。

详情如下:

dotnet NET6ConsoleApp1.dll
Unhandled exception. System.BadImageFormatException: Could not load file or assembly 'SaxonCS, Version=11.2.0.0, Culture=neutral, PublicKeyToken=null'. An attempt was made to load a program with an incorrect format.

File name: 'SaxonCS, Version=11.2.0.0, Culture=neutral, PublicKeyToken=null'
zsh: abort      dotnet NET6ConsoleApp1.dll

所用 .NET 的详细信息:

dotnet --info
.NET SDK (gemäß "global.json"):
 Version:   6.0.200
 Commit:    4c30de7899

Laufzeitumgebung:
 OS Name:     Mac OS X
 OS Version:  11.6
 OS Platform: Darwin
 RID:         osx.11.0-arm64
 Base Path:   /usr/local/share/dotnet/sdk/6.0.200/

Host (useful for support):
  Version: 6.0.2
  Commit:  839cdfb0ec

.NET SDKs installed:
  6.0.200 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

就 C# 代码而言,控制台应用程序无非就是

using Saxon.Api;

Console.WriteLine("{0} {1} {2}", Environment.Version, Environment.OSVersion, Environment.ProcessPath);

Environment.SetEnvironmentVariable("SAXON_LICENSE_DIR", "/Users/username/Library/SaxonCS");

Processor processor = new Processor(true);

Console.WriteLine("{0} {1}", processor.ProductTitle, processor.ProductVersion);

我不明白为什么代码 运行 在 Windows 下与 .NET 6 但在 Mac M1 ARM 下失败。

有人解释一下吗?我该如何解决这个问题,而不必等待或要求库所有者发布 .NET 6 版本?

Saxonica 同时发布了 SaxonCS 11.3,它通过确保 NuGet 包包含平台 independent/MSIL 库而不是 Amd64 目标库来解决问题。这样我就可以在 AMD 64 机器和 ARM 64 机器(如 M1 mini)上使用和 运行 库。

故事的另一个令人困惑的部分是 .NET 5 运行A​​RM 64/M1 机器上的时间确实“消耗”Windows 编译的 AMD 64 库作为 .NET 5 在M1 平台只能通过兼容层(Rosetta?)工作。

了解 .NET 为目标体系结构编译程序集的方式很重要。

  • 如果您使用 x64 架构,它将针对您正在编译的 OS 的 x64 二进制版本进行编译。
  • 如果您使用任何 CPU 架构,您的程序集将被编译成一个中间二进制代码,当您 运行 您的申请。

您必须使用特定的目标架构,以防您使用某些特定于架构的第三方库或您使用的是本机库(如 C++ 库)。

在所有其他情况下,您应该使用 Any CPU 并让 JIT 为您完成工作。 为了在您的小测试项目中证明这一点,只需使用任何 CPU 配置编译您的 .NET 5 库,一切都会得到修复。

很明显,Saxonica 没有发布架构 库的独立版本。所以你不能自己解决问题。