1.1在这之前,我们需要了解程序的编译过程

a.预处理:检查语法错误,展开宏,包含头文件等

b.编译:*.c-->*.S

c.汇编:*.S-->*.o

d.链接:.o +库文件=*.exe

1.2体验在VC下程序的编译

a.先编译,在链接

b.修改了哪个文件,就单独编译此文件,在链接

c.修改了哪个头文件,就单独编译使用该头文件的源文件,在链接

1.3在linux下实现上述要求

2.编写一个测试的Makefile

2.1直接编译链接

gcc -o test a.c b.c

缺点:改变其中一个文件,还需要重新编译所有文件,最后链接,效率低

2.2编写一个通用的Makefile

核心:规则

目标:依赖1 依赖2...

  命令

命令的执行条件:

a.依赖文件比目标文件新

b.没有目标文件

2.2.1一个简单的Makefile文件

test:a.c b.c a.h
gcc -o test a.c b.c

缺点:当其中一个文件发生改变时,另一个文件又将从新编译链接

2.2.2针对上述,改为如下

test:a.o b.o
gcc -o test a.o b.o a.o : a.c
gcc -c -o a.o a.c b.o : b.c
gcc -c -o b.o b.c

缺点:a.如果test依赖于多个文件,将写许多代码。

b.修改a.h程序没有反应。

2.2.3

针对上述a,可将其改为通配符;针对b,可增加“a.o:a.c a.h”这段代码。

$@:表示目标;$^:表示全部依赖;$<:第一个依赖。

test:a.o b.o
gcc -o test a.o b.o a.o:a.c a.h %.o : %.c
gcc -c -o $@ $<

缺点:如果一个文件的头文件非常多,不可能一个一个列出来,应该生成一个依赖文件。

2.2.4生成依赖文件

wildcard:检查文件是否存在

-Wp,-MD:生成依赖文件

objs := a.o b.o

test:$(objs)
gcc -o test $^ # .a.o.d .b.o.d
dep_files := $(foreach f,$(objs),.$(f).d)//对于objs里的每个文件,生成对应的依赖文件。eg:a.o-->.a.o.d
dep_files := $(wildcard $(dep_files)) ifneq ($(dep_files),)
include $(dep_files)
endif %.o : %.c
gcc -Wp,-MD,.$@.d -c -o $@ $< clean:
rm *.o test

3.参照内核的Makefile和上述的test_Makefile,编写一个通用的Makefile

3.1子目录下的Makefile
   它最简单,形式如下:
obj-y += file.o
obj-y += subdir/
   
   "obj-y += file.o"表示把当前目录下的file.c编进程序里,
   "obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。

注意: "subdir/"中的斜杠"/"不可省略

3.2顶层目录的Makefile:
   它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数──就是文件中用export导出的各变量。

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 STRIP OBJCOPY OBJDUMP CFLAGS := -Wall -O2 -g //编译选项
CFLAGS += -I $(shell pwd)/include LDFLAGS := -lm -lfreetype //链接选项 export CFLAGS LDFLAGS TOPDIR := $(shell pwd)
export TOPDIR TARGET := show_file obj-y += main.o
obj-y += display/
obj-y += draw/
obj-y += encoding/
obj-y += fonts/ all :
make -C ./ -f $(TOPDIR)/Makefile.build //打开文件,按照顶层目录下的Makefile.build来编译
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o //link 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)

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

PHONY := __build
__build: obj-y :=
subdir-y := include Makefile
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o) cur_objs := $(filter-out %/, $(obj-y))
dep_files := $(foreach f,$(cur_objs),.$(f).d)
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)

编写一个通用的Makefile文件的更多相关文章

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

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

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

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

  3. 一个简单的makefile文件

    一个简单的makefile文件:可以编译指定目录下的所有c和cpp文件,暂未加入自动头文件的依赖. #!/bin/bash #编译器 CROSS_COMPILING_PATH = #源文件路径 VPA ...

  4. 一个简单的makefile文件编写

    下午闲来无聊,就打开很久没动过的linux系统想熟悉熟悉在linux上面编译代码,结果一个makefile文件搞到晚上才搞定,哈哈! 先把代码简单贴上来,就写了一个冒泡排序: sort.h: #ifn ...

  5. 一个通用的Makefile (转)

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

  6. 一个通用的makefile(一)

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

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

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

  8. 一个通用的Makefile(二)

    1.各级子目录的Makefile: obj-y += file.o obj-y += subdir/ “obj-y += file.o” 表示把当前目录下的file.c编进程序里. “obj-y += ...

  9. 一个通用的Makefile框架

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

随机推荐

  1. jsp中出现onclick函数提示Cannot return from outside a function or method

    在使用Myeclipse10部署完项目后,原先不出错的项目,会有红色的叉叉,JSP页面会提示onclick函数错误 Cannot return from outside a function or m ...

  2. Android 几种消息推送方案总结

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6241354.html 首先看一张国内Top500 Android应用中它们用到的第三方推送以及所占数量: 现 ...

  3. AI人工智能系列随笔:syntaxnet 初探(1)

    人工智能是 最近的一个比较火的名词,相信大家对于阿尔法狗都不陌生吧?其实我对人工智能以前也是非常抵触的,因为我认为机器人会取代人类,成为地球乃至宇宙的霸主,但是人工智能带给我的这种冲击,我个人感觉是欲 ...

  4. python 数据类型---文件二

    1.打印进度条 import sys,time for i in range(20): sys.stdout.write("#") sys.stdout.flush() #不等缓冲 ...

  5. 【JavaScript】javascript中伪协议(javascript:)使用探讨

    javascript:这个特殊的协议类型声明了URL的主体是任意的javascript代码,它由javascript的解释器运行. 比如下面这个死链接: <a href="javasc ...

  6. Create a bridge using a tagged vlan (8021.q) interface

    SOLUTION VERIFIED April 27 2013 KB26727 Environment Red Hat Enterprise Linux 5 Red Hat Enterprise Li ...

  7. OpenGL shader 中关于顶点坐标值的思考

    今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...

  8. AlloyTeam2015前端大会都说了啥

    昨天在腾讯大厦参与了鹅厂AlloyTeam召开的AC2015前端大会,度过了充满精彩和收获的一个下午,用一句话形容这次前端Event应该是“诚意满满,干货满满”. 说实话,这次AlloyTeam没有对 ...

  9. MVVM大比拼之AngularJS源码精析

    MVVM大比拼之AngularJS源码精析 简介 AngularJS的学习资源已经非常非常多了,AngularJS基础请直接看官网文档.这里推荐几个深度学习的资料: AngularJS学习笔记 作者: ...

  10. 浅谈命令查询职责分离(CQRS)模式

    在常用的三层架构中,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体.在一些业务逻辑简单的系统中可能没有什么问题,但是随着系统逻辑变得复杂,用户增多,这种设计就会出现一些性能 ...