《操作系统》的实验代码。
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

389 行
10 KiB

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