gcc以及makefile规则应用

gcc生成ELF文件的整个流程
在这里插入图片描述
1.0预处理
#开头的都是预处理,生成.i文件
2.0编译
对预处理过后的代码进行词法与句法分析,生成目标系统的汇编代码,生成.s文件
3.0汇编
对汇编文件进行优化,生成目标代码文件,生成.o文件
4.0链接
解析目标代码的外部引用,将多个目标代码文件连接为一个可执行文件

gcc命令
gcc 【选项】 文件列表

过程控制选项
(1)预处理选项(-E)

(2)编译选项(-S)

(3)汇编选项(-c)

输出目标选项控制

-o filename
gcc main.c -o main

输出所有警告选项 -Wall
gcc main.c -o main.c

头文件选项 -I filename

将dirname目录加入到头文件搜索目录列表中。当gcc在默认的路径中没有找到头文件时,就到本选项指定的目录中去找
$ tree
.
├── inc
│ └── test.h
└── main.c

gcc main.c -I inc -o main

链接库选项

添加库文件搜索目录(-Ldirname)

将dirname目录加入到库文件的搜索目录列表中。

加载库名选项(-lname)

加载名为libname.a或libname.so的函数库。例如:-lm表示链接名为libm.so的函数库。

静态库选项(-static)

代码优化选项
gcc提供几种不同级别的代码优化方案,用“-O*level”*选项表示。level取值可以是0、1、2、3和s。

默认0级,即不进行优化。典型的优化选项:

(1)-O或-O1:基本优化,使代码执行的更快。

(2)-O2:产生尽可能小和快的代码。如无特殊要求,不建议使用O2以上的优化。

(3)-Os:生成最小的可执行文件,适合用于嵌入式软件。

调试选项及调试示例
代码:GIT下载后在“05_100ASK_IMX6ULL裸机程序/6_Makefile与GCC/001_gcc_02”目录下。

gcc支持数种调试选项:

-g:产生能被GDB调试器使用的调试信息。

举个例子,首先需要在编译时加上“-g”选项,操作步骤如下:

$ gcc main.c -g -o main
GDB调试示例:

(1)run命令

调试运行,使用run命令开始执行被调试的程序,run命令的格式:

run [运行参数]

$ gdb -q main <—进入调试程序
Reading symbols from output…done.
(gdb) run <—开始执行程序
Starting program: /home/100ask/makefile/
100 ask
[Inferior 1 (process 7425) exited normally]
(gdb)
(2)list命令

列出源代码,使用list命令来查看源程序以及行号信息,list命令的格式:

list [行号]

(gdb) list 1 <—列出第一行附近的源码,每次10行
#include <stdio.h>

#define HUNDRED 100

int main()
{
int a = 100;

  printf("%d ask\n",HUNDRED);
  return 0;

(gdb) <—按Enter键,列出下10行源码
}
(gdb)
(3)设置断点

1)break命令,设置断点命令,break命令的格式: break <行号> | <函数名>

(gdb) break 7
Breakpoint 1 at 0x40052e: file main.c, line 7.
(gdb)
2)info break命令,查 看断点命令:

(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040052e in main at main.c:7
(gdb)
3)delete breakpoint命令,删除断点命令, delete breakpoint命令的格式: delete breakpoint <断点号>

(gdb) delete breakpoint 1
(gdb) info break
No breakpoints or watchpoints.
(gdb)
(4)跟踪运行结果

1)print命令,显示变量的值,print命令的格式:print[/格式] <表达式>

2)display命令,设置自动现实命令,display命令的格式: display <表达式>

3)step和 next命令,单步执行命令,step和next命令的格式:step <行号> 或 next <行号>

4)continue命令,继续执行命令。

(gdb) break 7
Breakpoint 1 at 0x40052e: file main.c, line 7.
(gdb) break 9
Breakpoint 2 at 0x400535: file main.c, line 9.
(gdb) run
Starting program:/home/100ask/makefile/

Breakpoint 1, main () at main.c:7
7 int a = 100;
(gdb) continue
Continuing.

动态链接库和静态链接库使用例程
静态库和动态库,是根据链接时期的不同来划分。

静态库:在链接阶段,所用的库就被加进可执行程序里了。静态链接生成的可执行文件,已经内嵌了所有的库,可以独立运行。链接静态库从某种意义上来说是一种复制粘贴,被链接后库就直接嵌入可执行程序中了。如果有多个程序都用到这些库,并且都使用静态 接,那么系统里空间就有很大的浪费,而且一旦发现系统中有bug,就必须把所有程序都重新编译、重新链接,十分麻烦。静态库是不是一无是处了呢?不是的,如果代码在其他系统上运行,且没有相应的库时,解决办法就是使用静态库。而且由于动态库是在程序运行的时候被链接,因此动态库的运行速度比较慢。

动态库:在程序执行的时候,才把所需要的库跟程序链接在一起。多个程序可以合用一份动态库,节省存储空间。如果发现bug或者是要升级,只要用新的库把原来的替换掉就可以了。

一个例子

VERSION = 1.0.0
SOURCE = $(wildcard ./src/*.c)
OBJECT = $(patsubst %.c, %.o, $(SOURCE))

INCLUDES = -I ./inc 

TARGET = enable
CC	   = gcc
CFLAGS = -Wall -g

$(TARGET) : $(OBJECT)
	@mkdir	-p output/
	$(CC) $^ $(CFLAGS) -o output/$(TARGET)_$(VERSION)

%.o : %.c
	$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@

.PHONYl : clean
clean:
	@rm -rm $(OBJECT) output/

# 行1 将版本号赋值给变量VERSION
# 行2 获取当前目录下src所有.c文件,并赋值给SOURCE
# 行3 将所有的从src查找出符合.c文件类型的文件,然后一一替换并生成.o文件
# 行5 通过-I选项指明头文件的目录,并赋值给INCLUDES
# 行7 最终目标文件名为 enable
# 行8  CC 替换 gcc 编译工具
# 行9 将显示的所有警告信息选项和gdb调试选项赋值给变量CFLAGS
# 行12 级联创建 output文件
# 行13  编译生成可执行文件enable
# 行16 将源文件生成对应的目标文件
# 行18  伪目标防止该目录下有clean的文件夹
#       #现在我们的目录里面有名为“clean”的文件,目标文件是有的,并且没有依赖文件,没有办法判断依赖文件的时间。
#       这种写法会导致:有同名的"clean"文件时,就没有办法执行make clean操作。解决办法:我们需要把目标定义为假想目标,用关键字PHONY。
# %.o:表示所用的.o文件
# %.c:表示所有的.c文件
# $@:表示目标
# $<:表示第1个依赖文件
# $^:表示所有依赖文件
# 主要参考:  http://wiki.100ask.org/%E7%AC%AC009%E8%AF%BE_gcc%E5%92%8Carm-linux-gcc%E5%92%8CMakefile
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值