博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Makefile教程(四)
阅读量:3522 次
发布时间:2019-05-20

本文共 2359 字,大约阅读时间需要 7 分钟。

多目录结构的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.oSRCS = test.cSUB_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.ogcc -c test.c -o test.o #生成对应的.old main.o test.o -r -o main #链接 -r:生成可重定位的输出(称为部分连接)gcc main -o a.out #生成终极目标

扩展

获取上一级目录

#当前目录 的上一级目录 关键字direxport 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 是变量名,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

转载地址:http://fxqqj.baihongyu.com/

你可能感兴趣的文章
springboot读取配置文件 例:读取配置文件的优先顺序;在主配置文件中激活其他配置文件;加载非主配置文件
查看>>
自动配置原理
查看>>
TCP协议
查看>>
关于Linux系统使用遇到的问题-1:vi 打开只读(readonly)文件如何退出保存?
查看>>
redis 持久化详解,RDB和AOF是什么?他们优缺点是什么?运行流程是什么?
查看>>
spring注解版(一)
查看>>
SpringBoot中访问控制层(controller)得不到Json数据
查看>>
react项目报出警告Warning: Cannot update during an existing state transition (such as within `render`).
查看>>
BFC(Block Formatting Context)
查看>>
什么是作用域,什么是闭包,什么是作用域链
查看>>
惰性求值,面向对象
查看>>
lodash源码分析之baseSlice()函数
查看>>
数据结构之列表
查看>>
发布/订阅模式 vs 观察者模式
查看>>
es5中的arguments对象
查看>>
git本地仓库和远程仓库关联,分支重命名
查看>>
js对象的深拷贝,你真的觉得很简单吗?
查看>>
你真的了解map方法吗?手动实现数组map方法。
查看>>
带你手动实现call方法,让你收获满满
查看>>
前端知识体系
查看>>