web-dev-qa-db-fra.com

Clang vs GCC pour mon projet de développement Linux

Je suis au collège et pour un projet nous utilisons C. Nous avons exploré GCC et Clang, et Clang semble être beaucoup plus convivial que GCC. En conséquence, je me demande quels sont les avantages ou les inconvénients de l’utilisation de clang, par opposition à GCC, pour le développement en C et C++ sous Linux?

Dans mon cas, cela serait utilisé pour les programmes de niveau étudiant, pas pour la production.

Si j'utilise Clang, dois-je déboguer avec GDB et utiliser GNU Make, ou utiliser un autre débogueur et make utility?

165
haziz

EDIT:

Les gars de gcc ont vraiment amélioré l'expérience de diagnostic dans gcc (ah concurrence). Ils ont créé une page wiki pour la présenter ici . gcc 4.8 dispose maintenant d’un bon diagnostic (gcc 4.9x support de couleurs ajouté). Clang est toujours en tête, mais l'écart se réduit.


Original:

Pour les étudiants, je recommanderais sans réserve Clang.

La performance en termes de code généré entre gcc et Clang est maintenant incertaine (bien que je pense que gcc 4.7 reste en tête, je n’ai pas encore vu de points de repère concluants), mais que les étudiants l’apprennent n’importe quand même pas.

D'autre part, les diagnostics extrêmement clairs de Clang sont nettement plus faciles à interpréter pour les débutants.

Considérez cet extrait simple:

#include <string>
#include <iostream>

struct Student {
std::string surname;
std::string givenname;
}

std::ostream& operator<<(std::ostream& out, Student const& s) {
  return out << "{" << s.surname << ", " << s.givenname << "}";
}

int main() {
  Student me = { "Doe", "John" };
  std::cout << me << "\n";
}

Vous remarquerez tout de suite que le point-virgule est manquant après la définition de la classe Student, n'est-ce pas :)?

Eh bien, gcc le remarque aussi , à la mode:

prog.cpp:9: error: expected initializer before ‘&’ token
prog.cpp: In function ‘int main()’:
prog.cpp:15: error: no match for ‘operator<<’ in ‘std::cout << me’
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:121: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:131: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:169: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:173: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:177: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:97: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:184: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:111: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:195: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:204: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:208: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:213: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:217: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:225: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:229: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:125: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]

Et Clang ne joue pas vraiment ici, mais quand même:

/tmp/webcompile/_25327_1.cc:9:6: error: redefinition of 'ostream' as different kind of symbol
std::ostream& operator<<(std::ostream& out, Student const& s) {
     ^
In file included from /tmp/webcompile/_25327_1.cc:1:
In file included from /usr/include/c++/4.3/string:49:
In file included from /usr/include/c++/4.3/bits/localefwd.h:47:
/usr/include/c++/4.3/iosfwd:134:33: note: previous definition is here
  typedef basic_ostream<char>           ostream;        ///< @isiosfwd
                                        ^
/tmp/webcompile/_25327_1.cc:9:13: error: expected ';' after top level declarator
std::ostream& operator<<(std::ostream& out, Student const& s) {
            ^
            ;
2 errors generated.

J'ai choisi à dessein un exemple qui déclenche un message d'erreur peu clair (provenant d'une ambiguïté de la grammaire) plutôt que les exemples typiques "Oh, mon Dieu, lis mon esprit". Néanmoins, nous remarquons que Clang évite le flot d’erreurs. Pas besoin de faire peur aux étudiants.

111
Matthieu M.

À l'heure actuelle, GCC prend en charge les fonctionnalités C++ 11 de manière bien meilleure et plus complète que Clang. En outre, le générateur de code pour GCC effectue une optimisation supérieure à celle de Clang (selon mon expérience, je n’ai pas vu de tests exhaustifs).

D'autre part, Clang compile souvent le code plus rapidement que GCC et génère de meilleurs messages d'erreur en cas de problème avec votre code.

Le choix de l’utilisation dépend vraiment de ce qui est important pour vous. J'apprécie davantage le support C++ 11 et la qualité de la génération de code que la commodité de la compilation. Pour cette raison, j'utilise GCC. Pour vous, les compromis pourraient être différents.

34
Mankarse

J'utilise les deux parce que parfois ils donnent des messages d'erreur différents et utiles.

Le projet Python a été en mesure de trouver et de réparer un certain nombre de petits boutons lorsque l'un des principaux développeurs a essayé de compiler avec clang.

23
Raymond Hettinger

J'utilise à la fois Clang et GCC, je trouve que Clang a quelques avertissements utiles, mais pour mes propres repères de tracé de rayons - il est toujours 5-15% plus lent que GCC (prenez cela avec un grain de sel de bien sûr, mais a essayé d'utiliser des indicateurs d'optimisation similaires pour les deux).

Donc pour l'instant j'utilise l'analyse statique de Clang et ses avertissements avec des macros complexes: (bien que maintenant les avertissements de GCC soient à peu près aussi bons - gcc4.8 - 4.9).

Quelques considérations:

  • Clang n'a pas de support OpenMP, ça ne compte que si vous en profitez, mais comme je le fais, c'est une limitation pour moi. (*****)
  • La compilation croisée peut ne pas être aussi bien supportée (FreeBSD 10 par exemple utilise toujours GCC4.x pour ARM), gcc-mingw par exemple est disponible sous Linux ... (YMMV).
  • Certains IDE ne supportent pas encore l'analyse de la sortie de Clangs (QtCreator par exemple *****). EDIT: QtCreator supporte maintenant la sortie de Clang
  • Certains aspects de GCC sont mieux documentés et, puisque GCC existe depuis plus longtemps et qu'il est largement utilisé, vous trouverez peut-être plus facile d'obtenir de l'aide pour les avertissements/messages d'erreur.

***** - ces domaines sont en développement actif et pourraient bientôt être pris en charge

10
ideasman42

Pour les programmes de niveau étudiant, Clang présente l'avantage d'être, par défaut, plus strict. le standard C. Par exemple, la version suivante de Hello World K & R est acceptée sans avertissement par GCC, mais rejetée par Clang avec quelques jolis messages d'erreur descriptifs:

main()
{
    puts("Hello, world!");
}

Avec GCC, vous devez lui donner -Werror pour le faire comprendre que ce n’est pas un programme C89 valide. De plus, vous devez toujours utiliser c99 ou gcc -std=c99 pour obtenir le langage C99.

7
Fred Foo

Je pense que Clang pourrait être une alternative.

GCC et clang ont des différences sur des expressions comme a+++++a, et j'ai beaucoup de réponses différentes avec mon pair qui utilise clang sur Mac alors que j'utilise gcc.

GCC est devenu la norme, et Clang pourrait être une alternative. Parce que GCC est très stable et que le son est encore en développement.

3
songziming