Linux Geliştirme projem için Clang vs GCC


175

Üniversitedeyim ve bir proje için C kullanıyoruz. GCC ve Clang'ı keşfettik ve Clang GCC'den çok daha kullanıcı dostu görünüyor. Sonuç olarak, Linux'ta C ve C ++ 'da geliştirmek için GCC'nin aksine clang kullanmanın avantajlarının veya dezavantajlarının ne olduğunu merak ediyorum?

Benim durumumda bu, üretim değil öğrenci düzeyindeki programlar için kullanılacaktı.

Clang kullanırsam GDB ile hata ayıklamalı ve GNU Make kullanmalı mıyım, yoksa başka bir hata ayıklayıcı ve yardımcı program mı kullanmalıyım?


7
Anlayabildiğim kadarıyla, Clang hala "olgun" olmaktan uzak, özellikle standart kütüphane desteği konusunda. Yine de, harika hata mesajları vardır, bu yüzden her zaman gizemli bir derleyici hatasına Clang'daki kodu deneyerek yaklaşabilirsiniz. Clang ayrıca C ++ 'dan C' ye kadar derleyebilir.
Kerrek SB

3
@KerrekSB: clang'da "standart kütüphane desteği" nin hangi öğesi eksik?
Stephen Canon

2
@StephenCanon: En son denediğimde, libstdc ++ kullanmak zorunda kaldım (ki anladığım kadarıyla Clang'ın bir parçası değil). Ve geçen gün bu sorunu yaşadık . Her neyse, kanayan kenarı takip etmiyorum, bu yüzden benim görüşüm tamamen eski olabilir.
Kerrek SB

4
@KerrekSB: Bağlantınızla ilgili olarak, Clang saf Windows üzerinde çalışmaz. Olsa da MinGW çalışır. Standart kütüphane ile ilgili olarak, şu anda Clang'ın gerçek standart kütüphane kısmı yoktur. Clang, OSX'te libc ++ ile birlikte gelir, ancak libc ++ diğer ortamlarda tam olarak taşınmaz, bu nedenle bu Clang'da başka bir Standart Kitaplık uygulamasının yüklenmesi gerekir. Linux'ta libstdc ++ çalışır.
Matthieu M.

1
@KerrekSB: C ++ 98% 100 desteklenmektedir. C ++ 11 çoğunlukla desteklenir (son kontrol ettim, <atomic>desteklenmiyor, belki de bazı küçük şeyler eksik ... Kullanamıyorum, bu yüzden tamamen onunla hızlanmıyorum).
James McNellis

Yanıtlar:


122

DÜZENLE:

Gcc çocuklar gcc'deki tanı deneyimini gerçekten geliştirdi (rekabet). Burada sergilemek için bir wiki sayfası oluşturdular . gcc 4.8 artık oldukça iyi bir tanılamaya sahip (gcc 4.9x renk desteği eklendi). Clang hala önde gidiyor, ancak boşluk kapanıyor.


Orijinal:

Öğrenciler için koşulsuz olarak Clang'ı tavsiye ederim.

Gcc ve Clang arasında üretilen kod açısından performans şimdi belirsizdir (gcc 4.7'nin hala öncü olduğunu düşünüyorum, ancak henüz kesin kriterler görmedim), ancak öğrencilerin öğrenmesi için zaten önemli değil.

Öte yandan, Clang'ın son derece net teşhisi yeni başlayanlar için kesinlikle daha kolaydır.

Bu basit snippet'i düşünün:

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

StudentSınıfın tanımından sonra noktalı virgülün eksik olduğunu hemen fark edeceksiniz , değil mi?

Eh, gcc de bunu fark şöyle böyle,:

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

Clang da burada tam olarak oynamıyor, ama yine de:

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

Kasten tipik "Oh tanrım Clang aklımı oku" örneklerinden ziyade belirsiz bir hata mesajını (gramerdeki bir belirsizlikten geliyor) tetikleyen bir örnek seçiyorum. Yine de, Clang'ın hatalardan kaçındığını fark ediyoruz. Öğrencileri korkutmaya gerek yok.


2
Um ... en son kontrol ettiğimde, clang'ın testte sudan gcc'yi uçurduğu çeşitli kriterler yayınlayan bir makale okudum. Kaynak: clang.llvm.org/features.html#performance

31
@AscensionSystems: dikkat edin, bu testler Clang ikili dosyasının (ve bir süre önce) performansını gösterir, derlediğiniz ikili sistemin performansını değil.
Matthieu M.8

Derlenmiş yürütülebilir dosyalar arasında bir stand-up karşılaştırması görmek iyi bir nokta. Clang'ın optimizasyonda çok daha iyi bir iş çıkardığı izlenimindeyim ama aslında herhangi bir kriter görmedim. Kontrol edeceğim.

4
@AscensionSystems: gcc 4.6 ile ortalama gcc'nin net bir avantajını gösteren gcc 4.6'yı llvm 3.0 ile karşılaştırmanın farkında olduğum en son tezgah . DragonEgg tezgahı da ilginç olabilir , DragonEgg, kodu oluşturmak için gcc ön ucunun (ve muhtemelen optimize edici) ve daha sonra LLVM arka ucunun kullanılmasına izin veren bir eklentidir.
Matthieu M.8

1
En son kontrol ettiğimde, phoronix kriterleri çok güvenilmezdi: derleyici bayrakları düzgün bir şekilde belgelenmedi, ancak sonuçlar, şeylerin düzgün bir şekilde ayarlanmadığını önerdi.
Eamon Nerbonne

35

Şu an itibariyle, GCC, Clang 11 özellikleri için Clang'dan çok daha iyi ve daha eksiksiz bir desteğe sahip. Ayrıca, GCC için kod üreteci Clang'dakinden daha iyi optimizasyon gerçekleştirir (benim deneyimime göre, kapsamlı testler görmedim).

Öte yandan, Clang genellikle kodu GCC'den daha hızlı derler ve kodunuzda bir sorun olduğunda daha iyi hata mesajları üretir.

Hangisini kullanacağınız seçimi sizin için önemli olan şeylere bağlıdır. C ++ 11 desteğine ve kod oluşturma kalitesine değer veri derlemeden daha fazla değer veriyorum. Bu nedenle GCC kullanıyorum. Sizin için ödünleşmeler farklı olabilir.


3
İşte GCC 4.6 vs Clang 3.0 ve buldozer platformuna özgü bir önceki makaleyi karşılaştıran en son Phoronix makalesi . Karşılaştırma ölçütlerine bağlı olarak, kazanan ya biri ya da diğeri (önceki makalede, gcc 4.7 de görünüyor), bu yüzden kişisel olarak hangisinin daha iyi performans gösterdiğini net değilim.
Matthieu M.

Neden her ikisini de kullanmıyorsunuz? Geliştirme için Clang ve üretim için GCC.
segfault

5
@segfault: Şu anda bunu yapıyorum. Bu cevap oldukça eskidir ve artık tamamen doğru değildir. Clang ve GCC, yazdığımdan beri önemli ölçüde iyileşti (özellikle, Clang artık GCC genel C ++ 11 desteğiyle eşleşiyor ve GCC hata mesajlarını ve derleme hızını geliştirdi). Şimdi, Clang kaynak kodunu anlamak GCC kaynağından çok daha kolay olduğu için her ikisini de kullanmanızı öneririm.
Mankarse

23

İkisini de kullanıyorum çünkü bazen farklı, faydalı hata mesajları veriyorlar.

Python projesi, çekirdek geliştiricilerden biri ilk kez clang ile derlemeyi denediğinde bir dizi küçük mermi bulabildi ve düzeltebildi.


1
Hata ayıklama sürümleri için clang, optimize sürümler için gcc kullanma hakkındaki düşünceleriniz nelerdir?
Olical

5
Clang ile geliştirmek ve GCC ile serbest bırakmak mantıklıdır, ancak GCC sürümünüzün test paketinizi geçtiğinden emin olun (hem NDEBUG ile hem de NDEBUG olmadan).
Raymond Hettinger

2
Yanıt için teşekkürler. Biraz deniyorum ve gerçekten iyi çalışıyor. Farklı uyarılar da alıyorum, bu harika.
Olical

11

Hem Clang hem de GCC kullanıyorum, Clang'ın bazı yararlı uyarıları olduğunu düşünüyorum, ancak kendi ışın izleme kriterlerim için - GCC'den sonra sürekli olarak% 5-15 daha yavaş (tabii ki tuz tanesi ile alın, ancak benzer optimizasyon bayraklarını kullanmaya çalıştı) her ikisi için).

Şimdilik Clang statik analizini ve uyarılarını karmaşık makrolarla kullanıyorum: (şimdi GCC'nin uyarıları neredeyse iyi - gcc4.8 - 4.9).

Bazı düşünceler:

  • Clang'ın OpenMP desteği yoktur, sadece bundan faydalanırsanız önemlidir, ancak yaptığımdan beri benim için bir sınırlama. (*****)
  • Çapraz derleme iyi desteklenmeyebilir (örneğin FreeBSD 10 hala ARM için GCC4.x kullanır), örneğin gcc-mingw Linux'ta kullanılabilir ... (YMMV).
  • Bazı IDE'ler henüz Clangs çıktısının ayrıştırılmasını desteklemez ( örneğin, QtCreator *****). EDIT: QtCreator artık Clang çıktısını destekliyor
  • GCC'nin bazı yönleri daha iyi belgelenmiştir ve GCC daha uzun süredir etrafta bulunduğundan ve yaygın olarak kullanıldığından, uyarı / hata mesajlarıyla ilgili yardım almayı daha kolay bulabilirsiniz.

***** - bu alanlar aktif olarak geliştirilmektedir ve yakında desteklenecektir


Ben de OpenMP kullanıyorum ama Clang ile çalışacağını tahmin TBB geçiş düşünüyorum.

1
TBB, bazı durumlarda OpenMP için uygun bir alternatif olabilir (ancak sadece anlayabildiğim kadarıyla C ++ için), C için desteklenmez - ayrıca büyük projeler için, OpenMP'den başka bir şeye geçmek özellikle Clang sonunda olacaksa zaten OpenMP desteği.
ideasman42

7

Öğrenci düzeyindeki programlar için, Clang, varsayılan olarak daha katı wrt olma avantajına sahiptir. C standardı. Örneğin, Hello World'ün aşağıdaki K&R sürümü GCC tarafından uyarı yapılmaksızın kabul edilir, ancak Clang tarafından bazı açıklayıcı hata mesajları ile reddedilir:

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

GCC ile, bunun -Werrorgeçerli bir C89 programı olmadığı konusunda gerçekten bir noktaya gelmesini sağlamak için vermelisiniz . Ayrıca, hala C99 dilini kullanmanız c99veya gcc -std=c99almanız gerekir .


8
gccgenellikle en azından -Wallbu program için uyarır. clangyine de iyi uyarılar / hatalar üretir.
caf

2
@caf: tam olarak yapmaya çalıştığım nokta bu, GCC ile seçenekleri geçmek zorundasınız. Kutudan çıkarıldığında, öğretim amaçları için çok toleranslı olabilir.
Fred Foo

Bu doğru olabilir, ancak oldukça küçük bir nokta. Daha da önemlisi, hata mesajlarının kalitesidir . GCC 4.6 oldukça iyi oldu, ancak clang'ın orada gerçek bir sihir yaptığını anlıyorum.
Kerrek SB

2
@dreamlax: Doğru; ayrıca var gnu99ve gnu++98ve gnu++0x. Bence bunlar gerçek uzantılar , yani, bir ISO olmadan standart ISO kodunu derleyecekler. İşte detaylar: C , C ++ .
Kerrek SB

1
Bu program hata veya uyarı vermemelidir. Standarda uygundur.
Miles Rout

3

Bence clang bir alternatif olabilir.

GCC ve clang gibi ifadelerde bazı farklılıklar a+++++avar ve gcc kullanırken Mac'te clang kullanan akranımla birçok farklı cevabım var.

GCC standart haline geldi ve clang bir alternatif olabilir. Çünkü GCC çok kararlı ve clang hala gelişmekte.


5
Clang hızla Linux dünyasında GCC'nin yerini almaya hazırlanıyor ve bunu büyük ölçüde BSD dünyasında yaptı. Yıllar önce Mac'te GCC'nin yerini aldı. Clang iyi şeyler. Bence GCC kişisel olarak alternatif olabilir ve bundan memnun olurum.
coder543

5
A +++++ a ifadesi tanımsızdır, bu nedenle her derleyicide veya hatta aynı derleyicinin farklı sürümlerinde farklı bir yanıt almayı bekleyin. Farklı zamanlarda derlendiğinde aynı derleyicide bu ifade için farklı sonuçlar bile alabilirsiniz. "Tanımsız" demek budur.
Lelanthran

1
a+++++aa ++ ++ + asözdizimi hatası olarak ayrıştırıldığı için başarısız olmalıdır .
Miles Rout

@Lelanthran undefined demek değildir. Tanımlanmamış davranışa sahiptir, böylece derleyici bunu derleyemez veya çalışma zamanında fırlatabilir veya CPU'yu kilitleyebilir, böylece sabit sıfırlama veya daha da kötü bir şey yapmanız gerekir.
Antti Haapala
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.