|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||||||
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
Bonjour à vous,
J'aimerais présenter un petit projet que j'ai en tête depuis quelques temps. Comme vous le savez sûrement si vous programmez en C++, il est parfois pénible de gérer à la fois les fichiers d'entête .h/.hpp et les fichiers d'implémentation .cpp. Par exemple, on doit (pour chaque classe si l'on est rigoureux) créer un couple .cpp/.h, alors que ces deux fichiers représentent une seule et même entité : la classe en question. Grâce à certains IDE comme Code::Blocks, on peut créer les deux à la fois et y placer un squelette de classe en quelques clicks, mais il reste toujours le besoin de les maintenir séparément : changer le .h revient souvent à changer le .cpp (et réciproquement, mais c'est plus rare). Du point de vue du langage, cette distinction entête/implémentation est absolument nécessaire, je ne le contredis pas. Mais n'est-il pas possible de générer ces deux fichiers à partir d'un seul ? On pourrait de fait réduire significativement le volume de code à maintenir, et simplifier les opérations de maintenance. J'ai donc programmé rapidement un "compilateur" capable de transformer un fichier ".mpp" ("m" pour "module") en deux fichiers .cpp et .hpp, directement compilables via gcc ou autre. Exemple (test.mpp) : Code c++ :
Code c++ :
Code c++ :
Le code (cross-platform, pas de licence) est disponible à cette adresse :
Les fichiers projets sont seulement disponibles pour Code::Blocks. J'imagine qu'il doit exister un convertisseur pour les importer dans Visual et consorts. Le "pseudo-langage" utilisé dans les fichiers .mpp n'est pas encore totalement bien défini, il manque encore :
J'ai déjà intégré les features suivantes :
Comme vous pouvez le voir, ce "langage" se veut un poil moins généraliste que le C++ : il est plutôt orienté programmation avec classes et s'éloigne du C (pas ou peu de macros). Le but n'étant pas de faire un (C++)++, ce qui est complètement en dehors de mes compétences, mais juste de développer un outil intermédiaire pour faciliter l'écriture et la maintenance du code pour un style de programmation particulier. Ce qui est bon, c'est qu'on n'est pas dépendant du format ".mpp" : on peut toujours choisir de reprendre/distribuer le code C++ généré. Si vous avez des commentaires, n'hésitez pas Le code n'est probablement pas organisé au mieux, mais ça tourne pour le moment. Pour ceux que le détails techniques intéressent, la "compilation" se fait de la manière suivante :
Pour "compiler" plus d'un fichier .mpp à la fois, il est probablement plus efficace de passer par un fichier projet .mproj. En effet, tout se passera dans une seule même unité de compilation : il n'y aura donc besoin de lire chaque module qu'une seule fois, peu importe combien de fois celui-ci est utilisé par les autres modules. |
||||||
|
|
00
|
|
|
#2 | ||
|
Membre confirmé
![]() ![]() Inscription : décembre 2005 Messages : 165 ![]() |
C'est ce genre de lourdeurs et limitations qui me fait préférer les langages modernes "orientés imports binaires" (Java, C#, Haskell, etc.) aux vieux langages "orientés includes sources" (C, C++, Objective C, etc.).
Quoiqu'il en soit, j'aurais procédé différement pour automatiser la production de fichiers d'entêtes. Je me serais contenté de définir des macros vides nommées PUBLIC, PROTECTED et PRIVATE afin d'annoter mes fichiers "cpp", sans introduire un nouveau format "mpp" (ce qui ressemble beaucoup à un nouveau langage qui marcherait dans les pas du D). Par exemple : Code :
Note : nested -> imbriqué. |
||
|
|
01
|
|
|
#3 | |
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
Je ne sais pas si ton exemple est réellement possible à parser.
Un exemple simple (et c'est ce pour quoi j'ai utilisé les std::string dans mon bout de code) c'est la gestion des namespaces. Il est hors de question de coller un "using namespace std;" dans le fichier header, donc tous les types standards devraient être préfixés par "std::". Ca rajoute une lourdeur qui rendrait probablement le tout pas très intéressant comparé au C++ seul. Citation:
Il faudra que je jette un œil au Haskell un de ces jours, j'en entend beaucoup parler et souvent en bien. |
|
|
|
00
|
|
|
#4 | |
|
Membre confirmé
![]() ![]() Inscription : décembre 2005 Messages : 165 ![]() |
Citation:
C'est en effet plus correct de dire ça et c'est un peu là que réside le compromis de langages comme Java : simplifier en retirant des possibilités pas vraiment utilisées. D'ailleurs B. Soustroup avait émis un souhait dans ce sens pour un C++ 2.0 (et sauf erreur de ma part, relativement à la notion de modules en C++). |
|
|
|
01
|
|
|
#5 | ||
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
Citation:
La solution que j'utilise n'est pas exactement codée "en dur". A termes, le but est de supporter n'importe quel namespace (boost, MyLibrary, ...) grâce au concept de "dépendance". Par exemple le "using std::string" dans le .mpp n'a pas le même sens qu'un "using std::string" en C++ : il indique que le module "Test" dépend du module "std::string", lequel met à disposition la classe "string" dans le namespace "std". C'est cette dernière information qui est codée en dur dans mon programme, rien de plus. Citation:
|
||
|
|
00
|
|
|
#6 | |
|
Membre confirmé
![]() ![]() Inscription : décembre 2005 Messages : 165 ![]() |
Citation:
Dans mes recherches, je suis toutefois tombé là dessus : http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess. Les espaces de nommages n'y sont cependant pas gérés... |
|
|
|
00
|
|
|
#7 |
![]() ![]() Inscription : juin 2002 Messages : 2 034 ![]() |
|
|
|
00
|
|
|
#8 |
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
Intéressant ce draft ! Ça n'a pas donné de suite ?
|
|
|
00
|
|
|
#9 |
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
J'ai mis à jour les fichiers du premier post avec la toute dernière version.
Il ne manque plus grand chose pour qu'il soit pleinement fonctionnel, mais on peut déjà faire beaucoup ! J'ai introduit un nouveau type de fichier, .mproj, qui rassemble les modules d'un même projet pour compiler le tout en un .exe (ou plus tard, .lib, .a, etc). Pour cela, le programme utilise le compilateur C++ installé sur votre machine (pour le moment seul GCC est supporté, mais rajouter le support pour Visual ou autres ne devrait pas poser trop de problème : c'est taillé pour). Pour plus d'info, utiliser la commande "-h" ou lire le readme.txt fourni dans mcpp_bin_win32.7z/zip. |
|
|
00
|
|
|
#10 | ||
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
Mise à jour des fichiers du premier post avec la dernière version.
Le programme supporte maintenant les classes, structures et unions imbriquées (nested), ainsi que les fonctions templates. Comme le contenu des fonctions n'est pas analysé, le programme n'a aucun moyen de savoir quelles dépendances sont exposées dans le fichier .hpp par ces fonctions template. Du coup j'ai introduit une nouvelle notation : Code c++ :
C'est peut être une solution temporaire. Je n'ai pas envie pour l'instant d'écrire un vrai parser de C++ pour analyser le corps des fonctions Devraient venir prochainement : les typedefs et enums. |
||
|
|
00
|
|
|
#11 | ||
|
Membre éprouvé
![]() ![]() Doctorant en astrophysique Inscription : juin 2007 Messages : 310 ![]() |
Comme prévu, voilà le support des typedefs ("normaux", de fonction, de fonction membre) et des enums, imbriqués ou en portée globale.
Comme il s'agit de nouveaux types dont on ne peut pas faire de déclaration anticipée (forward declaration), l'utilisation de ceux-ci dans un header implique obligatoirement l'inclusion du header dans lequel ils sont définis (d'autant plus s'ils s'agit de types imbriqués). Bien sûr, ce programme s'en occupe tout seul Ne reste plus que le support des modules et classes templates. Une fois que ça sera fait, je m'attellerai au problème des bibliothèques externes, et en particulier à la STL (qui, comme son nom l'indique, est principalement composée de types templates). Pour le préprocesseur, j'ai quelques doutes. Je ne peux pas utiliser la même syntaxe que pré-processeur du C++ a priori, car il y aurait risque de conflit avec le contenu des fonctions par exemple. Une solution pourrait être d'utiliser un double dièse : "##", mais c'est moche. Une autre solution serait de ne pas implémenter de pré-processeur du tout... L'intérêt de celui-ci est principalement la compilation conditionnelle. Les autres features (constantes et macros, j'en oublie ?) sont plutôt héritées du C, et on dispose d'équivalent plus propres en C++. Du coup il suffirait de trouver un autre moyen de faire de la compilation conditionnelle, par exemple en implémentant une structure proche de celle du C++ : Code c++ :
... si possible avec d'autres mots clés que "if" et "else", de manière à pouvoir les utiliser aussi à l'intérieur des fonctions (pas de "#ifdef" dans les fonctions et "if/else" ailleurs). Le tout serait alors transformé en pré-processeur C++. |
||
|
|
00
|
|
|
#12 |
|
Inactif
|
Bonjour,
C'est effectivement intéressant de réduire le taux de code qui est présent dans les sources. Si l'on part du principe, qu'il faut faire deux fois la même chose dans le header et dans l'implémentation alors effectivement, c'est efficient. |
|
|
00
|
Copyright © 2000-2013 - www.developpez.com