Linux嵌入式学习——GCC

一、GCC编译过程

1.一般程序编译的过程如下:

.c 文件【预处理】后生成 .i 文件,.i 文件经过【编译】后生成 .s (汇编码)文件,.s 文件经过【汇编】后生成 .o 文件,一个或多个 .o 文件【链接】生成可执行程序。

  1. 预处理: 对.c文件中的“#”进行展开,包括查找头文件和展开宏等  gcc -E -o main.i main.c
  2. 编译:将高级语言转化成汇编语言   gcc -S -o main.s main.i
  3. 汇编:将汇编语言转化成机器语言(01码)  gcc -c -o main.o main.s
  4. 链接:将机器语言转化成可执行程序      gcc -o main main.o

gcc编译过程中用到的工具包括:cc1、as、collect2

2.gcc 常用选项:

常用选项

描述

-E

预处理,开发过程中想快速确定某个宏可以使用“-E  -dM”

-S

编译,将.i文件编译成.s(汇编码)文件

-c

把预处理、编译、汇编都做了,但是不链接

-o

指定输出文件

-I

指定头文件目录

-L

指定链接时库文件目录

-l

指定链接哪一个库文件

头文件:

  • < > :这种符号的头文件,编译器会去系统目录中查找该头文件,程序员可以用 -I 指定头文件的查找目录(此时,编译器先去程序员指定目录查找,再去系统目录查找)
  • "   ":这种符号的头文件,编译器会去当前目录查找

3.其他选项

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)

二、GCC编译静态库和动态库

1.gcc多文件编译

  • 直接一起编译生成可执行程序:gcc -o test a1.c a2.c a3.c ...
  • 每个文件各自编译但不链接,等多有文件都编译好再一起链接:                                          gcc -c -o  a1.o a1.c                                                                                                                      gcc -c -o  a2.o a2.c                                                                                                                      gcc -c -o  a3.o a3.c                                                                                                                      ...                                                                                                                                                  gcc -o test  a1.o a2.o a3.o ...

已有文件main.c , sub.c , sub.h. 三个文件内容如下:

//main.c 文件内容如下
#include <stdio.h>
#include "sub.h"

int main(int argc,char* argv[])
{
        int i;
        printf("Main fun\n");
        sub_fun();
        return 0;
}

//sub.h 文件内容如下
void sub_fun();

//sub.c 文件内容如下
#include <stdio.h>
#include "sub.h"

void sub_fun()
{
        printf("Sub fun!\n");
}

  • 直接编译生成可执行程序:gcc -o test main.c sub.c
  • 先各自编译不链接,最后一起链接成可执行程序:gcc -c -o main.o main.c    gcc -c -o sub.o sub.c     gcc -o test1 main.o sub.o

2.静态库

以上面三个文件为例,sub.c可以作为编译成库文件和 main.o 链接

将sub.c编译成静态库文件,并且和main.o 链接生成可执行程序步骤:

#1.先只编译不链接main.c文件
gcc -c -o main.o main.c   

#2.将sub.c编译成静态库文件
gcc -c -o sub.o sub.c
ar crs libsub.a sub.o

#3.链接
gcc -o test main.o libsub.a

#4.执行程序
./test

其中,libsub.a就是静态库文件。静态库文件链接生成的可执行程序占用内存大,因为是直接将代码搬移过去的,所以可执行程序运行时不需要再去找静态库文件了。

3.动态库

以上面三个文件为例,sub.c可以作为编译成库文件和 main.o 链接

将sub.c编译成动态库文件,并且和main.o 链接生成可执行程序步骤:

#1.只编译不链接main.c文件
gcc -c -o main.o main.c

#2.编译生成动态库文件
gcc -c -o sub.o sub.c
gcc -shared -o libsub.so sub.o

#3.将所有文件链接
gcc -o test main.o libsub.so     #方法一
gcc -o test main.o -lsub -L ./   #方法二

#4.执行程序
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./   #配置环境变量:动态库目录指定
./test

几点注意:

  1. 动态库文件链接的时候有两中表示方法;
  2. 第一种方法直接用之前编译生成的动态库.so 文件;
  3. 第二种方法用 -l 指定链接哪个库文件,如果动态库文件名字是libsub.so,那么用-l的时候只要sub就行,前面的lib和后面的.so都不要。-l 会去系统提供的库文件目录下查找库文件,但我们这里库文件是在当前目录下,所以用 -L 指定库文件目录;
  4. 含有动态库链接的程序,在运行时也会去查找动态库,系统默认是去/lib, /usr/lib目录去查找,若该动态库文件不在系统默认库文件目录下,要么将其拷贝到系统默认库文件目录,要么配置环境变量,指定动态库目录:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./

三、总结

1.头文件

  • < > :这种符号的头文件,编译器会去系统目录中查找该头文件,程序员可以用 -I 指定头文件的查找目录(此时,编译器先去程序员指定目录查找,再去系统目录查找)
  • "   ":这种符号的头文件,编译器会去当前目录查找

2.动态库文件链接时:-lxxx

  • 系统指定lib目录
  • -L dir:程序员指定目录

3.含动态库的程序运行时

  • 系统指定目录:/lib , /usr/lib
  • 程序员指定,配置环境变量:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值