-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
221 lines (184 loc) · 5.95 KB
/
CMakeLists.txt
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
cmake_minimum_required(VERSION 3.28)
# configure compiler and linker first
find_program(CMAKE_C_COMPILER NAMES
"riscv64-unknown-linux-gnu-gcc" "riscv64-unknown-elf-gcc" "riscv64-linux-gnu-gcc"
REQUIRED)
get_filename_component(C_COMPILER_BIN ${CMAKE_C_COMPILER} NAME)
string(REPLACE "-gcc" "" CROSS_COMPILE ${C_COMPILER_BIN})
find_program(CMAKE_LINKER "${CROSS_COMPILE}-ld" REQUIRED)
find_program(OBJDUMP "${CROSS_COMPILE}-objdump" REQUIRED)
find_program(OBJCOPY "${CROSS_COMPILE}-objcopy" REQUIRED)
# check for qemu
find_program(QEMU "qemu-system-riscv64" REQUIRED)
# skip compiling a test program
set(CMAKE_C_COMPILER_WORKS 1)
project("xv6-riscv" C ASM)
add_compile_options(
# enables common warnings
-Wall
# treat warnings as errors
-Werror
# basic optimizations
-O
# prevents the compiler from omitting the frame pointer,
# which can aid in debugging and generating accurate stack traces
-fno-omit-frame-pointer
-ggdb
-gdwarf-2
# Generate code for the medium-any code model.
# The program and its statically defined symbols must be within any single
# 2 GiB address range. Programs can be statically or dynamically linked.
-mcmodel=medany
# This flag tells the compiler that the program is running in a "freestanding"
# environment, meaning there is no standard library or operating system. It
# prevents the compiler from assuming that standard library functions like
# printf or exit are available.
-ffreestanding
# disable position-independent code
-fno-pie -no-pie
# disables the generation of stack protection code
-fno-stack-protector
)
add_link_options(
# configure the linker to align sections to 4 KB boundaries, optimizing memory
# layout and potentially reducing binary size, especially useful in
# resource-constrained environments
-z max-page-size=4096
# revent the compiler from linking against any standard libraries, such as the
# C standard library, and skips the standard startup files
-nostdlib
# tell the linker to remove unused code and data sections from the final
# binary
-Wl,--gc-sections
# prevent embedding a unique identifier in the binary
# which would move the entry code to other than 0x80000000
-Wl,--build-id=none
# Prevent from using a dynamic linker, making it suitable for
# statically linked binaries.
-Wl,--no-dynamic-linker
)
# find headers in directory of source file and kernel
include_directories("." "kernel")
function(add_executable_with_asm_and_sym target_name)
add_executable(${target_name} ${ARGN})
add_custom_target(${target_name}_asm ALL
COMMAND ${OBJDUMP} -S $<TARGET_FILE:${target_name}> > ${target_name}.asm
DEPENDS ${target_name}
BYPRODUCTS ${target_name}.asm
)
add_custom_target(${target_name}_sym ALL
COMMAND ${OBJDUMP} -t $<TARGET_FILE:${target_name}> |
sed -e '1,/SYMBOL TABLE/d' -e 's/ .* / /' -e '/^$$/d'
> ${target_name}.sym
DEPENDS ${target_name}
BYPRODUCTS ${target_name}.sym
)
install(FILES ${CMAKE_BINARY_DIR}/${target_name}.asm DESTINATION asm)
install(FILES ${CMAKE_BINARY_DIR}/${target_name}.sym DESTINATION sym)
endfunction()
# build kernel
set(KERNEL_SOURCE
kernel/entry.S # entry must come first to be located at 0x80000000
kernel/string.c
kernel/kalloc.c
kernel/main.c
kernel/vm.c
kernel/proc.c
kernel/swtch.S
kernel/trampoline.S
kernel/trap.c
kernel/syscall.c
kernel/sysproc.c
kernel/bio.c
kernel/fs.c
kernel/log.c
kernel/sleeplock.c
kernel/file.c
kernel/pipe.c
kernel/exec.c
kernel/sysfile.c
kernel/kernelvec.S
kernel/plic.c
kernel/virtio_disk.c
kernel/start.c
kernel/console.c
kernel/printf.c
kernel/uart.c
kernel/spinlock.c
)
add_executable_with_asm_and_sym("kernel" ${KERNEL_SOURCE})
find_file(KERNEL_LD NAMES "kernel.ld" PATHS kernel REQUIRED)
target_link_options("kernel" PRIVATE -T ${KERNEL_LD} -static)
install(TARGETS "kernel" DESTINATION .)
add_library("initcode" OBJECT user/initcode.S)
install(TARGETS "initcode" DESTINATION .)
# build userspace
find_package(Perl REQUIRED)
add_custom_target(usys ALL
COMMAND ${Perl_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/user/usys.pl > usys.S
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/user/usys.pl
BYPRODUCTS usys.S)
SET(ULIB_SOURCE
usys.S
user/ulib.c
user/printf.c
user/umalloc.c
)
add_library(ulib OBJECT ${ULIB_SOURCE})
find_file(USER_LD NAMES "user.ld" PATHS user REQUIRED)
target_link_options(ulib PRIVATE -T ${USER_LD})
SET(USER_SOURCE
user/cat.c
user/echo.c
user/forktest.c
user/grep.c
user/init.c
user/kill.c
user/ln.c
user/ls.c
user/mkdir.c
user/rm.c
user/sh.c
user/stressfs.c
user/usertests.c
user/grind.c
user/wc.c
user/zombie.c
)
# for each user/source.c, create an executable _source
foreach(source ${USER_SOURCE})
get_filename_component(name ${source} NAME_WE)
add_executable_with_asm_and_sym(_${name} ${source})
target_link_options(_${name} PRIVATE -T ${USER_LD})
target_link_libraries(_${name} PRIVATE ulib)
list(APPEND USER _${name})
endforeach()
# make filesystem image
include(ExternalProject)
ExternalProject_Add(mkfs
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mkfs
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)
find_file(README NAMES README PATHS . REQUIRED)
add_custom_target(fs_img
ALL ${CMAKE_INSTALL_PREFIX}/bin/mkfs fs.img ${README} ${USER}
DEPENDS mkfs ${README} ${USER}
BYPRODUCTS fs.img
)
install(FILES ${CMAKE_BINARY_DIR}/fs.img DESTINATION .)
# show how to run qemu
string(CONCAT QEMU
"message(STATUS \"\n\nqemu-system-riscv64 -machine virt -bios none "
"-kernel ${CMAKE_INSTALL_PREFIX}/kernel "
"-m 128M -smp 3 -nographic "
"-global virtio-mmio.force-legacy=false "
"-drive file=${CMAKE_INSTALL_PREFIX}/fs.img,if=none,format=raw,id=x0 "
"-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0\n\")"
)
# see initcode[] in kernel/proc.c
string(CONCAT INITCODE
"message(STATUS \"\n\n${OBJCOPY} --dump-section .text=/dev/stdout "
"$<TARGET_OBJECTS:initcode> | od -t xC -\n\")"
)
install(CODE "${INITCODE}")
install(CODE "${QEMU}")