2010-06-04 8 views
3

J'ai une grande base de code que j'ai été chargé de porter sur 64 bits. Le code compile, mais il imprime une très grande quantité d'avertissements de pointeurs incompatibles (comme on peut s'y attendre). Y at-il un moyen pour que gcc imprime la ligne sur laquelle l'erreur se produit? À ce stade, je n'utilise que les messages d'erreur de gcc pour essayer de retrouver les hypothèses qui ont besoin d'être modifiées, et le fait d'avoir à chercher tout le monde n'est pas amusant.Existe-t-il un moyen de faire en sorte que gcc imprime les lignes incriminées lorsqu'il émet une erreur?

+1

... Je suis sûr que GCC * écrit * la ligne et le fichier où il a détecté le problème. (Par exemple, "variant.hpp: 1140: warning: déclaration de 'which' qui masque un membre de 'this'", signifie que l'avertissement est dans le fichier variant.hpp, sur la ligne 1140.) –

Répondre

2

J'ai volé de façon flagrante le answer de Joseph Quinsey pour cela. La seule différence est que j'ai essayé de rendre le code plus facile à comprendre:

Pour bash, utilisez make 2>&1 | show_gcc_line avec show_gcc_line le script suivant:

#!/bin/bash 
# Read and echo each line only if it is an error or warning message 
# The lines printed will start something like "foobar:123:" so that 
# line 123 of file foobar will be printed. 

while read input 
do 
    loc=$(echo "$input" | sed -n 's/^\([^ :]*\):\([0-9]*\):.*/\1 \2/p') 
    len=${#loc} 
    file=${loc% *} 
    line=${loc#* } 

    if [ $len -gt 0 ] 
    then 
     echo "$input" 
     echo "$(sed -n ${line}p $file)" 
     echo 
    fi 
done 

Ce fut en partie parce que je n'ai pas aimé la mise en forme du original. Cela imprime uniquement les avertissements/erreurs, suivi de la ligne de code à l'origine du problème, suivie d'une ligne vide. J'ai également supprimé la chaîne de traits d'union.

+0

+1 Mais peut-être que cela devrait être fait, par exemple, en Python? _Shell_ scripting est apparemment _passe_. –

+0

En général, vous devez utiliser quelque chose comme ** find **, car Makefiles change souvent le répertoire. J'ai _assumed_ que tout est au niveau ou au-dessous du répertoire de premier niveau. –

+0

À moins, bien sûr, que les codeurs de code existants de l'OP aient lu _Recursive Make Considered Harmful_ http://aegis.sourceforge.net/auug97.pdf –

1

Utilisez l'option -W pour contrôler les avertissements que vous souhaitez afficher. ce paramètre a été expliqué here.

vous pouvez également utiliser cette astuce pour supprimer les sorties progressives:

gcc ... 1>/dev/nul 
+0

Eh bien, j'aimerais pouvoir pour voir la ligne source elle-même pour l'erreur. – Alex

0

Au moment où le compilateur émet un message d'erreur, la ligne de source réelle est révolue depuis longtemps, (en particulier en C) - il a été transformé à un flux de jeton, puis à un arbre de syntaxe abstraite, puis à un arbre de syntaxe décoré ... gcc a assez de choses sur sa plaque avec les nombreuses étapes de compilation, donc intentionnellement il n'inclut pas de fonctionnalité pour rouvrir le fichier et re-récupérer le source primaire. C'est ce à quoi servent les éditeurs, et pratiquement tous ont des commandes pour démarrer une compilation et passer à l'erreur suivante à une touche. Faites-vous plaisir et utilisez un éditeur moderne pour parcourir les erreurs (et peut-être même les corriger de manière semi-automatique).

0

Ce petit script devrait fonctionner, mais je ne peux pas le tester maintenant. désolé si besoin modifier.

LAST_ERROR_LINE=`(gcc ... 2>&1 >/dev/null) | grep error | tail -n1` 
FILE=`echo $LAST_ERROR_LINE | cut -f1 -d':'` 
LINE=`echo $LAST_ERROR_LINE | cut -f2 -d':'` 
sed -n "${LINE}p" $FILE 
2

Peut-être qu'un script pour imprimer les lignes souhaitées aiderait. Si vous utilisez csh (! Improbable) utiliser:

make ... |& show_gcc_line 

avec show_gcc_line le script suivant:

#!/bin/csh 
# Read and echo each line. And, if it starts with "foobar:123:", print line 123 
# of foobar, using find(1) to find it, prefaced by ---------------. 

set input="$<" 
while ("$input") 
    echo "$input" 
    set loc=`echo "$input" | sed -n 's/^\([^ :]*\):\([0-9]*\):.*/\1 \2/p'` 
    if ($#loc) then 
     find . -name $loc[1] | xargs sed -n $loc[2]s/^/---------------/p 
    endif 
    set input="$<" 
end 

Et pour bash, utilisez make ... 2>&1 | show_gcc_line avec:

#!/bin/bash 
# Read and echo each line. And, if it starts with "foobar:123:", print line 123 
# of foobar, using find(1) to find it, prefaced by ---------------. 

while read input 
do 
    echo "$input" 
    loc=$(echo "$input" | sed -n 's/^\([^ :]*\):\([0-9]*\):.*/\1 \2/p') 
    if [ ${#loc} -gt 0 ] 
    then 
     find . -name ${loc% *} | xargs sed -n ${loc#* }s/^/---------------/p 
    fi 
done 
0

Pour moi, le symbole de la redirection des messages d'erreur est difficile à retenir.

Donc, voici ma version à imprimer sur gcc messages d'erreur:

$ee make 

pour les messages d'erreur et d'avertissement:

ee2 make 

Comment: ajouter ceux-ci dans.bashrc

function ee() { 
    $* 2>&1 | grep error 
} 

function ee2() { 
    $* 2> ha 
    echo "-----" 
    echo "Error" 
    echo "-----" 
    grep error ha 
    echo "-------" 
    echo "Warning" 
    echo "-------" 
    grep warning ha 
}