1、各级子目录的Makefile:

  • obj-y += file.o
  • obj-y += subdir/

“obj-y += file.o” 表示把当前目录下的file.c编进程序里。

“obj-y += subdir/”表示进入subdir这个子目录下去寻找文件来编进子程序中;

2、顶层目录的Makefile:

CROSS_COMPILE =                        #如果要交叉编译的话,就是:CROSS_COMPILE = arm-linux-

AS           = $(CROSS_COMPILE)as

LD      = $(CROSS_COMPILE)ld

CC           = $(CROSS_COMPILE)gcc

CPP         = $(CC) -E

AR           = $(CROSS_COMPILE)ar

NM           = $(CROSS_COMPILE)nm

STRIP           = $(CROSS_COMPILE)strip

OBJCOPY         = $(CROSS_COMPILE)objcopy

OBJDUMP         = $(CROSS_COMPILE)objdump

export AS  LD CC CPP  AR  NM       #把上面定义的变量用export导出来,后面的子目录就能用:

export STRIP OBJCOPY OBJDUMP

CFLAGS := -Wall -O2 -g

CFLAGS += -I $(shell pwd)/include -I 。。。。      # -I 指定到哪个目录去搜索头文件。

LDFLAGS := -lm 。。。。。

export CFLAGS LDFLAGS      #把这两个也导出来。

TOPDIR := $(shell pwd)         #顶层目录

export TOPDIR

TARGET := show_file             #目标

  • obj-y += main.o
  • obj-y += 目录名如package/
  • obj-y += framework/

all :

make -C ./ -f $(TOPDIR)/Makefile.build

$(CC) $(LDFLAGS) -o $(TARGET) built-in.o

clean:

rm -f $(shell find -name "*.o")

rm -f $(TARGET)

distclean:

rm -f $(shell find -name "*.o")

rm -f $(shell find -name "*.d")

rm -f $(TARGET)

我们这个工程顶层有:main.c,还有package,framework等子目录

framwork子目录下又有libs、manager、services等子目录;

编译过程:

Makefile是先从子目录下开始执行的:

1> 执行顶层目录的makefile程序时,先进入顶层目录,发现有些文件和目录,将会进入如DSVICICOMSVC/

2> 进入子目录后,又会发现又有子目录的makefile,DSVICICOMSVC、DSVICICOMMGR,执行子目录的makefile;

3> 把test.c编译成test.o,把test目录下的.o文件打包成build_in.o

4> 经过多个子目录后,回到顶层目录.把main.c 编译成main.o ,并与各个子目录的build-in.o打包成最终的build-in.o.
make -C ./ -f  Makefile.build

3、顶层目录的Makefile.build:

这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o;

PHONY := __build      
#假目标

__build:

obj-y :=

subdir-y :=

include Makefile                      #包含当前目录的makefile,才知道目标是哪些目标和目录

# obj-y := a.o b.o c/ d/

# $(filter %/, $(obj-y))   : c/ d/

# __subdir-y  :
c d

# subdir-y    :
c d

__subdir-y    :=
$(patsubst %/,%,$(filter %/, $(obj-y)))

subdir-y   +=
$(__subdir-y)

# c/built-in.o d/built-in.o

subdir_objs := $(foreach
f,$(subdir-y),$(f)/built-in.o)

# a.o b.o

cur_objs := $(filter-out %/, $(obj-y))

dep_files := $(foreach f,$(cur_objs),.$(f).d)   #(foreach var,list,text) 结果是由空格隔开的‘text’ 在‘list’中多次扩展的字组成的新的‘list’

dep_files := $(wildcard $(dep_files))

ifneq ($(dep_files),)

include
$(dep_files)

endif

PHONY += $(subdir-y)

__build : $(subdir-y) built-in.o

$(subdir-y):

make -C $@ -f
$(TOPDIR)/Makefile.build

built-in.o : $(cur_objs)
$(subdir_objs)

$(LD)
-r -o $@ $^            #打包

dep_file = .$@.d

%.o
: %.c

$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<

.PHONY
: $(PHONY)

4、怎么使用这套Makefile:

1.把顶层Makefile, Makefile.build放入程序的顶层目录

2.修改顶层Makefile

2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET,这是用来指定编译出来的程序的名字

3. 在各一个子目录下都建一个Makefile,

形式为:

obj-y += file1.o
obj-y += file2.o
obj-y += subdir1/
obj-y += subdir2/

执行"make"来编译,执行"make
clean"来清除,执行"make distclean"来彻底清除

一个通用的Makefile(二)的更多相关文章

  1. 编写一个通用的Makefile文件

    1.1在这之前,我们需要了解程序的编译过程 a.预处理:检查语法错误,展开宏,包含头文件等 b.编译:*.c-->*.S c.汇编:*.S-->*.o d.链接:.o +库文件=*.exe ...

  2. Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile

    GNU Make简介 大型项目的开发过程中,往往会划分出若干个功能模块,这样可以保证软件的易维护性. 作为项目的组成部分,各个模块不可避免的存在各种联系,如果其中某个模块发生改动,那么其他的模块需要相 ...

  3. 一步一步写一个简单通用的makefile(二)

    这一篇源代码沿用上一篇的源代码hellomake.c hellofunc.c hellofunc.h makefile 但是代码内容和结构有变化,如下: . ├── include │   └── h ...

  4. 一个通用的Makefile (转)

    据http://bbs.chinaunix.net/thread-2300778-1-1.html的讨论,发现还是有很多人在问通用Makefile的问题,这里做一个总结.也作为以后的参考.       ...

  5. 14、编写一个通用的Makefile

    编译test_Makefile的方法:a. gcc -o test a.c b.c对于a.c: 预处理.编译(C文件转换成汇编).汇编(汇编转换成机器码)对于b.c:预处理.编译.汇编最后链接优点:命 ...

  6. 一步一步写一个简单通用的makefile(四)--写一个通用的makefile编译android可执行文件

    通常要把我们自己的的代码编译成在android里面编译的可执行文件,我们通常是建一个文件夹 . ├── Android.mk ├── Application.mk ├── convolve.cl ├─ ...

  7. 一个通用的makefile(一)

    最近在编写Android编译系统时,需要遍历每一个目录下每一个文件夹下的makefile,网上的方法有些繁琐 :就直接贴上自己遍历子目录深度为1:(for  temporary)(之后会继续更新) 下 ...

  8. 一个通用的Makefile框架

    先做一个简单的记录,后续有时间再慢慢完善补充细节. 先上一个整体图片: 其中,最重要的文件就是:program_template.mk. 下面是program_template.mk最重要的内容: $ ...

  9. 一个通用的makefile

    # ESDK the makefile setting file - chenwg@20131014 # you can modify "PC = 1" such as " ...

随机推荐

  1. Java的流程控制结构,细节详解

    位运算符 &与 |或 ^异或 <<左移 >>右移 >>>无符号右移  ~取反 注意:位运算是针对整数运算的 int i = 6,j = 10; 方式一 ...

  2. mysql与服务器之间的编码问题

    1.之前在练习一个java web的项目时,mysql的编码设置正确,服务器的编码也设置正确,但向mysql中存储数据时,就会出现乱码问题,后来发现是mysql与服务器之间的编码设置问题,以下是mys ...

  3. 深入理解计算机系统_3e 第八章家庭作业 CS:APP3e chapter 8 homework

    8.9 关于并行的定义我之前写过一篇文章,参考: 并发与并行的区别 The differences between Concurrency and Parallel +---------------- ...

  4. 聊聊属性方法property的用法

    写之前随便百度了一下博客,又看到廖雪峰的博客了.果然置顶的能力很强. 我想说其实property的用法并不是主要用来做类型检查.反而更多应该是用于简化操作的目的. 写之前想聊一个古老的话题.年初的时候 ...

  5. intellij安装lombok插件,解决注解@Slf4j注入后找不到变量log

    1.进入设置 2.搜索插件 3.安装

  6. MongodDB学习笔记(二)(复制)

    mongoDB的复制非常容易配置,其实现有两种方式,一种是主从复制,一种是复制集,前者的好处是容易配置,但是如果主服务器宕掉了,整个系统就崩溃了,后者的好处是如果主服务器宕掉了,其他服务器会通过投票选 ...

  7. Data Base mongodb driver2.5环境注意事项

    mongodb driver2.5环境注意事项 一.问题: 如果使用vs2012开发就会报这个错误: 未能加载文件或程序集“System.Runtime.InteropServices.Runtime ...

  8. ABP PUT、DELETE请求错误405.0 - Method Not Allowed 因为使用了无效方法(HTTP 谓词) 引发客户端错误 No 'Access-Control-Allow-Origin' header is present on the requested resource

    先请检查是否是跨域配置问题,请参考博客:http://www.cnblogs.com/donaldtdz/p/7882225.html 一.问题描述 ABP angular前端部署后,查询,新增都没问 ...

  9. Android Weekly Notes Issue #288

    Android Weekly Issue #288 December 17th, 2017 Android Weekly Issue #288 本期内容主要包括介绍Kotlin DSL使用kotlin ...

  10. bzoj 3932: [CQOI2015]任务查询系统

    Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si ...