it-swarm.com.ru

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

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

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

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

161
haziz

EDIT:

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


Оригинал:

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

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

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

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

#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 избегает потока ошибок. Не нужно пугать учеников.

110
Matthieu M.

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

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

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

34
Mankarse

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

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

23
Raymond Hettinger

Я использую и Clang, и GCC, и я обнаружил, что у Clang есть несколько полезных предупреждений, но для моих собственных тестов трассировки лучей - он на 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 существует дольше и широко используется, вам может оказаться проще получить помощь с предупреждениями/сообщениями об ошибках.

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

10
ideasman42

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

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

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

7
Fred Foo

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

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

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

3
songziming