Makefile教程(四)

多目录结构的Makefile编写

目录结构

在这里插入图片描述

主Makefile

#主Makefile

#终极目标
TGT = target
#子目录
SUB_DIR = main test
#子目标
export SUB_TGT = built-in.o

#顶层目录
export TOP_DIR = $(shell pwd)
#头文件目录
export HEAD_DIR = $(TOP_DIR)/head

#交叉编译器
#CROSS_COMPILE = arm-linux-gnueabihf-
export CC = $(CROSS_COMPILE)gcc

#编译选项
export CFLAGS = -I$(HEAD_DIR) -Wall
#编译链接器
export LD = ld
#编译链接选项
export LDFLAGS = 

#终极目标规则
$(TGT): $(SUB_DIR)
	$(CC) $(CFLAGS) $(^:=/$(SUB_TGT)) -o $@

#如何进入子目录规则
$(SUB_DIR): 
	make -C $@

clean:
	rm -vf $(TGT) 
	for dir in $(SUB_DIR); do \
		make -C $$dir clean; \
	done

.PHONY: clean $(SUB_DIR)

解析
make中有三条规则
1.  $(TGT) 链接生成最终目标规则
2. $(SUB_DIR) 第一条规则的依赖,因为依赖是个目录,所以要有一个规则来说明如何进入到此目录
3. clean 清理规则

子Makefile

#子Makefile:用来告诉make如何生成当前目录下的子目标built-in.o

SRCS = test.c
SUB_DIR = foo

$(SUB_TGT): $(SRCS:.c=.o) $(SUB_DIR)
	$(LD) $(LDFLAGS) $(SRCS:.c=.o) $(SUB_DIR:=/$(SUB_TGT)) -r -o $@

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

%.d: %.c
	$(CC) $(CFLAGS) $< -MM > $@
sinclude $(SRCS:.c=.d)

$(SUB_DIR): 
	make -C $@

clean:
	rm -vf $(SUB_TGT) $(SRCS:.c=.o) $(SRCS:.c=.d)
	for dir in $(SUB_DIR); do \
		make -C $$dir clean; \
	done

.PHONY: clean $(SUB_DIR)

分析

  1. 主makefile首先说明了终极目标,然后开始找终极目标的依赖,发现依赖是一个目录,那么就去找如何进入目录的指令,也就是执行了第二条指令,成功进入子目录
  2. 在子目录中,makefile说明了子目录的目标(这个目标是主makefile -> export下来的),依赖就是(当前目录下的.c生成的.o && 当面目录下的子目录)
    2.1. 找到.o的规则开始生成.o
    2.2 找到进入子目录的规则进入子目录
    2.3 找到所有的依赖以后开始链接(ld) 生成子目标built-in.o
  3. 又回到了主makefile中,将所有的built-in.o生成终极目标

图解:
├── main.c
├── Makefile
└── test.c

gcc -c main.c -o main.o
gcc -c test.c -o test.o #生成对应的.o
ld main.o test.o -r -o main #链接 -r:生成可重定位的输出(称为部分连接)
gcc main -o a.out #生成终极目标

扩展

获取上一级目录

#当前目录 的上一级目录 关键字dir
export HEAD_DIR = $(dir $(TOP_DIR))include

从make中获取参数

ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

上述代码中先使用 ifeq 来判断"$(origin O)"和"command line"是否相等。这里用到了 Makefile
中的函数 origin,origin 和其他的函数不一样,它不操作变量的值,origin 用于告诉你变量是哪
来的,语法为:

$(origin <variable>)
variable 是变量名,origin 函数的返回值就是变量来源,因此$(origin O)就是变量 O 的来源。
如果变量 O 是在命令行定义的那么它的来源就是"command line",这样"$(origin O)"和"command line"就相等了。
当这两个相等的时候变量 KBUILD_OUTPUT 就等于 O 的值,比如在命令行中输入
“make O=/home/zys/linux/uboot/out “ 的 话 那 么 KBUILD_OUTPUT =/home/zys/linux/uboot/out 。
如果没有在命令行输入 O 的 话KBUILD_OUTPUT = 空。

创建文件夹

参考来自uboot的主Makefile

ifneq ($(KBUILD_OUTPUT),)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
								&& /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error failed to create output directory "$(saved-output)"))
     
endif
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值