makefile 指定文件的生成目录[通俗易懂]

makefile 指定文件的生成目录[通俗易懂]1.上一篇博客虽然简单实现了自动处理依赖关系,但是生成的各种临时文件都混在一起,太乱了。假定我们的源文件放在src目录,头文件放在inc目录,.o文件放在obj目录,.d文件放在dmk目录,Makefile和上述4个目录为同一级别。则定义如下变量:D_SRC=srcD_INC=-I./incD_OBJ=objD_MK=dmk2.自动遍历src目录下的所有.c

大家好,又见面了,我是你们的朋友全栈君。

1.上一篇博客虽然简单实现了自动处理依赖关系,但是生成的各种临时文件都混在一起,太乱了。

假定我们的源文件放在src目录,头文件放在inc目录,.o文件放在obj目录,.d文件放在dmk目录,Makefile和上述4个目录为同一级别。

则定义如下变量:

D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK  = dmk

2.自动遍历src目录下的所有.c文件

SRC_C   = $(wildcard $(D_SRC)/*.c)
         # wildcard表示把$(D_SRC)目录下的.c文件遍历出来

SRC_C   = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
       # foreach表示遍历$(D_SRC)的所有子目录同时把子目录下的.c文件遍历出来

假设src目录中有a.c,b.c,则$(SRC_C) 表示 src/a.c src/b.c

3.生成所有的.o文件依赖和.d文件集合

OBJ_C   = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK  = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))

notdir表示去除目录,则$(notdir $(SRC_C))表示a.c b.c

patsubst表示把$(notdir $(SRC_C))中的.c替换成.o,即a.o b.o

addprefix表示增加前缀$(D_OBJ)/,则OBJ_C变量表示为obj/a.o obj/b.o

4.明白了上述语句之后我们可以把makefile写成如下状态

D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK  = dmk
TATGET = hello

SRC_C   = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
OBJ_C   = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK  = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))

$(TATGET):$(OBJ_C)
	gcc -o $@ $^

$(D_OBJ)/%.o:$(D_SRC)/%.c
	gcc -c -Wall $(D_INC) $< -o $@

$(D_MK)/%.d:$(D_SRC)/%.c
	@set -e; rm -f $@; \
	$(CC) -MM $(D_INC) $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,$(D_OBJ)/\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$

include $(SRC_MK)

.PHONY: clean
clean:
	rm -f $(D_OBJ)/* $(TATGET) $(D_MK)/*

多出来的几行依赖关系其实就是一个字符串匹配的模式,clean就不需要解释了。

5.vpath 自动变量的使用,第一个参数是查找的类型,第二个是查找的目录

vpath %.c src #查找依赖时如果遇到%.c,则自动到src目录下寻找
D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK  = dmk
TATGET = hello

SRC_C   = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
OBJ_C   = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK  = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))

$(TATGET):$(OBJ_C)
	gcc -o $@ $^

$(D_OBJ)/%.o:%.c  #自动去src目录下找.c结尾的文件。
	gcc -c -Wall $(D_INC) $< -o $@

$(D_MK)/%.d:%.c
	@set -e; rm -f $@; \
	$(CC) -MM $(D_INC) $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,$(D_OBJ)/\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$

include $(SRC_MK)

.PHONY: clean
clean:
	rm -f $(D_OBJ)/* $(TATGET) $(D_MK)/*

查找多个目录用下面的写法

vpath %.c src:src1:src2

大写VPATH只能指定依赖的查找目录,不能指定类型,所以也可以写成

VPATH = src
D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK  = dmk
TATGET = hello

SRC_C   = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
OBJ_C   = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK  = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))

$(TATGET):$(OBJ_C)
	gcc -o $@ $^

$(D_OBJ)/%.o:%.c
	gcc -c -Wall $(D_INC) $< -o $@

$(D_MK)/%.d:%.c  #自动去VPATH指定的目录查找,指定多个路径 写成VPATH = src:src1:src2
	@set -e; rm -f $@; \
	$(CC) -MM $(D_INC) $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,$(D_OBJ)/\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$

include $(SRC_MK)

.PHONY: clean
clean:
	rm -f $(D_OBJ)/* $(TATGET) $(D_MK)/*
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143708.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java 解决中文乱码问题

    Java 解决中文乱码问题一:服务端解析客户端二:客户端解析服务端三:Filter设置编码四:Get提交中文乱码

    2022年7月8日
    17
  • 倍增

    倍增法可以有很多变化。1.用data[i][j]记录从i到他的第2j个父亲的路径长度,就可以边求LCA边求出两点距离,因为data[i][j]满足倍增的递推式:data[i][j]=data[i][j-1]+data[fa[i][j-1]][j-1]。2.用maxlen[i][j]记录i到第2^j^个父亲的路径上最长边的边权,它满足…

    2022年4月9日
    45
  • 商城数据库表设计介绍怎么写_商城数据库设计

    商城数据库表设计介绍怎么写_商城数据库设计前言  一个商城系统,需要有,用户表,商品表,商品分类表,购物车表,订单表,订单明细表,支付信息表,以及物流信息表。  使用PowerDesigner对数据表以及他们之间的关系进行了粗略的设计得出了如下E-R图:  1.用户表2.商品表3.商品类别表4.购物车表5.订单表6.订单明细表7.支付信息表8.收货信息表SQL实例SETFOREIGN_KEY_CHECKS=0;———-…

    2025年11月5日
    2
  • 闭包概念及面试题

    闭包概念及面试题如何产生闭包(closure)闭包(closure),是指函数变量可以保存在函数作用域内,因此看起来是函数将变量“包裹”了起来。//根据定义,包含变量的函数就是闭包也就是函数嵌套函数就可以称之为闭包.作用域应对的特殊情况,有两种表现:函数作为参数被传递函数作为返回值被带回函数中的自由变量,取决于函数定义的地方,跟执行的地方没关系闭包的应用场景闭包应用场景1,封装对象的私有属性和方法隐藏数据做一个简单的缓存工具//闭包隐藏数据,只提供APIfunctioncreat

    2022年10月9日
    2
  • Linux有问必答:如何在Linux上检查SSH的版本

    Linux有问必答:如何在Linux上检查SSH的版本

    2022年3月2日
    40
  • MYSQL ERROR CODE 错误编号的意义

    mysql error code(备忘)转1005:创建表失败1006:创建数据库失败1007:数据库已存在,创建数据库失败1008:数据库不存在,删除数据库失败1009:不能删除数据库文件导致删除数据库失败1010:不能删除数据目录导致删除数据库失败1011:删除数据库文件失败1012:不能读取系统表中的记录1020:记录已

    2022年3月9日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号