层级目录结构的Makefile编写方法.

0.前言

假如现在有这样一个目录结构:

要怎么实现简洁的自动化编译呢?

现在我想要实现的效果 
1.在顶级目录,直接make即可编译整个工程. 
2.可以很方便的在Makefile中添加或过滤掉只有我想编译的目录或不需要编译的目录. 
3.新添加的模块,只需要直接编写本模块的Makefile即可,其余地方不需要改动. 
4.将所有输出的目标文件和可执行文件,定向输出到指定目录(如out/bin;out/obj)

因为新建的工程,暂且就这些基本功能,如果还有没实现的好目标,再继续添加.

接下来一个一个目标的看看怎么实现.

1.如何编译整个工程

想要编译整个工程,那么所有需要编译的目录都要能够编译. 
最简单的方法:依依编译每一个需要的目录. 
如:


WIFI := wifi
BLUETOOTH := bluetooth
all:
cd $(WIFI); make
cd $(BLUETOOTH); make

很直观,但是每个目录写一遍,就是每添加一个模块,你都得在Makefile里面加一句,写起来内容偏多.

另一种递归的编译层层目录. 
要这么做,首先需要获得每层目录下的目录名:


GET_SUBDIRS1 := $(shell find . -maxdepth 1 -type d)
GET_SUBDIRS2 := $(basename $(patsubst ./%,%,$(GET_SUBDIRS1)))
SUBDIRS := $(GET_SUBDIRS2)

之后在每层目录make -C 进入目录编译即可


all : $(SUBDIRS)
$(SUBDIRS) : ECHO
$(MAKE) -C $@
ECHO :
@echo "Compiling " $(SUBDIRS) "..."

2.过滤每层不需要编译的目录

有些不需要编译的目录,像include,env,document 
进去make会因为找不到make停止编译. 
所以我们需要在每层目录过滤掉所有不需要编译的目录. 
这里我们可以设置一个通用的Makefile环境文件,如Makefile.env


OBJOUT := $(ROOT_DIR)/out/obj/
EXEOUT := $(ROOT_DIR)/out/bin/
INCLUDE_DIR := $(ROOT_DIR)/source/include
MAKE := make
CC := gcc
GET_SUBDIRS1 := $(shell find . -maxdepth 1 -type d)
GET_SUBDIRS2 := $(basename $(patsubst ./%,%,$(GET_SUBDIRS1)))
GET_SUBDIRS3 := $(filter-out $(EX_INCLUDE),$(GET_SUBDIRS2))
SUBDIRS := $(GET_SUBDIRS3)

之后再每层的Makefile将Makefile.env包含进来,并里面配置一个EX_INCLUDE变量进行过滤. 
顶层目录Makefile:


CUR_DIR := $(shell pwd)
#ROOT_DIR := $(ROOT_DIRS)
SOURCE_DIR := $(CUR_DIR)/source
MAKEFILE_PARA := $(SOURCE_DIR)/Makefile.env
EX_INCLUDE := PlatformHeandle out document env
include $(MAKEFILE_PARA)
all : $(SUBDIRS)
$(SUBDIRS) : ECHO
$(MAKE) -C $@
ECHO :
@echo "Compiling " $(SUBDIRS) "..."

其余层的Makefile均是这样编写,只需要改一下Makefile.env的路径.

3将所有输出文件定向输出.

这个比较简单吧,只要知道根目录,然后直接在编译的时候输出到指定目录即可.


all: $(TARGET)
$(TARGET) : $(OBJ)
$(CC) $(CFLAGS) $(OBJOUT)$^ -o $(EXEOUT)$@
@echo "Compiling" $@ "end\n"
%.o : %.c
@echo "Compiling" $< "..."
$(CC) $(CFLAGS) -c $^ -o $(OBJOUT)$@
%.o : %.cpp
@echo "Compiling" $< "..."
$(CC) $(CFLAGS) -c $^ -o $(OBJOUT)$@

那么问题来了,底层的Makefile怎么知道根目录呢. 
上一级Makefile中的变量,底层Makefile是不知道的.

1.最呆的方法,写死的,每一层Makefile都来个相对根目录深度的../:


ROOT_DIR = ../../../

2.通过配置一个都知道的系统环境,我在env/env.sh里面声明. 
当然,env.sh 还可以干一些其他事,如创建out下的输出目录.


ROOT_DIRS=$(pwd)
export ROOT_DIRS
mkdir -p @{ROOT_DIRS}/out/bin
mkdir -p @{ROOT_DIRS}/out/obj

之后只要在根目录 source ./env/env.sh 即可,然后在Makefile里面取它.


ROOT_DIR := $(ROOT_DIRS)
SOURCE_DIR := $(ROOT_DIR)/source
MAKEFILE_PARA := $(SOURCE_DIR)/Makefile.para
EX_INCLUDE :=

这样即实现了这个工程简便的自动化编译了,以后也能很快捷的修改. 
如果有什么不足的地方或者更好的方法欢迎提出.

层级目录结构的Makefile递归编译方法的更多相关文章

  1. 一个适用于层级目录结构的makefile模版

    今天写了个层次化的Makefile模版,用来自动化编译项目,这个模版应当包含以下功能: 适用于层次化结构,Makefile主要内容都放在顶层目录下的Makefile.env中,子层Makefile包含 ...

  2. 二十一、【.Net开源框架】EFW框架Web前端开发之目录结构和使用FireBug调试方法

    回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.2:http://pan.baidu.com/s/1hcnuA EFW框架实例源代码下载:http://pan.baidu. ...

  3. [Makefile] 递归编译的Makefile的实现

    转自:http://www.linuxidc.com/Linux/2017-01/139702.htm 最近写了一个递归Makefile,目的是既可以实现子模块的单独编译,也可以不做任何修改就和整个程 ...

  4. 自定义一个compass可编译的目录结构

    在学习compass的过程中, 根绝文档说明,如果使用compass create myObject命令会创建一个标准的Compass项目目录结构,如下图: 此时如果使用compass compile ...

  5. 使用递归方法实现,向FTP服务器上传整个目录结构、从FTP服务器下载整个目录到本地的功能

    我最近由于在做一个关于FTP文件上传和下载的功能时候,发现Apache FTP jar包没有提供对整个目录结构的上传和下载功能,只能非目录类型的文件进行上传和下载操作,后来我查阅很多网上的实现方法,再 ...

  6. JAVA 实现将多目录多层级文件打成ZIP包后保留层级目录下载 ZIP压缩 下载

    将文件夹保留目录打包为 ZIP 压缩包并下载 上周做了一个需求,要求将数据库保存的 html 界面取出后将服务器下的css和js文件一起打包压缩为ZIP文件,返回给前台:在数据库中保存的是html标签 ...

  7. vue-cli 脚手架目录结构说明

    目录结构截图如下 /build 编译配置文件目录,由脚手架自动生成 /config webpack 配置文件目录,由脚手架自动生成 /node_modules node依赖目录,可通过package. ...

  8. (DT系列一)DTS结构及其编译方法

    DTS结构及其编译方法 一:主要问题 1,需要了解dtsi与dts的关系 2,dts的结构模型 3,dts是如何被编译的,以及编译后会生成一个什么文件. 二:参考文字 1,DTS(device tre ...

  9. 【转】(DT系列一)DTS结构及其编译方法----不错

    原文网址:http://www.cnblogs.com/biglucky/p/4057476.html DTS结构及其编译方法 一:主要问题 1,需要了解dtsi与dts的关系 2,dts的结构模型 ...

随机推荐

  1. 【学习笔记】FreeMarker 之于Servlet与Stuts2的应用

    FreeMarker应用在Servlet(0配置web.xml形式): 准备环境: tomcat7.eclipse最新版.jdk1.8.freemarker v2.3.20.jar 举例项目结构图: ...

  2. urllib模块和urllib2模块的区别

    一开始我以为urllib2模块单纯是urllib模块的升级版,因为我看到它们都有urlopen方法,但是经过查找资料,发现两者差别还是很大的. 这是我在网上看到的总结: urllib2可以接受一个Re ...

  3. Bzoj4763 雪辉

    Time Limit: 39 Sec  Memory Limit: 666 MBSubmit: 151  Solved: 80 Description 上次立下的NOIP退役Flag没有成功   这次 ...

  4. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  5. select 函数小结 -- 转自百度知道

    http://zhidao.baidu.com/link?url=UVTXeK4ncKmnwatGUW2deMFylNYBuur-zHmK3w53NXNRpgPbhld2WdkMD766nKl_6Hj ...

  6. php中各种hash算法的执行速度比较

    更多内容推荐微信公众号,欢迎关注: PHP中的Hash函数很多,像MD4.MD5.SHA-1.SHA-256.SHA-384.SHA-512等我们比较常见,那么各个哈希的执行速度呢? $algos = ...

  7. 2017-2018-2 20179205《网络攻防技术与实践》第十一周作业 SQL注入攻击与实践

    <网络攻防技术与实践>第十一周作业 SQL注入攻击与实践 1.研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究 缓冲区溢出原理   在计算机内部,输入数据通常被存放在一个临时空间内, ...

  8. Sort Colors I & II

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  9. Linux内存初始化【转】

    转自:http://www.cnblogs.com/super-king/p/3291120.html start_kernel -> setup_arch 在这个函数中我们主要看这几个函数. ...

  10. Django-模板继承、包含和静态文件配置

    一.模板继承 模板继承可以减少页面内容的重复定义,实现页面内容的重用 典型应用:网站的头部.尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义 block标签:在父模板中预留区域,在子模板 ...