Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Erstellen Sie Arm64X-Binärdateien, auch als Arm64X PE-Dateien bezeichnet, um das Laden einer einzelnen Binärdatei in x64/Arm64EC- und Arm64-Prozesse zu unterstützen.
Erstellen einer Arm64X-Binärdatei aus einem Visual Studio-Projekt
Um das Erstellen von Arm64X-Binärdateien zu ermöglichen, verfügt die Seite „Property“ der Arm64EC-Konfiguration über die neue Eigenschaft „Build Project as ARM64X“, die in der Projektdatei als BuildAsX bezeichnet wird.
Wenn Sie ein Projekt erstellen, kompiliert Visual Studio normalerweise für Arm64EC und verknüpft dann die Ausgaben zu einer Arm64EC-Binärdatei. Wenn Sie BuildAsX auf true festlegen, kompiliert Visual Studio sowohl für Arm64EC als auch für Arm64. Der Arm64EC-Verknüpfungsschritt verknüpft beide Ausgaben mit einer einzelnen Arm64X-Binärdatei. Das Ausgabeverzeichnis für diese Arm64X-Binärdatei ist das Ausgabeverzeichnis, das unter der Arm64EC-Konfiguration festgelegt ist.
Damit BuildAsX ordnungsgemäß funktioniert, müssen Sie neben der Arm64EC-Konfiguration auch über eine vorhandene Arm64-Konfiguration verfügen. Die Arm64- und Arm64EC-Konfigurationen müssen dieselbe C-Laufzeit- und C++-Standardbibliothek verwenden (z. B. beide auf /MT festgelegt). Um Ineffizienzen zu vermeiden, z. B. das Erstellen vollständiger Arm64-Projekte und nicht nur die Kompilierung, legen Sie BuildAsX für alle direkten und indirekten Verweise des Projekts auf "true" fest.
Das Buildsystem geht davon aus, dass die Konfigurationen Arm64 und Arm64EC denselben Namen haben. Wenn die Arm64- und Arm64EC-Konfigurationen unterschiedliche Namen haben (wie Debug|ARM64 und MyDebug|ARM64EC), können Sie vcxproj oder die Datei Directory.Build.props manuell bearbeiten, um der Arm64EC-Konfiguration eine ARM64ConfigurationNameForX-Eigenschaft hinzuzufügen, die den Namen der Arm64-Konfiguration bereitstellt.
Wenn Sie möchten, dass die Arm64X-Binärdatei zwei separate Projekte kombiniert, eins als Arm64 und eins als Arm64EC, können Sie das vxcproj des Arm64EC-Projekts manuell bearbeiten, um eine ARM64ProjectForX Eigenschaft hinzuzufügen und den Pfad zum Arm64-Projekt anzugeben. Die beiden Projekte müssen sich in derselben Lösung befinden.
Erstellen einer Arm64X-DLL mit CMake
Um Ihre CMake-Projektbinärdateien als Arm64X zu erstellen, verwenden Sie eine beliebige Version von CMake , die das Erstellen als Arm64EC unterstützt. Zunächst erstellen Sie das Projekt für Arm64, um Eingaben für den Arm64-Linker zu generieren. Erstellen Sie dann das Projekt erneut für Arm64EC, wobei die Arm64- und Arm64EC-Eingaben kombiniert werden, um Arm64X-Binärdateien zu bilden. Die folgenden Schritte zeigen, wie CMakePresets.json verwendet wird.
Stellen Sie sicher, dass Sie über separate Konfigurationsvoreinstellungen für Arm64 und Arm64EC verfügen. Zum Beispiel:
{ "version": 3, "configurePresets": [ { "name": "windows-base", "hidden": true, "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe" }, "generator": "Visual Studio 17 2022", }, { "name": "arm64-debug", "displayName": "arm64 Debug", "inherits": "windows-base", "hidden": true, "architecture": { "value": "arm64", "strategy": "set" }, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } }, { "name": "arm64ec-debug", "displayName": "arm64ec Debug", "inherits": "windows-base", "hidden": true, "architecture": { "value": "arm64ec", "strategy": "set" }, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } } ] }Fügen Sie zwei neue Konfigurationen hinzu, die von den im vorherigen Schritt erstellten Voreinstellungen "Arm64" und "Arm64EC" erben. Setzen Sie
BUILD_AS_ARM64XaufARM64ECin der Konfiguration, die von Arm64EC erbt, undBUILD_AS_ARM64XaufARM64in der anderen. Diese Variablen bedeuten, dass die Builds aus diesen beiden Voreinstellungen Teil von Arm64X sind.{ "name": "arm64-debug-x", "displayName": "arm64 Debug (arm64x)", "inherits": "arm64-debug", "cacheVariables": { "BUILD_AS_ARM64X": "ARM64" } }, { "name": "arm64ec-debug-x", "displayName": "arm64ec Debug (arm64x)", "inherits": "arm64ec-debug", "cacheVariables": { "BUILD_AS_ARM64X": "ARM64EC" } }Fügen Sie Ihrem CMake-Projekt eine neue .cmake-Datei namens
arm64x.cmakehinzu. Kopieren Sie den folgenden Codeausschnitt in die neue CMAKE-Datei.# directory where the link.rsp file generated during arm64 build will be stored set(arm64ReproDir "${CMAKE_CURRENT_SOURCE_DIR}/repros") # This function reads in the content of the rsp file outputted from arm64 build for a target. Then passes the arm64 libs, objs and def file to the linker using /machine:arm64x to combine them with the arm64ec counterparts and create an arm64x binary. function(set_arm64_dependencies n) set(REPRO_FILE "${arm64ReproDir}/${n}.rsp") file(STRINGS "${REPRO_FILE}" ARM64_OBJS REGEX obj\"$) file(STRINGS "${REPRO_FILE}" ARM64_DEF REGEX def\"$) file(STRINGS "${REPRO_FILE}" ARM64_LIBS REGEX lib\"$) string(REPLACE "\"" ";" ARM64_OBJS "${ARM64_OBJS}") string(REPLACE "\"" ";" ARM64_LIBS "${ARM64_LIBS}") string(REPLACE "\"" ";" ARM64_DEF "${ARM64_DEF}") string(REPLACE "/def:" "/defArm64Native:" ARM64_DEF "${ARM64_DEF}") target_sources(${n} PRIVATE ${ARM64_OBJS}) target_link_options(${n} PRIVATE /machine:arm64x "${ARM64_DEF}" "${ARM64_LIBS}") endfunction() # During the arm64 build, create link.rsp files that containes the absolute path to the inputs passed to the linker (objs, def files, libs). if("${BUILD_AS_ARM64X}" STREQUAL "ARM64") add_custom_target(mkdirs ALL COMMAND cmd /c (if not exist \"${arm64ReproDir}/\" mkdir \"${arm64ReproDir}\" )) foreach (n ${ARM64X_TARGETS}) add_dependencies(${n} mkdirs) # tell the linker to produce this special rsp file that has absolute paths to its inputs target_link_options(${n} PRIVATE "/LINKREPROFULLPATHRSP:${arm64ReproDir}/${n}.rsp") endforeach() # During the ARM64EC build, modify the link step appropriately to produce an arm64x binary elseif("${BUILD_AS_ARM64X}" STREQUAL "ARM64EC") foreach (n ${ARM64X_TARGETS}) set_arm64_dependencies(${n}) endforeach() endif()
/LINKREPROFULLPATHRSP wird nur unterstützt, wenn Sie den MSVC-Linker aus Visual Studio Version 17.11 oder höher verwenden.
Wenn Sie einen älteren Linker verwenden müssen, kopieren Sie stattdessen den folgenden Codeausschnitt. Diese Route verwendet ein älteres Flag /LINK_REPRO. Die Verwendung der Route "/LINK_REPRO" führt zu einer langsameren Gesamtbuildzeit aufgrund des Kopierens von Dateien und hat bekannte Probleme bei der Verwendung des Ninja-Generators.
# directory where the link_repro directories for each arm64x target will be created during arm64 build.
set(arm64ReproDir "${CMAKE_CURRENT_SOURCE_DIR}/repros")
# This function globs the linker input files that was copied into a repro_directory for each target during arm64 build. Then it passes the arm64 libs, objs and def file to the linker using /machine:arm64x to combine them with the arm64ec counterparts and create an arm64x binary.
function(set_arm64_dependencies n)
set(ARM64_LIBS)
set(ARM64_OBJS)
set(ARM64_DEF)
set(REPRO_PATH "${arm64ReproDir}/${n}")
if(NOT EXISTS "${REPRO_PATH}")
set(REPRO_PATH "${arm64ReproDir}/${n}_temp")
endif()
file(GLOB ARM64_OBJS "${REPRO_PATH}/*.obj")
file(GLOB ARM64_DEF "${REPRO_PATH}/*.def")
file(GLOB ARM64_LIBS "${REPRO_PATH}/*.LIB")
if(NOT "${ARM64_DEF}" STREQUAL "")
set(ARM64_DEF "/defArm64Native:${ARM64_DEF}")
endif()
target_sources(${n} PRIVATE ${ARM64_OBJS})
target_link_options(${n} PRIVATE /machine:arm64x "${ARM64_DEF}" "${ARM64_LIBS}")
endfunction()
# During the arm64 build, pass the /link_repro flag to linker so it knows to copy into a directory, all the file inputs needed by the linker for arm64 build (objs, def files, libs).
# extra logic added to deal with rebuilds and avoiding overwriting directories.
if("${BUILD_AS_ARM64X}" STREQUAL "ARM64")
foreach (n ${ARM64X_TARGETS})
add_custom_target(mkdirs_${n} ALL COMMAND cmd /c (if exist \"${arm64ReproDir}/${n}_temp/\" rmdir /s /q \"${arm64ReproDir}/${n}_temp\") && mkdir \"${arm64ReproDir}/${n}_temp\" )
add_dependencies(${n} mkdirs_${n})
target_link_options(${n} PRIVATE "/LINKREPRO:${arm64ReproDir}/${n}_temp")
add_custom_target(${n}_checkRepro ALL COMMAND cmd /c if exist \"${n}_temp/*.obj\" if exist \"${n}\" rmdir /s /q \"${n}\" 2>nul && if not exist \"${n}\" ren \"${n}_temp\" \"${n}\" WORKING_DIRECTORY ${arm64ReproDir})
add_dependencies(${n}_checkRepro ${n})
endforeach()
# During the ARM64EC build, modify the link step appropriately to produce an arm64x binary
elseif("${BUILD_AS_ARM64X}" STREQUAL "ARM64EC")
foreach (n ${ARM64X_TARGETS})
set_arm64_dependencies(${n})
endforeach()
endif()
Fügen Sie unten in der Datei auf oberster Ebene
CMakeLists.txtin Ihrem Projekt den folgenden Codeausschnitt hinzu. Achten Sie darauf, den Inhalt der spitzen Klammern durch tatsächliche Werte zu ersetzen. Dieser Schritt verwendet diearm64x.cmakesoeben erstellte Datei.if(DEFINED BUILD_AS_ARM64X) set(ARM64X_TARGETS <Targets you want to Build as ARM64X>) include("<directory location of the arm64x.cmake file>/arm64x.cmake") endif()Erstellen Sie Ihr CMake-Projekt mit der Arm64X-aktivierten Arm64-Voreinstellung "arm64-debug-x".
Erstellen Sie Ihr CMake-Projekt mithilfe der Arm64X-fähigen Arm64EC-Voreinstellung (arm64ec-debug-x). Die endgültigen DLLs im Ausgabeverzeichnis für diesen Build sind Arm64X-Binärdateien.
Erstellen einer reinen Arm64X-Weiterleitungs-DLL
Eine reine Arm64X-Weiterleitungs-DLL ist eine kleine Arm64X-DLL, die APIs je nach Typ an separate DLLs weiterleitet:
Arm64-APIs werden an eine Arm64-DLL weitergeleitet.
x64-APIs werden an eine x64- oder Arm64EC-DLL weitergeleitet.
Eine reine Arm64X-Weiterleitung ermöglicht die Vorteile der Verwendung einer Arm64X-Binärdatei, auch wenn es Herausforderungen beim Erstellen einer zusammengeführten Arm64X-Binärdatei mit dem gesamten Arm64EC- und Arm64-Code gibt. Weitere Informationen finden Sie unter Arm64X PE-Dateien.
Sie können eine reine Arm64X-Weiterleitung über die Arm64-Entwickler-Eingabeaufforderung erstellen, indem Sie die folgenden Schritte ausführen. Die resultierende Arm64X-Reinweiterleitung leitet x64-Anrufe an foo_x64.DLL und Arm64-Anrufe an foo_arm64.DLL.
Erstellen Sie leere
OBJ-Dateien, die der Linker verwendet, um die reine Weiterleitungsdatei zu erstellen. Diese Dateien sind leer, da die reine Weiterleitung keinen Code enthält. Um diese Dateien zu erstellen, erstellen Sie eine leere Datei. Im folgenden Beispiel wird die Datei empty.cpp benannt. Dientclzum Erstellen leererOBJDateien mit einer für Arm64 (empty_arm64.obj) und einer für Arm64EC (empty_x64.obj):cl /c /Foempty_arm64.obj empty.cpp cl /c /arm64EC /Foempty_x64.obj empty.cppWenn die Fehlermeldung "cl : Befehlszeilenwarnung D9002 : Unbekannte Option '-arm64EC' ignoriert" angezeigt wird, verwenden Sie den falschen Compiler. Um dieses Problem zu beheben, wechseln Sie zur Arm64 Developer-Eingabeaufforderung.
Erstellen Sie
DEF-Dateien für x64 und Arm64. Diese Dateien listen alle API-Exporte der DLL auf und leiten den Loader zum Namen der DLL, die diese API-Aufrufe ausführen kann.foo_x64.def:EXPORTS MyAPI1 = foo_x64.MyAPI1 MyAPI2 = foo_x64.MyAPI2foo_arm64.def:EXPORTS MyAPI1 = foo_arm64.MyAPI1 MyAPI2 = foo_arm64.MyAPI2Verwenden Sie
link, umLIB-Importdateien für x64 und Arm64 zu erstellen.link /lib /machine:x64 /def:foo_x64.def /out:foo_x64.lib link /lib /machine:arm64 /def:foo_arm64.def /out:foo_arm64.libVerknüpfen Sie die leeren
OBJDateien und importieren SieLIBdateien mithilfe des Flags/MACHINE:ARM64X, um die reine Arm6X-Weiterleitungs-DLL zu erzeugen: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
Die daraus resultierende foo.dll kann entweder in einen Arm64- oder einen x64/Arm64EC-Prozess geladen werden. Sobald ein Arm64-Prozess foo.dll lädt, lädt das Betriebssystem unmittelbar foo_arm64.dll an dessen Stelle, und alle API-Aufrufe werden von foo_arm64.dll bearbeitet.
Windows on Arm