Nouvelles Du Monde

C++20 : Plus de détails sur la prise en charge des modules par les trois grands compilateurs

C++20 : Plus de détails sur la prise en charge des modules par les trois grands compilateurs

2023-10-23 14:28:00

Dans mon dernier article, « C++20 : prise en charge des modules par les trois grands compilateurs », j’ai compilé un module simple à l’aide des trois grands compilateurs. Aujourd’hui, je vais approfondir et utiliser GCC, Clang et le compilateur Microsoft.

Publicité


Rainer Grimm travaille depuis de nombreuses années en tant qu’architecte logiciel, responsable d’équipe et de formation. Il aime écrire des articles sur les langages de programmation C++, Python et Haskell, mais aime également intervenir fréquemment lors de conférences spécialisées. Sur son blog Modern C++, il parle intensément de sa passion C++.



Cet article est assez technique et se termine par une curieuse observation. De plus, cela nécessite des connaissances de base sur les modules, que l’on retrouve dans les articles précédents sur les modules :

  1. Les avantages des modules
  2. Un module mathématique simple
  3. Unité d’interface de module et unité d’implémentation de module
  4. Modules structurants
  5. Autres questions ouvertes sur les modules
  6. Fragment de module privé et unités d’en-tête

Prise en charge des modules par le compilateur

J’utilise le cl.exe 19.29.20133 de Microsoft pour x64, le compilateur Clang 16.0.5 et GCC 11.1.0 pour mes expériences.

Commençons par le compilateur Microsoft.

Le compilateur Microsoft Visual propose plusieurs options d’utilisation des modules :



Il y en a aussi quelques généralistes cl.exe Options du compilateur :



Dans les lignes de commande suivantes, j’utilise diverses options du compilateur sur le fichier ifc. Le fichier ifc est le module et contient la description des métadonnées de l’interface du module.

  • Utiliser le module math.cppmpour créer les fichiers obj et ifc.

cl.exe /c /std:c++latest /interface /TP math.cppm​

  • Utiliser le module math.cppmpour créer uniquement le fichier ifc.

cl.exe /c /std:c++latest /ifcOnly /interface /TP math.cppm​

  • Utiliser le module math.cppmpour obtenir le fichier obj math.obj et le fichier ifc mathematic.ifc créer.

cl.exe /c /std:c++latest /interface /TP math.cppm /ifcOutput mathematic.ifc​

  • Créer le fichier exécutable client.exe et utilisez le fichier ifc math.inter.

cl.exe /std:c++latest client.cpp math.obj /reference math.inter​

  • Crée le fichier exécutable client.exe et utilise explicitement le fichier ifc math.interqui se trouve dans le répertoire ifcFiles situé.

cl.exe /std:c++latest client.cpp math.obj /ifcSearchDir ifcFiles /reference math.inter

Le compilateur Clang est désormais utilisé.

Le compilateur Clang propose différentes options pour créer des modules :



De plus amples détails peuvent être trouvés dans la documentation officielle Modules C++ standards. Dans les lignes de commande suivantes, j’utilise les options du compilateur pour le module et le fichier ifc.

  • Utiliser le fichier de déclaration du module math.cppmpour obtenir le fichier pcm math.pcm créer.

clang++ -c -std=c++20 -fmodule-output math.cppm -o math.pcm​

Utilisez le module avec l’extension ixx (math.ixx) au fichier pcm math.pcm créer.

clang++ -std=c++20 --precompile -x c++-module math.ixx -o math.pcm​

Créez le fichier pcm et utilisez-le.

clang++ -std=c++20 -c math.pcm -o math.o​
clang++ -std=c++20 -fprebuilt-module-path=. math.o client.cpp -o client.exe​

Utilisez le fichier pcm other.pcm et les compiler.

clang++ -std=c++20 -c client.cpp -fmodule-file=math=other.pcm -o client.o

Cela m’amène au compilateur GCC.




Les concepts introduits avec C++20, ainsi que la bibliothèque, les modules et les coroutines Ranges, ont redéfini la façon de créer des applications C++ modernes. Du 7 au 9 novembre 2023, Rainer Grimm vous emmène dans son atelier intensif C++20 : les nouveaux concepts expliqués en détail à jour et aborde les nombreuses fonctions utiles apportées par C++20.

Le tableau suivant montre les quelques options GCC :



De nombreuses options parmi les unités d’en-tête d’adresse Big Three.

Les unités d’en-tête sont une représentation binaire des fichiers d’en-tête et représentent une transition des en-têtes aux modules. Vous devez utiliser le #include-Directive du nouveau Import-replace instruction et un point-virgule (;) ajouter.

#include       => import ;
#include "myHeader.h"  => import "myHeader.h";

Pour plus d’informations sur les unités d’en-tête, consultez mon article précédent « Fragment de module privé et unités d’en-tête ». Dans les lignes suivantes, je joue avec les unités d’en-tête et j’utilise les fichiers suivants :

// head.h

#include 

void hello();

  • Le fichier source head.cppqui importe l’unité d’en-tête

// head.cpp

import "head.h";

void hello() {

    std::cout << 'n';
    std::cout << "Hello World: header unitsn";
    std::cout << 'n';

}

  • Le programme principal helloWorld3.cppqui importe l'unité d'en-tête

// helloWorld3.cpp

import "head.h";

int main() {

    hello();

}

Je vais créer une unité d'en-tête à partir du fichier d'en-tête head.h pour le compilateur Microsoft Visual et le compilateur GCC. Contrairement à la documentation officielle Modules C++ standards Je n'ai pas pu créer d'unités d'en-tête avec le compilateur Clang.

  • Compilateur visuel Microsoft

Ce sont les étapes nécessaires pour utiliser les unités d’en-tête.

cl.exe /std:c++latest /EHsc /exportHeader head.h
cl.exe /c /std:c++latest /EHsc /headerUnit head.h=head.h.ifc head.cpp
cl.exe /std:c++latest /EHsc /headerUnit head.h=head.h.ifc helloWorld3.cpp head.obj

  • Le drapeau /exportHeader à la ligne 1 provoque le fichier ifc head.h.ifc à partir du fichier d'en-tête head.h est créé.
  • Le dossier de mise en œuvre head.cpp (ligne 2) et le dossier client helloWordl3.cpp (Ligne 3) utilisez l’unité principale. Le drapeau /headerUnit head.h=head.h.ifc importe l'unité d'en-tête et indique au compilateur le nom du fichier ifc pour l'en-tête spécifié.

La création et l'utilisation du module se composent de trois étapes.

g++ -fmodules-ts -fmodule-header head.h -std=c++20
g++ -fmodules-ts -c  -std=c++20 head.cpp 
g++ -fmodules-ts  -std=c++20 head.o helloWorld3.cpp -o helloWorld3

  • (1) crée le module head.gcm. Le drapeau -fmodule-header indique qu'à partir de head.h une unité d'en-tête doit être créée.
  • La ligne suivante crée le fichier objet head.o.
  • Enfin, la ligne 3 crée le fichier exécutable qui contient implicitement le module head.gcm utilisé.

Comme promis, voici la curieuse observation.

Lorsqu'il s'agit de modules, il faut faire la différence entre accessibilité et visibilité. Lorsqu'un module exporte une entité, un client importateur peut la voir et l'utiliser. Les entités non exportées ne sont pas visibles, mais peuvent être accessibles.

// bar.cppm

module;

#include 

export module bar;

struct Foo {
    void writeName() {
        std::cout << "nFoon";
    }

};

export struct Bar {
    Foo getFoo() {
        return Foo{};
    }
};

Le module bar exporte la classe Bar. Bar est visible et accessible. Foo cependant, n'est pas visible.

// bar.cpp

#include 

import bar;

int main() {

    Bar b;
    // Foo f;                   // (1)          
    auto f = b.getFoo();   
    f.writeName();              // (2)

    using FooAlias = 
      decltype(std::declval().getFoo());   // (3)
    FooAlias f2;                // (4)
    f2.writeName();             // (5)

}

La classe Foo n’est pas exporté et n’est donc pas visible. Son utilisation dans (1) provoquerait une erreur de l'éditeur de liens. Au contraire, Foo est accessible car la fonction membre getFoo (dans bar.cppm) les renvoie. Par conséquent la fonction peut writeName (2) peut être appelé. Je peux également utiliser un alias de type de données Foo créer (3) et l'utiliser pour Foo pour instancier (4) et writeName (5) appeler. L'expression std::declval().getFoo() (3) renvoie l'objet qu'un appel Bar.getFoo() retournerais. Enfin là decltype renvoie le type de données de cet objet hypothétique.



Dans mon prochain article, je plongerai plus profondément dans la bibliothèque Ranges en C++20.


(moi)

Vers la page d'accueil



#C20 #détails #sur #prise #charge #des #modules #par #les #trois #grands #compilateurs
1698117806

Facebook
Twitter
LinkedIn
Pinterest

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

ADVERTISEMENT