在大多项目中都会合理设计目录结构来提高维护性,在编译一个项目时会产生大量中间文件,如果中间文件直接和源文件放在一起,就显得杂乱而不利于维护。在为现在这个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——让编译环境更加有序的更多相关文章

  1. 【SpringCloud之pigx框架学习之路 】2.部署环境

    [SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.下载代码 git clone https://git.pig4c ...

  2. 【SpringCloud之pigx框架学习之路 】1.基础环境安装

    [SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.Cmder.exe安装 (1) windows常用命令行工具 下 ...

  3. C++学习之路——1.linux下环境搭建

    学习之路,可说各有各的看法和方法.对于我来说,完全是兴趣一下子来了,脑壳发热吧.就想有个干净的环境,只想着与程序有关的东西练一练. 目前想学习C++,可是打开VC++6,再安了VS2010.VS201 ...

  4. 【转】Ant学习笔记——自己构建Ant编译环境

    自从年初开始用NetBeans6.0,才接触到Ant. 这是今年6月份的一篇Ant学习笔记.安装 1.下载并构建环境.   去官网下载src包和bin包.解压缩它们到同一目录,运行build.bat, ...

  5. Makefile学习之路——4

    变量的类别有递归扩展变量和简单扩展变量.只用一个“=”符号定义的变量被称为递归扩展变量.通过下面例子观察递归扩展变量的特点. .PHONY: all foo=$(bar) bar=$(ugh) ugh ...

  6. 嵌入式Linux驱动学习之路(四)u-boot编译分析

    u-boot编译分析 在配置完成后,执行make开始编译.这里打开Makefile. 首先在目标all前有一句话首先检查是否有include/config.mk文件来判断是否成功配置过. ifeq ( ...

  7. Makefile学习之路——1

    编写makefile,不是一个猛子扎进去试着写一个规则并对之调试,而应该先采用面向依赖关系的思考方法勾勒出makefile要表达怎样的依赖关系,这一点尤为重要.通过不断地练习这种思考方法,才可能达到流 ...

  8. go语言学习之路 一:开发环境配置

    1. 安装go 1)下载地址:http://www.golangtc.com/download,下载后直接双击msi文件安装,默认安装在c:\go 2)安装完成后默认会在环境变量 Path 后添加 G ...

  9. Sass学习之路(3)——Sass编译

    Sass的编译也是在我们使用Sass的时候必须要经过的一个步骤,因为".sass"和".scss"文件并不能直接使用<link>标签引用,最终其实还 ...

随机推荐

  1. SPSS Clementine 数据挖掘入门2

    下面使用Adventure Works数据库中的Target Mail作例子,通过建立分类树和神经网络模型,决策树用来预测哪些人会响应促销,神经网络用来预测年收入. Target Mail数据在SQL ...

  2. 数字证书相关技术 : Versign信任签章

    资料网址: 淘宝网站可信服务 http://www.ert7.com/case/eb/1391.html Versign信任签章 http://www.ert7.com/verisign/ssl/29 ...

  3. Maven核心概念之仓库,生命周期与插件

    宏观图 一.仓库 统一存储全部Maven项目共享的构建的位置就是仓库. 仓库分为本地仓库和远程仓库.远程仓库又分为中央仓库(中央仓库是Maven核心自带的远程仓库),伺服(还有一种特殊的远程仓库,为节 ...

  4. 超棒的在线Bootstrap主题编辑工具 - lollytin

    lollytin 是一款帮助制作Bootstrap3主题的在线工具,虽然现在仍旧是Beta版本,但是已经非常不错了. 主要功能: 通过拖拽来生成主题 支持拖拽页头,页脚,内容,幻灯,地图,表单,画廊, ...

  5. 深入一点 让细节帮你和Fragment更熟络

    有一段时间没有写博客了.作为2017年的第一篇,初衷起始于前段时间一个接触安卓开发还不算太长时间的朋友聊到的一个问题: "假设,想要对一个Fragment每次在隐藏/显示之间做状态切换时进行 ...

  6. iOS 检查app版本更新操作

    iOS 检查app版本更新操作 1:获取本地安装的版本信息: [NSString stringWithFormat:@"Version %@ (%@)", [[[NSBundle ...

  7. JDK中枚举的底层实现

    前提 上一篇文章复习介绍了JDK中注解的底层实现,跟注解一样比较常用,但是底层实现比较神秘的还有枚举类型.趁着国庆假期的最后两天,把JDK中枚举的底层实现也进行一次探究. 通过例子查找本质 在探究JD ...

  8. Map 和 WeakMap 数据结构

    Map 和 WeakMap 是ES6 新增的数据结构 一.Map 它们本质与对象一样,都是键值对的集合,但是他们与 Object 对象主要的不同是,键可以是各种类型的数值,而Object 对象的键 只 ...

  9. com.tongyan.tutelage:bdservice_v1

    3-21 10:14:20.833 2892-2892/? E/art: No implementation found for long com.baidu.platform.comjni.map. ...

  10. /dev/null 和 /dev/zero

    1.概论 -- 来自维基的解释 /dev/null  : 在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一 ...