《操作系统》的实验代码。
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.

395 lines
10 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  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. $(SFSROOT):
  214. $(V)$(MKDIR) $@
  215. $(SFSIMG): $(SFSROOT) $(SFSBINS) | $(call totarget,mksfs)
  216. $(V)dd if=/dev/zero of=$@ bs=1M count=128
  217. @$(call totarget,mksfs) $@ $(SFSROOT)
  218. $(call create_target,sfs.img)
  219. # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  220. $(call finish_all)
  221. IGNORE_ALLDEPS = clean \
  222. dist-clean \
  223. grade \
  224. touch \
  225. print-.+ \
  226. run-.+ \
  227. build-.+ \
  228. sh-.+ \
  229. script-.+ \
  230. handin
  231. ifeq ($(call match,$(MAKECMDGOALS),$(IGNORE_ALLDEPS)),0)
  232. -include $(ALLDEPS)
  233. endif
  234. # files for grade script
  235. TARGETS: $(TARGETS)
  236. .DEFAULT_GOAL := TARGETS
  237. QEMUOPTS = -hda $(UCOREIMG) -drive file=$(SWAPIMG),media=disk,cache=writeback -drive file=$(SFSIMG),media=disk,cache=writeback
  238. .PHONY: qemu qemu-nox debug debug-nox monitor
  239. qemu-mon: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  240. $(V)$(QEMU) -no-reboot -monitor stdio $(QEMUOPTS) -serial null
  241. qemu: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  242. $(V)$(QEMU) -no-reboot -parallel stdio $(QEMUOPTS) -serial null
  243. qemu-nox: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  244. $(V)$(QEMU) -no-reboot -serial mon:stdio $(QEMUOPTS) -nographic
  245. monitor: $(UCOREIMG) $(SWAPING) $(SFSIMG)
  246. $(V)$(QEMU) -no-reboot -monitor stdio $(QEMUOPTS) -serial null
  247. TERMINAL := gnome-terminal
  248. debug: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  249. $(V)$(QEMU) -S -s -parallel stdio $(QEMUOPTS) -serial null &
  250. $(V)sleep 2
  251. $(V)$(TERMINAL) -e "$(GDB) -q -x tools/gdbinit"
  252. debug-nox: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
  253. $(V)$(QEMU) -S -s -serial mon:stdio $(QEMUOPTS) -nographic &
  254. $(V)sleep 2
  255. $(V)$(TERMINAL) -e "$(GDB) -q -x tools/gdbinit"
  256. RUN_PREFIX := _binary_$(OBJDIR)_$(USER_PREFIX)
  257. MAKEOPTS := --quiet --no-print-directory
  258. run-%: build-%
  259. $(V)$(QEMU) -parallel stdio $(QEMUOPTS) -serial null
  260. sh-%: script-%
  261. $(V)$(QEMU) -parallel stdio $(QEMUOPTS) -serial null
  262. run-nox-%: build-%
  263. $(V)$(QEMU) -serial mon:stdio $(QEMUOPTS) -nographic
  264. build-%: touch
  265. $(V)$(MAKE) $(MAKEOPTS) "DEFS+=-DTEST=$*"
  266. script-%: touch
  267. $(V)$(MAKE) $(MAKEOPTS) "DEFS+=-DTEST=sh -DTESTSCRIPT=/script/$*"
  268. .PHONY: grade touch buildfs
  269. GRADE_GDB_IN := .gdb.in
  270. GRADE_QEMU_OUT := .qemu.out
  271. HANDIN := proj$(PROJ)-handin.tar.gz
  272. TOUCH_FILES := kern/process/proc.c
  273. MAKEOPTS := --quiet --no-print-directory
  274. grade:
  275. $(V)$(MAKE) $(MAKEOPTS) clean
  276. $(V)$(SH) tools/grade.sh
  277. touch:
  278. $(V)$(foreach f,$(TOUCH_FILES),$(TOUCH) $(f))
  279. print-%:
  280. @echo $($(shell echo $(patsubst print-%,%,$@) | $(TR) [a-z] [A-Z]))
  281. .PHONY: clean dist-clean handin packall tags
  282. clean:
  283. $(V)$(RM) $(GRADE_GDB_IN) $(GRADE_QEMU_OUT) $(SFSBINS) cscope* tags
  284. $(V)$(RM) -r $(OBJDIR) $(BINDIR) $(SFSROOT)
  285. dist-clean: clean
  286. -$(RM) $(HANDIN)
  287. handin: packall
  288. @echo Please visit http://learn.tsinghua.edu.cn and upload $(HANDIN). Thanks!
  289. packall: clean
  290. @$(RM) -f $(HANDIN)
  291. @tar -czf $(HANDIN) `find . -type f -o -type d | grep -v '^\.*$$' | grep -vF '$(HANDIN)'`
  292. tags:
  293. @echo TAGS ALL
  294. $(V)rm -f cscope.files cscope.in.out cscope.out cscope.po.out tags
  295. $(V)find . -type f -name "*.[chS]" >cscope.files
  296. $(V)cscope -bq
  297. $(V)ctags -L cscope.files