Générez des binaires Arm64X

Vous pouvez générer des binaires Arm64X, également connus sous le nom de fichiers PE Arm64X, pour supporter le chargement d’un seul binaire à la fois dans les processus x64/Arm64EC et Arm64.

Génération d’un binaire Arm64X à partir d’un projet Visual Studio

Pour activer la génération de binaires Arm64X, les pages de propriétés de la configuration Arm64EC ont une nouvelle propriété appelée « Construire le projet comme ARM64X », connue sous le nom de BuildAsX dans le fichier du projet.

Property page for an Arm64EC configuration showing the Build Project as ARM64X option

Lorsqu’un utilisateur génère un projet, Visual Studio compile normalement pour Arm64EC puis lie les sorties en un binaire Arm64EC. Lorsque BuildAsX est paramétré sur true, Visual Studio compilera à la place pour Arm64EC et Arm64. L’étape de liaison Arm64EC est ensuite utilisée pour lier les deux ensemble en un seul binaire Arm64X. Le répertoire de sortie pour ce binaire Arm64X sera celui qui est défini sous la configuration Arm64EC

Pour que BuildAsX fonctionne correctement, l’utilisateur doit avoir une configuration Arm64 existante, en plus de la configuration Arm64EC. Les configurations Arm64 et Arm64EC doivent avoir le même runtime C et la même bibliothèque standard C++ (par exemple, les deux définissent /MT). Pour éviter les inefficacités de construction, telles que la construction de projets Arm64 complets plutôt que juste la compilation, toutes les références directes et indirectes du projet doivent avoir BuildAsX réglé sur vrai (True).

Le système de génération suppose que les configurations Arm64 et Arm64EC ont le même nom. Si les configurations Arm64 et Arm64EC ont des noms différents (comme Debug|ARM64 et MyDebug|ARM64EC), vous pouvez éditer manuellement le fichier vcxproj ou Directory.Build.props pour ajouter une propriété ARM64ConfigurationNameForX à la configuration Arm64EC qui fournit le nom de la configuration Arm64.

Si le binaire Arm64X souhaité est une combinaison de deux projets séparés, l’un en tant qu’Arm64 et l’autre en tant qu’Arm64EC, vous pouvez éditer manuellement le vxcproj du projet Arm64EC pour ajouter une propriété ARM64ProjectForX et spécifier le chemin vers le projet Arm64. Les deux projets doivent être dans la même solution.

Créer un DLL de transfert pur Arm64X

Un DLL de transfert pur Arm64X est un petit DLL Arm64X qui transfère les API à des DLL séparées en fonction de leur type :

  • Les API Arm64 sont transférées à un DLL Arm64, et
  • les API x64 sont transférées à un DLL x64 ou Arm64EC.

Un transfert pur Arm64X accorde les avantages de l’utilisation d’un binaire Arm64X même en cas de difficultés avec la création d’un binaire Arm64X fusionné contenant tout le code Arm64EC et Arm64. Vous pouvez en apprendre davantage concernant les DLL de transfert pur Arm64X dans la page de vue d’ensemble des fichiers PE Arm64X.

Vous pouvez créer un transfert pur Arm64X à partir de la commande développeur Arm64 en suivant la procédure ci-dessous. Le transfert pur Arm64X résultant acheminera les appels x64 vers foo_x64.DLL et les appels Arm64 vers foo_arm64.DLL.

  1. Créez des fichiers OBJ vides qui seront utilisés plus tard par l’éditeur de liens pour créer le transfert pur. Ceux-ci sont vides car le transfert pur ne contient pas de code Pour cela, créez un fichier vide. Pour l’exemple ci-dessous, nous avons nommé le fichier empty.cpp. Des fichiers OBJ vides sont ensuite créés en utilisant cl, avec un pour Arm64 (empty_arm64.obj) et un pour Arm64EC (empty_x64.obj) :

    cl /c /Foempty_arm64.obj empty.cpp
    cl /c /arm64EC /Foempty_x64.obj empty.cpp
    

    Si le message d’erreur « cl : Command line warning D9002 : ignoring unknown option "-arm64EC" » apparaît, le compilateur incorrect est utilisé. Pour résoudre cela, veuillez passer à la commande développeur ARM64.

  2. Créez des fichiers DEF pour x64 et Arm64. Ces fichiers énumèrent toutes les exportations d’API du DLL et indiquent au chargeur le nom du DLL qui peut répondre à ces appels API.

    foo_x64.def:

    EXPORTS
        MyAPI1  =  foo_x64.MyAPI1
        MyAPI2  =  foo_x64.MyAPI2
    

    foo_arm64.def:

    EXPORTS
        MyAPI1  =  foo_arm64.MyAPI1
        MyAPI2  =  foo_arm64.MyAPI2
    
  3. Vous pouvez ensuite utiliser link pour créer des fichiers d’importation LIB pour x64 et Arm64 :

    link /lib /machine:x64 /def:foo_x64.def /out:foo_x64.lib
    link /lib /machine:arm64 /def:foo_arm64.def /out:foo_arm64.lib
    
  4. Liez les fichiers OBJ vides et importez LIB en utilisant l’indicateur /MACHINE:ARM64X pour produire le DLL de transfert pur 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
    

Le foo.dll résultant peut être chargé dans un processus Arm64 ou x64/Arm64EC. Quand un processus Arm64 charge foo.dll, le système d’exploitation chargera immédiatement foo_arm64.dll à sa place et tout appel API sera géré par foo_arm64.dll.