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. 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代

    2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...

  2. Canvas坐标系转换

    默认坐标系与当前坐标系 canvas中的坐标是从左上角开始的,x轴沿着水平方向(按像素)向右延伸,y轴沿垂直方向向下延伸.左上角坐标为x=0,y=0的点称作原点.在默认坐标系中,每一个点的坐标都是直接 ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(71)-微信公众平台开发-公众号管理

    系列目录 思维导图 下面我们来看一个思维导图,这样就可以更快了解所需要的功能: 上一节我们利用了一个简单的代码例子,完成了与微信公众号的对话(给公众号发一条信息,并得到回复) 这一节将讲解公众号如何设 ...

  4. scp报错 -bash: scp: command not found

    环境:RHEL6.5 使用scp命令报错: [root@oradb23 media]# scp /etc/hosts oradb24:/etc/ -bash: scp: command not fou ...

  5. 不懂CSS的后端难道就不是好程序猿?

    由于H5在移动端的发展如日中天,现在大部分公司对高级前端需求也是到处挖墙角,前端薪资也随之水涨船高,那公司没有配备专用的前端怎么办呢? 作为老板眼中的“程序猿” 前端都不会是非常无能的表现,那作为后端 ...

  6. 【Java学习系列】第3课--Java 高级教程

    本文地址 可以拜读: 从零开始学 Java 分享提纲: 1. Java数据结构 2. Java 集合框架 3. Java泛型 4. Java序列化 5. Java网络编程 6. Java发送Email ...

  7. Flexible 弹性盒子模型之CSS flex-shrink 属性

    实例 让第二个元素收缩到其他元素的三分之一: 效果预览 div:nth-of-type(2){flex-shrink:3;} 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本号. 紧跟在 - ...

  8. H3 BPM让天下没有难用的流程之技术特性

    一.集成性  H3 BPM可以与其它系统进行多个层面的集成,满足企业的针对不同系统的集成需求. 图:多种集成维度 Ø  用户集成 可与企业现有系统进行组织架构同步或调用,也可以直接与AD 进行集成. ...

  9. Android中点击事件的实现方式

    在之前博文中多次使用了点击事件的处理实现,有朋友就问了,发现了很多按钮的点击实现,但有很多博文中使用的实现方式有都不一样,到底是怎么回事.今天我们就汇总一下点击事件的实现方式. 点击事件的实现大致分为 ...

  10. android Handler介绍

    Handler使用介绍: Handler根据接收的消息,处理UI更新.Thread线程发出消息,通知Handler更新UI. Handler mHandler = new Handler() {  p ...