程序5‑1 linux/Makefile文件


  1 #

  2 # if you want the ram-disk device, define this to be the

  3 # size in blocks.

  4 #

    # 如果你要使用RAM(RAMDISK)设备的话就定义块的大小。这里默认RAMDISK没有定义(注释掉了),

    # 否则gcc编译时会带有选项'-DRAMDISK=512',参见第13行。

  5 RAMDISK = #-DRAMDISK=512

  6

  7 AS86    =as86 -0 -a       # 8086汇编编译器和连接器,见列表后的介绍。后带的参数含义分别

  8 LD86    =ld86 -0          # 是:-0 生成8086目标程序;-a 生成与gasgld部分兼容的代码。

  9

 10 AS      =gas              # GNU汇编编译器和连接器,见列表后的介绍。

 11 LD      =gld

    # 下面是GNU链接器gld运行时用到的选项。含义是:-s 输出文件中省略所有的符号信息;-x 删除

    # 所有局部符号;-M 表示需要在标准输出设备(显示器)上打印连接映像(link map),是指由连接程序

    # 产生的一种内存地址映像,其中列出了程序段装入到内存中的位置信息。具体来讲有如下信息:

    # • 目标文件及符号信息映射到内存中的位置;

    # • 公共符号如何放置;

    # • 连接中包含的所有文件成员及其引用的符号。

 12 LDFLAGS =-s -x -M

 

    # gccGNU C程序编译器。对于UNIX类的脚本(script)程序而言,在引用定义的标识符时,需在前

    # 面加上$符号并用括号括住标识符。

 13 CC      =gcc $(RAMDISK)

 

    # 下面指定gcc使用的选项。前一行最后的'\'符号表示下一行是续行。选项含义为:-Wall 打印所有

    # 警告信息;-O 对代码进行优化。'-f标志'指定与机器无关的编译标志。其中-fstrength-reduce

    # 于优化循环语句;-fcombine-regs用于指明编译器在组合编译阶段把复制一个寄存器到另一个寄存

    # 器的指令组合在一起。-fomit-frame-pointer 指明对于无需帧指针(Frame pointer)的函数不要

    # 把帧指针保留在寄存器中。这样在函数中可以避免对帧指针的操作和维护。-mstring-insns

    # Linus在学习gcc编译器时为gcc增加的选项,用于gcc-1.40在复制结构等操作时使用386 CPU

    # 字符串指令,可以去掉。

 14 CFLAGS  =-Wall -O -fstrength-reduce -fomit-frame-pointer \ 

 15 -fcombine-regs -mstring-insns

 

    # 下面cppgcc的前()处理器程序。前处理器用于进行程序中的宏替换处理、条件编译处理以及

    # 包含进指定文件的内容,即把使用'#include'指定的文件包含进来。源程序文件中所有以符号'#'

    # 开始的行均需要由前处理器进行处理。程序中所有'#define'定义的宏都会使用其定义部分替换掉。

    # 程序中所有'#if''#ifdef''#ifndef''#endif'等条件判别行用于确定是否包含其指定范围中

    # 的语句。

    # '-nostdinc -Iinclude'含义是不要搜索标准头文件目录中的文件,即不用系统/usr/include/目录

    # 下的头文件,而是使用'-I'选项指定的目录或者是在当前目录里搜索头文件。

 16 CPP     =cpp -nostdinc -Iinclude

 17

 18 #

 19 # ROOT_DEV specifies the default root-device when making the image.

 20 # This can be either FLOPPY, /dev/xxxx or empty, in which case the

 21 # default of /dev/hd6 is used by 'build'.

 22 #

    # ROOT_DEV指定在创建内核映像(image)文件时所使用的默认根文件系统所

    # 在的设备,这可以是软盘(FLOPPY)/dev/xxxx或者干脆空着,空着时

    # build程序(在tools/目录中)就使用默认值/dev/hd6

    #

    # 这里/dev/hd6对应第2个硬盘的第1个分区。这是Linus开发Linux内核时自己的机器上根

    # 文件系统所在的分区位置。/dev/hd2表示把第1个硬盘的第2个分区用作交换分区。

 23 ROOT_DEV=/dev/hd6

 24 SWAP_DEV=/dev/hd2

 25

    # 下面是kernel目录、mm目录和fs目录所产生的目标代码文件。为了方便引用在这里将它们用

    # ARCHIVES(归档文件)标识符表示。

 26 ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o

 

    # 块和字符设备库文件。'.a'表示该文件是个归档文件,也即包含有许多可执行二进制代码子程序

    # 集合的库文件,通常是用GNUar程序生成。arGNU的二进制文件处理程序,用于创建、修改

    # 以及从归档文件中抽取文件。

 27 DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a

 28 MATH    =kernel/math/math.a        # 数学运算库文件。

 29 LIBS    =lib/lib.a                 # lib/目录中的文件所编译生成的通用库文件。

 30

    # 下面是make老式的隐式后缀规则。该行指示make利用下面的命令将所有的'.c'文件编译生成'.s'

    # 汇编程序。':'表示下面是该规则的命令。整句表示让gcc采用前面CFLAGS所指定的选项以及仅使

    # include/目录中的头文件,在适当地编译后不进行汇编就停止(-S),从而产生与输入的各个C

    # 文件对应的汇编语言形式的代码文件。默认情况下所产生的汇编程序文件是原C文件名去掉'.c'

    # 再加上'.s'后缀。'-o'表示其后是输出文件的形式。其中'$*.s'(或'$@')是自动目标变量,'$<'

    # 代表第一个先决条件,这里即是符合条件'*.c'的文件。

    # 下面这3个不同规则分别用于不同的操作要求。若目标是.s文件,而源文件是.c文件则会使

    # 用第一个规则;若目录是.o,而原文件是.s,则使用第2个规则;若目标是.o文件而原文件

    # c文件,则可直接使用第3个规则。

 31 .c.s:

 32         $(CC) $(CFLAGS) \

 33         -nostdinc -Iinclude -S -o $*.s $<

 

    # 表示将所有.s汇编程序文件编译成.o目标文件。 整句表示使用gas编译器将汇编程序编译成.o

    # 目标文件。-c 表示只编译或汇编,但不进行连接操作。

 34 .s.o:

 35         $(AS) -c -o $*.o $<

    # 类似上面,*.c文件-à*.o目标文件。整句表示使用gccC语言文件编译成目标文件但不连接。

 36 .c.o:

 37         $(CC) $(CFLAGS) \

 38         -nostdinc -Iinclude -c -o $*.o $<

 39

 

    # 下面'all'表示创建Makefile所知的最顶层的目标。这里即是Image文件。这里生成的Image文件

    # 即是引导启动盘映像文件bootimage。若将其写入软盘就可以使用该软盘引导Linux系统了。在

    # Linux下将Image写入软盘的命令参见46行。DOS系统下可以使用软件rawrite.exe

 40 all:    Image

 41

    # 说明目标(Image文件)是由冒号后面的4个元素产生,分别是boot/目录中的bootsectsetup

    # 文件、tools/目录中的systembuild文件。42--43行这是执行的命令。42行表示使用tools

    # 录下的build工具程序(下面会说明如何生成)将bootsectsetupsystem文件以$(ROOT_DEV)

    # 为根文件系统设备组装成内核映像文件Image。第43行的sync同步命令是迫使缓冲块数据立即写盘

    # 并更新超级块。

 42 Image: boot/bootsect boot/setup tools/system tools/build

 43         tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) \

 44                 $(SWAP_DEV) > Image

 45         sync

 46

    # 表示disk这个目标要由Image产生。ddUNIX标准命令:复制一个文件,根据选项进行转换和格

    # 式化。bs=表示一次读/写的字节数。if=表示输入的文件,of=表示输出到的文件。这里/dev/PS0

    # 指第一个软盘驱动器(设备文件)。在Linux系统下使用/dev/fd0

 47 disk: Image

 48         dd bs=8192 if=Image of=/dev/PS0

 49

 50 tools/build: tools/build.c            # tools目录下的build.c程序生成执行程序build

 51         $(CC) $(CFLAGS) \

 52         -o tools/build tools/build.c  # 编译生成执行程序build的命令。

 53

 54 boot/head.o: boot/head.s              # 利用上面给出的.s.o规则生成head.o目标文件。

 55

    # 表示tools目录中的system文件要由冒号右边所列的元素生成。56--61行是生成system的命令。

    # 最后的 > System.map 表示gld需要将连接映像重定向存放在System.map文件中。

    # 关于System.map文件的用途参见注释后的说明。

 56 tools/system:   boot/head.o init/main.o \

 57                 $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)

 58         $(LD) $(LDFLAGS) boot/head.o init/main.o \

 59         $(ARCHIVES) \

 60         $(DRIVERS) \

 61         $(MATH) \

 62         $(LIBS) \

 63         -o tools/system > System.map

 64

    # 数学协处理函数文件math.a64行上的命令实现:进入kernel/math/目录;运行make工具程序。

 65 kernel/math/math.a:

 66         (cd kernel/math; make)

 67

 68 kernel/blk_drv/blk_drv.a:           # 生成块设备库文件blk_drv.a,其中含有可重定位目标文件。

 69         (cd kernel/blk_drv; make)

 70

 71 kernel/chr_drv/chr_drv.a:           # 生成字符设备函数文件chr_drv.a

 72         (cd kernel/chr_drv; make)

 73

 74 kernel/kernel.o:                    # 内核目标模块kernel.o

 75         (cd kernel; make)

 76

 77 mm/mm.o:                            # 内存管理模块mm.o

 78         (cd mm; make)

 79

 80 fs/fs.o:                            # 文件系统目标模块fs.o

 81         (cd fs; make)

 82

 83 lib/lib.a:                          # 库函数lib.a

 84         (cd lib; make)

 85

 86 boot/setup: boot/setup.s                        # 这里开始的三行是使用8086汇编和连接器

 87         $(AS86) -o boot/setup.o boot/setup.s    # setup.s文件进行编译生成setup文件。

 88         $(LD86) -s -o boot/setup boot/setup.o   # -s 选项表示要去除目标文件中的符号信息。

 89

 90 boot/setup.s:   boot/setup.S include/linux/config.h       # 执行C语言预处理,替换*.S

 91         $(CPP) -traditional boot/setup.S -o boot/setup.s  # 件中的宏生成对应的*.s文件。

 92

 93 boot/bootsect.s:        boot/bootsect.S include/linux/config.h

 94         $(CPP) -traditional boot/bootsect.S -o boot/bootsect.s

 95

 96 boot/bootsect:  boot/bootsect.s                 # 同上。生成bootsect.o磁盘引导块。

 97         $(AS86) -o boot/bootsect.o boot/bootsect.s

 98         $(LD86) -s -o boot/bootsect boot/bootsect.o

 99

    # 当执行'make clean'时,就会执行98--103行上的命令,去除所有编译连接生成的文件。

    # 'rm'是文件删除命令,选项-f含义是忽略不存在的文件,并且不显示删除信息。

100 clean:

101         rm -f Image System.map tmp_make core boot/bootsect boot/setup \

102                 boot/bootsect.s boot/setup.s

103         rm -f init/*.o tools/system tools/build boot/*.o

104         (cd mm;make clean)       # 进入mm/目录;执行该目录Makefile文件中的clean规则。

105         (cd fs;make clean)

106         (cd kernel;make clean)

107         (cd lib;make clean)

108

    # 该规则将首先执行上面的clean规则,然后对linux/目录进行压缩,生成'backup.Z'压缩文件。

    # 'cd .. '表示退到linux/的上一级(父)目录;'tar cf - linux'表示对linux/目录执行tar归档

    # 程序。'-cf'表示需要创建新的归档文件 '| compress -'表示将tar程序的执行通过管道操作('|')

    # 传递给压缩程序compress,并将压缩程序的输出存成backup.Z文件。

109 backup: clean

110         (cd .. ; tar cf - linux | compress - > backup.Z)

111         sync                                    # 迫使缓冲块数据立即写盘并更新磁盘超级块。

112

113 dep: 

# 该目标或规则用于产生各文件之间的依赖关系。创建这些依赖关系是为了让make命令用它们来确定

# 是否需要重建一个目标对象。比如当某个头文件被改动过后,make就能通过生成的依赖关系,重新

# 编译与该头文件有关的所有*.c文件。具体方法如下:

    # 使用字符串编辑程序sedMakefile文件(这里即是本文件)进行处理,输出为删除了Makefile

    # 文件中'### Dependencies'行后面的所有行,即删除了下面从122开始到文件末的所有行,并生成

    # 一个临时文件tmp_make(也即114行的作用)。然后对指定目录下(init/)的每一个C文件(其实

    # 只有一个文件main.c)执行gcc预处理操作。标志'-M'告诉预处理程序cpp输出描述每个目标文件

    # 相关性的规则,并且这些规则符合make语法。对于每一个源文件,预处理程序会输出一个规则,其

    # 结果形式就是相应源程序文件的目标文件名加上其依赖关系,即该源文件中包含的所有头文件列表。

    # 然后把预处理结果都添加到临时文件tmp_make中,最后将该临时文件复制成新的Makefile文件。

    # 115行上的'$$i'实际上是'$($i) '。这里'$i'是这句前面的shell变量'i'的值。

114         sed '/\#\#\# Dependencies/q' < Makefile > tmp_make

115         (for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make

116         cp tmp_make Makefile

117         (cd fs; make dep)                  # fs/目录下的Makefile文件也作同样的处理。

118         (cd kernel; make dep)

119         (cd mm; make dep)

120

121 ### Dependencies:

122 init/main.o : init/main.c include/unistd.h include/sys/stat.h \

123   include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \

124   include/sys/utsname.h include/sys/param.h include/sys/resource.h \

125   include/utime.h include/linux/tty.h include/termios.h include/linux/sched.h \

126   include/linux/head.h include/linux/fs.h include/linux/mm.h \

127   include/linux/kernel.h include/signal.h include/asm/system.h \

128   include/asm/io.h include/stddef.h include/stdarg.h include/fcntl.h \

129   include/string.h