Linuxでのgccコンパイラのコンパイルプロセス

1.GCCとは

GCCは、GPLライセンスの下でリリースされた自由ソフトウェアであり、GNUプロジェクトの重要な部分でもあります。GCCの本来の目的は、GNUオペレーティングシステム用のコンパイラを作成することでした。これは、ほとんどのUnixライクなオペレーティングシステム(Linux、BSD、MacOS Xなど)で標準コンパイラとして採用されており、 Microsoft WindowsGCCで使用されます。GCCは、x86、ARM、MIPSなどのさまざまなコンピュータアーキテクチャチップをサポートし、他のさまざまなハードウェアプラットフォームに移植されています。ここではまず、LinuxでのC言語gccの使用について主に説明します。

1.gccの使用方法

gcc [选项] 文件名
在linux下我们可以使用 gcc --help 查看gcc的各个选项

2.gccの一般的なオプション

ここに画像の説明を挿入します

gccのコンパイルプロセス

gccコンパイルのプロセスは、4つの主要なステップに分けることができます。

前処理(前処理)
コンパイル(コンパイル)
アセンブリ(アセンブリ)
リンク(リンク)

ここに画像の説明を挿入します

gccコンパイルの特定のステップについて話しましょう

1.前処理

前処理とは、cソースプログラムを読み取り、その中の疑似命令と特殊シンボルを「置き換える」ことです。この処理の後、マクロ定義、条件付きコンパイル命令、および特殊シンボルのない出力ファイルは生成されません。このファイルの意味は、前処理されていないソースファイルと同じです。Cファイルのままですが、内容が異なります。疑似命令には、主に次の3つの側面が含まれます。
(1)#define NAME TokenString、#undefなどのマクロ定義命令、および__DATE __、FILE、LINE、TIME、__ FUNCTION__などのコンパイラの組み込みマクロ。
(2)#ifdef、#ifndef、#else、#elif、#endifなどの条件付きコンパイル命令。
(3)ヘッダーファイルには、#include "FileName"や#includeなどの命令が含まれています。

前処理プロセスには、主に次のプロセスが含まれます。

  • すべての#definesを削除し、すべてのマクロ定義を展開します
  • #if、#ifdef、#elif、#else、#endifなどのすべての条件付きプリコンパイル命令を処理します。
  • #includeプリコンパイル済みディレクティブを処理し、インクルードされたファイルをプリコンパイル済みディレクティブの位置に挿入します。
  • コメント「//」と「/ * * /」をすべて削除します
  • 行番号とファイル識別子を追加して、コンパイル中にデバッグ行番号とコンパイルエラー警告行番号を生成できるようにします。
  • コンパイラはそれらを使用する必要があるため、すべての#pragmaコンパイラ指令を保持します

通常、次のコマンドが前処理に使用されます。パラメーター-Eは、前処理のみを意味します
。gcc-E hello.c -o hello.i
次のコマンドを使用して、前処理プロセスを完了することもできます。ここで、cppはプリプロセッサーです:
cpphello。 c> hello.i

前処理された結果hello.iはまだc言語のソースコードです。catまたはvimコマンドを使用してそのコードを表示できます
vimhello.i

2.コンパイル

コンパイラが行う必要のある作業は、すべての命令が文法規則に準拠していることを確認した後、字句解析と文法解析に合格し、それらを同等の中間コード表現またはアセンブリコードに変換することです。コンパイルプロセスについて詳しく知りたい場合は、他のブログを参照してください。

次のコマンドを使用して、アセンブリファイルをコンパイルおよび生成できます
。gcc-Shello.i> hello.s
catコマンドを使用して、コードを表示できます
。cathello.s

3.コンパイル

アセンブリプロセスは、実際にアセンブリ言語コードをターゲットマシン命令に変換します翻訳システムによって処理される各c言語ソースプログラムについて、対応するターゲットファイルがプロセスを通じて最終的に取得されます。

次のコマンドを使用してアセンブルできます
。gcc-chello.s-o hello.o

4.リンク

アセンブラで生成されたオブジェクトファイルはすぐに実行できず、未解決の問題が多い可能性があります。たとえば、ソースファイル内の関数は、別のソースファイルで定義されたシンボル(変数や関数呼び出しなど)を参照する場合があります。ライブラリファイル内の関数は、プログラムなどで呼び出される場合があります。これらすべての問題解決するには、リンクする必要があります。リンカーの主な役割は、関連するオブジェクトファイルを相互に接続することです。つまり、あるファイルで参照されているシンボルを別のファイルのシンボルの定義にリンクすることです。オブジェクトファイルは、オペレーティングシステム、つまり実行可能なプログラムでロードおよび実行できる統合された全体になります。開発者が指定したライブラリ関数のさまざまなリンク方法に応じて、リンクプロセスは次の2つのタイプに分類できます。①静的リンク②ダイナミックリンク。

実行可能ファイル内の関数呼び出しには、動的リンクまたは静的リンクの方法をそれぞれ採用できます。動的リンクを使用すると、共有オブジェクトのコードのコピーを1つだけメモリに格納する必要があるため、共有オブジェクトが複数のプロセスで使用される場合に、最終的な実行可能ファイルが短くなり、メモリを節約できますただし、必ずしも動的リンクの使用が静的リンクの使用よりも優れているとは限りません。場合によっては、動的リンクによってパフォーマンスが低下することがあります

おすすめ

転載: blog.csdn.net/KingRing_/article/details/115051281