应用与驱动Makefile示例

应用Makefile

target := test 
objs := test1.o test.o

$(target) : $(objs)
gcc -o $@ $^ -lpthread -lrt -lm -Wall

%.o : %.c
gcc -c -o $@ $<

clean:
rm $(target) *.o

驱动Makefile

PWD := $(shell pwd)
ARCH := arm
PLAT := samsung

ifeq ($(PLAT) , samsung)
CROSS_COMPILE := arm-linux-gnueabi-
KDIR := /work/plat/samsung
endif

modules:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean

obj-m += test_drv.o

Makefile例子详解

CC   = arm-linux-gcc  #编译工具
LD = arm-linux-ld #连接工具
AR = arm-linux-ar #将多个.o文件合并成一个.O或者静态库文件(.a文件)
OBJCOPY = arm-linux-objcopy #复制一个目标的内容到另一个文件中,例:将elf转化成bin文件
OBJDUMP = arm-linux-objdump #用于显示二进制文件信息,将elf文件反汇编
INCLUDEDIR := $(shell pwd)/include #shell函数,本句是在当前目录下的include文件夹下
CFLAGS := -Wall -O2 #CFLAGS为C语言编译器参数,-Wall打开警告和优化级别为O2
CPPFLAGS := -nostdinc -I$(INCLUDEDIR)
# CPPFALGS 为c++语言预处理参数,这里-nostdinc的意思是:Do not search the standard
# system directories for header files。 -I 指定只对#include “file”的头文件搜集目录
LDFLAGS := -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
#LDFLAGS为链接器,参数-print-libgcc-file-name:打印编译器伴随库的名称
export CC LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS AR
#用export声明这些变量使得他们可以被子目录的Makefile使用
objs := head.o init.o nand.o interrupt.o adc_ts.o serial.o main.o lib/libc.a
#objs 为变量,代替后面.o程序。lib/libc.a为连接库文件
adc_ts.bin: $(objs)
${LD} -Tadc_ts.lds -o adc_ts_elf $^ ${LDFLASG}
${OBJCOPY} -O binary -S adc_ts_elf $@
${OBJDUMP} -D -m arm adc_ts_elf > adc_ts.dis
# '-m'后面跟的是cpu构架,arm就表示是arm构架cpu,'>' 表示将这个程序的反汇编程序写入
#到led.dis,在终端中不显示出来.当你打开led.dis这个文件时就会看到上面命令的输出的反汇编程序了
.PHONY : lib/libc.a #.PHONY用来声明一个伪目标
lib/libc.a:
cd lib; make; cd ..
%.o:%.c
${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $< #将所有的[.C]文件都编译成[.O]文件
%.o:%.S
${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $< #将所有的[.s]文件都编译成[.O]文件
clean:#删除文件
make clean -C lib
rm -f adc_ts.bin adc_ts_elf adc_ts.dis *.o

注意:

CC,LD,AR等是Makefile的隐藏命令变量。

CFLAGS,CPPFLAGS,LDFLAGS,LIBS等是Makefile的隐藏参数变量。

隐藏命令变量和隐藏参数变量见《Makefile手册中文版》=>10.3隐含变量

另见:

网页收藏“Makefile $@ $^ $<_飞鹰0苍狼_新浪博客”

第3期 “第1课第4节_数码相框_编写通用的Makefile_P”

网页收藏 “GNU Make 使用手册(中译版)  (于凤昌)” (对应的英文版是 make.pdf)

Makefile用法

make详细使用手册见:

网页收藏 “​GNU Make 使用手册(中译版)  (于凤昌)​”  (对应的英文版是 ​make.pdf​)


目标 : 依赖1 依赖2 ...

[TAB]命令


例:

test : a.o b.o
gcc -o $@ $^
%.o : %.c
gcc -c -o $@ $<;

clean:
rm *.o test

1. 执行命令可以由以下两个原因引起

   ·"目标文件"不存在,

   ·某个依赖文件比目标文件"新"

2. 若直接make ,则会生成第一个目标。

   本处,直接make,会直接进行生成test相关的操作,执行make clean会清除

3.  make时可以传入变量的值。例如 make gcc=arm-linux-gcc

4. make时,会读入整个Makefile文件,设置好所有的变量,然后会进行生成第一个目标的操作。

5.  如果@gcc -o test $^,则执行此命令的时候不会打印,如果没有@,则会打印gcc -o test a.o b.o

Makefile添加头文件等依赖文件示例

objs = a.o b.o c.o

dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))

CFLAGS = -Werror -Iinclude

test: $(objs)
gcc -o test $^

ifneq ($(dep_files),)
include $(dep_files)
endif
# 这个宏判断,第一次执行Make时为假(没有dep_files),不会执行。
# 只有执行一次之后,生成了依赖文件,之后make才会执行

%.o : %.c
gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d
@echo $^
# -MD -MF .$@.d可以生成依赖文件到.$@.d中。例如:当执行到c.o时,
# 写到.c.o.d的内容是:c.o : c.c c.h ... 第二次及以后执行时,
# 会通过识别这些依赖的.c,.h文件来确定是否用新的文件编译。

clean:
rm *.o test

distclean:
rm $(dep_files)

.PHONY: clean

其他:

1.依赖文件的追加的问题

例:


(1). 创建b,c,d,f空文件
(2). 同级目录下新建Makefile:
          A : b c
          A : d
          A : f
              @echo $<<br>#          @echo $^
          执行结果:
          f
          f b c d
(3). 总结:通过这个实验可得:依赖可以通过这样的方法来追加,追加之后,
        最后新加的依赖会放到第一个,而前边的追加会加到后边。


2.gcc -M c.c // 打印出依赖(包括编译器的库)

   gcc -MM c.c  //打印出依赖(不包括编译器的库)

   gcc -M -MF c.d c.c  // 把依赖写入文件c.d

   gcc -c -o c.o c.c -MD -MF c.d  // 编译c.o, 把依赖写入文件c.d

单独编译驱动时Makefile必须指定的东西

交叉编译工具链

arch

内核路径

Makefile调试方法

$(warning text)   :text为字符串  例如:$(warning "hehe")  

$(warning $(xxx))   :可以输出xxx变量

$(error  text)           :  text为字符串  例如:$(error"hehe")  

$(error  $(xxx))       : 可以输出xxx变量

warning和error区别:warning可以继续运行,而error会立刻中断运行

这个$(warning text)、$(error text)可以放在Makefile任何位置。

其他网址

GNU Make 使用手册(中译版)(于凤昌)

驱动模块Makefile解析 - 华清远见嵌入式学院