Dentang vs GCC untuk proyek Pengembangan Linux saya

175

Saya kuliah, dan untuk sebuah proyek kami menggunakan C. Kami telah menjelajahi GCC dan Dentang, dan Dentang tampaknya jauh lebih ramah pengguna daripada GCC. Akibatnya, saya bertanya-tanya apa keuntungan atau kerugian menggunakan clang, berbeda dengan GCC, untuk pengembangan di C dan C ++ di Linux?

Dalam kasus saya ini akan digunakan untuk program tingkat siswa, bukan produksi.

Jika saya menggunakan Dentang, haruskah saya men-debug dengan GDB dan menggunakan GNU Make, atau menggunakan debugger lain dan membuat utilitas?

Haziz
sumber
7
Sejauh yang saya tahu, Clang masih jauh dari "dewasa", terutama mengenai dukungan perpustakaan standar. Meskipun demikian, ia memiliki pesan kesalahan yang fantastis, sehingga Anda selalu dapat mendekati kesalahan kompiler misterius dengan mencoba kode di Dentang. Dentang juga dapat mengkompilasi C ++ ke C, saya percaya.
Kerrek SB
3
@ GerrekSB: elemen apa dari "dukungan perpustakaan standar" yang hilang dari dentang?
Stephen Canon
2
@StephenCanon: Terakhir kali saya mencobanya, saya harus menggunakan libstdc ++ (yang bukan bagian dari Dentang sejauh yang saya mengerti). Dan beberapa hari yang lalu kami mengalami masalah ini . Lagi pula, saya tidak mengikuti tepi pendarahan, jadi pandangan saya mungkin sepenuhnya usang.
Kerrek SB
4
@ GerrekSB: Mengenai tautan Anda, Dentang tidak berfungsi pada Windows murni. Ia bekerja di MinGW. Mengenai perpustakaan standar, tidak ada bagian perpustakaan standar nyata dentang saat ini. Dentang dibundel dengan libc ++ pada OSX, namun libc ++ tidak sepenuhnya porting di lingkungan lain, sehingga pada dentang tersebut perlu implementasi Perpustakaan Standar lain untuk diinstal. Di Linux, libstdc ++ berfungsi.
Matthieu M.
1
@ GerrekSB: C ++ 98 didukung 100%. C ++ 11 sebagian besar didukung (terakhir saya periksa, <atomic>tidak didukung, mungkin beberapa hal kecil lainnya hilang ... Saya tidak dapat menggunakannya, jadi saya tidak sepenuhnya dapat mempercepatnya).
James McNellis

Jawaban:

122

EDIT:

Orang-orang gcc benar-benar meningkatkan pengalaman diagnosis dalam gcc (kompetisi ah). Mereka membuat halaman wiki untuk memamerkannya di sini . gcc 4.8 sekarang memiliki diagnostik yang cukup baik (gcc 4.9x menambahkan dukungan warna). Dentang masih memimpin, tetapi celahnya semakin dekat.


Asli:

Untuk siswa, saya akan merekomendasikan Dentang tanpa syarat.

Kinerja dalam hal kode yang dihasilkan antara gcc dan Clang sekarang tidak jelas (meskipun saya pikir gcc 4.7 masih memiliki petunjuk, saya belum melihat tolok ukur konklusif), tetapi bagi siswa untuk mempelajarinya tidak terlalu penting.

Di sisi lain, diagnostik Clang yang sangat jernih jelas lebih mudah bagi para pemula untuk menafsirkannya.

Pertimbangkan cuplikan sederhana ini:

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

Anda akan segera melihat bahwa titik koma hilang setelah definisi Studentkelas, benar :)?

Nah, gcc memperhatikannya juga , setelah 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>]

Dan Dentang juga tidak benar-benar dibintangi di sini, tetapi tetap:

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

Saya sengaja memilih contoh yang memicu pesan kesalahan yang tidak jelas (berasal dari ambiguitas dalam tata bahasa) daripada contoh "Oh my god Clang read my mind" contoh. Namun, kami melihat bahwa Dentang menghindari banjir kesalahan. Tidak perlu menakuti siswa.

Matthieu M.
sumber
2
Um ... terakhir kali saya memeriksa, saya membaca sebuah artikel yang menerbitkan berbagai tolok ukur di mana dentang cukup banyak meniup gcc dari air dalam tes yang pernah. Sumber: clang.llvm.org/features.html#performance
31
@AscensionSystems: berhati-hatilah, tes-tes itu menunjukkan kinerja biner Dentang itu sendiri (dan itu beberapa waktu yang lalu), bukan kinerja biner yang Anda kompilasi.
Matthieu M.
Itu poin yang baik saya akan tertarik untuk melihat perbandingan berdiri antara executable dikompilasi. Saya mendapat kesan bahwa dentang melakukan pekerjaan yang lebih baik pada pengoptimalan tapi saya belum benar-benar melihat adanya tolok ukur. Saya akan mengeceknya.
4
@AscensionSystems: di sini adalah bangku terbaru yang saya tahu membandingkan gcc 4,6 sampai llvm 3.0 yang menunjukkan keuntungan bersih rata-rata gcc. Yang juga menarik adalah bangku DragonEgg , DragonEgg adalah sebuah plugin yang memungkinkan penggunaan front-end gcc (dan mungkin pengoptimal) dan kemudian backend LLVM untuk menghasilkan kode.
Matthieu M.
1
Terakhir kali saya memeriksa, tolok ukur phoronix sangat tidak dapat dipercaya: bendera kompiler tidak didokumentasikan dengan baik, tetapi hasilnya menyarankan hal-hal yang tidak diatur dengan benar.
Eamon Nerbonne
35

Sampai sekarang, GCC memiliki dukungan yang jauh lebih baik dan lebih lengkap untuk fitur C ++ 11 daripada Dentang. Juga, pembuat kode untuk GCC melakukan optimasi yang lebih baik daripada yang ada di Dentang (dalam pengalaman saya, saya belum melihat tes lengkap).

Di sisi lain, Dentang sering mengkompilasi kode lebih cepat dari GCC, dan menghasilkan pesan kesalahan yang lebih baik ketika ada sesuatu yang salah dengan kode Anda.

Pilihan mana yang akan digunakan benar-benar tergantung pada hal-hal apa yang penting bagi Anda. Saya menghargai dukungan C ++ 11 dan kualitas pembuatan kode lebih dari saya menghargai kenyamanan kompilasi. Karena itu, saya menggunakan GCC. Bagi Anda, pengorbanannya bisa berbeda.

Mankarse
sumber
3
Berikut ini adalah artikel Phoronix terbaru yang membandingkan GCC 4.6 vs Clang 3.0 serta artikel sebelumnya yang khusus untuk platform bulldozer. Tergantung pada tolok ukurnya, pemenangnya adalah satu atau yang lain (pada artikel sebelumnya, gcc 4.7 juga muncul), jadi saya pribadi merasa tidak jelas mana yang berkinerja lebih baik.
Matthieu M.
Mengapa tidak menggunakan keduanya? Dentang untuk pengembangan, dan GCC untuk produksi.
Segfault
5
@segfault: Itulah yang saya lakukan saat ini. Jawaban ini sudah cukup lama, dan tidak lagi sepenuhnya benar. Baik Dentang dan GCC telah meningkat secara signifikan sejak saya menulisnya (khususnya, Dentang sekarang cocok dengan GCC keseluruhan dukungan C ++ 11, dan GCC telah meningkatkan pesan kesalahan dan kecepatan kompilasi). Sekarang saya akan menyarankan menggunakan keduanya, dengan sedikit preferensi terhadap Dentang karena kode sumber Dentang jauh lebih mudah dipahami daripada sumber GCC.
Mankarse
23

Saya menggunakan keduanya karena kadang-kadang mereka memberikan pesan kesalahan yang berbeda dan bermanfaat.

Proyek Python dapat menemukan dan memperbaiki sejumlah buglets kecil ketika salah satu pengembang inti pertama kali mencoba kompilasi dengan dentang.

Raymond Hettinger
sumber
1
Apa pendapat Anda tentang menggunakan dentang untuk debug build tetapi gcc untuk rilis yang dioptimalkan?
Olical
5
Masuk akal untuk mengembangkan dengan Dentang dan rilis dengan GCC, tetapi pastikan rilis GCC Anda melewati suite pengujian Anda (baik dengan dan tanpa NDEBUG).
Raymond Hettinger
2
Terima kasih atas tanggapannya. Saya telah mencobanya sebentar dan ini bekerja dengan sangat baik. Saya juga mendapat serangkaian peringatan berbeda, yang sangat bagus.
Olical
11

Saya menggunakan Clang dan GCC, saya menemukan Clang memiliki beberapa peringatan yang berguna, tetapi untuk tolok ukur ray-tracing saya sendiri - secara konsisten 5-15% lebih lambat dari GCC (mengambilnya dengan butiran garam tentu saja, tetapi mencoba menggunakan flag optimasi yang serupa untuk keduanya).

Jadi untuk saat ini saya menggunakan analisis statis Dentang dan peringatannya dengan makro kompleks: (meskipun sekarang peringatan GCC hampir sama baiknya - gcc4.8 - 4.9).

Beberapa pertimbangan:

  • Dentang tidak memiliki dukungan OpenMP, hanya masalah jika Anda mengambil keuntungan dari itu tetapi karena saya lakukan, itu adalah batasan bagi saya. (*****)
  • Kompilasi silang mungkin tidak didukung dengan baik (FreeBSD 10 misalnya masih menggunakan GCC4.x untuk ARM), gcc-mingw misalnya tersedia di Linux ... (YMMV).
  • Beberapa IDE belum mendukung parsing output Clangs ( QtCreator misalnya *****). EDIT: QtCreator sekarang mendukung output Dentang
  • Beberapa aspek GCC didokumentasikan lebih baik dan karena GCC telah ada lebih lama dan banyak digunakan, Anda mungkin merasa lebih mudah untuk mendapatkan bantuan dengan peringatan / pesan kesalahan.

***** - area ini dalam pengembangan aktif dan mungkin segera didukung

gagasanman42
sumber
Saya menggunakan OpenMP juga tetapi saya berpikir untuk beralih ke TBB yang saya kira akan bekerja dengan Dentang.
1
TBB mungkin menjadi alternatif yang layak untuk OpenMP dalam beberapa kasus (tetapi hanya untuk C ++ sejauh yang saya tahu), karena C tidak didukung - juga untuk proyek-proyek besar, beralih dari OpenMP ke sesuatu yang lain mungkin tidak bermanfaat terutama jika Clang akhirnya akan tetap mendukung OpenMP.
ideasman42
7

Untuk program tingkat siswa, Dentang memiliki manfaat, secara default, wrt ketat. standar C. Misalnya, versi K&R Hello World berikut diterima tanpa peringatan oleh GCC, tetapi ditolak oleh Dentang dengan beberapa pesan kesalahan yang cukup deskriptif:

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

Dengan GCC, Anda harus memberikannya -Werroragar benar-benar menunjukkan bahwa ini bukan program C89 yang valid. Selain itu, Anda masih perlu menggunakan c99atau gcc -std=c99untuk mendapatkan bahasa C99.

Fred Foo
sumber
8
gccumumnya harus dipanggil dengan paling tidak -Wall, yang memang memperingatkan untuk program ini. clangtidak menghasilkan peringatan / kesalahan yang baik.
caf
2
@caf: tepatnya yang ingin saya sampaikan, dengan GCC Anda harus memberikan opsi. Di luar kotak, mungkin terlalu toleran untuk tujuan pengajaran.
Fred Foo
Itu mungkin benar, tapi itu poin yang cukup kecil. Yang lebih penting adalah kualitas pesan kesalahan. GCC 4.6 sudah cukup bagus, meskipun saya mengerti bahwa dentang melakukan beberapa sihir nyata di sana.
Kerrek SB
2
@dreamlax: Benar; ada juga gnu99, dan gnu++98dan gnu++0x. Saya pikir itu adalah ekstensi asli , meskipun, yaitu mereka akan mengkompilasi sesuai kode standar ISO tanpa hambatan. Berikut detailnya: untuk C , untuk C ++ .
Kerrek SB
1
Program ini seharusnya tidak menghasilkan kesalahan atau peringatan. Ini sesuai dengan standar.
Miles Rout
3

Saya pikir dentang bisa menjadi alternatif.

GCC dan dentang memiliki beberapa perbedaan pada ekspresi seperti a+++++a , dan saya punya banyak jawaban berbeda dengan rekan saya yang menggunakan dentang di Mac sementara saya menggunakan gcc.

GCC telah menjadi standar, dan dentang bisa menjadi alternatif. Karena GCC sangat stabil dan dentang masih dalam pengembangan.

songziming
sumber
5
Dentang cepat bersiap untuk menggantikan GCC sepenuhnya di dunia Linux, dan sebagian besar telah melakukannya di dunia BSD. Itu menggantikan GCC pada Mac tahun yang lalu. Dentang adalah hal yang baik. Saya pikir GCC bisa menjadi alternatif, secara pribadi, dan saya akan senang tentang itu.
coder543
5
Ekspresi a +++++ a tidak terdefinisi sehingga diharapkan untuk mendapatkan jawaban yang berbeda pada setiap kompiler, atau bahkan pada versi berbeda dari kompiler yang sama. Anda bahkan bisa mendapatkan hasil berbeda untuk ekspresi itu di kompiler yang sama ketika dikompilasi pada waktu yang berbeda. Itulah yang dimaksud "tidak terdefinisi".
Lelanthran
1
a+++++aharus gagal, karena diuraikan sebagai a ++ ++ + akesalahan sintaks.
Miles Rout
@Lanthanthran bukan itu artinya tidak terdefinisi. Ini memiliki perilaku yang tidak terdefinisi sehingga kompiler dapat gagal mengkompilasi, atau dapat membuang saat runtime atau mengunci CPU sehingga Anda perlu melakukan hard reset atau sesuatu yang bahkan lebih menyeramkan.
Antti Haapala