首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的。

意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文件直接复制到相应目录即可方便编译出所有文件。这些makefile文件是通用的,只需根据自己的工程情况改动少许内容即可。下面会说。

总体思路是:把目标文件放在debug文件夹下的obj目录下,把最终的二进制文件放在debug文件夹下的bin目录下;如何递归编译所有除了debug目录下的makefile文件呢:获得当前目录下的所有子目录,执行子目录下的makefile文件;获取当前目录下的所有c文件,编译c文件并放到指定的目标文件夹下。最后再执行debug目录下的makefile文件生成bin文件。

注意:除了debug文件夹比较特殊外,其他的子目录下都需要有Makefile文件,而且这些Makefile是相同的,除了根目录下的makefile文件有些不同外。即除了bin和obj目录以外的其他目录都需要Makefile文件,即使目录下没有c文件或者其他目录。

过程:首先在根目录下新建一个debug文件夹,debug文件夹下有bin目录和obj目录和一个Makefile文件,结构如下图。(这个debug文件里的makefile文件需要最后执行)(tree工具需要自己安装的,ubuntu下直接输入sudo apt-get install tree即可,但有时可能需要先sudo apt-get update才行)

整个目录结果如下图:

然后在根目录下新建Makefile文件,根目录下也可能会有c文件,故也需处理根目录下的c文件,内容如下:

#设置编译器
CC=gcc
#debug文件夹里的makefile文件需要最后执行,所以这里需要执行的子目录要排除debug文件夹,这里使用awk排除了debug文件夹,读取剩下的文件夹
SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "debug") print $$9}')
#无需下一行的注释代码,因为我们已经知道debug里的makefile是最后执行的,所以最后直接去debug目录下执行指定的makefile文件就行,具体下面有注释
#DEBUG=$(shell ls -l | grep ^d | awk '{if($$9 == "debug") print $$9}')
#记住当前工程的根目录路径
ROOT_DIR=$(shell pwd)
#最终bin文件的名字,可以更改为自己需要的
BIN=myapp
#目标文件所在的目录
OBJS_DIR=debug/obj
#bin文件所在的目录
BIN_DIR=debug/bin
#获取当前目录下的c文件集,放在变量CUR_SOURCE中
CUR_SOURCE=${wildcard *.c}
#将对应的c文件名转为o文件后放在下面的CUR_OBJS变量中
CUR_OBJS=${patsubst %.c, %.o, $(CUR_SOURCE)}
#将以下变量导出到子shell中,本次相当于导出到子目录下的makefile中
export CC BIN OBJS_DIR BIN_DIR ROOT_DIR
#注意这里的顺序,需要先执行SUBDIRS最后才能是DEBUG
all:$(SUBDIRS) $(CUR_OBJS) DEBUG
#递归执行子目录下的makefile文件,这是递归执行的关键
$(SUBDIRS):ECHO
make -C $@
DEBUG:ECHO
#直接去debug目录下执行makefile文件
make -C debug
ECHO:
@echo $(SUBDIRS)
#将c文件编译为o文件,并放在指定放置目标文件的目录中即OBJS_DIR
$(CUR_OBJS):%.o:%.c
$(CC) -c $^ -o $(ROOT_DIR)/$(OBJS_DIR)/$@
CLEAN:
@rm $(OBJS_DIR)/*.o
@rm -rf $(BIN_DIR)/*

上面的注释很详细了,具体的命令如果不清楚,自己可以google一下,譬如:wildcard patsubst awk等

读者可以根据自己的需要更改自己的debug目录和目标文件目录和bin文件目录

其他子目录下的Makefile文件的内容如下:

#子目录的Makefile直接读取其子目录就行
SUBDIRS=$(shell ls -l | grep ^d | awk '{print $$9}')
#以下同根目录下的makefile的相同代码的解释
CUR_SOURCE=${wildcard *.c}
CUR_OBJS=${patsubst %.c, %.o, $(CUR_SOURCE)}
all:$(SUBDIRS) $(CUR_OBJS)
$(SUBDIRS):ECHO
make -C $@
$(CUR_OBJS):%.o:%.c
$(CC) -c $^ -o $(ROOT_DIR)/$(OBJS_DIR)/$@
ECHO:
@echo $(SUBDIRS)

debug目录下的Makefile文件如下:

OBJS=*.o
ODIR=obj
$(ROOT_DIR)/$(BIN_DIR)/$(BIN):$(ODIR)/$(OBJS)
  $(CC) -o $@ $^

最后只需在根目录下,我的是我的根目录makefile目录下,执行make命令即可:

结果目录结果为:

然后执行". debug/bin/myapp"即可;最后可以执行make CLEAN清楚掉所有的目标文件和bin文件。

参考资料为:http://blog.csdn.net/zplove003/article/details/7066595

关于makefile文件的编写,见一下链接:跟我一起写makefile和http://wiki.ubuntu.org.cn/index.php?title=%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile&variant=zh-cn

【转】多文件目录下makefile文件递归执行编译所有c文件的更多相关文章

  1. 多文件目录下makefile文件递归执行编译所有c文件

    首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的. 意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文 ...

  2. 问题006:为什么用java.exe执行编译的类文件的时候,不这样写java Welcome.class

    为什么用java.exe执行编译的类文件的时候,不这样写java Welcome.class 是因为java虚拟机调用Welcome的时候,已经替我们增减了.class,如果你还要写java Welc ...

  3. 多个文件目录下Makefile的写法

    1.前言 目前从事于linux下程序开发,涉及到多个文件,多个目录,这时候编译文件的任务量比较大,需要写Makefile.关于Makefile的详细内容可以参考网上流传非常广泛的<跟我一起写Ma ...

  4. [转] 多个文件目录下Makefile的写法

    1.前言 目前从事于linux下程序开发,涉及到多个文件,多个目录,这时候编译文件的任务量比较大,需要写Makefile.关于Makefile的详细内容可以参考网上流传非常广泛的<跟我一起写Ma ...

  5. 关于H5项目开发中TS(或JS)文件按照顺序编译成一个文件的记录

    由于js的执行特性,多个js文件合成一个文件或者进行多个js文件加载时,时需要按照指定的顺序进行的,否则会出现报错的情况. 我们看一下目前几个主流H5引擎的做法. 白鹭的做法 当前版本的做法 在tsc ...

  6. JavaSE 文件递归之删除&amp;获取文件夹文件夹中全部的以.jpg的文件的绝对路径

    1.递归删除文件 假设一个文件夹以下还有子文件夹,进行删除的话会 报错,这个时候要使用递归的方式来删除这个文件文件夹中的全部文件以及文件夹 package cn.itcast.digui; impor ...

  7. 使用gcc命令编译多个文件

    使用g++命令直接一次性编译多个文件 这里以简单的HelloWorld程序为例,假设我们一共有三个文件:main.cpp,HelloWorld.cpp和HelloWorld.h. 其中HelloWor ...

  8. 【转载】Linux下makefile详解--跟我一起写 Makefile

    概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...

  9. 2.linux下Makefile编写规范

    转自陈皓 (CSDN) 概述—— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和 profession ...

随机推荐

  1. Hibernate中Session的几个方法的简单说明

    Hibernate对普通JDBC的操作进行了轻量级的封装,使得开发人员可以利用Session对象以面向对象的思想来实现对关系数据库的操作. 一般通过Configuration对象读取相应的配置文件来创 ...

  2. python3-day6(模块)

    一.OS模块 1.os.system('ls -l') #子shell运行,获取返回值,不是结果. 2.os.popen('ls -l').read() #获取结果. 二.sys模块 1.sys.ar ...

  3. http接口测试浏览器插件

    http接口测试浏览器插件: Chrome: https://chrome.google.com/webstore/detail/chrome-poster/cdjfedloinmbppobahmon ...

  4. Android 按二次后退键退出应用程序

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  5. JSON解析---初识

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式 全然独立于语言的文本格式 易于人阅读和编写 易于解析和生成 (网络传输速度快) JSON语法规则 数据在 ...

  6. VC6.0建立控制台程序实现PDA应用

    作者:iamlaosong 由于须要,又写起了文本界面的程序,以便PDA通过telnet连上运行. 假设是Linuxserver的话.这是非常easy的事,但是用户server是windows ser ...

  7. Python安装后在CMD命令行下出现“应用程序无法启动.............”问题

    问题存在之一:系统是刚刚重做的精简版服务器系统(阉割版) AN就是在阿里云上刚开的Windows Server 2008 系统上碰到的  吓尿了都 症状:            正常安装python环 ...

  8. Sass函数--颜色函数--RGB颜色函数

    RGB颜色函数-RGB()颜色函数 主要分为 RGB , HSL 和 Opacity 三大函数,当然其还包括一些其他的颜色函数,比如说 adjust-color 和 change-color 等.1. ...

  9. Chinese_PRC_CI_AS and SQL_Latin1_General_CP1_CI_AS类型错误

    在编写存储过程时,经常会用到临时表,而且往往会使用临时表与正式表相关联. 当临时表与正式表关联的字段是字符类型的时候,因为临时表创建的字符类型会默认数据库的编码,而正式表的字符编码可能不同,那么这个时 ...

  10. (原).cc 和 .cpp 后缀结尾的文件的区别

    This caused a few problems the first time C++ was ported to a system where case wasn't significant i ...