Makefile学习之路6——让编译环境更加有序
在大多项目中都会合理设计目录结构来提高维护性,在编译一个项目时会产生大量中间文件,如果中间文件直接和源文件放在一起,就显得杂乱而不利于维护。在为现在这个complicated项目编写makefile之前,我们先给出目录结构需求:
1.将所有的目标文件放在objs子目录中;
2.将最终生成的可执行程序放在exes子目录中;
在编译项目之前,需要将生成的文件目录准备好,可以手动创建,也可以通过编译Makefile创建。
.PHONY: all clean MKDIR = mkdir
RM = rm
RMFLAGS = -rf DIRS =objs exes all:$(DIRS)
$(DIRS):
$(MKDIR) $@
clean:
$(RM) $(RMFLAGS) $(DIRS)
为了将项目编译时所创建的文件分别放入objs和exes中,需要用到前面介绍的一个函数,addprefix。
.PHONY: all clean MKDIR = mkdir
RM = rm
RMFLAGS = -rf CC=gcc DIR_OBJS=objs
DIR_EXES=exes
DIRS =$(DIR_OBJS) $(DIR_EXES)
EXE=complicated
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS)) all:$(DIRS) $(DIR_EXES)/$(EXE)
$(DIRS):
$(MKDIR) $@
$(DIR_EXES)/$(EXE):$(OBJS)
$(CC) -o $@ $^
$(DIR_OBJS)/%.o:%.c
$(CC) -o $@ -c $^
clean:
$(RM) $(RMFLAGS) $(DIRS) $(EXE)
这里运行之后就会在objs文件夹这种存放.o,在exes文件中存放可执行文件complicated。由于书上是把可执行文件放在当前目录的,所以它在clean加上了删除$(EXE),在我的Makefile中其实这句多余,因为把exes文件夹都删除了,在单独删除exes文件中的可执行文件没有意义,之所以没改,是为了提醒一下自己,这里完成了书上的不再赘述的任务O(∩_∩)O。
到这里 ,你可能觉得自己又get了一个新技能,但是,这却不是一个好的Makefile,比如,我们把foo.h更改为:
#ifndef __FOO_H
#define __FOO_H void foo(int value); #endif /*__FOO_H*/
这里仅仅改变了foo函数的参数,从void变成了int,但是我们执行make:

注意,这里是在没有更改foo.h之前先make一次,然后在更改了foo.h之后再make,然后make提示居然没有任何事情可以做?奇怪吧,我们明明更改了函数声明不再匹配了啊,我们执行clean之后,再执行make:

这下make终于发现错误了,为什么第一次重新make的时候,make不发现错误呢?因为我们的Makefile中,并没有依赖foo.h,所以,我们可以更改Makefile如下:
.PHONY: all clean MKDIR = mkdir
RM = rm
RMFLAGS = -rf CC=gcc DIR_OBJS=objs
DIR_EXES=exes
DIRS =$(DIR_OBJS) $(DIR_EXES)
EXE=complicated
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS)) all:$(DIRS) $(DIR_EXES)/$(EXE)
$(DIRS):
$(MKDIR) $@
$(DIR_EXES)/$(EXE):$(OBJS)
$(CC) -o $@ $^
$(DIR_OBJS)/%.o:%.c foo.h
$(CC) -o $@ -c $<
clean:
$(RM) $(RMFLAGS) $(DIRS) $(EXE)
其中红色部分为更改部分。

可以看到,我们先执行make生成目标文件,然后更改foo.h,再make,立即报错了。虽然这样可以解决问题,但是当项目复杂时,如果每一个头文件都要写入Makefile相应的规则中,那么将会是一个噩梦。看来我们还要寻找一个更好的办法。——当然,在后面的随笔中会提出的。
Makefile学习之路6——让编译环境更加有序的更多相关文章
- 【SpringCloud之pigx框架学习之路 】2.部署环境
[SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.下载代码 git clone https://git.pig4c ...
- 【SpringCloud之pigx框架学习之路 】1.基础环境安装
[SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.Cmder.exe安装 (1) windows常用命令行工具 下 ...
- C++学习之路——1.linux下环境搭建
学习之路,可说各有各的看法和方法.对于我来说,完全是兴趣一下子来了,脑壳发热吧.就想有个干净的环境,只想着与程序有关的东西练一练. 目前想学习C++,可是打开VC++6,再安了VS2010.VS201 ...
- 【转】Ant学习笔记——自己构建Ant编译环境
自从年初开始用NetBeans6.0,才接触到Ant. 这是今年6月份的一篇Ant学习笔记.安装 1.下载并构建环境. 去官网下载src包和bin包.解压缩它们到同一目录,运行build.bat, ...
- Makefile学习之路——4
变量的类别有递归扩展变量和简单扩展变量.只用一个“=”符号定义的变量被称为递归扩展变量.通过下面例子观察递归扩展变量的特点. .PHONY: all foo=$(bar) bar=$(ugh) ugh ...
- 嵌入式Linux驱动学习之路(四)u-boot编译分析
u-boot编译分析 在配置完成后,执行make开始编译.这里打开Makefile. 首先在目标all前有一句话首先检查是否有include/config.mk文件来判断是否成功配置过. ifeq ( ...
- Makefile学习之路——1
编写makefile,不是一个猛子扎进去试着写一个规则并对之调试,而应该先采用面向依赖关系的思考方法勾勒出makefile要表达怎样的依赖关系,这一点尤为重要.通过不断地练习这种思考方法,才可能达到流 ...
- go语言学习之路 一:开发环境配置
1. 安装go 1)下载地址:http://www.golangtc.com/download,下载后直接双击msi文件安装,默认安装在c:\go 2)安装完成后默认会在环境变量 Path 后添加 G ...
- Sass学习之路(3)——Sass编译
Sass的编译也是在我们使用Sass的时候必须要经过的一个步骤,因为".sass"和".scss"文件并不能直接使用<link>标签引用,最终其实还 ...
随机推荐
- Web开发者需养成的8个好习惯
优秀的Web开发人员工作效率更高,因为他们拥有丰富的经验和良好的习惯.作者Gregor Dorfbauer分享了用于Web开发中的8个好习惯,这些良好的工作习惯不仅能提高效率,还能让您创建更加优秀的应 ...
- 高性能WEB开发:重排与重绘
DOM编程可能最耗时的地方,重排和重绘. 1.什么是重排和重绘 浏览器下载完页面中的所有组件——HTML标记.JavaScript.CSS.图片之后会解析生成两个内部数据结构——DOM树和渲染树. D ...
- 设置 IE 默认模式为 IE8
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
- Android -- Activity的销毁和重建
两种销毁 第一种是正常的销毁,比如用户按下Back按钮或者是activity自己调用了finish()方法: 另一种是由于activity处于stopped状态,并且它长期未被使用,或者前台的acti ...
- x为正变数,求y=x^3/(x^4+4)的最大值
设z=1/y=x4+4/x3 显然,当z有最小值时,y有最大值,求得zmin,就得到了ymax 而z=x+4/x3=x/3+x/3+x/3+4/x3 根据正实数算术平均数大于等于它们的几何平均数的定理 ...
- spring错误汇总
在学习spring过程中遇见了种种不同的异常错误,这里做了一下总结.希望遇见类似错误的同学们共勉一下. 1. 错误一 Error creating bean with name 'helloServi ...
- Codeforces Round #FF (Div. 1)-A,B,C
A:DZY Loves Sequences 一開始看错题了. .sad. 题目非常easy.做法也非常easy.DP一下就好了. dp[i][0]:到当前位置,没有不论什么数改变,得到的长度. dp[ ...
- android使用achartengine 实现折线图
折线图的实现分为下边几个步骤: 1.第一步:数据的准备 XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset(); XYSeri ...
- SDL视频显示进阶
原文地址:http://blog.csdn.net/qingkongyeyue/article/details/53024467 1.SDL中事件和线程(函数同时运行) 2.练习 (1)创建线程 第一 ...
- Android自己定义截屏功能,相似QQ截屏
由于公司业务需求 须要对一个屏幕进行截屏.但自带的截屏功能是远远不够项目的功能需求 ,我们是做一个画板软件 .须要的像QQ那样截屏之后 ,能够看到我们自己定义的工具.有画笔,button等等 .and ...