Linuxのgccとは何ですか

青灯夜游
青灯夜游オリジナル
2023-04-18 13:41:464383ブラウズ

Linux における gcc の正式名称は「GNU Compiler Collection」、中国語で「GNU Compiler Suite」を意味し、GNU が開発したプログラミング言語コンパイラであり、複数の言語をコンパイルできるコンパイラです。 gcc スイートには、C、C、Objective-C、Fortran、Java、Ada、Go 言語のフロント エンドと、これらの言語のライブラリが含まれています。

Linuxのgccとは何ですか

#このチュートリアルの動作環境: linux7.3 システム、Dell G3 コンピューター。

1. gcc とは

GCC (GNU Compiler Collection、GNU コンパイラ スイート) は、GNU によって開発されたプログラミング言語コンパイラです。複数の言語をコンパイルできるコンパイラ。 GNU コンパイラ スイートには、C、C、Objective-C、Fortran、Java、Ada、Go 言語のフロント エンドと、これらの言語のライブラリ (libstdc、libgcj など) が含まれています。 gcc は C として使用されました。 言語コンパイラー (GNU C Compiler) は、C 言語に加えて、C、Java、Pascal などの言語をサポートするようになりました。 gcc は複数のハードウェア プラットフォームをサポートします。

2. gcc の特徴

gcc は、複数のハードウェア プラットフォームをサポートするポータブル コンパイラーです。たとえば、ARM、X86 などです。
  • gcc はローカル コンパイラであるだけでなく、プラットフォーム間でクロスコンパイルすることもできます。いわゆるローカル コンパイラとは、コンパイルされたプログラムがローカル環境でのみ実行できることを意味します。 gcc によってコンパイルされたプログラムは、他のプラットフォームでも実行できます。たとえば、組み込みプログラムを x86 でコンパイルし、arm で実行できます。
  • gcc には、さまざまな言語を解析するための複数の言語フロント エンドがあります。
  • gcc はモジュール式に設計されており、新しい言語や新しい CPU アーキテクチャのサポートを追加できます。
  • gcc はフリー ソフトウェアです。誰でもこのソフトウェアを使用または変更することができます。

3. gcc コンパイル プログラムのプロセス gcc コンパイル プログラムは主に 4 つのプロセスを経ます:


##前処理
  • コンパイル
  • アセンブル
  • リンク
Linuxのgccとは何ですか
前処理では、実際にはヘッダー ファイルとマクロが展開されます。コンパイル段階で、gcc はさまざまな言語のコンパイラーを呼び出します。たとえば、C 言語はコンパイラー ccl を呼び出します。 Gcc は実際には、プログラムのコンパイル中にさまざまなツールを呼び出すツール チェーンです。アセンブリ段階では、gcc はアセンブリのためにアセンブラを呼び出します。リンク プロセスでは、プログラムに必要なオブジェクト ファイルが実行可能ファイルにリンクされます。アセンブラはリロケータブルオブジェクトファイルを生成しますが、OSを調べてみると、ソースプログラムのアドレスは0から始まることが分かりますが、これは相対アドレスであり、実際にメモリ上でプログラムが実行されている時のアドレスは決してそこから始まるものではありません。は0から始まり、ソースコードを書くときにはプログラムの絶対アドレスが分からないため、

Relocation
はソースコードのコードや変数などを特定のメモリアドレスとして配置することができます。 次は、このプロセスを表す図です。プロセス中にファイルのサフィックスが変更されることに注意してください。コンパイル オプションは、これらのサフィックスに関連しています。

これらは、GCC コンパイルの 4 つのステップです。

4. 共通の gcc オプション 共通の gcc オプションを見てみましょう

Linuxのgccとは何ですかソース ファイル hello.c が完成しました。gcc の使用例をいくつか示します。

gcc -E hello.c -o hello.i   对hello.c文件进行预处理,生成了hello.i 文件
gcc -S hello.i -o hello.s    对预处理文件进行编译,生成了汇编文件
gcc -c hello.s -o hello.o  对汇编文件进行编译,生成了目标文件
gcc hello.o -o hello 对目标文件进行链接,生成可执行文件
gcc hello.c -o hello 直接编译链接成可执行目标文件
gcc -c hello.c 或 gcc -c hello.c -o hello.o 编译生成可重定位目标文件

使用gcc时可以加上-Wall选项。下面这个例子如果不加上-Wall选项,编译器不会报出任何错误或警告,但是程序的结果却不是预期的:

//bad.c
#includeade979de5fc0e1ca0540f360a64c230b
int main()
{
    printf("the number is %f ",5);  //程序输出了the number is 0.000000,结果错误
    return 0;
 }

使用-Wall选项:

gcc -Wall bad.c -o bad

gcc将输出警告信息:

warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
printf("the number is %f\n",5);

5、gcc编译多个文件

// hello.c
#includeade979de5fc0e1ca0540f360a64c230b
#include"hello.h"
void printHello()
{
        printf("hello world!\n");
}
//main.c
#includeade979de5fc0e1ca0540f360a64c230b
#include"hello.h"
int main()
{
        printHello();
        return 0;
}
//hello.h
//仅包含函数声明
#ifndef _HELLO_
#define _HELLO_
void printHello();
#endif

编译这三个文件,可以一次编译:

gcc hello.c main.c -o main 生成可执行文件main

也可以独立编译:

gcc -Wall -c main.c -o main.o
gcc -Wall -c hello.c -o hello.o
gcc -Wall main.o hello.o -o main

独立编译的好处是,当其中某个模块发送改变时,只需要编译该模块就行,不必重新编译所有文件,这样可以节省编译时间。

6、使用外部库

在使用C语言和其他语言进行程序设计的时候,我们需要头文件来提供对常数的定义和对系统及库函数调用的声明。库文件是一些预先编译好的函数集合,那些函数都是按照可重用原则编写的。它们通常由一组互相关联的可重用原则编写的,它们通常由一组互相关联的用来完成某项常见工作的函数构成。使用库的优点在于:

  • 模块化的开发
  • 可重用性
  • 可维护性

库又可以分为静态库与动态库:

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。静态库比较占用磁盘空间,而且程序不可以共享静态库。运行时也是比较占内存的,因为每个程序都包含了一份静态库。
  • 动态库(.so或.sa):程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码,这样就减少了程序的体积。

一般头文件或库文件的位置在:

  • /usr/include及其子目录底下的include文件夹
  • /usr/local/include及其子目录底下的include文件夹
  • /usr/lib
  • /usr/local/lib
  • /lib

7、生成静态库

为了生成.a文件,我们需要先生成.o文件。下面这行命令将我们的hello.o打包成静态库libhello.a:

ar rcs libhello.a hello.o

ar是gun归档工具,rcs表示replace and create,如果libhello之前存在,将创建新的libhello.a并将其替换。

然后就可以这样来使用静态库libhello.a

gcc -Wall main.c libhello.a -o main

还有另外一种使用方式:

gcc -Wall -L. main.c -o main -lhello 【lhello 是 libhello的缩写】

其中 -L.表示库文件的位置在当前目录下,由于libhello.a是我们自己生成的,并存放在当前录下下,所以需要加上-L.选项。默认库文件是在系统的目录下进行搜索。同样的,-I.选项用于头文件的搜索。

8、生成共享库

生成一个共享库,名称的规则是libxxx.so。将刚才hello.o生成libhello.so的命令为:

gcc -shared -fPIC hello.o -o libhello.so

生成了共享库之后,可以这样来使用共享库:

gcc -Wall main.o -o main -L. -lhello

该命令与使用静态库的命令相同,但是在共享库与静态库共存的情况下,优先使用共享库。

共享库有时候并不不在当前的目录下,为了让gcc能够找得到共享库,有下面几种方法:

  • 拷贝.so文件到系统共享库路径下,一般指/usr/lib

  • 在~/.bash_profile文件中,配置LD_LIBRARY_PATH变量

  • 配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache

其中,shared选项表示生成共享库格式。fPIC表示产生位置无关码(position independent code),位置无关码表示它的运行、加载与内存位置无关,可以在任何内存地址进行加载。

9、库的搜索路径

库的搜索路径遵循几个搜索原则:从左到右搜索-I -l指定的目录,如果在这些目录中找不到,那么gcc会从由环境 变量指定的目录进行查找。头文件的环境变量是C_INCLUDE_PATH,库的环境变量是LIBRARY_PATH.如果还是找不到,那么会从系统指定指定的目录进行搜索。

相关推荐:《Linux视频教程

以上がLinuxのgccとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。