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会使用
echomain(){}| 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工具的前提条件

  1. 编译源码时,需要加-g选项
  2. 使用方法:例如编译得到最终的可执行文件 a.out: gdb ./a.out

基础指令

list:简写 llist 1 或者l 1列出源码,根据源码指定行号设置断点.
bb 20,在20行位置设置断点
run:简写r:运行程序
start:直接运行到程序中mian函数入口处
n/next: 按下n则执行下一条指令(如果下一条指令是函数调用,则会执行完函数直接到下下条指令前)
s/step:下一条指令(不过跳过函数)
p/printp <变量名> 查看变量的值: 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的变量

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值