一个通用的Makefile(二)
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(二)的更多相关文章
- 编写一个通用的Makefile文件
1.1在这之前,我们需要了解程序的编译过程 a.预处理:检查语法错误,展开宏,包含头文件等 b.编译:*.c-->*.S c.汇编:*.S-->*.o d.链接:.o +库文件=*.exe ...
- Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile
GNU Make简介 大型项目的开发过程中,往往会划分出若干个功能模块,这样可以保证软件的易维护性. 作为项目的组成部分,各个模块不可避免的存在各种联系,如果其中某个模块发生改动,那么其他的模块需要相 ...
- 一步一步写一个简单通用的makefile(二)
这一篇源代码沿用上一篇的源代码hellomake.c hellofunc.c hellofunc.h makefile 但是代码内容和结构有变化,如下: . ├── include │ └── h ...
- 一个通用的Makefile (转)
据http://bbs.chinaunix.net/thread-2300778-1-1.html的讨论,发现还是有很多人在问通用Makefile的问题,这里做一个总结.也作为以后的参考. ...
- 14、编写一个通用的Makefile
编译test_Makefile的方法:a. gcc -o test a.c b.c对于a.c: 预处理.编译(C文件转换成汇编).汇编(汇编转换成机器码)对于b.c:预处理.编译.汇编最后链接优点:命 ...
- 一步一步写一个简单通用的makefile(四)--写一个通用的makefile编译android可执行文件
通常要把我们自己的的代码编译成在android里面编译的可执行文件,我们通常是建一个文件夹 . ├── Android.mk ├── Application.mk ├── convolve.cl ├─ ...
- 一个通用的makefile(一)
最近在编写Android编译系统时,需要遍历每一个目录下每一个文件夹下的makefile,网上的方法有些繁琐 :就直接贴上自己遍历子目录深度为1:(for temporary)(之后会继续更新) 下 ...
- 一个通用的Makefile框架
先做一个简单的记录,后续有时间再慢慢完善补充细节. 先上一个整体图片: 其中,最重要的文件就是:program_template.mk. 下面是program_template.mk最重要的内容: $ ...
- 一个通用的makefile
# ESDK the makefile setting file - chenwg@20131014 # you can modify "PC = 1" such as " ...
随机推荐
- 《RabbitMQ Tutorial》译文 第 6 章 远程过程调用(RPC)
原文来自 RabbitMQ 英文官网的教程(6.Remote procedure call - RPC),其示例代码采用了 .NET C# 语言. In the second tutorial we ...
- Java数组的一些使用方法及堆栈存储
数组 用于存储一组同一数据类型数据的容器 数组会对放入其中的数据自动编号,编号是从0开始的---下标 定义格式 数据类型[] 数组名 = new 数据类型[数组的大小];---可以先声明再初始化 in ...
- MFC学习之CWinApp类
CWinApp是一个基类,你通过它来继承Windows应用程序对象.应用程序对象为你提供了初始化应用程序(以及它的每一个实例 和运行应用程序所需的成员函数.它实现主事件循环并把事件分发给MFC中其他类 ...
- MyBatis学习总结(一)简单入门案例
MyBatis学习总结(一)简单入门案例 主要内容:本文主要通过对数据库中的use表进行增删改查总结mybatis的环境搭建和基本入门使用 一.需要的jar包: 1.核心包 2.依赖包 3.jdbc数 ...
- OC学习10——内存管理
1.对于面向对象的语言,程序需要不断地创建对象.这些对象都是保存在堆内存中,而我们的指针变量中保存的是这些对象在堆内存中的地址,当该对象使用结束之后,指针变量指向其他对象或者指向nil时,这个对象将称 ...
- 在IntelliJ IDEA里创建简单的基于Maven的SpringMVC项目
后来发现了一种更加方便的创建方式,即第一步不选择Create from archetype,创建完毕后打开Project Structure-Modules,然后添加Web,但是注意添加的Web里面的 ...
- lesson - 4 Linux目录文件管理
内容概要:1. 和目录相关的几个命令mkdir 关注-p选项 rmdir 同样也有一个-p选项rm -r -f 两个常用选项cp -r 针对目录, 有时我们使用/bin/cpmv 重命名或者移动, 有 ...
- vue 自定义指令directive
//自定义指令:directive 的传参--可以数据也可以是字符串 Vue.directive('scroll', function (binding) { window.addEventListe ...
- Python第二十二天 stat模块 os.chmod方法 os.stat方法 pwd grp模块
Python第二十二天 stat模块 os.chmod方法 os.stat方法 pwd grp模块 stat模块描述了os.stat(filename)返回的文件属性列表中各值的意义,根据 ...
- zabbix 图形插件 Grafana的安装
看http://www.myexception.cn/software-testing/2008870.html 就好了.