Clang vs GCC для моего проекта разработки Linux

Я в колледже, и для проекта мы используем C. Мы изучили GCC и Clang, а Clang, похоже, гораздо удобнее, чем GCC. В результате, мне интересно, какие преимущества или недостатки в использовании clang, в отличие от GCC, для разработки на C и С++ в Linux?

В моем случае это будет использоваться для программ уровня учащихся, а не для производства.

Если я использую Clang, должен ли я отлаживать GDB и использовать GNU Make, или использовать другой отладчик и делать утилиту?

Ответ 1

EDIT:

Ребята из gcc действительно улучшили диагностику в gcc (ah competition). Они создали страницу вики, чтобы продемонстрировать ее здесь. gcc 4.8 теперь имеет неплохую диагностику (добавлена ​​поддержка цвета gcc 4.9x). Кланг все еще лидирует, но разрыв закрывается.


Оригинал:

Для студентов я бы безоговорочно рекомендовал Clang.

Производительность сгенерированного кода между gcc и Clang теперь неясна (хотя я думаю, что gcc 4.7 все еще лидирует, я еще не видел окончательных тестов), но для студентов это не имеет никакого значения..

С другой стороны, Clang чрезвычайно четкая диагностика, безусловно, легче для начинающих интерпретировать.

Рассмотрим этот простой фрагмент:

#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";
}

Вы сразу заметите, что после определения класса Student отсутствует точка с запятой, справа:)?

Ну, gcc замечает это тоже, после мода:

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>]

И Кланг тоже не играет главную роль, но все же:

/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.

Я целенаправленно выбираю пример, который вызывает нечеткое сообщение об ошибке (исходящее из двусмысленности в грамматике), а не типичные примеры "О мой бог Кланг читал мой разум". Тем не менее, мы замечаем, что Clang избегает потопа ошибок. Не нужно пугать студентов.

Ответ 2

Как сейчас, GCC имеет гораздо лучшую и более полную поддержку возможностей С++ 11, чем Clang. Кроме того, генератор кода для GCC обеспечивает лучшую оптимизацию, чем в Clang (по моему опыту, я не видел никаких исчерпывающих тестов).

С другой стороны, Clang часто компилирует код быстрее, чем GCC, и создает лучшие сообщения об ошибках, когда что-то не так с вашим кодом.

Выбор того, какой из них использовать, зависит от того, что для вас важно. Я ценю поддержку С++ 11 и качество генерации кода больше, чем я оцениваю удобство компиляции. Из-за этого я использую GCC. Для вас компромиссы могут быть разными.

Ответ 3

Я использую оба, потому что иногда они дают разные полезные сообщения об ошибках.

Проект Python смог найти и исправить ряд небольших багглов, когда один из основных разработчиков сначала попытался скомпилировать с clang.

Ответ 4

Я использую как Clang, так и GCC, я нахожу, что у Клана есть некоторые полезные предупреждения, но для моих собственных тестов трассировки лучей - он последовательно на 5-15% медленнее, чем GCC (естественно, это с зерном соли, но попытался использовать аналогичные флаги оптимизации для обоих).

Итак, теперь я использую статический анализ Clang и его предупреждения со сложными макросами: (хотя теперь предупреждения GCC в значительной степени хороши - gcc4.8 - 4.9).

Некоторые соображения:

  • У Clang нет поддержки OpenMP, только если вы воспользуетесь этим, но, поскольку я это делаю, это ограничение для меня. (*****)
  • Кросс-компиляция может не поддерживаться (FreeBSD 10, например, все еще использует GCC4.x для ARM), gcc-mingw, например, доступен в Linux... (YMMV).
  • Некоторые IDE еще не поддерживают синтаксический анализ вывода Clangs ( QtCreator, например *****). EDIT: QtCreator теперь поддерживает вывод Clang
  • Некоторые аспекты GCC лучше документируются, и поскольку GCC работает дольше и широко используется, вам может быть легче получить помощь с предупреждениями/сообщениями об ошибках.

***** - эти области находятся в активной разработке и могут вскоре поддерживаться

Ответ 5

Для программ уровня ученика Clang имеет преимущество, которое по умолчанию является более строгим. стандарт C. Например, следующая версия K & R Hello World принимается без предупреждения GCC, но отклоняется Clang с некоторыми довольно описательными сообщениями об ошибке:

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

С GCC вы должны дать ему -Werror, чтобы заставить его действительно указать, что это не действительная программа C89. Кроме того, вам нужно использовать c99 или gcc -std=c99, чтобы получить язык C99.

Ответ 6

Я думаю, что clang может быть альтернативой.

GCC и clang имеют некоторые отличия от выражений типа a+++++a, и у меня есть много разных ответов с моим партнером, который использует clang на Mac, когда я использую gcc.

GCC стал стандартом, и clang может быть альтернативой. Потому что GCC очень стабилен, а clang все еще находится в разработке.