Les Modules C++ et L'ABI C++

J'ai lu sur la proposition de modules C++ ( dernier projet ) mais je ne comprends pas complètement quel(s) problème (s) il vise à résoudre.

Son but est-il de permettre à un module construit par un compilateur d'être utilisé par n'importe quel autre compilateur (sur le même système d'exploitation/architecture, bien sûr)? Autrement dit, la proposition équivaut-elle à normaliser L'ABI C++?

Si ce n'est pas le cas, une autre proposition est-elle envisagée pour normaliser L'ABI C++ et permettre aux compilateurs d'interopérer?

24
demandé sur Rapptz 2012-01-31 04:07:22

3 réponses

Les en-têtes pré-compilés (PCH) sont des fichiers spéciaux que certains compilateurs peuvent générer pour A.fichier cpp. Ce qu'ils sont est exactement cela: code source pré-compilé. Ils sont du code source qui a été alimenté par le compilateur et intégré dans un format dépendant du compilateur.

PCHs sont couramment utilisés pour accélérer la compilation. Vous mettez les en-têtes couramment utilisés dans le PCH, puis incluez simplement le PCH. Lorsque vous faites un #include sur le PCH, votre compilateur ne fait pas réellement le travail #include habituel. Au lieu charge ces symboles pré-compilés directement dans le compilateur. Pas d'exécution D'un préprocesseur C++. Pas d'exécution d'un compilateur C++. Non # y compris un million de fichiers différents. Un fichier est chargé et les symboles apparaissent entièrement formés directement dans l'espace de travail de votre compilateur.

Je mentionne tout cela parce que les modules sont des PCHs dans leur forme perfect . PCHs sont essentiellement un hack géant construit sur un système qui ne permet pas de modules réels. Le but des modules est finalement de pouvoir prendre un fichier, générer un fichier de module spécifique au compilateur qui contient des symboles, puis un autre fichier charge ce module au besoin. Les symboles sont pré-compilés, donc encore une fois, il n'est pas nécessaire d'inclure un tas de choses, d'exécuter un compilateur, etc. Votre code dit, import thing.foo, et il apparaît.

Regardez l'un des en-têtes de bibliothèque standard dérivés de STL. Prenez <map> par exemple. Les chances sont bonnes que ce fichier est gigantesque ou a beaucoup de #inclusions d'autres fichiers qui font le fichier résultant gigantesque. C'est beaucoup D'analyse C++ qui doit se produire. Il doit arriver pour tous les .fichier cpp qui contient #include <map>. Chaque fois que vous compilez un fichier source, le compilateur doit recompiler la même chose. Plus. Et plus. Et une fois de plus.

<map> change-t-il entre les compilations? Non, mais votre compilateur ne peut pas le savoir. Il doit donc continuer à le recompiler. Chaque fois que vous touchez une .fichier cpp, il doit compiler chaque en-tête que cela.fichier cpp comprend. Même si vous n'avez pas touché ces en-têtes ou fichiers source qui affectent ces en-têtes.

Les fichiers PCH étaient un moyen de contourner ce problème. Mais ils sont limités, parce qu'ils sont juste un hack. Vous ne pouvez inclure qu'un par .fichier cpp, car il doit être la première chose incluse par .fichiers cpp. Et comme il n'y a qu'un seul PCH, si vous faites quelque chose qui change le PCH (comme Ajouter un nouvel en-tête), vous devez recompiler Tout dans ce PCH.

Les Modules n'ont essentiellement rien à voir avec le compilateur croisé ABI (cependant avoir un de ceux-ci serait bien, et les modules rendraient un peu plus facile d'en définir un). Leur but fondamental est d'accélérer les temps de compilation.

33
répondu Nicol Bolas 2012-01-31 00:44:27

Les Modules sont ce que Java, C# et beaucoup d'autres langages modernes offrent. Ils réduisent énormément le temps de compilation simplement parce que le code qui se trouve dans l'en-tête d'aujourd'hui n'a pas besoin d'être analysé encore et encore, chaque fois qu'il est inclus. Lorsque vous dites #include <vector>, le contenu de <vector> sera copié dans le fichier actuel. #include n'est vraiment rien d'autre que copier et coller.

Dans le monde du module, vous dites simplement import std.vector; par exemple et le compilateur charge la table de requête / symbole de ce module. Le le fichier module a un format qui facilite l'analyse et l'utilisation du compilateur. Il est également analysé seulement une fois , lorsque le module est compilé. Après cela, le fichier de module généré par le compilateur est simplement interrogé pour les informations nécessaires.

Parce que les fichiers de module sont générés par le compilateur, ils seront assez étroitement liés à la représentation interne du compilateur du code C++ (AST) et ne seront probablement pas portables (comme aujourd'hui .o/.so/.a fichiers, parce que de nom mangling etc.).

12
répondu Xeo 2012-01-31 00:20:08

Les Modules en C++ doivent être principalement meilleurs que les solutions actuelles, c'est-à-dire lorsqu'une bibliothèque se compose d'un fichier *.so et *.h fichier avec l'API. Ils ont à résoudre les problèmes qui sont aujourd'hui avec #comprend, c'est:

  • require macroguards (macros qui empêchent que les définitions soient fournies plusieurs fois)
  • sont strictement basés sur du texte (de sorte qu'ils peuvent être trompés et dans des conditions normales, ils sont réinterprétés, ce qui donne aussi une chance de regarder différemment dans différents Unité de compilation à relier ensuite)
  • Ne faites pas de distinction entre les bibliothèques dépendantes utilisées uniquement de manière instrumentale et dérivées (surtout si l'en-tête fournit des modèles de fonction en ligne)

Malgré ce que dit Xeo, les modules N'existent pas en Java ou en C#. En fait ,dans ces langages, "charger des modules" repose sur ce "ok, ici vous avez le CLASSPATH et recherchez-le pour trouver les modules qui peuvent fournir des symboles que le fichier source utilise réellement". Le la déclaration" import "en Java n'est pas du tout une" demande de module "- la même chose que "using" en C++ ("import ns.ns2.* "en Java est le même que" Utilisation de l'espace de noms ns:: ns2 " en C++). Je ne pense pas qu'une telle solution puisse être utilisée en C++. L'approximation la plus proche que je puisse imaginer sont des paquets dans Vala ou des modules dans Tcl (ceux de la version 8.5).

J'imagine que les modules C++ ne peuvent pas être multi-plateformes, ni chargés dynamiquement (nécessite un chargeur de module dynamique c++ dédié - ce n'est pas impossible, mais aujourd'hui, difficile à définir). Ils seront certainement dépendants de la plate-forme et devraient également être configurables à la demande. Mais un ABI C++ stable n'est pratiquement requis que dans la plage d'un système, tout comme c'est le cas avec C++ ABI maintenant.

8
répondu Ethouris 2012-07-20 20:28:28