先手工创建几个文件目录:

接下来先创建code/foo/src目录下的Makefile:

 .PHONY: all clean

 MKDIR = mkdir
RM = rm
RMFLAGS = -rf CC =gcc
AR =ar
ARFLAGS =crs DIR_OBJS=objs
DIR_EXES=../../../build/exes
DIR_DEPS=deps
DIR_LIBS=../../../build/libs
DIRS =$(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)
RMS=$(DIR_OBJS) $(DIR_DEPS) EXE=
ifneq ("$(EXE)","")
EXE :=$(addprefix $(DIR_EXES)/,$(EXE))
RMS +=$(EXE)
endif LIB=libfoo.a
ifneq ("$(LIB)","")
LIB :=$(addprefix $(DIR_LIBS)/,$(LIB))
RM +=$(LIB)
endif SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS=$(SRCS:.c=.dep)
DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS)) ifeq ("$(wildcard $(DIR_OBJS))","")
DEP_DIR_OBJS :=$(DIR_OBJS)
endif#dir_objs
ifeq ("$(wildcard $(DIR_EXES))","")
DEP_DIR_EXES :=$(DIR_EXES)
endif#dir_exes
ifeq ("$(wildcard $(DIR_DEPS))","")
DEP_DIR_DEPS :=$(DIR_DEPS)
endif#dir_deps
ifeq ("$(wildcard $(DIR_LIBS))","")
DEP_DIR_LIBS :=$(DIR_LIBS)
endif#dir_libs all: $(EXE) $(LIB)
ifneq ($(MAKECMDGOALS),clean)
include $(DEPS)
endif#clean $(DIRS):
$(MKDIR) $@
$(EXE):$(DEP_DIR_EXES) $(OBJS)
$(CC) -o $@ $(filter %.o,$^)
$(LIB):$(DEP_DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o:$(DEP_DIR_OBJS) %.c
$(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c
@echo "Creating $@ ..."
@set -e;\
$(RM) $(RMFLAGS) $@.tmp;\
$(CC) -E -MM $(filter %.c,$^) > $@.tmp;\
sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' <$@.tmp >$@;\
$(RM) $(RMFLAGS) $@.tmp clean:
$(RM) $(RMFLAGS) $(RMS)

具体和complicated项目的差别可以看书或者上篇随笔。

第一个提示没有那个目录,可以在include的时候加上'-'就可以忽略这个,因为这里对我们的项目没有实质影响,但是新手对于报错或者警告总是不放心,故再次提示一下。

从运行结果来看,的确在build/libs目录下生成了一个libfoo.a库文件。运行make clean之后,也没有删除build/libs这个目录,而只是删除库文件libfoo.a

下面要做的就是将这个Makefile运用到code/huge/src目录。

增进复用性:

可以将公用部分放入一个独立的文件中——这就是bulid目录下make.rule文件的作用。这需要我们却别哪些是公用哪些是不能公用的变量。

在考虑复用的情况下,foo模块的Makefile有两部分组成,分别是bulid目录中的make.rule和code/foo/src目录中的Makefile。

foo模块中的Makefile比较简单,因为大部分代码移植道理make.rule中:

EXE=
LIB =libfoo.a
include $(ROOT)/build/make.rule

make.rule如下:

 .PHONY: all clean

 MKDIR = mkdir
RM = rm
RMFLAGS = -rf CC =gcc
AR =ar
ARFLAGS =crs DIR_OBJS=objs
DIR_EXES=$(ROOT)/build/exes
DIR_DEPS=deps
DIR_LIBS=$(ROOT)/build/libs
DIRS =$(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)
RMS=$(DIR_OBJS) $(DIR_DEPS) ifneq ("$(EXE)","")
EXE :=$(addprefix $(DIR_EXES)/,$(EXE))
RMS +=$(EXE)
endif ifneq ("$(LIB)","")
LIB :=$(addprefix $(DIR_LIBS)/,$(LIB))
RM +=$(LIB)
endif SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS=$(SRCS:.c=.dep)
DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS)) ifeq ("$(wildcard $(DIR_OBJS))","")
DEP_DIR_OBJS :=$(DIR_OBJS)
endif#dir_objs
ifeq ("$(wildcard $(DIR_EXES))","")
DEP_DIR_EXES :=$(DIR_EXES)
endif#dir_exes
ifeq ("$(wildcard $(DIR_DEPS))","")
DEP_DIR_DEPS :=$(DIR_DEPS)
endif#dir_deps
ifeq ("$(wildcard $(DIR_LIBS))","")
DEP_DIR_LIBS :=$(DIR_LIBS)
endif#dir_libs all: $(EXE) $(LIB)
ifneq ($(MAKECMDGOALS),clean)
include $(DEPS)
endif#clean $(DIRS):
$(MKDIR) $@
$(EXE):$(DEP_DIR_EXES) $(OBJS)
$(CC) -o $@ $(filter %.o,$^)
$(LIB):$(DEP_DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o:$(DEP_DIR_OBJS) %.c
$(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c
@echo "Creating $@ ..."
@set -e;\
$(RM) $(RMFLAGS) $@.tmp;\
$(CC) -E -MM $(filter %.c,$^) > $@.tmp;\
sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' <$@.tmp >$@;\
$(RM) $(RMFLAGS) $@.tmp clean:
$(RM) $(RMFLAGS) $(RMS)

如果想运行foo模块中的Makefile,先要在shell上导出所需的ROOT变量:

期间出现了一个问题,我检查了很久Makefile并没有发现问题,但是就是显示没有规则创建目标,最后,用vim重新输入了一下include后面的路径,就解决了,用vscode输入莫名奇妙不行,又没有出现TAB建这样字符,可能是文本编辑器本身的差异吧,但是vim是肯定不会出现格式不兼容问题的。所以以后还是用vim写Makefile把。

完成上面的之后,我们需要考虑把code/huge/src目录中的Makefile了,我们希望这个目录中存放的程序能生成一个可执行文件。在测试Makefile之前,我们现在该目录中放一个main.c文件,内容如下:

 int main(void)
{
return ;
}

Makefile如下所示:

 EXE =huge_app

 LIB =

 include $(ROOT)/build/make.rule

从结果看huge_app已经成功生成了。

Makefile 10——打造更专业的编译环境-huge项目的更多相关文章

  1. Makefile学习之路6——让编译环境更加有序

    在大多项目中都会合理设计目录结构来提高维护性,在编译一个项目时会产生大量中间文件,如果中间文件直接和源文件放在一起,就显得杂乱而不利于维护.在为现在这个complicated项目编写makefile之 ...

  2. MyEclipse中JDK运行环境和编译环境的设置

    一.设置myEclipse中新项目使用的JDK 1.运行环境   [Window]->[Preferences]->[Java]->[Installed JREs] 步骤:Add-- ...

  3. MyEclipse环境的项目改为在Eclipse中运行爬坑记【我】

      新检出一个web项目,同事都是运行在MyEclipse中的,我用Eclipse启动, 1.首先是许多jar包报错: 处理方法为 remove掉,然后 选 WEB-INF 下的所有 jar 重新添加 ...

  4. Ubuntu 14.10,准备C/C++的编译环境

    Ubuntu缺省情况下,并没有提供C/C++的编译环境,因此还需要手动安装. 如果单独安装gcc以及g++比较麻烦,幸运的是,为了能够编译Ubuntu的内核,Ubuntu提供了一个build-esse ...

  5. java 11 移除的一些其他内容,更简化的编译运行程序,Unicode 10,移除了不太使用的JavaEE模块和CORBA技术,废除Nashorn javascript引擎,不建议使用Pack200 相关api

    移除的一些其他内容 移除项 移除了com.sun.awt.AWTUtilities 移除了sun.misc.Unsafe.defineClass, 使用java.lang.invoke.MethodH ...

  6. Win 10 MSYS2 VS Code 配置 c++ 的编译环境

    博客参考 https://www.cnblogs.com/esllovesn/p/10012653.html 和 https://blog.csdn.net/bat67/article/details ...

  7. 使用 Windows 10 WSL 搭建 ESP8266 编译环境并使用 VSCODE 编程(一)(2019-08-23)

    目录 使用 Windows 10 WSL 搭建 ESP8266 编译环境并使用 VSCODE 编程 安装前准备 安装 ESP8266 工具链 下载 ESP8266 SDK 编译 花絮 使用 Windo ...

  8. windows 10环境下 使用 msys2 + vs code 配置 c++ 的编译环境

    不太多描述 msys2 与  vs code  ,既然你需要安装 一种语言的编译环境了 ,你肯定对这两个不陌生: 1. 先安装msys2; (下载多少位的msys2就安装多少位的 mingw,本人安装 ...

  9. Android编译环境折腾记

    题记:感觉是时候写点什么了=_=! 第一次安装了ubuntu14.04.5,官网下载的iso,官网下的jar,编译android4.x需要安装jdk6,更高的版本会有问题,baidu到很多搭建环境的步 ...

随机推荐

  1. go语言基础之格式化输出

    1.fmt包的格式化输出输入 格式说明 格式 含义 %% 一个%字面量 %b 一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数 %c 字符型.可以把输入的数字按照A ...

  2. 用mysqlslap对MySQL进行压力测试

    MySQL5.1地的确提供了好多有力的工具来帮助我们DBA进行数据库管理.现在看一下这个压力测试工具mysqlslap.关于他的选项手册上以及--help介绍的很详细.我解释一下一些常用的选项.这里要 ...

  3. pjsip视频通信开发(底层实现)之用户注册(1)

    一.PJSIP简介 对于pjsip的介绍可以看http://www.cnblogs.com/my_life/articles/2175462.html 文章,里面详细介绍了它的组成框架以及各部份的组成 ...

  4. Deep Learning论文笔记之(一)K-means特征学习

    Deep Learning论文笔记之(一)K-means特征学习 zouxy09@qq.com http://blog.csdn.net/zouxy09          自己平时看了一些论文,但老感 ...

  5. 转:Mac OS X下Sublime Text (V2.0.1)破解

    Mac OS X下Sublime Text (V2.0.1)破解 Mac OS X下Sublime Text (V2.0.1)破解 (2013-03-07 14:02:54) 转载▼     正版的买 ...

  6. winrar X64 win10 破解

    破解方法, win10 64位 复制下面内容到 RarReg.key 文件 RAR registration datawncnUnlimited Company LicenseUID=1b064ef8 ...

  7. 一种Android数据请求框架

    大部分Android应用一般都涉及到跟server的交互,除非是某些单机应用.既然要跟server打交道,向server请求数据差点儿是必做的事情,或许每家的APP都有一套自己的详细实现逻辑.但我们还 ...

  8. LoadRunner录制:事务

    背景 LoadRunner 会对事务的性能指标进行记录. 添加事务也是为了在测试的时候统计这段脚本运行时用的时间等等,方便定位性能瓶颈. 一个事务可以包含一个请求,也可以包含多个请求.一般把完成一件事 ...

  9. 完整的JavaScript版的信用卡校验代码

    function isValidCreditCard(type, ccnum) { if (type == "Visa") { // Visa: length 16, prefix ...

  10. [Done]java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

    java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed ...