《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

378 lines
9.8 KiB

преди 12 години
преди 12 години
преди 11 години
преди 12 години
преди 12 години
преди 12 години
  1. PROJ := 8
  2. EMPTY :=
  3. SPACE := $(EMPTY) $(EMPTY)
  4. SLASH := /
  5. V := @
  6. # try to infer the correct GCCPREFX
  7. ifndef GCCPREFIX
  8. GCCPREFIX := $(shell if i386-ucore-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \
  9. then echo 'i386-ucore-elf-'; \
  10. elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
  11. then echo ''; \
  12. else echo "***" 1>&2; \
  13. echo "*** Error: Couldn't find an i386-ucore-elf version of GCC/binutils." 1>&2; \
  14. echo "*** Is the directory with i386-ucore-elf-gcc in your PATH?" 1>&2; \
  15. echo "*** If your i386-ucore-elf toolchain is installed with a command" 1>&2; \
  16. echo "*** prefix other than 'i386-ucore-elf-', set your GCCPREFIX" 1>&2; \
  17. echo "*** environment variable to that prefix and run 'make' again." 1>&2; \
  18. echo "*** To turn off this error, run 'gmake GCCPREFIX= ...'." 1>&2; \
  19. echo "***" 1>&2; exit 1; fi)
  20. endif
  21. # try to infer the correct QEMU
  22. ifndef QEMU
  23. QEMU := $(shell if which qemu > /dev/null; \
  24. then echo 'qemu'; exit; \
  25. elif which i386-ucore-elf-qemu > /dev/null; \
  26. then echo 'i386-ucore-elf-qemu'; exit; \
  27. else \
  28. echo "***" 1>&2; \
  29. echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \
  30. echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \
  31. echo "***" 1>&2; exit 1; fi)
  32. endif
  33. # eliminate default suffix rules
  34. .SUFFIXES: .c .S .h
  35. # delete target files if there is an error (or make is interrupted)
  36. .DELETE_ON_ERROR:
  37. # define compiler and flags
  38. HOSTCC := gcc
  39. HOSTCFLAGS := -g -Wall -O2 -D_FILE_OFFSET_BITS=64
  40. GDB := $(GCCPREFIX)gdb
  41. CC ?= $(GCCPREFIX)gcc
  42. CFLAGS := -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc $(DEFS)
  43. CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
  44. CTYPE := c S
  45. LD := $(GCCPREFIX)ld
  46. LDFLAGS := -m $(shell $(LD) -V | grep elf_i386 2>/dev/null)
  47. LDFLAGS += -nostdlib
  48. OBJCOPY := $(GCCPREFIX)objcopy
  49. OBJDUMP := $(GCCPREFIX)objdump
  50. COPY := cp
  51. MKDIR := mkdir -p
  52. MV := mv
  53. RM := rm -f
  54. AWK := awk
  55. SED := sed
  56. SH := sh
  57. TR := tr
  58. TOUCH := touch -c
  59. OBJDIR := obj
  60. BINDIR := bin
  61. ALLOBJS :=
  62. ALLDEPS :=
  63. TARGETS :=
  64. USER_PREFIX := __user_
  65. include tools/function.mk
  66. listf_cc = $(call listf,$(1),$(CTYPE))
  67. # for cc
  68. add_files_cc = $(call add_files,$(1),$(CC),$(CFLAGS) $(3),$(2),$(4))
  69. create_target_cc = $(call create_target,$(1),$(2),$(3),$(CC),$(CFLAGS))
  70. # for hostcc
  71. add_files_host = $(call add_files,$(1),$(HOSTCC),$(HOSTCFLAGS),$(2),$(3))
  72. create_target_host = $(call create_target,$(1),$(2),$(3),$(HOSTCC),$(HOSTCFLAGS))
  73. cgtype = $(patsubst %.$(2),%.$(3),$(1))
  74. objfile = $(call toobj,$(1))
  75. asmfile = $(call cgtype,$(call toobj,$(1)),o,asm)
  76. outfile = $(call cgtype,$(call toobj,$(1)),o,out)
  77. symfile = $(call cgtype,$(call toobj,$(1)),o,sym)
  78. filename = $(basename $(notdir $(1)))
  79. ubinfile = $(call outfile,$(addprefix $(USER_PREFIX),$(call filename,$(1))))
  80. # for match pattern
  81. match = $(shell echo $(2) | $(AWK) '{for(i=1;i<=NF;i++){if(match("$(1)","^"$$(i)"$$")){exit 1;}}}'; echo $$?)
  82. # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  83. # include kernel/user
  84. INCLUDE += libs/
  85. CFLAGS += $(addprefix -I,$(INCLUDE))
  86. LIBDIR += libs
  87. $(call add_files_cc,$(call listf_cc,$(LIBDIR)),libs,)
  88. # -------------------------------------------------------------------
  89. # user programs
  90. UINCLUDE += user/include/ \
  91. user/libs/
  92. USRCDIR += user
  93. ULIBDIR += user/libs
  94. UCFLAGS += $(addprefix -I,$(UINCLUDE))
  95. USER_BINS :=
  96. $(call add_files_cc,$(call listf_cc,$(ULIBDIR)),ulibs,$(UCFLAGS))
  97. $(call add_files_cc,$(call listf_cc,$(USRCDIR)),uprog,$(UCFLAGS))
  98. UOBJS := $(call read_packet,ulibs libs)
  99. define uprog_ld
  100. __user_bin__ := $$(call ubinfile,$(1))
  101. USER_BINS += $$(__user_bin__)
  102. $$(__user_bin__): tools/user.ld
  103. $$(__user_bin__): $$(UOBJS)
  104. $$(__user_bin__): $(1) | $$$$(dir $$$$@)
  105. $(V)$(LD) $(LDFLAGS) -T tools/user.ld -o $$@ $$(UOBJS) $(1)
  106. @$(OBJDUMP) -S $$@ > $$(call cgtype,$$<,o,asm)
  107. @$(OBJDUMP) -t $$@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$$$/d' > $$(call cgtype,$$<,o,sym)
  108. endef
  109. $(foreach p,$(call read_packet,uprog),$(eval $(call uprog_ld,$(p))))
  110. # -------------------------------------------------------------------
  111. # kernel
  112. KINCLUDE += kern/debug/ \
  113. kern/driver/ \
  114. kern/trap/ \
  115. kern/mm/ \
  116. kern/libs/ \
  117. kern/sync/ \
  118. kern/fs/ \
  119. kern/process/ \
  120. kern/schedule/ \
  121. kern/syscall/ \
  122. kern/fs/swap/ \
  123. kern/fs/vfs/ \
  124. kern/fs/devs/ \
  125. kern/fs/sfs/
  126. KSRCDIR += kern/init \
  127. kern/libs \
  128. kern/debug \
  129. kern/driver \
  130. kern/trap \
  131. kern/mm \
  132. kern/sync \
  133. kern/fs \
  134. kern/process \
  135. kern/schedule \
  136. kern/syscall \
  137. kern/fs/swap \
  138. kern/fs/vfs \
  139. kern/fs/devs \
  140. kern/fs/sfs
  141. KCFLAGS += $(addprefix -I,$(KINCLUDE))
  142. $(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))
  143. KOBJS = $(call read_packet,kernel libs)
  144. # create kernel target
  145. kernel = $(call totarget,kernel)
  146. $(kernel): tools/kernel.ld
  147. $(kernel): $(KOBJS)
  148. @echo + ld $@
  149. $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
  150. @$(OBJDUMP) -S $@ > $(call asmfile,kernel)
  151. @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)
  152. $(call create_target,kernel)
  153. # -------------------------------------------------------------------
  154. # create bootblock
  155. bootfiles = $(call listf_cc,boot)
  156. $(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))
  157. bootblock = $(call totarget,bootblock)
  158. $(bootblock): $(call toobj,boot/bootasm.S) $(call toobj,$(bootfiles)) | $(call totarget,sign)
  159. @echo + ld $@
  160. $(V)$(LD) $(LDFLAGS) -N -T tools/boot.ld $^ -o $(call toobj,bootblock)
  161. @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
  162. @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
  163. @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)
  164. $(call create_target,bootblock)
  165. # -------------------------------------------------------------------
  166. # create 'sign' tools
  167. $(call add_files_host,tools/sign.c,sign,sign)
  168. $(call create_target_host,sign,sign)
  169. # -------------------------------------------------------------------
  170. # create 'mksfs' tools
  171. $(call add_files_host,tools/mksfs.c,mksfs,mksfs)
  172. $(call create_target_host,mksfs,mksfs)
  173. # -------------------------------------------------------------------
  174. # create ucore.img
  175. UCOREIMG := $(call totarget,ucore.img)
  176. $(UCOREIMG): $(kernel) $(bootblock)
  177. $(V)dd if=/dev/zero of=$@ count=10000
  178. $(V)dd if=$(bootblock) of=$@ conv=notrunc
  179. $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc
  180. $(call create_target,ucore.img)
  181. # -------------------------------------------------------------------
  182. # create swap.img
  183. SWAPIMG := $(call totarget,swap.img)
  184. $(SWAPIMG):
  185. $(V)dd if=/dev/zero of=$@ bs=1M count=128
  186. $(call create_target,swap.img)
  187. # -------------------------------------------------------------------
  188. # create sfs.img
  189. SFSIMG := $(call totarget,sfs.img)
  190. SFSBINS :=
  191. SFSROOT := disk0
  192. define fscopy
  193. __fs_bin__ := $(2)$(SLASH)$(patsubst $(USER_PREFIX)%,%,$(basename $(notdir $(1))))
  194. SFSBINS += $$(__fs_bin__)
  195. $$(__fs_bin__): $(1) | $$$$(dir $@)
  196. @$(COPY) $$< $$@
  197. endef
  198. $(foreach p,$(USER_BINS),$(eval $(call fscopy,$(p),$(SFSROOT)$(SLASH))))
  199. $(SFSROOT):
  200. if [ ! -d "$(SFSROOT)" ]; then mkdir $(SFSROOT); fi
  201. $(SFSIMG): $(SFSROOT) $(SFSBINS) | $(call totarget,mksfs)
  202. $(V)dd if=/dev/zero of=$@ bs=1M count=128
  203. @$(call totarget,mksfs) $@ $(SFSROOT)
  204. $(call create_target,sfs.img)
  205. # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  206. $(call finish_all)
  207. IGNORE_ALLDEPS = clean \
  208. dist-clean \
  209. grade \
  210. touch \
  211. print-.+ \
  212. run-.+ \
  213. build-.+ \
  214. sh-.+ \
  215. script-.+ \
  216. handin
  217. ifeq ($(call match,$(MAKECMDGOALS),$(IGNORE_ALLDEPS)),0)
  218. -include $(ALLDEPS)
  219. endif
  220. # files for grade script
  221. TARGETS: $(TARGETS)
  222. .DEFAULT_GOAL := TARGETS
  223. QEMUOPTS = -hda $(UCOREIMG) -drive file=$(SWAPIMG),media=disk,cache=writeback -drive file=$(SFSIMG),media=disk,cache=writeback
  224. .PHONY: qemu qemu-nox debug debug-nox monitor
  225. qemu: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  226. $(V)$(QEMU) -parallel stdio $(QEMUOPTS) -serial null
  227. qemu-nox: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  228. $(V)$(QEMU) -serial mon:stdio $(QEMUOPTS) -nographic
  229. monitor: $(UCOREIMG) $(SWAPING) $(SFSIMG)
  230. $(V)$(QEMU) -monitor stdio $(QEMUOPTS) -serial null
  231. TERMINAL := gnome-terminal
  232. debug: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  233. $(V)$(QEMU) -S -s -parallel stdio $(QEMUOPTS) -serial null &
  234. $(V)sleep 2
  235. $(V)$(TERMINAL) -e "$(GDB) -q -x tools/gdbinit"
  236. debug-nox: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  237. $(V)$(QEMU) -S -s -serial mon:stdio $(QEMUOPTS) -nographic &
  238. $(V)sleep 2
  239. $(V)$(TERMINAL) -e "$(GDB) -q -x tools/gdbinit"
  240. RUN_PREFIX := _binary_$(OBJDIR)_$(USER_PREFIX)
  241. MAKEOPTS := --quiet --no-print-directory
  242. run-%: build-%
  243. $(V)$(QEMU) -parallel stdio $(QEMUOPTS) -serial null
  244. sh-%: script-%
  245. $(V)$(QEMU) -parallel stdio $(QEMUOPTS) -serial null
  246. build-%: touch
  247. $(V)$(MAKE) $(MAKEOPTS) "DEFS+=-DTEST=$*"
  248. script-%: touch
  249. $(V)$(MAKE) $(MAKEOPTS) "DEFS+=-DTEST=sh -DTESTSCRIPT=/script/$*"
  250. .PHONY: grade touch buildfs
  251. GRADE_GDB_IN := .gdb.in
  252. GRADE_QEMU_OUT := .qemu.out
  253. HANDIN := proj$(PROJ)-handin.tar.gz
  254. TOUCH_FILES := kern/process/proc.c
  255. MAKEOPTS := --quiet --no-print-directory
  256. grade:
  257. $(V)$(MAKE) $(MAKEOPTS) clean
  258. $(V)$(SH) tools/grade.sh
  259. touch:
  260. $(V)$(foreach f,$(TOUCH_FILES),$(TOUCH) $(f))
  261. print-%:
  262. @echo $($(shell echo $(patsubst print-%,%,$@) | $(TR) [a-z] [A-Z]))
  263. .PHONY: clean dist-clean handin packall tags
  264. clean:
  265. $(V)$(RM) $(GRADE_GDB_IN) $(GRADE_QEMU_OUT) $(SFSBINS) cscope* tags
  266. -$(RM) -r $(OBJDIR) $(BINDIR)
  267. dist-clean: clean
  268. -$(RM) $(HANDIN)
  269. handin: packall
  270. @echo Please visit http://learn.tsinghua.edu.cn and upload $(HANDIN). Thanks!
  271. packall: clean
  272. @$(RM) -f $(HANDIN)
  273. @tar -czf $(HANDIN) `find . -type f -o -type d | grep -v '^\.*$$' | grep -vF '$(HANDIN)'`
  274. tags:
  275. @echo TAGS ALL
  276. $(V)rm -f cscope.files cscope.in.out cscope.out cscope.po.out tags
  277. $(V)find . -type f -name "*.[chS]" >cscope.files
  278. $(V)cscope -bq
  279. $(V)ctags -L cscope.files