Linux開発プロジェクトのClangとGCC


175

私は大学にいます。プロジェクトではCを使用しています。GCCとClangを調査してきましたが、ClangはGCCよりもはるかにユーザーフレンドリーであるようです。結果として、LinuxのCおよびC ++で開発するために、GCCではなくclangを使用することの利点または欠点は何ですか?

私の場合、これは制作ではなく、学生レベルのプログラムに使用されます。

Clangを使用する場合、GDBでデバッグしてGNU Makeを使用する必要がありますか、それとも別のデバッガーとmakeユーティリティを使用する必要がありますか?


7
私の知る限り、Clangは、特に標準ライブラリのサポートに関しては、まだ「成熟」していません。それにもかかわらず、それは素晴らしいエラーメッセージを持っているので、Clangでコードを試すことにより、いつでも神秘的なコンパイラエラーにアプローチできます。ClangはC ++をCにコンパイルすることもできると思います。
Kerrek SB、2011

3
@KerrekSB:「標準ライブラリサポート」のどの要素がclangにありませんか?
スティーブンキャノン

2
@StephenCanon:前回試したときは、libstdc ++を使用する必要がありました(私の知る限り、これはClangの一部ではありません)。そして先日、この問題が発生しました。とにかく、私は最先端をたどっていないので、私の見解は完全に時代遅れになっているかもしれません。
Kerrek SB、2011

4
@KerrekSB:リンクに関して、Clangは純粋なWindowsでは機能しません。MinGWでも動作します。標準ライブラリに関しては、現時点ではClangの実際の標準ライブラリ部分はありません。ClangはOSXのlibc ++にバンドルされていますが、libc ++は他の環境では完全に移植されていないため、これらのClangには別の標準ライブラリの実装をインストールする必要があります。Linuxでは、libstdc ++が機能します。
Matthieu M.

1
@KerrekSB:C ++ 98は100%サポートされています。C ++ 11はほとんどサポートされています(最後にチェックした、<atomic>サポートされていない、おそらく他のいくつかの小さなものが欠けています...私はそれを使用できないので、完全にスピードアップしていません)。
James McNellis、

回答:


122

編集:

gccの連中は、gcc(競合)での診断エクスペリエンスを本当に改善しました。彼らはここにそれを紹介するウィキページを作成しました。gcc 4.8にも非常に優れた診断機能が追加されました(gcc 4.9xがカラーサポートを追加)。Clangは引き続きリードしていますが、ギャップは縮小しています。


元の:

学生には無条件に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>]

そして、Clangもここで主演しているわけではありませんが、それでも:

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

私は意図的に、典型的な "Oh my god Clang read my mind"の例ではなく、不明確なエラーメッセージ(文法のあいまいさが原因)をトリガーする例を選択します。それでも、Clangはエラーのフラッドを回避していることがわかります。生徒を怖がらせる必要はありません。


2
えっと...前回チェックしたとき、clangがこれまでのテストでgccをかなり吹き飛ばしたさまざまなベンチマークを公開した記事を読みました。出典:clang.llvm.org/features.html#performance

31
@AscensionSystems:注意してください。これらのテストはClangバイナリ自体のパフォーマンスを示します(これは少し前のことです)。コンパイルしていたバイナリのパフォーマンスではありません。
Matthieu M.

これは、コンパイルされた実行可能ファイル間の比較を確認するのに興味があると思います。私はclangが最適化ではるかに良い仕事をしているように見えますが、実際にはベンチマークを見ていません。確かめます。

4
@AscensionSystems:gcc 4.6とllvm 3.0を比較していることがわかっている最新のベンチは、平均してgccの正味の利点を示しています。DragonEggベンチも興味深いかもしれません。DragonEggは、gccフロントエンド(およびおそらくオプティマイザ)を使用してLLVMバックエンドを使用してコードを生成できるプラグインです。
Matthieu M.

1
前回チェックしたとき、phoronixベンチマークは非常に信頼できませんでした。コンパイラフラグは適切に文書化されていませんでしたが、結果は物事が適切に設定されていないことを示唆しています。
イーモンネルボンヌ、2012

35

現在、GCCはClang11よりもはるかに優れたC ++ 11機能を完全にサポートしています。また、GCCのコードジェネレーターは、Clangのコードジェネレーターよりも優れた最適化を実行します(私の経験では、徹底的なテストは見ていません)。

一方、Clangは多くの場合、GCCよりも速くコードをコンパイルし、コードに問題がある場合により適切なエラーメッセージを生成します。

どちらを使用するかは、実際には何が重要かによって異なります。コンパイルの利便性よりも、C ++ 11のサポートとコード生成の品質を重視しています。このため、GCCを使用しています。あなたにとっては、トレードオフが異なる場合があります。


3
これは、GCC 4.6とClang 3.0を比較した最新のPhoronix記事と、ブルドーザープラットフォームに固有の以前の記事です。ベンチマークに応じて、どちらかがどちらかが勝者になる(前の記事では、gcc 4.7も表示されている)ので、どちらが優れているかははっきりしません。
Matthieu M.11年

なぜ両方使用しないのですか?開発にはClang、本番にはGCC。
segfault 2013年

5
@segfault:それは私が現在やっていることです。この答えはかなり古く、もはや完全に真実ではありません。私が書いて以来、ClangとGCCの両方が大幅に改善されました(特に、ClangはGCC全体のC ++ 11サポートと一致し、GCCはエラーメッセージとコンパイル速度を改善しました)。ClangのソースコードはGCCソースよりもはるかに理解しやすいため、Clangを少し優先して両方を使用することをお勧めします。
Mankarse 2013年

23

私は両方を使用します。それらは時々、異なる有用なエラーメッセージを与えるからです。

Pythonプロジェクトは、コア開発者の1人が最初にclangを使用してコンパイルしようとしたときに、いくつかの小さなバグレットを見つけて修正することができました。


1
デバッグビルドにはclangを使用し、最適化リリースにはgccを使用することについてどう思いますか?
Olical

5
Clangで開発し、GCCでリリースすることは妥当ですが、GCCリリースがテストスイート(NDEBUGの有無にかかわらず)に合格することを確認してください。
レイモンドヘッティンガー

2
ご返信ありがとうございます。私はそれを少しの間試しました、そしてそれは本当にうまくいきます。さまざまな警告のセットも表示されます。これは素晴らしいことです。
Olical

11

私はClangとGCCの両方を使用していますが、Clangにはいくつかの有用な警告がありますが、私自身のレイトレーシングベンチマークでは、GCCよりも常に5〜15%遅くなっています(もちろん、Grain of Saltを使用しますが、同様の最適化フラグを使用しようとしました)両方のための)。

そのため、今のところ、Clang静的分析とその警告を複雑なマクロで使用しています(ただし、GCCの警告はほぼ同じですが、gcc4.8-4.9)。

いくつかの考慮事項:

  • ClangはOpenMPをサポートしていません。それを利用する場合にのみ問題になりますが、私が使用しているため、制限があります。(*****)
  • クロスコンパイルはサポートされていない可能性があります(たとえば、FreeBSD 10はまだARMのGCC4.xを使用しています)。たとえば、gcc-mingwはLinux ...(YMMV)で使用できます。
  • 一部のIDEは、Clangs出力の解析をまだサポートしていません(例: *****)。編集:QtCreatorがClangの出力をサポートするようになりました
  • GCCの一部の側面はより適切に文書化されており、GCCは古くから存在し、広く使用されているため、警告/エラーメッセージのヘルプを取得する方が簡単な場合があります。

*****- これらの領域は活発に開発されており、まもなくサポートされる可能性があります


私もOpenMPを使用していますが、Clangで動作すると思うTBBに切り替えることを考えています。

1
TBBはOpenMPの実行可能な代替手段になる場合があります(ただし、私の知る限りC ++の場合のみ)。Cはサポートされていません。また、大規模なプロジェクトの場合、OpenMPから他の何かに切り替えることは、特にClangが最終的には価値がない場合があります。とにかくOpenMPをサポートします。
ideasman42

7

学生レベルのプログラムの場合、Clangにはデフォルトでより厳密なwrtであるという利点があります。C標準。たとえば、次のK&RバージョンのHello WorldはGCCからの警告なしに受け入れられますが、Clangによってかなり説明的なエラーメッセージで拒否されます。

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

GCCでは、-Werrorこれを有効にして、これが有効なC89プログラムではないことを実際に主張する必要があります。また、C99言語を使用するc99gcc -std=c99取得する必要があります。


8
gcc通常、少なくとも-Wallで起動する必要があります。これは、このプログラムに対して警告します。 clangただし、適切な警告/エラーが生成されます。
caf 11/11/21

2
@caf:これはまさに私が作ろうとしているポイントです。GCCでは、オプションを渡す必要があります。箱から出して、それは教育目的のために余りにも寛容かもしれません。
Fred Foo

それは本当かもしれませんが、それはかなりマイナーなポイントです。さらに重要なのは、エラーメッセージの品質です。GCC 4.6はかなり良くなりましたが、clangが実際に魔法をかけていることは理解しています。
Kerrek SB、2011

2
@dreamlax:True; gnu99gnu++98ともありgnu++0xます。ただし、これらは本物の拡張機能だと思います。つまり、問題なくISO準拠のコードをコンパイルできます。詳細は次のとおりです。Cの場合、C ++の場合
Kerrek SB、2011

1
このプログラムはエラーや警告を生成するべきではありません。規格に準拠しています。
Miles Rout 2013年

3

代わりにclangを使用することもできます。

GCCとclangはのような式にいくつかの違いがありa+++++aます。また、gccを使用しているときにMacでclangを使用している同僚からは、さまざまな答えが得られました。

GCCが標準になり、clangが代替になる可能性があります。GCCは非常に安定しており、clangはまだ開発中です。


5
ClangはLinuxの世界でGCCを完全に置き換える準備を急速に進めており、BSDの世界ではそのほとんどを行っています。MacのGCCを数年前に置き換えました。Clangは良いものです。個人的にはGCCが代替手段になる可能性があると思います。
coder543 2013年

5
式a +++++ aは定義されていないため、コンパイラごとに、または同じコンパイラの異なるバージョンでも、異なる回答が得られると予想されます。異なるタイミングでコンパイルすると、同じコンパイラでその式の異なる結果が得られることもあります。それが「未定義」の意味です。
Lelanthran 2014

1
a+++++aa ++ ++ + a構文エラーであると解析されるため、失敗するはずです。
マイルズルーティング2014年

未定義の意味ではない@Lelanthran。動作が定義されていないため、コンパイラはコンパイルに失敗したり、実行時にスローしたり、CPUをロックしたりして、ハードリセットやさらに不吉なことを行う必要があります。
Antti Haapala
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.