Je sais PC-Lint peut vous parler des en-têtes inclus mais non utilisés. Existe-t-il d’autres outils permettant de le faire, de préférence sous Linux?
Nous avons une grande base de code qui, au cours des 15 dernières années, a vu beaucoup de fonctionnalités bouger, mais les directives #include restantes sont rarement supprimées lorsqu'elles se déplacent d'un fichier d'implémentation à un autre, ce qui nous laisse un désordre total. Je peux évidemment faire le travail fastidieux de supprimer toutes les directives #include et de laisser le compilateur me dire lesquelles renvoyer, mais je préfère résoudre le problème à l'envers - trouver les inutilisées - plutôt que de reconstruire une liste de celles qui ont été utilisées.
AVERTISSEMENT: Mon travail consiste à travailler pour une entreprise qui développe des outils d’analyse statique.
Je serais surpris que la plupart (sinon la totalité) des outils d’analyse statique ne disposent pas d’une forme de vérification de l’utilisation de l’en-tête. Vous pouvez utiliser this wikipedia pour obtenir une liste des outils disponibles, puis envoyer un courrier électronique aux entreprises pour leur demander.
Quelques points à considérer lors de l’évaluation d’un outil:
Pour les surcharges de fonctions, vous souhaitez que tous les en-têtes contenant des surcharges soient visibles, pas seulement l'en-tête contenant la fonction sélectionnée par résolution de surcharge:
// f1.h
void foo (char);
// f2.h
void foo (int);
// bar.cc
#include "f1.h"
#include "f2.h"
int main ()
{
foo (0); // Calls 'foo(int)' but all functions were in overload set
}
Si vous adoptez l'approche de la force brute, supprimez d'abord tous les en-têtes, puis rajoutez-les jusqu'à la compilation. Si 'f1.h' est ajouté, le code sera compilé mais la sémantique du programme a été modifiée.
Une règle similaire s'applique lorsque vous avez des spécialisations partielles et partielles. Peu importe que la spécialisation soit sélectionnée ou non, vous devez vous assurer que toutes les spécialisations sont visibles:
// f1.h
template <typename T>
void foo (T);
// f2.h
template <>
void foo (int);
// bar.cc
#include "f1.h"
#include "f2.h"
int main ()
{
foo (0); // Calls specialization 'foo<int>(int)'
}
En ce qui concerne l'exemple de surcharge, l'approche par force brute peut générer un programme qui compile toujours mais dont le comportement est différent.
Un autre type d'analyse connexe que vous pouvez rechercher consiste à vérifier si les types peuvent être déclarés en aval. Considérer ce qui suit:
// A.h
class A { };
// foo.h
#include "A.h"
void foo (A const &);
// bar.cc
#include "foo.h"
void bar (A const & a)
{
foo (a);
}
Dans l'exemple ci-dessus, la définition de 'A' n'est pas obligatoire. Le fichier d'en-tête 'foo.h' peut donc être modifié de sorte qu'il ne possède une déclaration en aval que pour 'A':
// foo.h
class A;
void foo (A const &);
Ce type de vérification réduit également les dépendances d'en-tête.
Voici un script qui le fait:
#!/bin/bash
# Prune include files one at a time, recompile, and put them back if it doesn't compile
# arguments are list of files to check
removeinclude() {
file=$1
header=$2
Perl -i -p -e 's+([ \t]*#include[ \t][ \t]*[\"\<]'$2'[\"\>])+//REMOVEINCLUDE $1+' $1
}
replaceinclude() {
file=$1
Perl -i -p -e 's+//REMOVEINCLUDE ++' $1
}
for file in $*
do
includes=`grep "^[ \t]*#include" $file | awk '{print $2;}' | sed 's/[\"\<\>]//g'`
echo $includes
for i in $includes
do
touch $file # just to be sure it recompiles
removeinclude $file $i
if make -j10 >/dev/null 2>&1;
then
grep -v REMOVEINCLUDE $file > tmp && mv tmp $file
echo removed $i from $file
else
replaceinclude $file
echo $i was needed in $file
fi
done
done
Regardez Dehydra .
Sur le site:
Dehydra est un outil d'analyse statique léger, scriptable et à usage général, capable d'analyser du code C++ spécifique à l'application. Dans le sens le plus simple, Dehydra peut être considéré comme un outil sémantique de grep.
Il devrait être possible de créer un script qui recherche les fichiers #include inutilisés.
Le fichier cppclean de Google semble faire un travail décent en recherchant des fichiers d’en-tête inutilisés. Je viens de commencer à l'utiliser. Cela produit quelques faux positifs. Il y aura souvent des inclus inutiles dans les fichiers d’en-tête, mais cela ne vous dira pas qu’il faut une déclaration en aval de la classe associée et que l’inclusion doit être déplacé vers le fichier source associé.
Si vous utilisez Eclipse CDT, vous pouvez essayer Includator qui est gratuit pour les bêta-testeurs (au moment de l'écriture de cette lettre) et supprime automatiquement les #includes superflus ou ajoute ceux qui sont manquants.
Disclaimer: Je travaille pour la société qui développe Includator et je l'utilise depuis quelques mois. Cela fonctionne assez bien pour moi, alors essayez-le :-)
Autant que je sache, il n'y en a pas (ce n'est pas PC-Lint), ce qui est dommage et surprenant. J'ai vu la suggestion de faire ce morceau de pseudocode (qui automatise fondamentalement votre "processus fastidieux":
pour chaque fichier cpp
pour chaque en-tête comprennent
commenter l'inclusion
compiler le fichier cpp
if (compile_errors)
commenter l'en-tête
autre
supprimer l'en-tête include de cpp
Mettez cela dans un cron nocturne, et il devrait faire le travail, en gardant le projet en question sans en-têtes inutilisés (vous pouvez toujours le lancer manuellement, évidemment, mais cela prendra beaucoup de temps). Le seul problème est que le fait de ne pas inclure d’en-tête ne génère pas d’erreur, mais produit toujours du code.
J'ai fait cela manuellement et ça en vaut la peine à court terme (Oh, est-ce le long terme? Cela prend beaucoup de temps) en raison du temps de compilation réduit:
C'est aussi un processus récursif - chaque fichier d'en-tête qui reste dans le fichier doit être examiné pour voir si des fichiers d'en-tête it includes peuvent être supprimés. De plus, vous pouvez parfois remplacer les déclarations en aval par les en-têtes.
Ensuite, tout le processus doit être répété tous les quelques mois/année pour rester au-dessus des en-têtes restants.
En fait, je suis un peu ennuyé par les compilateurs C++, ils devraient pouvoir vous dire ce qui n'est pas nécessaire - le compilateur Microsoft peut vous dire quand une modification d'un fichier d'en-tête peut être ignorée en toute sécurité lors de la compilation.
Si quelqu'un est intéressé, je viens de mettre sur sourceforge un petit outil en ligne de commande Java pour faire exactement cela .. .. Comme il est écrit en Java, il est évidemment utilisable sous Linux.
Le lien pour le projet est https://sourceforge.net/projects/chksem/files/chksem-1.0/