Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
U kunt binaire Arm64X-bestanden, ook wel Arm64X PE-bestanden genoemd, bouwen ter ondersteuning van het laden van één binair bestand in zowel x64/Arm64EC- als Arm64-processen.
Een Arm64X-binair bestand bouwen vanuit een Visual Studio-project
Als u Arm64X-binaries wilt bouwen, heeft de eigenschapspagina van de Arm64EC-configuratie een nieuwe eigenschap 'Project bouwen als ARM64X', ook wel bekend als BuildAsX in het projectbestand.
Wanneer u een project bouwt, compileert Visual Studio normaal gesproken voor Arm64EC en koppelt de uitvoer vervolgens aan een binaire Arm64EC-bestand. Wanneer u BuildAsX op true instelt, compileert Visual Studio zowel voor Arm64EC als voor Arm64. De arm64EC-koppelingsstap koppelt beide uitvoer aan één binair arm64X-bestand. De uitvoermap voor dit binaire Arm64X-bestand is de uitvoermap die is ingesteld onder de Arm64EC-configuratie.
Voor BuildAsX om correct te werken, moet u een bestaande Arm64-configuratie hebben, naast de Arm64EC-configuratie. De configuraties Arm64 en Arm64EC moeten dezelfde C-runtime en C++-standaardbibliotheek gebruiken (bijvoorbeeld allebei ingesteld op /MT). Om bouwinefficiënties te vermijden, zoals volledige Arm64-projecten bouwen in plaats van alleen compilatie, stel BuildAsX in op waar voor alle directe en indirecte verwijzingen van het project.
Bij het buildsysteem wordt ervan uitgegaan dat de Arm64- en Arm64EC-configuraties dezelfde naam hebben. Als de Arm64- en Arm64EC-configuraties verschillende namen hebben (zoals Debug|ARM64 en MyDebug|ARM64EC), kunt u de vcxproj of Directory.Build.props het bestand handmatig bewerken om een ARM64ConfigurationNameForX eigenschap toe te voegen aan de Arm64EC-configuratie die de naam van de Arm64-configuratie biedt.
Als u wilt dat het binaire bestand Arm64X twee afzonderlijke projecten combineert, één als Arm64 en één als Arm64EC, kunt u de vxcproj van het Arm64EC-project handmatig bewerken om een ARM64ProjectForX eigenschap toe te voegen en het pad naar het Arm64-project op te geven. De twee projecten moeten zich in dezelfde oplossing bevinden.
Een Arm64X DLL bouwen met CMake
Als u binaire bestanden van uw CMake-project wilt bouwen als Arm64X, gebruikt u elke versie van CMake die ondersteuning biedt voor bouwen als Arm64EC. Bouw eerst het project dat is gericht op Arm64 om de Arm64-linkerinvoer te genereren. Bouw vervolgens opnieuw het project dat gericht is op Arm64EC, waarbij de Arm64- en Arm64EC-invoer worden gecombineerd om binaire Arm64X-bestanden te vormen. De volgende stappen laten zien hoe uCMakePresets.jsonkunt gebruiken.
Zorg ervoor dat u afzonderlijke configuratie-voorinstellingen hebt die gericht zijn op Arm64 en Arm64EC. Voorbeeld:
{ "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" } } ] }Voeg twee nieuwe configuraties toe die overnemen van de vooraf ingestelde arm64- en Arm64EC-instellingen die u in de vorige stap hebt gemaakt. Stel
BUILD_AS_ARM64Xin opARM64ECin de configuratie die wordt overgenomen van Arm64EC en stelBUILD_AS_ARM64Xin opARM64in de andere. Deze variabelen geven aan dat de builds van deze twee voorinstellingen deel uitmaken van 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" } }Voeg een nieuw CMAKE-bestand toe aan uw CMake-project met de naam
arm64x.cmake. Kopieer het volgende fragment naar het nieuwe CMAKE-bestand.# 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 wordt alleen ondersteund als u bouwt met behulp van de MSVC-linker van Visual Studio 17.11 of hoger.
Als u een oudere linker wilt gebruiken, kopieert u in plaats daarvan het volgende codefragment. Deze route maakt gebruik van een oudere vlag /LINK_REPRO. Het gebruik van de /LINK_REPRO route resulteert in een tragere algehele buildtijd vanwege het kopiëren van bestanden en heeft bekende problemen bij het gebruik van ninjagenerator.
# 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()
Voeg onder aan het bestand op het hoogste niveau
CMakeLists.txtin uw project het volgende fragment toe. Zorg ervoor dat u de inhoud van de hoekige haken vervangt door werkelijke waarden. Deze stap verbruikt hetarm64x.cmakebestand dat u zojuist hebt gemaakt.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()Bouw uw CMake-project door de Arm64X-geschikte arm64-voorinstelling (arm64-debug-x) te gebruiken.
Bouw uw CMake-project met behulp van de arm64X-voorinstelling Arm64EC (arm64ec-debug-x). De uiteindelijke DLL's in de uitvoermap voor deze build zijn binaire Arm64X-bestanden.
Een Arm64X pure forwarder DLL bouwen
Een Arm64X pure forwarder DLL is een kleine Arm64X DLL waarmee API's worden doorgestuurd om DLL's te scheiden, afhankelijk van hun type:
Arm64-API's worden doorgestuurd naar een Arm64-DLL.
x64 API's worden doorgestuurd naar een x64- of Arm64EC-DLL.
Een pure Arm64X-doorstuurserver maakt het gebruik van een Arm64X-binair mogelijk, zelfs als er problemen zijn met het bouwen van een samengevoegd arm64X-binair bestand met alle Arm64EC- en Arm64-code. Zie Arm64X PE-bestanden voor meer informatie.
U kunt een pure Arm64X-doorstuurserver bouwen vanaf de Opdrachtprompt van de Arm64-ontwikkelaar door de onderstaande stappen te volgen. De resulterende Arm64X pure doorstuurserver routeert x64-aanroepen naar foo_x64.DLL en Arm64-aanroepen naar foo_arm64.DLL.
Maak lege
OBJbestanden die door de linker worden gebruikt om de pure doorstuurserver te maken. Deze bestanden zijn leeg omdat de pure doorstuurserver geen code bevat. Als u deze bestanden wilt maken, maakt u een leeg bestand. In het volgende voorbeeld heeft het bestand de naam empty.cpp. Gebruikcldit om legeOBJbestanden te maken, met één voor Arm64 (empty_arm64.obj) en één voor Arm64EC (empty_x64.obj):cl /c /Foempty_arm64.obj empty.cpp cl /c /arm64EC /Foempty_x64.obj empty.cppAls u het foutbericht 'cl: opdrachtregelwaarschuwing D9002: onbekende optie '-arm64EC' negeert, gebruikt u de verkeerde compiler. U kunt dit probleem oplossen door over te schakelen naar de Arm64 Developer-opdrachtprompt.
Maak
DEFbestanden voor zowel x64 als Arm64. Deze bestanden bevatten alle API-exports van het DLL-bestand en wijzen het laadprogramma aan op de naam van het DLL-bestand dat aan deze API-aanroepen kan voldoen.foo_x64.def:EXPORTS MyAPI1 = foo_x64.MyAPI1 MyAPI2 = foo_x64.MyAPI2foo_arm64.def:EXPORTS MyAPI1 = foo_arm64.MyAPI1 MyAPI2 = foo_arm64.MyAPI2Gebruik
linkLIBom importbestanden te maken voor zowel x64 als Arm64:link /lib /machine:x64 /def:foo_x64.def /out:foo_x64.lib link /lib /machine:arm64 /def:foo_arm64.def /out:foo_arm64.libKoppel de lege
OBJbestanden en importeerLIBbestanden met behulp van de vlag/MACHINE:ARM64Xom de Pure Forwarder DLL van Arm6X te produceren: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
De resulterende foo.dll kan worden geladen in een Arm64- of een x64/Arm64EC-proces. Wanneer een Arm64-proces foo.dll laadt, laadt het besturingssysteem onmiddellijk foo_arm64.dll ter vervanging ervan, en verwerkt foo_arm64.dll alle API-aanroepen.
Windows on Arm