Makefile

Makefile for boot

Makefile

# Makefile for boot

# Programs, flags, etc.
ASM         =   nasm
ASMBFLAGS   =

# This Program
TARGET      =   bootsec.com

# All Phony Targets
.PHONY      :   everything clean all

# Default starting position
everything  :   $(TARGET)

clean :
    rm  -r  $(TARGET)

all :   clean   everything  

bootsec.com :   bootsec.asm
    $(ASM)  $(ASMBFLAGS)    -o  $@  $<

Makefile对格式有要求:每一行文本除非顶头开始,如果需要格式编排,不能使用空格键来控制文本行缩进,必须使用Tab键。我们严格一些,全部使用tab建进行文本行缩进。

使用tab键进行缩进

这样,执行make,效果:
执行make效果

修改目标文件路径:tutor-os/build,保持源码目录干净。

# Makefile for boot

# Programs, flags, etc.
ASM         =   nasm
ASMBFLAGS   =

# This Program
TARGET      =   ../build/bootsec.com

# All Phony Targets
.PHONY      :   everything clean all

# Default starting position
everything  :   $(TARGET)

clean :
    rm  -r  $(TARGET)

all :   clean   everything  

../build/bootsec.com    :   bootsec.asm
    $(ASM)  $(ASMBFLAGS)    -o  $@  $<

Makefile说明

以字符#开头的行是注释。
=用来定义变量。
这里ASM和ASMFLAGS就是两个变量。使用它们的时候需要用$(ASM)$(ASMFLAGS),而不是它们的原型。
Makefile最重要的语法:

target  :  prerequisites
            command

就是上面的

../build/bootsec.com    :   bootsec.asm
    $(ASM)  $(ASMBFLAGS)    -o  $@  $<

上面的行是表示两层意思:
1、要想得到target,需要执行命令command;
2、target依赖于prerequisites,当prerequisites中至少有一个文件比target文件新时,command才被执行。
(所以上面,执行完make后,紧接着再执行make的时候,会提示Nothing to be done...)
比如这个Makefile的最后两行,翻译出来就是:
1、要想得到../bulid/bootsec.com,需要执行命令(ASM)(ASMBFLAGS) -o @<
2、../bulid/bootsec.com依赖于bootsec.asm,当bootsec.asm比../bulid/bootsec.com新时,command被执行。
那么$(ASM) $(ASMBFLAGS) -o $@ $<是什么呢?
@和<表示target和prerequisites的第一个名字,因此,这个命令便等价于:
nasm -o ../build/bootsec.com bootsec.asm
everythingcleanall是3个动作名称。
如果运行make cleanrm -f $(TARGET)这个命令将会被执行,相当于rm -f ../build/bootsec.com。(后面的编译命令不会执行!!!)
all 后面跟着的是clean和everything,这表明如果我们执行make all,clean和everything所表示的所有的动作都会被执行。

make all

.PHONY也是一种行为的标号。
直接输入make,这时make程序会从我们第一个名字所代表的动作开始执行。在本例中,第一个标号时everything,所以makemake everything是一样的。
make everything

Makefile for loader

# Makefile for loader

# Programs, flags, etc.
ASM         =   nasm
ASMBFLAGS   =

# This Program
TARGET      =   ../build/loader.com

# All Phony Targets
.PHONY      :   everything clean all

# Default starting position
everything  :   $(TARGET)

clean :
    rm  -r  $(TARGET)

all :   clean   everything  

../build/loader.com :   loader.asm
    $(ASM)  $(ASMBFLAGS)    -o  $@  $<

Makefile for lib,仅编译成.o

#Makefile for lib
#
# tutor-os/lib:在内核编程中是不能用C语言标准库函数,这里的lib目录下的库函数就是用来替代那些标准库函数的。
# 
# 对外提供的函数功能有
# string.h (字符串操作)
#    int strlen(const char * s);                                  string.c
#    char * strcpy(char * dst, const char *src);                  string.c
#    extern  void*  memcpy(void* pDst, void* pSrc, int iSize);    _string.asm
#    PUBLIC int  sprintf(char *buf, const char *fmt, ...);        vsprintf.c
#
# print.h (屏幕打印功能)     
#    PUBLIC  void    print_str(char * info);                      print_str.asm
#    PUBLIC  void    print_str_fix_pos(int pos, char * info);     print_str.asm
#    PUBLIC  void    print_color_str(char * info, int color);     print_str.asm
#
# 生成的中间文件是:lib.a
#
#

ASM =   nasm
ASMFLAGS    =   -f  elf
CC  =   gcc
CFLAGS  =   -m32    -nostdinc   -I  ../include/string   -fno-stack-protector    -fno-builtin    -c

# This Program
OBJS    =   ../build/objs/_string.o \
            ../build/objs/string.o  \
            ../build/objs/vsprintf.o    \
            ../build/objs/print_str.o

.PHONY  :   everything  clean   all

# 默认起始位置
everything  :   $(OBJS)
clean   :
    rm  -r  $(OBJS)

all :   clean   everything  

### Dependencies:
#lib/string
../build/objs/_string.o :   ./string/_string.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<
    
../build/objs/string.o  :   ./string/string.c   ../include/string/string.h
    $(CC)   $(CFLAGS)   -o  $@  $<

../build/objs/vsprintf.o    :   ./string/vsprintf.c ./string/stdarg.h   ../include/string/string.h
    $(CC)   $(CFLAGS)   -o  $@  $<
#lib/.
../build/objs/print_str.o   :   ./print_str.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<

Makefile for lib,生成静态库文件

# Makefile for lib
#
# tutor-os/lib:在内核编程中是不能用C语言标准库函数,这里的lib目录下的库函数就是用来替代那些标准库函数的。
# 
# 对外提供的函数功能有
# string.h (字符串操作)
#    int strlen(const char * s);                                  string.c
#    char * strcpy(char * dst, const char *src);                  string.c
#    extern  void*  memcpy(void* pDst, void* pSrc, int iSize);    _string.asm
#    PUBLIC int  sprintf(char *buf, const char *fmt, ...);        vsprintf.c
#
# print.h (屏幕打印功能)     
#    PUBLIC  void    print_str(char * info);                      print_str.asm
#    PUBLIC  void    print_str_fix_pos(int pos, char * info);     print_str.asm
#    PUBLIC  void    print_color_str(char * info, int color);     print_str.asm
#
# 生成的中间文件是:lib.a
#
#

ASM =   nasm
ASMFLAGS    =   -f  elf
CC  =   gcc
CFLAGS  =   -m32    -nostdinc   -I  ../include/string   -fno-stack-protector    -fno-builtin    -c
AR  =   ar

# This Program
OBJS    =   ../build/objs/_string.o \
            ../build/objs/string.o  \
            ../build/objs/vsprintf.o    \
            ../build/objs/print_str.o

LIBS    =   ../build/libs/lib.a

.PHONY  :   everything  clean   all

# 默认起始位置
everything  :   $(LIBS)
clean   :
    rm  -r  $(OBJS)

all :   clean   everything  

### Dependencies:
# lib/string
../build/objs/_string.o :   ./string/_string.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<
    
../build/objs/string.o  :   ./string/string.c   ../include/string/string.h
    $(CC)   $(CFLAGS)   -o  $@  $<

../build/objs/vsprintf.o    :   ./string/vsprintf.c ./string/stdarg.h   ../include/string/string.h
    $(CC)   $(CFLAGS)   -o  $@  $<
# lib/.
../build/objs/print_str.o   :   ./print_str.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<
# 生成lib.a
$(LIBS):    $(OBJS)
    $(AR)   rcs $(LIBS) $(OBJS)

Makefile for kenel,当前只有protect子目录

# Makefile for kernel
#
# tutor-os/kernel:内核代码。
# 
# 对外提供的函数功能有:(提供给init模块使用)
# include/protect.h
# // GDT
# PUBLIC  void  relocate_gdt();
# PUBLIC  void  print_descriptor();
# // IDT
# PUBLIC  void  init_idt();
# 
# 

ASM =   nasm
ASMFLAGS    =   -f  elf
CC  =   gcc
CFLAGS  =   -m32    -nostdinc   -I  ../include  -fno-stack-protector    -fno-builtin    -c
AR  =   ar

# This Program
OBJS    =   ../build/objs/_interrupt.o  \
            ../build/objs/interrupt.o   \
            ../build/objs/io.o  \
            ../build/objs/protect.o

LIBS    =   ../build/libs/kernel_protect.a

.PHONY  :   everything  clean   all

# 默认起始位置
everything  :   $(LIBS)
clean   :
    rm  -r  $(OBJS)

all :   clean   everything  

### Dependencies:
# kernel/protect
../build/objs/_interrupt.o  :   ./protect/_interrupt.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<
    
../build/objs/interrupt.o   :   ./protect/interrupt.c   ../include/type.h   ../include/const.h  ../include/protect.h    ../include/string.h ../include/vsprintf.h   ../include/print.h
    $(CC)   $(CFLAGS)   -o  $@  $<

../build/objs/io.o  :   ./protect/io.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<

../build/objs/protect.o :   ./protect/protect.c ../include/type.h   ../include/const.h  ../include/protect.h    ../include/string.h ../include/vsprintf.h   ../include/print.h
    $(CC)   $(CFLAGS)   -o  $@  $<


# 生成../build/libs/kernel_protect.a
$(LIBS):    $(OBJS)
    $(AR)   rcs $(LIBS) $(OBJS)

Makefile for init

# Makefile for init
#
# tutor-os/init:内核启动代码。
#
ASM =   nasm
ASMFLAGS    =   -f  elf
CC  =   gcc
CFLAGS  =   -m32    -nostdinc   -I  ../include  -fno-stack-protector    -fno-builtin    -c
AR  =   ar

# This Program
OBJS    =   ../build/objs/_start.o  \
            ../build/objs/cstart.o  \

.PHONY  :   everything  clean   all

# 默认起始位置
everything  :   $(OBJS)
clean   :
    rm  -r  $(OBJS)

all :   clean   everything  

### Dependencies:
# kernel/protect
../build/objs/_start.o  :   ./_start.asm
    $(ASM)  $(ASMFLAGS) -o  $@  $<
    
../build/objs/cstart.o  :   ./cstart.c  ../include/type.h   ../include/const.h  ../include/protect.h    ../include/string.h ../include/vsprintf.h   ../include/print.h
    $(CC)   $(CFLAGS)   -o  $@  $<

Makefile for root,根目录下,主要是调用子目录的Makefile,然后链接生成kernel.bin

# Makefile for root
#
# 1、调用其他Makefile文件,生成objs和lib
# 2、连接生成目标文件

LD  =   ld
LDFLAGS =   -m  elf_i386    -s  -Ttext  0x30400

# This Program
TARGET  =   ../build/bootsec.com    \
            ../build/loader.com \
            ../build/kernel.bin

LIBS    =   ../build/libs/lib.a \
            ../build/libs/kernel_protect.a  \

OBJS    =   ../build/objs/_start.o  \
            ../build/objs/cstart.o
            
.PHONY  :   everything  clean   all

# 默认起始位置
everything  :   $(TARGET)
clean   :
    rm  -r  $(TARGET)

all :   clean   everything  

### Dependencies:
# boot & loader
../build/bootsec.com    :   
    (cd ./boot; make)
    
../build/loader.com :   
    (cd ./loader;   make)
# 生成lib
../build/libs/lib.a  :  
    (cd ./lib;  make)

../build/libs/kernel_protect.a  :   
    (cd ./kernel;   make)

# 生成objs
../build/objs/_start.o  :   
    (cd ./init; make)

../build/objs/cstart.o  :   
    (cd ./init; make)

# 生成kernel.bin
../build/kernel.bin :   $(LIBS) $(OBJS)
    $(LD)   $(LDFLAGS)  -o  ./build/kernel.bin  ./build/objs/cstart.o   ./build/objs/_start.o   ./build/libs/kernel_protect.a   ./build/libs/lib.a

$(LD) $(LDFLAGS) -o ./build/kernel.bin ./build/objs/cstart.o ./build/objs/_start.o ./build/libs/kernel_protect.a ./build/libs/lib.a注意顺序!!!
gcc在链接静态库时是从前往后找符号。因此如果一份文件foo引用了静态库bar.a,那么在链接命令中,bar.a必须放在foo的后面,也就是像gcc ... foo ... bar.a这样;否则链接时会报找不到定义的错误(即undefined reference to ...)。

make.bat,在windows上调用wsl,调用make命令

wsl (cd /mnt/c/Users/zkai/Desktop/OsDevLab/tutor-os; make)
pause
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容