Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Pliki binarne Arm64X, znane również jako pliki Arm64X PE, umożliwiają ładowanie pojedynczego pliku binarnego do procesów x64/Arm64EC i Arm644.
Tworzenie pliku binarnego Arm64X z projektu programu Visual Studio
Aby włączyć kompilowanie plików binarnych Arm64X, strony właściwości konfiguracji Arm64EC mają nową właściwość "Build Project as ARM64X" (Kompiluj projekt jako ARM64X) znaną w BuildAsX pliku projektu.
strona właściwości 
Podczas kompilowania projektu program Visual Studio zwykle kompiluje dla architektury Arm64EC, a następnie łączy dane wyjściowe z plikiem binarnym Arm64EC. W przypadku ustawienia BuildAsX na true, program Visual Studio kompiluje dla architektur Arm64EC oraz Arm64. Etap łączenia Arm64EC łączy oba wyniki w jeden plik binarny Arm64X. Katalog wyjściowy dla tej binarii Arm64X to katalog wyjściowy ustawiony w konfiguracji Arm64EC.
Aby BuildAsX działał poprawnie, oprócz konfiguracji arm64 musisz mieć istniejącą konfigurację arm64EC. Konfiguracje Arm64 i Arm64EC muszą używać tego samego środowiska uruchomieniowego języka C i standardowej biblioteki języka C++ (na przykład dla obu ustawionych na /MT). Aby uniknąć nieefektywności w budowaniu, takich jak tworzenie pełnych projektów Arm64 zamiast samej kompilacji, ustaw wartość BuildAsX na true dla wszystkich bezpośrednich i pośrednich odwołań projektu.
W systemie kompilacji przyjęto założenie, że konfiguracje Arm64 i Arm64EC mają taką samą nazwę. Jeśli konfiguracje Arm64 i Arm64EC mają różne nazwy (takie jak Debug|ARM64 i MyDebug|ARM64EC), można ręcznie edytować vcxproj lub Directory.Build.props plik, aby dodać ARM64ConfigurationNameForX właściwość do konfiguracji Arm64EC, która zapewnia nazwę konfiguracji arm64.
Jeśli chcesz, aby plik binarny Arm64X łączył dwa oddzielne projekty, jeden jako Arm64 i jeden jako Arm64EC, możesz ręcznie edytować plik vxcproj projektu Arm64EC, aby dodać ARM64ProjectForX właściwość i określić ścieżkę do projektu Arm64. Dwa projekty muszą znajdować się w tym samym rozwiązaniu.
Kompilowanie biblioteki DLL Arm64X za pomocą narzędzia CMake
Aby skompilować pliki binarne projektu CMake jako Arm64X, użyj dowolnej wersji narzędzia CMake , która obsługuje kompilowanie jako Arm64EC. Najpierw skompiluj projekt przeznaczony dla arm64, aby wygenerować dane wejściowe konsolidatora Arm64. Następnie skompiluj ponownie projekt przeznaczony dla arm64EC, łącząc dane wejściowe Arm64 i Arm64EC w celu utworzenia plików binarnych Arm64X. W poniższych krokach pokazano, jak używać CMakePresets.json.
Upewnij się, że masz oddzielne profile konfiguracji przeznaczone dla Arm64 i Arm64EC. Na przykład:
{ "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" } } ] }Dodaj dwie nowe konfiguracje dziedziczone z ustawień wstępnych Arm64 i Arm64EC utworzonych w poprzednim kroku. Ustaw
BUILD_AS_ARM64XnaARM64ECw konfiguracji, która dziedziczy z Arm64EC iBUILD_AS_ARM64XnaARM64w innej konfiguracji. Te zmienne oznaczają, że kompilacje z tych dwóch ustawień wstępnych są częścią arm64X.{ "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" } }Dodaj nowy plik cmake do projektu CMake o nazwie
arm64x.cmake. Skopiuj poniższy fragment kodu do nowego pliku cmake.# 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 jest obsługiwany tylko podczas kompilacji przy użyciu linkera MSVC z programu Visual Studio 17.11 lub nowszego.
Jeśli chcesz użyć starszej wersji konsolidatora, skopiuj poniższy fragment kodu zamiast tego. Ta trasa używa starszej flagi /LINK_REPRO. Użycie trasowania /LINK_REPRO powoduje wolniejszy ogólny czas kompilacji z powodu kopiowania plików i ma znane problemy przy użyciu generatora Ninja.
# 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()
W dolnej części pliku najwyższego poziomu
CMakeLists.txtw projekcie dodaj następujący fragment kodu. Pamiętaj, aby zastąpić zawartość nawiasów kątowych wartościami rzeczywistymi. Ten krok korzysta z właśnie utworzonegoarm64x.cmakepliku.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()Skompiluj projekt CMake, używając wstępnych ustawień Arm64 z włączoną obsługą Arm64X (arm64-debug-x).
Skompiluj projekt CMake za pomocą ustawienia wstępnego Arm64X z obsługą Arm64EC (arm64ec-debug-x). Końcowe biblioteki DLL w katalogu wyjściowym dla tej kompilacji to pliki binarne Arm64X.
Tworzenie biblioteki DLL przekierowującej Arm64X
Biblioteka DLL Arm64X typu forwarder to mała biblioteka Arm64X, która przekazuje interfejsy API do różnych bibliotek DLL w zależności od ich typu.
Interfejsy API arm64 są przekazywane do biblioteki DLL Arm64.
API x64 są przekazywane do biblioteki DLL x64 lub Arm64EC.
Czysty przekierowywacz Arm64X umożliwia czerpanie korzyści z używania plików binarnych Arm64X, nawet jeśli napotkano trudności przy budowaniu scalonego pliku binarnego Arm64X zawierającego cały kod Arm64EC i Arm64. Aby uzyskać więcej informacji, zobacz Pliki ARM64X PE.
Możesz utworzyć czysty przekaźnik Arm64X z poziomu wiersza polecenia dla deweloperów Arm64, wykonując poniższe kroki. Wynikowy czysty przesyłacz Arm64X kieruje wywołania x64 do foo_x64.DLL i wywołania Arm64 do foo_arm64.DLL.
Utwórz puste
OBJpliki, które linker używa do stworzenia czystego forwardera. Te pliki są puste, ponieważ czysty moduł przesyłania dalej nie zawiera kodu. Aby utworzyć te pliki, utwórz pusty plik. W poniższym przykładzie plik ma nazwę empty.cpp. Służycldo tworzenia pustychOBJplików z jednym dla arm64 (empty_arm64.obj) i jeden dla arm64EC (empty_x64.obj):cl /c /Foempty_arm64.obj empty.cpp cl /c /arm64EC /Foempty_x64.obj empty.cppJeśli zostanie wyświetlony komunikat o błędzie "cl : ostrzeżenie wiersza polecenia D9002: ignorowanie nieznanej opcji "-arm64EC", używasz nieprawidłowego kompilatora. Aby rozwiązać ten problem, przejdź do Arm64 Developer Command Prompt.
Utwórz
DEFpliki dla architektury x64 i arm64. Te pliki zawierają listę wszystkich eksportów API biblioteki DLL i wskazują modułowi ładującemu nazwę biblioteki DLL, która obsługuje te wywołania API.foo_x64.def:EXPORTS MyAPI1 = foo_x64.MyAPI1 MyAPI2 = foo_x64.MyAPI2foo_arm64.def:EXPORTS MyAPI1 = foo_arm64.MyAPI1 MyAPI2 = foo_arm64.MyAPI2Użyj
link, aby utworzyćLIBpliki importu dla architektur x64 i Arm64.link /lib /machine:x64 /def:foo_x64.def /out:foo_x64.lib link /lib /machine:arm64 /def:foo_arm64.def /out:foo_arm64.libPołącz puste pliki
OBJoraz pliki do zaimportowaniaLIBużywając flagi/MACHINE:ARM64X, aby wygenerować czystą bibliotekę DLL typu forwarder Arm6X.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
Wynikowy plik foo.dll można załadować do procesu Arm64 lub x64/Arm64EC. Gdy proces Arm64 ładuje foo.dll, system operacyjny natychmiast ładuje foo_arm64.dll w jego miejsce, a wszystkie wywołania interfejsu API są obsługiwane przez foo_arm64.dll.
Windows on Arm