-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmakefile
161 lines (127 loc) · 5.17 KB
/
makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
###############################################################################
#
# Makefile for TimingOS
#
# (C) 2016 Zachary Kurmas
#
# This Makefile requires that m4, grub (specifically, grub2-mkrescue),
# i686-elf-gcc, and other necessary toolchain compnents, be in the PATH.
#
# User code goes in usr_src. This directory must contain exactly one .c file
# with a kernel_main function.
#
###############################################################################
# makefile.local should contain the definition for KERNEL_MAIN
# Begin by loading makefile.local.sample. If makefile.local exists,
# it will overwrite the values set in makefile.local.sample. If it doesn't
# exist, nothing will happen.
include makefile.local.sample
-include makefile.local
OS_SRC = os_src
USR_SRC = usr_src
OS_OBJ = obj/os
USR_OBJ = obj/usr
elfCC = i686-elf-gcc
CFLAGS = -std=c99 -ffreestanding -Wall -Wextra
os_sources = $(wildcard $(OS_SRC)/*.c) # all *.c files in the os_src dir
usr_sources = $(wildcard $(USR_SRC)/*.c) # all *.c files in the usr_src dir
# Convert each .c file name into the corresponding .o file name
# (change .c to .o, and change the directory name)
os_objs = $(subst $(OS_SRC), $(OS_OBJ), $(os_sources:.c=.o))
usr_objs = $(subst $(USR_SRC), $(USR_OBJ), $(usr_sources:.c=.o))
all_objs = $(os_objs) $(OS_OBJ)/boot.o $(usr_objs)
# timingos.iso is a bootable iso image intended to be run on "real" hardware
# timingos.debug is an executable program designed to be run for debugging
all: timingos.iso timingos.debug
#
# Make the obj directories, if they don't already exist.
#
$(OS_OBJ):
mkdir -p $@
$(USR_OBJ):
mkdir -p $@
#
# create makefile.local if it doesn't already exist
#
makefile.local:
cp makefile.local.sample $@
#############################################################################
#
# Compile "core" OS
#
#############################################################################
# Headers shouldn't change much. If they do, then just
# re-build all the .o files
$(OS_OBJ)/%.o: $(OS_SRC)/%.c $(OS_SRC)/*.h | $(OS_OBJ)
$(elfCC) $(CFLAGS) -c $< -o $@ -O2
# generate the assembly file, in case we want to look at it later.
$(elfCC) $(CFLAGS) -S $< -o $(@:.o=.s) -O2
# By naming the file boot.S (instead of boot.s), gcc will run the
# pre-processor and substitute KERNEL_MAIN with the user-chosen
# kernel entry point.
$(OS_OBJ)/boot.o: $(OS_SRC)/boot.S | $(OS_OBJ) makefile.local
mkdir -p $(@D)
$(elfCC) $(CFLAGS) -DKERNEL_MAIN=$(KERNEL_MAIN) -c $< -o $@ -O2
############################################################################
#
# Compile "user provided" parts of OS
#
###########################################################################
# Headers shouldn't change much. If they do, then just re-build all the
# .o files
$(USR_OBJ)/%.o: $(USR_SRC)/%.c $(OS_SRC)/*.h $(wildcard $(USR_SRC)/*.h) | $(USR_OBJ)
$(elfCC) $(CFLAGS) -c $< -o $@ -I $(OS_SRC)
# generate the assembly file, in case we want to look at it later.
$(elfCC) $(CFLAGS) -S $< -o $(@:.o=.s) -I $(OS_SRC)
##########################################################################
#
# Prepare the grub config file
#
# This rule builds a custom grub config file that
# includes the build time in the name of the image.
#
# Listing the build time in the grub menu allows us to
# easily see at boot time that we are loading the
# correct image.
#
# (We found that we would occationally fail to notice
# a failure when running the makefile. As a result, we
# would unknowning run an image that we mistakenly
# believed had been updated. Glancing at the build
# time in the grub menu lets us verify that the image
# was correctly updated.)
########################################################################
# isodir contains the new OS image. We place the updated grub image
# (the one with the current timestamp) in a "magic" location in this directory
# This target is declared to be .PHONY so that it is rebuilt every time.
.PHONY: isodir/boot/grub/grub.cfg
isodir/boot/grub/grub.cfg: | makefile.local
echo $(MYOS_NAME)
mkdir -p $(@D)
m4 -DMYOS_NAME=$(MYOS_NAME) -DTIMESTAMP="`date`" grub.cfg.m4 > $@
#######################################################################
#
# Build the OS image
#
#######################################################################
# Create the binary image for the OS
# The filename "theos.bin" is used by boot/grub/grub.cfg.
# You can change the name of the bin file to mach the name of the iso file,
# just be sure to update grub.cfg also if you do.
isodir/boot/theos.bin: $(all_objs)
mkdir -p $(@D)
$(elfCC) -T linker.ld -o $@ -ffreestanding -O2 -nostdlib $^ -lgcc
# Create the bootable iso image
timingos.iso: isodir/boot/theos.bin isodir/boot/grub/grub.cfg
grub2-mkrescue -o $@ isodir
# Create an executable that can be run locally for debugging (checking
# output, using valgrind, etc.)
timingos.debug: $(os_sources) $(usr_sources)
$(CC) -DDEBUG -g -std=c99 -DKERNEL_MAIN=$(KERNEL_MAIN) -o $@ $^ -I $(OS_SRC)
#######################################################################
#
# clean
#
#######################################################################
clean::
rm obj/*/* timingos.iso timingos.debug isodir/boot/theos.bin