Existe-t-il un moyen de comparer des fichiers obj à partir de Visual Studio?

J’ai un projet C ++ qui intègre plusieurs configurations (pas seulement Debug / Release), et c’est un projet plutôt volumineux. Appelons cela KitchenSink.vcproj

Je soupçonne que de nombreux éléments de ce projet ont été conçus de manière identique, quelle que soit la configuration. Par exemple, construire avec / sans support Unicode n’aura pas d’importance pour un fichier source qui n’utilise pas de chaînes.

Cela conduirait au même fichier source compilé dans plusieurs configurations, mais générant (effectivement) le même fichier .obj. Il ne génère pas le même fichier, car les horodatages et autres sont incorporés dans le fichier, mais toutes les parties fonctionnelles du fichier object sont identiques.

Y a-t-il un moyen de vérifier cela? J’aimerais extraire des morceaux de KitchenSink dans leurs propres projets, plus simples, où ils ne doivent être construits qu’une seule fois. Cela accélèrerait les temps de construction et simplifierait notre base de code. Mais j’ai besoin d’un moyen de trouver automatiquement les parties du code qui construisent la même chose, quelle que soit la configuration. Y a-t-il un moyen facile de faire ça?

EDIT: Clarifier mon point. Imaginez le fichier suivant:

// Some header file int calculate_something(int a, int b); // The source file int calculate_something(int a, int b) { return a * b; } 

Maintenant, ce fichier source n’a rien à voir avec Unicode. Donc, si nous le construisons dans une configuration Unicode, puis le reconstruisons avec une configuration Multi-octets, nous perdons simplement du temps. Nous pourrions l’insérer dans sa propre bibliothèque statique, construite sans support Unicode, puis cette nouvelle bibliothèque pourrait être utilisée par mes autres projets. Il n’y a rien de risqué à cela.

J’ai juste besoin de trouver ces fichiers qui peuvent être déplacés en toute sécurité vers un projet séparé.

EDIT: Précisions supplémentaires:

 KitchenSink.vcproj has the following files (among others) SsortingngUtils.h SsortingngUtils.cpp MathStuff.h MathStuff.cpp 

À présent, si vous construisez KitchenSink en Unicode, puis à nouveau dans MultiByte, vous créerez SsortingngUtils.obj à deux resockets et MathStuff.obj à deux resockets. Ceci est évidemment nécessaire pour SsortingngUtils.obj, car ce sera différent en Unicode et MultiByte. Mais MathStuff.obj devrait construire exactement la même chose.

Donc, je voudrais réorganiser / restructurer / refactoriser les éléments suivants:

 KitchenSink.vcproj has the following files (among others) SsortingngUtils.h SsortingngUtils.cpp NewProject.vcproj has the following files MathStuff.h MathStuff.cpp 

Maintenant, KitchenSink peut être construit dans ses multiples configurations, tandis que NewProject peut être construit avec une seule option Debug / Release.

Encore une fois, je ne parle pas de partage de fichiers obj. Je parle de supprimer les fichiers cpp / h d’un projet et de les placer dans un autre.

Notez également que Unicode / Multi-octets est un exemple de projet avec plusieurs configurations. La réalité dans mon projet est en réalité plus compliquée, de sorte que chaque fichier source est compilé 4 fois, plutôt que les 2 qui auraient lieu avec Unicode / Multibyte.

Sous Linux et Cygwin / MINGW, ccache est utile pour cela (détecter des sources prétraitées identiques avec des indicateurs de compilation identiques). SCons (un remplacement de make utilisant python) peut faire la même chose.

Pour Visual Studio, je crains que vous ne consultiez IncrediBuild.

Cela dit, cette réponse répertorie certaines références à d’autres candidats (projets en cours): Existe – t-il un Ccache pour Visual Studio?

Eh bien, vous pourriez utiliser diff -b pour comparer les fichiers .obj mais je pense que vous seriez stupide de suivre cette voie. Tout ce qu’il faudrait, c’est un petit changement du code source pour rendre votre processus de construction optimisé invalide. Je n’envisage pas de faire quelque chose comme ça.

Dans Visual Studio, le principal outil permettant d’inspecter les fichiers binarys générés par le compilateur / éditeur de liens est le fichier dumpbin.exe. Cochez la case Comment comparer des images binarys des mêmes versions de projet

Sachez que l’unité de traduction utilisée ne fait pas appel à des chaînes, cela ne signifie pas que les versions Unicode et non Unicode seront identiques. La génération Unicode affecte l’utilisation de l’API Windows. Par conséquent, les fichiers object seront éventuellement liés à différents symboles dans les bibliothèques système.

Note latérale, l’idée est de réutiliser des fichiers .obj entre les versions, en particulier entre les versions avec une configuration même légèrement différente, est très faible. Il y a beaucoup de problèmes subtils possibles. Par exemple, en considérant exactement la même configuration de construction, une bibliothèque statique est théoriquement équivalente à une collection de fichiers .obj. Mais j’ai rencontré des différences et des problèmes très étranges liant mon application à une bibliothèque statique ou à des fichiers * .obj de cette bibliothèque. Voici mon fil de discussion sur les forums MSDN où vous pouvez trouver des détails sur les fichiers .obj en remplacement immédiat de la bibliothèque statique .

Pour voir si un projet est en train de créer le même fichier dans différentes configurations, il est préférable de comparer le résultat du pré-processeur. La comparaison de fichiers objects est tout simplement trop sujette à échec et n’est donc pas nécessaire.

L’idée de base est la suivante: Exécutez le préprocesseur sur un fichier dans plusieurs configurations et comparez les fichiers de sortie. S’ils sont identiques, il est alors inutile de créer ce fichier dans différentes configurations. Il est donc judicieux de refactoriser un projet différent, avec moins de configurations.

Dans Visual Studio:

  1. Cliquez avec le bouton droit sur le projet et accédez à Propriétés.
  2. Sous Propriétés de configuration -> C / C ++ -> Préprocesseur, modifiez “Générer un fichier prétraité”.
  3. Réglez-le sur Without Line Numbers (/EP /P)
  4. faire une construction dans ConfigurationA
  5. les fichiers prétraités sont générés dans le même répertoire que le fichier source, et NON dans le sous-répertoire de configuration. Déplacez donc tous les fichiers *.i dans le sous-répertoire ConfigurationA pour plus de sécurité.
  6. Répétez les étapes 4 et 5 pour ConfigurationB (et toute autre configuration).
  7. Comparez les fichiers *.i individuels de chaque sous-répertoire de configuration. Si un fichier source produit le même fichier .i dans toutes les configurations, il convient de l’extraire dans une bibliothèque différente (à configuration unique).
  8. Définissez Generate Preprocessed File sur son paramètre d’origine.

Cependant , si vous utilisez des en-têtes précompilés, vous risquez de vous tromper. L’en-tête précompilé peut inclure des éléments qui ne sont tout simplement pas nécessaires pour un fichier donné, mais qui entraînent une modification inutile de la sortie du préprocesseur.

Par exemple, SimpleFile.cpp et SimpleFile.h n’utilisent que des types de base, ils n’ont donc pas besoin d’inclure quoi que ce soit. Mais SimpleFile.cpp inclut stdafx.h , car VisualStudio exige que tous les fichiers d’un projet incluent l’en-tête précompilé. stdafx.h inclut plusieurs fichiers, y compris HighlyConfigurable.h , qui contient plusieurs instructions #ifdef et se comporte de manière très différente, en fonction de la configuration. Ainsi, puisque SimpleFile.cpp inclut stdafx.h qui inclut HighlyConfigurable.h , la sortie du pré-processeur SimpleFile.i sera très différente pour chaque configuration. Alors que, si stdafx.h n’était pas utilisé, SimpleFile.i serait le même dans toutes les configurations.

La solution de contournement simple consiste à commenter l’intégralité de stdafx.h . Cela peut sembler drastique, mais vous n’allez pas enregistrer le fichier de cette façon. Vous allez simplement suivre les étapes ci-dessus pour générer des fichiers de pré-processeur à des fins de comparaison, puis restaurer stdafx.h dans son ancienne gloire.