使用为 .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 运行ARM 64/M1 机器上的时间确实“消耗”Windows 编译的 AMD 64 库作为 .NET 5 在M1 平台只能通过兼容层(Rosetta?)工作。
了解 .NET 为目标体系结构编译程序集的方式很重要。
- 如果您使用 x64 架构,它将针对您正在编译的 OS 的 x64 二进制版本进行编译。
- 如果您使用任何 CPU 架构,您的程序集将被编译成一个中间二进制代码,当您 运行 您的申请。
您必须使用特定的目标架构,以防您使用某些特定于架构的第三方库或您使用的是本机库(如 C++ 库)。
在所有其他情况下,您应该使用 Any CPU 并让 JIT 为您完成工作。
为了在您的小测试项目中证明这一点,只需使用任何 CPU 配置编译您的 .NET 5 库,一切都会得到修复。
很明显,Saxonica 没有发布架构
库的独立版本。所以你不能自己解决问题。
在 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 运行ARM 64/M1 机器上的时间确实“消耗”Windows 编译的 AMD 64 库作为 .NET 5 在M1 平台只能通过兼容层(Rosetta?)工作。
了解 .NET 为目标体系结构编译程序集的方式很重要。
- 如果您使用 x64 架构,它将针对您正在编译的 OS 的 x64 二进制版本进行编译。
- 如果您使用任何 CPU 架构,您的程序集将被编译成一个中间二进制代码,当您 运行 您的申请。
您必须使用特定的目标架构,以防您使用某些特定于架构的第三方库或您使用的是本机库(如 C++ 库)。
在所有其他情况下,您应该使用 Any CPU 并让 JIT 为您完成工作。 为了在您的小测试项目中证明这一点,只需使用任何 CPU 配置编译您的 .NET 5 库,一切都会得到修复。
很明显,Saxonica 没有发布架构 库的独立版本。所以你不能自己解决问题。