赞
踩
今天是我闭关的第31天,离秋招更进一步了,加油!今天给大家带来Makefile,或许很多Winodws 的程序员都不知道这个东西,因为那Windows 的IDE都为你做了这个工作,但我觉得要作一个好的和 professional 的程序员,makefile 还是要懂。在Linux 下的软件编译,你就不能不自己写makefile 了,会不会写makefile,从一个侧面说明了一个人是否具备完 成大型工程的能力。
makefile 关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系 列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile 就像一个Shell 脚本一样,其中也可以执行操作系统的命令。
makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。
Linux内核的配置系统由三个部分组成,分别是:
①Makefile:分布在 Linux 内核源代码中的 Makefile,定义 Linux 内核的编译规则;
②配置文件(config.in):给用户提供配置选择的功能;
③配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses 图形界面以及基于 Xwindows 图形界面的用户配置界面,各自对应于 Make config、Make menuconfig 和 make xconfig)。
Makefile 的作用是根据配置的情况,构造出需要编译的源文件列表,然后分别 编译,并把目标代码链接到一起,最终形成 Linux 内核二进制文件。 由于 Linux 内核源代码是按照树形结构组织的,所以 Makefile 也被分布在目 录树中。Linux 内核中的 Makefile 以及与 Makefile 直接相关的文件有makefile: 顶层 Makefile,是整个内核配置、编译的总体控制文件。.config:内核配置文 件,包含由用户选择的配置选项,用来存放内核配置后的结果(如 make config)。 arch/*/Makefile:位于各种 CPU 体系目录下的 Makefile,如 arch/arm/Makefile, 是针对特定平台的 Makefile。各个子目录下的 Makefile:比如 drivers/Makefile,负责所在子目录下源代码的管理。 Rules.make:规则文件,被所有的 Makefile 使用。用户通过 make config 配置 后,产生了 .config。顶层 Makefile 读入 .config 中的配置选择。顶层 Makefile 有两个主要的任务:产生 vmlinux 文件和内核模块(module)。为了达到此目的, 顶层 Makefile 递归的进入到内核的各个子目录中,分别调用位于这些子目录中的 Makefile。 至于到底进入哪些子目录,取决于内核的配置。在顶层 Makefile 中,有一句:include arch/$(ARCH)/Makefile,包含了特定 CPU 体系结构下的 Makefile,这 Makefile 中包含了平台相关的信息位于各个子目录下的 Makefile 同样也根据 .config 给出的配置信息,构造出当前配置下需要的源文件列表,并在文件的最后有 include $(TOPDIR)/Rules.make。 Rules.make 文件起着非常重要的作用,它定义了所有 Makefile 共用的编译规则。比如,如果需要将本目录下所有的 c 程序编译成汇编代码,需要在 Makefile 中有以下的编译规则: %.s: %.c $(CC) $(CFLAGS) -S $< -o $@ 有很多子目录下都有同样的要求,就需要在各自的 Makefile 中包含此编译 规则,这会比较麻烦。而 Linux 内核中则把此类的编译规则统一放置到 Rules.make 中,并在各自的 Makefile 中包含进了 Rules.make(include Rules.make),这样就避免了在多个 Makefile 中重复同样的规则。 对于上面的例子,在 Rules.make 中对应的规则为: %.s: %.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o $@
目标:依赖文件
$^ 代表所有依赖文件
$@ 代表所有目标文件
$< 代表第一个依赖文件
% 代表通配符
@指令:屏蔽指令
定义变量(变量大写)
变量名=值1 值2 ...
使用变量 $(变量名)
#以'#'开头的行表示注释 #定义变量VAR,强制赋值为app VAR=test #在VAR之前定义的值后面再追加app这个值,这时该变量值扩展为testapp VAR+=app #如果之前VAR没有被定义,则定义并使用testapp;否则使用之前的值。 VAR?=testapp # 第一条目标为总的目标, # 依赖可以是文件(目录)或为其他目标 # 动作可以是Linux命令,动作的那一行必须以TAB键开头 target: depend1 depend2 depend3 ... [TAB] action1 [TAB ] action2 target1: [TAB] action1 [TAB] action2
事例:
假设我们有很多个文件(fun1.c fun2.c fun3.c main.h)
假设最后我们就想得到main一个文件
初级版:
.PHONY : clean
main : fun1.o fun2.o fun3.o main.o
gcc -g fun1.o fun2.o fun3.o main.o -o main
fun1.o : fun1.c main.h
gcc -Wall -c -g -o fun1.o
fun2.o : fun2.c main.h
gcc -Wall -c -g -o fun2.o
fun3.o : fun3.c main.h
gcc -Wall -c -g -o fun3.o
clean :
rm -rf *.o
升级版:
.PHONY : clean
FM=fun1.o fun2.o fun3.o main.o
main : $(FM)
(前面一个tab键)gcc -g $^ -o $@
%.c : %.o
(前面一个tab键)gcc -c -g - Wall $< -o $@
clean :
(前面一个tab键)rm -rf *.o
展示图:
Makefile是在Linux开发中经常用到的,曾经在学驱动开发的时候,深有体会,望大家努力学好!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。