GCC与Makefile
GCC(交叉编译工具链同理)
常用选项
| 常用选项 | 描述 |
|---|---|
-E | 预处理,开发过程中想要快速确定某个宏可以使用"-E -dM" |
-S | - |
-c | 预处理、编译、汇编,生成.o文件但是不链接 |
-o | 指定输出文件名 |
-I | 指定头文件路径 |
-L | 指定库路径 // 运行时 通过 LD_LIBRARY_PATH环境变量来指定库路径。 |
-l | 指定要连接的库文件 |
-D | 添加宏定义 |
有用的选项
gcc -E -dM main.c > 1.txt // 把所有的宏展开,存在1.txt中
gcc -Wp,-MD, abc.dep -c -o main.o main.c //生成依赖文件,后面makefile会使用
echo ’main(){}’ | gcc -E -v - // 列出头文件目录,库文件目录(LIBRARY_PATH)
gcc -M c.c // 打印出依赖,后面makefile会使用
gcc -M -MF c.d c.c //把依赖写入c.d,后面makefile会使用
gcc -c -o c.c -M -MF c.d //编译c.c并把依赖写入c.d,后面makefile会使用
Makefile
Makefile的基本规则
[OBJ]:[依赖文件列表]
[TAB]cmd
基本规则1: 先生成依赖文件
基本规则2: 依赖比目标新则执行cmd(节省编译时长)
基本规则3: 默认以第一个目标作为最终目标。
例如:
OBJ:=main.o test.o test1.o test2.o
export $(OBJ)
OBJ?= main2.o
test:$(OBJ)
gcc -o test $(OBJ)
#gcc -o test $^
OBJ+= test3.o
变量
定义变量
变量的名称=值列表
变量赋值的4种方式
:=即时变量,常规赋值,只对当前语句变量有效
=延时变量,在使用到该变量时,其值才确定。可能影响其它变量,所有与该变量相关的变量都会受影响
?=变量是否已定义,如果没有定义则定义,延时变量。
+=在变量的后面追加
引用变量
使用$(VAL)符号来引用变量,这里的引用在笔者看来相当于替换
导出变量
使用export导出Makefile变量给子Makefile
ifeq …(else ifeq …)else …endif语句
条件判断语句
ifeq ($(CHIP),HI3520DV300)
# ifneq($(CHIP),HI3520DV300)
compile = arm-hisiv300-linux-gcc
dostrip = arm-hisiv300-linux-strip
target = tl_panel
endif
include、-include和sinclude
包含语句,用于包含其它Makefile相关的文件
include后面是绝对路径,那么Makefile会去绝对路径下寻找;否则Makefile会去命令行选项“-I”或者“–include-dir”指定的目录下寻找,接着去“/usr/gnu/include”、“/usr/local/include”和“/usr/include”寻找
-include,忽略“错误”
sinclude,同“-include”
@
不回显Makefile语句
all: a.c b.c c.c
@gcc a.c b.c c.c -o a.out
-
忽略makefile中cmd的错误
all: a.c b.c c.c
@gcc a.c b.c c.c -o a.out
-cp ./a.out /share
cp ./a.out ./output
会忽略cp ./a.out /share继续执行
目标与伪目标
.PHONY: clean
用于解决有与目标同名的文件时,makefile不执行的问题。
常用函数
$(foreach var,list,text) # 对于list中的每一个值,执行 text。
$(filter pattern...,text) # 从text中取出符合pattern的值 这里可以使用通配符 %
$(filter-out pattern...,text) # 从text中取出不符合pattern的值 这里可以使用通配符 %
$(wildcard pattern) # 从目录中取出符合pattern的文件名 这里可以使用通配符 *
$(patsubst pattern, replacement, $(var)) # 从$(var)中取出符合pattern的值并作替换成repalcement格式 这里可以使用通配符 %
例1:
A = a b c
B = $(foreach var,$(A),$(var).o)
all:
echo $(B)
# 最终输出
# a.o b.o c.o
例2:
# 当前目录下存在以下的文件
#----------------------------------------------
# ls ./
# a.c b.c c.c abc d/
#----------------------------------------------
A = a b c d/
B = $(filter %/,$(A)) # 这里可以使用通配符 %
C = $(filter-out %/,$(A)) # 这里可以使用通配符 %
files = $(wildcard *.c) # 这里可以使用通配符*, 从目录中取出所有的.c文件名并复值给变量files
files1 = a.c b.c c.c abc
files2 = $(patsubst %.c, %.o, $(files1))
all:
echo $(B)
echo $(C)
echo $(files)
echo $(files2)
# 最终输出
# d/
# a b c
# a.c b.c c.c
# a.o b.o c.o
自动变量(类似通配符)
$@ 代表目标
$^ 代表上述所有依赖文件
$< 代表第一个依赖文件
模式规则
% 常常用作目标和函数中的通配符
%.o:%.c %.h
$(CC) -c $< -o $@
静态模式规则
#只对$(obj)中的.o文件执行该模式规则
% 常常用作目标和函数中的通配符
CC:= gcc
src:= $(wildcard ./*.c) #匹配当前目录下的所有.c文件,形成列表赋值给src
obj:= $(patsubst %c, %.o, $(src)) #将src列表中的%c替换成%.o,形成列表赋值给obj
all: $(obj)
$(CC) -o $@ $^
$(obj):%.o:%.c %.h #只对$(obj)中的.o文件执行该模式规则
$(CC) -c $< -o $@
依赖关系
objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d, $(objs)) #获得依赖文件名列表
dep_files := $(wildcard $(dep_files)) #获得目录中真正存在的依赖文件的名字列表
test : $(objs)
gcc -o $@ $^
ifneq ($(dep_files),) # 如果 存在依赖文件, 则包含依赖文件
include $(dep_files)
endif
%.o : %.c
gcc -c -o $@ S< -MD -MF .$@.d # 生成依赖文件并编译
clean:
rm *.test
distclean: clean
rm $(dep_files)
.PHONY: clean distclean
make命令的参数
-n:模拟执行make、make clean指令
-f:指定的文件名执行make
shell调用
本章仅仅介绍,在Makefile中如何调用shell。实际上在笔者看来,在Makefile中调用shell,相当于在命令行中执行shell脚本。
获得当前绝对路径
ROOT_DIR := $(shell pwd)
定义与引用shell变量
x=
$$x
算术运算
for 语句
all:
for x in $(SRC_N); do \
dd if=$$x.upk of=$$x.bin bs=128 skip=1;\
done
获取文件大小
len=`ls -l $$filename | awk '{print $$5}'`;
gdb调试工具
使用gdb工具的前提条件
- 编译源码时,需要加
-g选项 - 使用方法:例如编译得到最终的可执行文件 a.out:
gdb ./a.out
基础指令
list:简写 l;list 1 或者l 1列出源码,根据源码指定行号设置断点.
b:b 20,在20行位置设置断点
run:简写r:运行程序
start:直接运行到程序中mian函数入口处
n/next: 按下n则执行下一条指令(如果下一条指令是函数调用,则会执行完函数直接到下下条指令前)
s/step:下一条指令(不过跳过函数)
p/print:p <变量名> 查看变量的值: p i 查看变量i的值
continue:继续执行程序
quit: 退出gdb调试
其他重要指令
finish:结束当前函数调用,直接到函数调用后的指令。
set args 字串1 字串2:设置程序中mian函数的命令行参数,必须在程序运行前设置
run 字串1 字串2:运行并设置程序中mian函数的命令行参数
info b: 查看断点信息表
b 20 if i = 5: 当变量i的值为5时,在函数的20行设置一个断点,条件断点
ptype:查看变量的类型,只能查看当前栈帧中的变量
bt:列出当前栈帧,及其编号
frame:根据栈帧编号,切换栈帧。
display:设置跟踪变量,并且给该变量提供一个序号,跟踪显示变量的值:display i 不断显示变量i的值
undisplay:取消跟踪显示变量的值:使用跟踪变量的序号来取消:undisplay 1:取消编号为1的变量

2296

被折叠的 条评论
为什么被折叠?



