Makefile使用细节

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/M_N_N/article/details/82254738

变量及通配符

这里写图片描述

A := $(C)  # 即时变量,此时C未定义,A为空
B = $(C)   # 延时变量,用到B时再确定具体的值
C = abc
C ?= 123    # C不是第一次定义,被忽略
C += 789
D ?= xyz    # D是第一次定义

all:
    @echo A = $(A)
    @echo B = $(B)
    @echo C = $(C)
    @echo D = $(D)

输出:

A =
B = abc 789
C = abc 789
D = xyz 

函数

这里写图片描述

A = a b c
B = $(foreach v, $(A), $(var).c)	# 取出$(A)中的每一项存到v中,执行$(v).c,最后以空格分隔返回
C = $(B)
C += d.o
D = $(filter %.c, $(C))           # 返回$(C)中所有符合%.c的项
E = $(filter-out %.c, $(C))       # 返回$(C)中所有不符合%.c的项
files := $(wildcard *.c)       # 获取当前目录下所有的.c文件
files_obj := $(patsubst %.c, %.o, $(files))  # 将$(files)中所有符合%.c的项替换为%.o
files_obj2 := $(files:%.c=%.o) # 效果和patsubat相同


func:
    @echo A = $(A)
    @echo B = $(B)
    @echo C = $(C)
    @echo D = $(D)
    @echo E = $(E)
    @echo files = $(files)
    @echo files_obj = $(files_obj)
    @echo files_obj2 = $(files_obj2)

输出:

A = a b c
B = a.c b.c c.c
C = a.c b.c c.c d.o
D = a.c b.c c.c
E = d.o
files = a.c test.c
files_obj = a.o test.o
files_obj2 = a.o test.o

实例:

default:
    arm-linux-gcc -c start.s -o OBJ/start.o
    arm-linux-gcc -c LED/led.c -o OBJ/led.o
    arm-linux-gcc -c KEY/key.c -o OBJ/key.o
    arm-linux-gcc -c main.c -o OBJ/main.o
    arm-linux-ld -Ttext=0x42C00000 OBJ/start.o OBJ/led.o OBJ/key.o OBJ/main.o -o OBJ/main.elf
    arm-linux-objcopy -I elf32-littlearm -Obinary OBJ/main.elf main.bin

clean:
    rm *.bin OBJ/*.o OBJ/*.elf

上面是一般的写法;
下面是优雅点的写法:

CC          = arm-linux-gcc
LD          = arm-linux-ld
OBJCOPY     = arm-linux-objcopy
CFLAGS      = -Wall -g

TARGET      := main

TOP_DIR     := $(shell pwd)
# SRC_DIRS  := $(shell ls -F | grep /$)
SRC_DIRS    := $(shell find $(TOP_DIR) -maxdepth 1 -type d)

C_SRCS      = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))
C_HEADS     = $(patsubst %.c, %.h, $(C_SRCS))
C_OBJS      = $(patsubst %.c, %.o, $(C_SRCS))
C_OBJS      += $(TOP_DIR)/start.o

$(TARGET):$(C_OBJS)
    $(shell if [ ! -d $(TOP_DIR)/OBJ ]; then mkdir $(TOP_DIR)/OBJ; fi)
    $(LD) -Ttext=0x42C00000 $^ -o OBJ/$@.elf
    $(OBJCOPY) -I elf32-littlearm -Obinary OBJ/$@.elf OBJ/$@.bin

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

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

.PHONY:clean
clean:
    rm -rf $(C_OBJS) OBJ/*.*

测试这段优雅的Makefile后,发现生成的.bin文件下载到板子上运行不了。
原来,ld链接器对文件顺序是有要求的,从左到右,如果a依赖b,则a应该放在b的左边,ld a b,上面的例子,start.o是启动文件,所以start.o应该放在最前头;

C_OBJS      = $(patsubst %.c, %.o, $(C_SRCS))
C_OBJS      += $(TOP_DIR)/start.o

替换成

C_OBJS      = $(TOP_DIR)/start.o $(patsubst %.c, %.o, $(C_SRCS))

猜你喜欢

转载自blog.csdn.net/M_N_N/article/details/82254738