生成 Arm64X 二进制文件
你可以生成 Arm64X 二进制文件(也称为 Arm64X PE 文件),以支持将单个二进制文件加载到 x64/Arm64EC 和 Arm64 进程。
从 Visual Studio 项目生成 Arm64X 二进制文件
若要启用生成 Arm64X 二进制文件,Arm64EC 配置的属性页新增了“生成项目作为 ARM64X”属性,即项目文件中的 BuildAsX
。
当用户生成项目时,Visual Studio 通常会针对 Arm64EC 进行编译,然后将输出链接到 Arm64EC 二进制文件。 当 BuildAsX
别设置为 true
时,Visual Studio 将改为同时为 Arm64EC 和 Arm64 进行编译。 然后,使用 Arm64EC 链接步骤将两者同时链接到一个 Arm64X 二进制文件。 Arm64X 二进制文件的输出目录将与 Arm64EC 配置中设置的输出目录相同。
若要让 BuildAsX
正常工作,除了 Arm64EC 配置之外,用户还必须拥有现有的 Arm64 配置。 Arm64 和 Arm64EC 配置必须具有相同的 C 运行时和 C++ 标准库(例如,同时设置 /MT)。 为了避免生成效率低下的问题,例如生成完整的 Arm64 项目,而不仅仅是编译,项目的所有直接和间接引用都应将 BuildAsX
设置为 true。
生成系统假定 Arm64 和 Arm64EC 配置具有相同的名称。 如果 Arm64 和 Arm64EC 配置的名称不同(例如 Debug|ARM64
和 MyDebug|ARM64EC
)你可以手动编辑 vcxproj 或 Directory.Build.props
文件,以便为提供 Arm64 配置名称的 Arm64EC 配置添加 ARM64ConfigurationNameForX
属性。
如果所需的 Arm64X 二进制文件是两个独立项目(一个是 Arm64 项目,另一个是 Arm64EC 项目)的组合,则可以手动编辑 Arm64EC 项目的 vxcproj,以便添加 ARM64ProjectForX
属性并指定 Arm64 项目的路径。 这两个项目必须在同一个解决方案中。
生成 Arm64X 纯转发器 DLL
Arm64X 纯转发器 DLL 是一个小型 Arm64X DLL,它会根据 API 的类型将 API 转发到单独的 DLL:
- Arm64 API 会被转发到 Arm64 DLL,并且
- x64 API 会被转发到 x64 或 Arm64EC DLL。
即使在生成包含所有 Arm64EC 和 Arm64 代码的合并 Arm64X 二进制文件时遇到困难,Arm64X 纯转发器也能发挥使用 Arm64X 二进制文件的优势。 在 Arm64X PE 文件概述页面了解有关 Arm64X 纯转发器 DLL 的更多信息。
你可以按照以下步骤从 Arm64 开发人员命令提示符生成 Arm64X 纯转发器。 生成的 Arm64X 纯转发器会将 x64 调用路由至 foo_x64.DLL
,并将 Arm64 调用路由至 foo_arm64.DLL
。
创建稍后供链接器用来创建纯转发器的空
OBJ
文件。 这些文件都是空的,因为纯转发器中没有代码。 为此,请创建一个空文件。 对于以下示例,我们将文件命名为 empty.cpp。 然后使用cl
来创建空OBJ
文件,其中一个用于 Arm64 (empty_arm64.obj
),而另一个用于 Arm64EC (empty_x64.obj
):cl /c /Foempty_arm64.obj empty.cpp cl /c /arm64EC /Foempty_x64.obj empty.cpp
如果出现错误消息“cl : Command line warning D9002 : ignoring unknown option '-arm64EC'”,则说明使用的编译器不正确。 若要解决此问题,请切换到 ARM64 开发人员命令提示符。
为 x64 和 Arm64 创建
DEF
文件。 这些文件枚举了 DLL 的所有 API 导出,并将加载程序指向可实现这些 API 调用的 DLL 的名称。foo_x64.def
:EXPORTS MyAPI1 = foo_x64.MyAPI1 MyAPI2 = foo_x64.MyAPI2
foo_arm64.def
:EXPORTS MyAPI1 = foo_arm64.MyAPI1 MyAPI2 = foo_arm64.MyAPI2
然后,你可以使用
link
来为 x64 和 Arm64 创建LIB
导入文件:link /lib /machine:x64 /def:foo_x64.def /out:foo_x64.lib link /lib /machine:arm64 /def:foo_arm64.def /out:foo_arm64.lib
链接空的
OBJ
并使用标志/MACHINE:ARM64X
导入LIB
文件,以便生成 Arm6X 纯转发器 DLL:link /dll /noentry /machine:arm64x /defArm64Native:foo_arm64.def /def:foo_x64.def empty_arm64.obj empty_x64.obj /out:foo.dll foo_arm64.lib foo_x64.lib
最终的 foo.dll
可以被加载到 Arm64 或 x64/Arm64EC 进程中。 当 Arm64 进程加载 foo.dll
时,操作系统将立即加载 foo_arm64.dll
到其位置,而任何 API 调用都将由 foo_arm64.dll
处理。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈