GCC 编译器的使用

1.GCC 编译过程

一个 C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇 编(assembly)和链接(linking)等 4 步才能变成可执行文件。

GCC 编译器的使用_第1张图片

注:本文章使用 x86 上的gcc 来试验,使用 ARM 板的交叉编译工具链做实验时效果也是类似的。不同的交叉编译器工具链前缀可能不同,比如 arm-linux-gcc。

1.1 预处理

C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令 “#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。 预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件 编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一 步处理

总结:“ .c/.cpp ”文件  ——>  " .i "文件

1.2 编译

编译就是把 C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码".s"文件,所用到的工具为 cc1(它的名字就是 cc1,x86 有自己的 cc1 命令,ARM 板也有自己的 cc1 命令)。

总结:“ .i ”文件  ——>  " .s "文件

1.3 汇编

汇编就是将第二步输出的汇编代码“.s”翻译成符合一定格式的机器代码,在 Linux 系统上一般表现为 ELF 目标文件(OBJ 文件),用到的工具为 as。x86 有 自己的 as 命令,ARM 版也有自己的 as 命令,也可能是 xxxx-as(比如 arm-linux-as)。 “反汇编”是指将机器代码转换为汇编代码,这在调试程序时常常用到。

总结:“ .s ”文件  ——>  " .o "文件

1.4 链接

链接就是将上步生成的 OBJ 文件和系统库的 OBJ 文件、库文件链接起来,最 终生成了可以在特定平台运行的可执行文件,用到的工具为 ld 或 collect2。

总结:“.o ”文件  ——>  可执行文件

1.5 图解

GCC 编译器的使用_第2张图片

2. GCC命令

2.1 GCC命令格式:

gcc   [-命令选项]   编译后文件   编译前文件

示例1:gcc -E -o hello.i hello.c                        将hello.c预处理为hello.i

示例2:gcc -S -o hello.s hello.i                        将hello.i编译为hello.s

示例3:gcc -c -o hello.o hello.s                       将hello.s汇编为hello.o

示例4:gcc -o hello hello.o                              将hello.o链接为hello可执行文件

示例5:gcc -o test main.c sub.c                      将main.c和sub.s一起编译为test可执行文件

2.2 GCC常用命令选项:

常用选项 描述
-E 预处理,开发过程中想快速确定某个宏可以使用“-E -dM”
-c 把预处理、编译、汇编都做了,但是不链接
-o 指定输出文件
-I 指定头文件目录
-L 指定链接时库文件目录 -l 指定链接哪一个库文件

很有用的命令:

gcc -E main.c

// 查看预处理结果,比如头文件是哪个

gcc -E -dM main.c > 1.txt

// 把所有的宏展开,存在 1.txt 里

gcc -Wp,-MD,abc.dep -c -o main.o main.c

// 生成依赖文件 abc.dep,后面 Makefile 会用

echo 'main(){}'| gcc -E -v -

// 它会列出头文件目录、库目录(LIBRARY_PATH)

3.GCC其他使用

3.1怎么编译多个文件

法1:一起编译、链接:

gcc -o test main.c sub.c

法2:分开编译,统一链接:

单独编译main.c

gcc -c -o main.o main.c

单独编译sub.c

gcc -c -o sub.o sub.c

一起链接main.o和sub.o

gcc -o test main.o sub.o

法1与法2的优缺点:

(1).对于法一

优点:只需要一行代码,减少软件资源,代码精简。

缺点:当main.c和sub.c中有一个的代码改变后,所有的.c文件都要全部重新编译,会将没改变的也重新编译一遍。

(2).对于法二:正正相反。

3.2 如何知道头文件,库文件指定去哪个目录寻找

在命令后加上" -v "。

3.3 如何制作使用静态库动态库

3.3.1 制作使用静态库

gcc -c -o main.o main.c

gcc -c -o sub.o sub.c

ar crs libsub.a sub.o sub2.o sub3.o(可以使用多个.o 生成静态库)

gcc -o test main.o libsub.a (如果.a 不在当前目录下,需要指定它的绝对或相对路径)

运行:不需要把静态库 libsub.a 放到板子上。

注意:执行 arm-buildroot-linux-gnueabihf-gcc -c -o sub.o sub.c 交叉编译需要在 最后面加上-fPIC 参数。

3.3.2 制作使用动态库

第1步 制作、编译:

gcc -c -o main.o main.c

gcc -c -o sub.o sub.c

gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o 生成动态库)

gcc -o test main.o -lsub -L /libsub.so/所在目录/ 

第2步 运行: 先把 libsub.so 放到 Ubuntu 的/lib 目录,然后就可以运行 test 程序。 如果不想把 libsub.so 放到/lib,也可以放在某个目录比如/a,然后如下执行:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a

./test

GCC 编译器的使用_第3张图片

你可能感兴趣的:(嵌入式应用开发,linux,运维,服务器)