make生成执行文件的过程

来源:互联网 发布:班班通教学软件下载 编辑:程序博客网 时间:2024/05/17 02:28

想要生成ucore.img

$(UCOREIMG): $(kernel) $(bootblock)    $(V)dd if=/dev/zero of=$@ count=10000    $(V)dd if=$(bootblock) of=$@ conv=notrunc    $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc

为了生成ucore.img,首先需要生成bootblock、kernel

    生成bootloaer相关代码    $(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)        @echo + ld $@        $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)        @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)        @$(OBJDUMP) -t $(call objfile,bootblock) | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,bootblock)        @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)        @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)

为了生成bootblock,首先需要生成bootasm.o、bootmain.o、sign

            生成bootasm.o,bootmain.o的相关makefile代码为            bootfiles = $(call listf_cc,boot)            $(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

为了生成bootasm.o需要bootasm.S

用gcc命令,把boot目录下的文件编译成obj/boot/*.o文件
 gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs \     -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc \     -c boot/bootasm.S -o obj/boot/bootasm.o

生成bootmain.o需要bootmain.c

 gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc \    -fno-stack-protector -Ilibs/ -Os -nostdinc \    -c boot/bootmain.c -o obj/boot/bootmain.o

bin/sign

生成sign工具的makefile代码为

用gcc把tools/sign.c编译成obj/sign/tools/sign.o;

生成的obj/sign/tools/sign.o,将obj/bootblock.o文件规范化为,符合规范的硬盘住引导扇区的文件bin/bootblock

 $(call add_files_host,tools/sign.c,sign,sign) $(call create_target_host,sign,sign) 实际命令为 gcc -Itools/ -g -Wall -O2 -c tools/sign.c \    -o obj/sign/tools/sign.o gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign

首先生成bootblock.o

用ld把obj/boot/*.o连接成obj/bootblock.o;
 ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 \    obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o

| | 拷贝二进制代码bootblock.o到bootblock.out

objcopy -S -O binary obj/bootblock.o obj/bootblock.out

使用sign工具处理bootblock.out,生成bootblock

bin/sign obj/bootblock.out bin/bootblock

bin/kernel

生成kernel的相关代码为

        $(kernel): tools/kernel.ld        $(kernel): $(KOBJS)        @echo + ld $@        $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)        @$(OBJDUMP) -S $@ > $(call asmfile,kernel)        @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)

为了生成kernel,

首先需要 kernel.ld init.o readline.o stdio.o kdebug.o
| | kmonitor.o panic.o clock.o console.o intr.o picirq.o trap.o
| | trapentry.o vectors.o pmm.o printfmt.o string.o
| | kernel.ld已存在

obj/kern//.o

生成这些.o文件的相关makefile代码为
obj/kern/init/init.o
编译需要init.c

先使用gcc命令,把./kern目录下的代码都编译成obj/kern//.o文件;
实际命令为    gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 \        -gstabs -nostdinc  -fno-stack-protector \        -Ilibs/ -Ikern/debug/ -Ikern/driver/ \        -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c \        -o obj/kern/init/init.o

生成kernel时,makefile的几条指令中有@前缀的都不必需

用ld命令通过/tools/kern.ls文件配置,把obj/kern//.o文件连接成bin/kern
|   | ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel \|   |   obj/kern/init/init.o obj/kern/libs/readline.o \|   |   obj/kern/libs/stdio.o obj/kern/debug/kdebug.o \|   |   obj/kern/debug/kmonitor.o obj/kern/debug/panic.o \|   |   obj/kern/driver/clock.o obj/kern/driver/console.o \|   |   obj/kern/driver/intr.o obj/kern/driver/picirq.o \|   |   obj/kern/trap/trap.o obj/kern/trap/trapentry.o \|   |   obj/kern/trap/vectors.o obj/kern/mm/pmm.o \|   |   obj/libs/printfmt.o obj/libs/string.o

生成一个有10000个块的文件,每个块默认512字节,用0填充

用dd命令创建了一个bin/ucore.img文件

dd if=/dev/zero of=bin/ucore.img count=10000

用dd命令把bin/bootblock写入bin/ucore.img文件

把bootblock中的内容写到第一个块
dd if=bin/bootblock of=bin/ucore.img conv=notrunc

用dd命令创bin/kernel写入bin/ucore.img文件

从第二个块开始写kernel中的内容
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc

==========================================================

以下是根据输出的结果分析:

生成bin/kernel–用ld命令通过/tools/kern.ls文件配置,把obj/kern//.o文件连接成bin/kern;

1、gcc命令,把./kern目录下的代码都编译成obj/kern//.o文件;

生成init.o
+ cc kern/init/init.c
gcc -Ikern/init/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o

生成stdio.o
+ cc kern/libs/stdio.c
gcc -Ikern/libs/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o

生成readline.o
+ cc kern/libs/readline.c
gcc -Ikern/libs/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o

生成panic.o
+ cc kern/debug/panic.c
gcc -Ikern/debug/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o

生成kdebug.o
+ cc kern/debug/kdebug.c
gcc -Ikern/debug/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o

生成kmonitor.o
+ cc kern/debug/kmonitor.c
gcc -Ikern/debug/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o

生成clock.o
+ cc kern/driver/clock.c
gcc -Ikern/driver/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o

生成console.o
+ cc kern/driver/console.c
gcc -Ikern/driver/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o

生成picirq.o
+ cc kern/driver/picirq.c
gcc -Ikern/driver/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o

生成intr.o
+ cc kern/driver/intr.c
gcc -Ikern/driver/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o

生成trap.o
+ cc kern/trap/trap.c
gcc -Ikern/trap/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o

生成vectors.o
+ cc kern/trap/vectors.S
gcc -Ikern/trap/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o

+ cc kern/trap/trapentry.Sgcc -Ikern/trap/ -fno-builtin  -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o

生成pmm.o

  • cc kern/mm/pmm.c
    gcc -Ikern/mm/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o

生成string.o

  • cc libs/string.c
    gcc -Ilibs/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -c libs/string.c -o obj/libs/string.o

生成printfmt.o

  • cc libs/printfmt.c
    gcc -Ilibs/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -c libs/printfmt.c -o obj/libs/printfmt.o

2、用ld命令通过/tools/kern.ls文件配置,把obj/kern//.o文件连接成bin/kern

连接.o文件生成bin/kernel

  • ld bin/kernel
    ld -m elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel obj/kern/init/init.o obj/kern/libs/stdio.o obj/kern/libs/readline.o obj/kern/debug/panic.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/picirq.o obj/kern/driver/intr.o obj/kern/trap/trap.o obj/kern/trap/vectors.o obj/kern/trap/trapentry.o obj/kern/mm/pmm.o obj/libs/string.o obj/libs/printfmt.o

生成bin/bootblock—用ld把obj/boot/*.o连接成obj/bootblock.o

3、用gcc命令,把boot目录下的文件编译成obj/boot/*.o文件

生成bootasm.o

  • cc boot/bootasm.S
    gcc -Iboot/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
    生成bootmain.o
  • cc boot/bootmain.c
    gcc -Iboot/ -fno-builtin -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o

生成bin/sign

//4、用gcc把tools/sign.c编译成obj/sign/tools/sign.o;
+ cc tools/sign.c
gcc -Itools/ -g -O2 -c tools/sign.c -o obj/sign/tools/sign.o
gcc -g -O2 obj/sign/tools/sign.o -o bin/sign

连接,生成bootblock

//使用第4步生成的obj/sign/tools/sign.o,将obj/bootblock.o文件规范化为,符合规范的硬盘住引导扇区的文件bin/bootblock
+ ld bin/bootblock
ld -m elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
‘obj/bootblock.out’ size: 468 bytes
build 512 bytes boot sector: ‘bin/bootblock’ success!

生成ucore.img

//用dd命令创建了一个bin/ucore.img文件
dd if=/dev/zero of=bin/ucore.img count=10000//生成一个有10000个块的文件,每个块默认512字节,用0填充
记录了10000+0 的读入
记录了10000+0 的写出
5120000字节(5.1 MB)已复制,0.219116 秒,23.4 MB/秒

dd if=bin/bootblock of=bin/ucore.img conv=notrunc//用dd命令把bin/bootblock写入bin/ucore.img文件;
记录了1+0 的读入
记录了1+0 的写出
512字节(512 B)已复制,0.000170474 秒,3.0 MB/秒

dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc//用dd命令创bin/kernel写入bin/ucore.img文件。
记录了138+1 的读入
记录了138+1 的写出
70824字节(71 kB)已复制,0.00297832 秒,23.8 MB/秒

==============================================================================

参数

GCCFLAGS
-g 是为了gdb能够对程序进行调试
-Wall 生成警告信息
-O2 优化处理(0,1,2,3表示不同的优化程度,0为不优化)
-fno-builtin 不接受非“__”开头的内建函数
-ggdb让gcc 为gdb生成比较丰富的调试信息
-m32 编译32位程序
-gstabs 此选项以stabs格式声称调试信息,但是不包括gdb调试信息
-nostdinc 不在标准系统目录中搜索头文件,只在-I指定的目录中搜索
-fstack-protector-all 启用堆栈保护,为所有函数插入保护代码
-E 仅作预处理,不进行编译、汇编和链接
-x c 指明使用的语言为C语言

LDFLAGS
-nostdlib 不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器
-m elf_i386使用elf_i386模拟器
-N把 text 和 data 节设置为可读写.同时,取消数据节的页对齐,同时,取消对共享库的连接.
-e func以符号func的位置作为程序开始运行的位置
-Ttext addr指定节在文件中的绝对地址为addr

命令及参数解释:

gcc: Linux下的C语言编译器。

ld:把一定量的目标文件跟档案文件连接起来,并重定位它们的数据,连接符号引用。一般,在编译一个程序时,最后一步就是运行’ld’。

用法:

ld [option] [objs…]
参数:

-o:指定输出文件名;
-e:指定程序的入口符号。
-m: 指定连接器
-N: 指定 可读写 的 正文 和 数据 节(section). 如果 输出格式 支持 Unix 风格的 幻数(magic number), 则 输出文件 标记为 OMAGIC.当 使用 `-N’ 选项 时, linker 不做数据段 的 页对齐(page-align).
-e: 设置程序开端
-T: 等同于 -c 告诉 ld 从指定文件中读取连接命令.
dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。

参数注释:

if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
bs=bytes:同时设置读入/输出的块大小为bytes个字节。
cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
注意:通常只用当输出文件是磁盘或磁带时才有效,即备份到磁盘或磁带时才有效。
count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
conv=conversion:用指定的参数转换文件。
ascii:转换ebcdic为ascii
ebcdic:转换ascii为ebcdic
ibm:转换ascii为alternate ebcdic
block:把每一行转换为长度为cbs,不足部分用空格填充
unblock:使每一行的长度都为cbs,不足部分用空格填充
lcase:把大写字符转换为小写字符
ucase:把小写字符转换为大写字符
swab:交换输入的每对字节
noerror:出错时不停止
notrunc:不截短输出文件
sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。
/dev/zero: 是一个输入设备,你可你用它来初始化文件。该设备无穷尽地提供0(是ASCII 0 就是NULL),