Enregistrement de chaque fichier source C / C ++ pour créer une liste d'exécution des sources utilisées

StackOverflow https://stackoverflow.com/questions/618581

Question

Pour une bibliothèque de débogage et de journalisation, je souhaite pouvoir rechercher, au moment de l'exécution, une liste de tous les fichiers source compilés et liés par le projet. J'imagine que je vais inclure une sorte d'en-tête dans chaque fichier source et que la macro __FILE__ du préprocesseur peut me donner une constante de caractère pour ce fichier; il me faut donc d'une manière ou d'une autre & "; Diffuser &"; Ces informations de chaque fichier doivent être collectées par une fonction d'exécution.

La question est de savoir comment procéder avec élégance, en particulier si cela peut être fait en C plutôt qu'en C ++. En C ++, j'essaierais probablement de créer une classe avec un stockage statique pour contenir la liste des noms de fichiers. Chaque fichier d’en-tête créerait une instance statique locale de cette classe, qui lors de la création, ajouterait le pointeur FILE ou quoi que ce soit dans les membres de données statiques de la classe, par exemple sous forme de liste chaînée.

Mais je ne pense pas que cela fonctionnera en C, et même en C ++, je ne suis pas sûr qu'il soit garanti que chaque élément sera créé.

Était-ce utile?

La solution

Je ne ferais pas ce genre de chose dans le code. J'écrivais un outil qui analysait le fichier de projet (vcproj, makefile ou même scannait simplement le répertoire du projet pour y trouver des fichiers * .c *) et générais un fichier source C supplémentaire contenant les noms de tous les fichiers source dans structure de données initialisée.

Je ferais alors de cet outil une partie du processus de construction de sorte que chaque fois que vous effectuez une construction, tout se fasse automatiquement. Au moment de l'exécution, tout ce que vous avez à faire est de lire la structure de données qui a été construite.

Autres conseils

Je suis d’accord avec Ferruccio, le meilleur moyen de faire cela est dans le système de compilation, pas dans le code lui-même. Pour étendre son idée, ajoutez à votre système de génération une cible qui dumpe la liste des fichiers (qu’il doit connaître de toute façon) dans un fichier C sous forme de chaîne ou de tableau de chaînes, puis compilez ce fichier dans votre source. Cela évite beaucoup de complications dans la source et est extensible si vous souhaitez ajouter des informations supplémentaires, telles que le numéro de version de votre système de contrôle du code source, qui a construit l'exécutable, etc.

.

Il existe une méthode standard sous UNIX et Linux - ident. Pour chaque fichier source que vous créez, une balise ID est généralement attribuée par votre système de contrôle de version, par exemple. Mots clés SVN .

Ensuite, pour connaître le nom et la révision de chaque fichier source, utilisez simplement la commande <=>. Si vous avez besoin de le faire au moment de l'exécution, voyez comment <=> le fait - la source devrait être disponible gratuitement.

Il n'y a aucun moyen de le faire en C. En C ++, vous pouvez créer une classe comme celle-ci:

struct Reg {
   Reg( const char * file ) {
      StaticDictionary::Register( file );
};

où StaticDictionary est un conteneur singleton pour tous vos noms de fichiers. Puis dans chaque fichier source:

static Reg regthisfile( __FILE__ );

Vous voudriez faire du dictionnaire un Meyers singleton pour éviter des problèmes d'ordre de création.

Je ne pense pas que vous puissiez le faire comme vous le décrivez dans un & "passif &"; mode. C'est-à-dire que vous allez en quelque sorte exécuter du code pour chaque fichier source à ajouter au registre, il est difficile de l'obtenir automatiquement.

Bien sûr, il est possible de rendre ce code très discret à l’aide de macros. Cela pourrait poser problème pour les fichiers source C qui n'ont pas de & Quot; entrypoint & ";, donc si votre code n'est pas déjà organisé en tant que &"; Modules & ";, avec par exemple. une init() fonction pour chaque module, cela pourrait être difficile. Le code d’initialisation statique est peut-être possible. Je ne suis pas sûr à 100% si l’ordre dans lequel les choses sont initialisées crée des problèmes ici.

L'utilisation de static l'espace de stockage dans le module de registre semble une excellente idée. Il est assez simple d'implémenter une simple liste chaînée ou une simple table de hachage si votre projet n'inclut pas déjà une bibliothèque d'utilitaires à usage général.

En C ++, votre solution fonctionnera. C'est garanti.

Modifier: Je viens de découvrir une solution qui me trotte dans la tête: modifiez une règle dans votre fichier Make pour l'ajouter. '-include " cfiles_register.h "' à chaque 'g ++ fichier.cpp'.

%.o : %.cpp
    $(CC) -include 'cfiles_register.h' -o $@ $<

placez votre proposition dans la question relative à l'implémentation de celle-ci "cfiles_register.h".

L'utilisation d'instances statiques en C ++ fonctionnerait correctement.

Vous pouvez le faire aussi en C, mais vous devez utiliser des fonctionnalités spécifiques à l'exécution - pour MSVC CRT, consultez http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/

Pour C - vous pouvez le faire avec une macro - définissez une variable nommée correspondant à votre fichier, puis analysez les symboles de votre fichier exécutable, comme une idée:

 #define TRACK_FILE(name) char _file_tracker_##name;

utilisez-le dans votre my_c_file.c comme ceci:

 TRACK_FILE(my_c_file_c)

et ensuite grep tous les noms de fichiers / variables du binaire comme ceci

nm my-binary | grep _file_tracker

Pas vraiment sympa, mais ...

Horrible idée, j'en suis sûr, mais utilisez un singleton. Et sur chaque fichier, faites quelque chose comme

  Singleton.register(__FILE__); 

au niveau mondial. Cela ne marchera que sur les fichiers cpp. J'ai fait quelque chose comme cela il y a des années en tant que novice et cela a fonctionné. Mais je craquerais de le faire maintenant. J'ajouterais une étape de construction maintenant.

Je suis d'accord avec ceux qui disent qu'il est préférable d'éviter cela au moment de l'exécution, mais en C, vous pouvez initialiser une variable statique avec un appel de fonction, c'est-à-dire dans chaque fichier:

static int doesntmatter = register( __FILE__);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top