-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
run
executable file
·351 lines (303 loc) · 11.2 KB
/
run
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#!/usr/bin/env sh
# MIT License, Copyright (c) 2020 Marvin Borner
set -e
cd "$(dirname "$0")"
MELVIX_CONFIG="${MELVIX_CONFIG:-dev}"
MAKE=make
NPROC=nproc
SUDO=sudo
TAGS=ctags
if [ "$(uname -s)" = "OpenBSD" ]; then
NPROC="sysctl -n hw.ncpuonline"
SUDO="doas"
TAGS="ectags"
export MAKE=gmake
export CC="egcc"
export CXX="eg++"
export LDFLAGS=-Wl,-z,notext
fi
mode="${1}"
no_ask="${2}"
# TODO: Support q35 chipset ('-machine q35')
qemu_with_flags() {
network="rtl8139"
[ -e /dev/kvm ] && [ -r /dev/kvm ] && [ -w /dev/kvm ] && accel="-enable-kvm" || echo "KVM acceleration not available. Make sure your PC supports it and that you're in the KVM group"
qemu-system-i386 -d guest_errors,unimp,pcall -cpu max -no-reboot -vga std -rtc base=localtime -m 256M -netdev user,id=net0,hostfwd=tcp:127.0.0.1:8000-10.0.2.15:8000 -device $network,netdev=net0 -object filter-dump,id=dump,netdev=net0,file=dump.pcap $accel "$@"
}
make_cross() {
if [ ! -d "./cross/" ]; then
if [ "$no_ask" != "-y" ]; then
echo -n "Do you want to compile a cross compiler (this can take up to 20 minutes)? [yn] "
read -r answer
if ! [ "$answer" != "${answer#[Yy]}" ]; then
echo "The compilation of melvix requires a cross compiler!"
exit 1
fi
fi
# Create directory
mkdir -p cross
cd cross
DIR=$(pwd)
# Get sources
mkdir "${DIR}/src" && cd "${DIR}/src"
echo "Downloading..."
curl "https://ftp.gnu.org/gnu/binutils/binutils-2.36.1.tar.gz" >binutils.tar.gz
tar xzf binutils.tar.gz
curl "https://ftp.gnu.org/gnu/gcc/gcc-11.1.0/gcc-11.1.0.tar.gz" >gcc.tar.gz
tar xzf gcc.tar.gz
# Prepare compiling
mkdir -p "${DIR}/opt/bin"
export CFLAGS="-g0 -O2"
export PREFIX="${DIR}/opt"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"
if [ "$(uname -s)" = "OpenBSD" ]; then
export with_gmp=/usr/local
sed -i 's/-no-pie/-nopie/g' "${DIR}/src/gcc-11.1.0/gcc/configure"
fi
# Compile binutils
mkdir "${DIR}/src/build-binutils" && cd "${DIR}/src/build-binutils"
../binutils-2.36.1/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
$MAKE -j $($NPROC)
$MAKE install
# Compile GCC
mkdir "${DIR}/src/build-gcc" && cd "${DIR}/src/build-gcc"
../gcc-11.1.0/configure --target="$TARGET" --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers
$MAKE -j $($NPROC) all-gcc all-target-libgcc
$MAKE install-gcc install-target-libgcc
# Fix things
if [ "$(uname -s)" = "OpenBSD" ]; then
cd "${DIR}/opt/libexec/gcc/i686-elf/11.1.0/" && ln -sf liblto_plugin.so.0.0 liblto_plugin.so
fi
# Remove sources
rm -rf "${DIR}/src/"
cd "${DIR}/.."
fi
}
make_disk() {
rm -rf disk && mkdir -p disk/font/ && mkdir -p disk/icons/ && mkdir -p disk/conf/ && mkdir -p disk/boot/
echo "Hallo" >disk/conf/test
cp -r res/ disk/
echo "Getting font"
cd disk/font/
VERSION="1.9.1"
wget -q "https://github.com/fcambus/spleen/releases/download/$VERSION/spleen-$VERSION.tar.gz"
tar xzf "spleen-$VERSION.tar.gz"
mv spleen-"$VERSION"/*.psfu .
rm -rf "spleen-$VERSION"*
cd ../../
icons="close
chess-bishop
chess-king
chess-knight
chess-pawn
chess-queen
chess-rook"
[ -d icons/ ] || git clone --depth=1 https://github.com/Templarian/MaterialDesign.git icons/
inkscape_version="$(inkscape --version | awk '{print $2}' | cut -c1)"
echo "$icons" | while read icon; do
echo "Converting $icon"
if [ "$inkscape_version" = "0" ]; then
inkscape -z -w 18 -h 18 icons/svg/"$icon".svg -e disk/icons/"$icon"-18.png
inkscape -z -w 24 -h 24 icons/svg/"$icon".svg -e disk/icons/"$icon"-24.png
inkscape -z -w 36 -h 36 icons/svg/"$icon".svg -e disk/icons/"$icon"-36.png
inkscape -z -w 48 -h 48 icons/svg/"$icon".svg -e disk/icons/"$icon"-48.png
else
inkscape -w 18 -h 18 icons/svg/"$icon".svg -o disk/icons/"$icon"-18.png
inkscape -w 24 -h 24 icons/svg/"$icon".svg -o disk/icons/"$icon"-24.png
inkscape -w 36 -h 36 icons/svg/"$icon".svg -o disk/icons/"$icon"-36.png
inkscape -w 48 -h 48 icons/svg/"$icon".svg -o disk/icons/"$icon"-48.png
fi
done
echo "Done!"
}
make_build() {
if ! [ -d "disk/" ]; then
echo "Creating disk..."
make_disk
fi
mkdir -p build/
rm -rf build/*
printf "\nBuilding...\n"
$MAKE -j $($NPROC) CONFIG="$MELVIX_CONFIG" $MELVIX_MAKE
# Prepare Grub
mkdir -p disk/boot/grub/
cp build/apps/kernel/exec disk/boot/melvix
cp boot/grub.cfg disk/boot/grub/
# Create disk image # TODO: Fix build for OpenBSD
dd if=/dev/zero of=build/disk.img bs=1k count=32k status=none
DEV=$($SUDO losetup --find --partscan --show build/disk.img)
PART="p1"
$SUDO parted -s "$DEV" mklabel msdos mkpart primary ext2 32k 100% -a minimal set 1 boot on
if [ "$(uname -s)" = "OpenBSD" ]; then
VND=$($SUDO vnconfig build/disk.img)
(
echo "e 0"
echo 83
echo n
echo 0
echo "*"
echo "quit"
) | $SUDO fdisk -e $VND >/dev/null
$SUDO mkfs.ext2 -F /dev/${VND}i >/dev/null
else
$SUDO mke2fs -b 1024 -q "$DEV$PART"
fi
# Set test app as init
if [ "$mode" = "test" ]; then
cp build/apps/test/exec build/apps/init/exec
fi
mkdir -p mnt/
if [ "$(uname -s)" = "OpenBSD" ]; then
$SUDO mount -t ext2fs /dev/${VND}i mnt/
else
$SUDO mount "$DEV$PART" mnt/
fi
$SUDO cp -r disk/* mnt/
$SUDO chmod -R 0 mnt/conf/
$SUDO cp -r build/apps/ mnt/apps/
# Install grub if release
if [ "$MELVIX_CONFIG" = "release" ]; then
$SUDO grub-install --boot-directory=mnt/boot --target=i386-pc --modules="ext2" "$DEV"
fi
$SUDO umount mnt/ || (sync && sudo umount mnt/)
$SUDO rm -rf mnt/
if [ "$(uname -s)" = "OpenBSD" ]; then
$SUDO vnconfig -u $VND
else
$SUDO losetup -d "$DEV"
fi
printf "Build finshed successfully!\n\n"
}
make_test() {
if [ "$mode" = "test" ]; then
qemu_with_flags -serial file:test.log -nographic -kernel build/apps/kernel/exec -drive file=build/disk.img,format=raw,index=1,media=disk
echo
grep -E 'PASS|FAIL' test.log
if grep -q "All tests passed" test.log; then exit 0; else exit 1; fi
else
qemu_with_flags -serial stdio -kernel build/apps/kernel/exec -drive file=build/disk.img,format=raw,index=1,media=disk
fi
}
make_debug() {
qemu_with_flags -serial stdio -kernel build/apps/kernel/exec -drive file=build/disk.img,format=raw,index=1,media=disk -s -S
}
make_disasm() {
if [ -z "$1" ]; then
echo "Usage: './run disasm {kernel, wm, ...} [-S]'"
exit 1
fi
objdump -drwC "$2" -Mintel build/apps/"$1"/exec | less -R
#hexdump -C build/kernel.bin | less -R
}
make_addr() {
printf "Info: Make sure that you've turned the debug build on (e.g. with MELVIX_CONFIG=debug)\n\n"
if [ -z "$2" ]; then
echo "Usage: './run addr kernel 0x50042'"
exit 1
fi
addr2line -e build/apps/"$1"/exec -f -p "$2"
}
make_cloc() {
cloc . --exclude-dir=build,iso,disk,res,cross,icons
}
make_append_commands() {
s=""
while read -r data; do
s="${s}
${data}"
done
echo "$s" |
sed -n "/Compiled $1/,/Compiled $2/p" |
grep -wE 'gcc' |
grep -w '\-c' |
jq -nR '[inputs|{directory:"'"$(pwd)/$3"'/", command:., file: match(" [^ ]+$").string[1:]}]' \
>>compile_commands.json
}
make_sync() {
$TAGS -R --exclude=.git --exclude=build --exclude=disk --exclude=cross --exclude=boot .
rm -f compile_commands.json
output=$($MAKE --always-make --dry-run)
echo "$output" | make_append_commands libc libk libs/libc
echo "$output" | make_append_commands libk libgui libs/libgui
echo "$output" | make_append_commands libgui libtxt libs/libtxt
echo "$output" | make_append_commands libtxt kernel kernel
echo "$output" | make_append_commands kernel apps apps
tr <compile_commands.json '\n' '\r' | sed -e 's/\r]\r\[/,/g' | tr '\r' '\n' >tmp
mv tmp compile_commands.json
}
make_lint() {
format=$({ find . -path ./cross -prune -false -o -iname *.h -o -iname *.c -exec clang-format-11 -n --Werror {} \;; } 2>&1)
if [ $(echo -n "$format" | head -c1 | wc -c) -ne 0 ]; then
echo "$format"
exit 1
fi
# TODO: Implement clang-tidy linting
# find . -path ./cross -prune -o -iname *.h -o -iname *.c | xargs clang-tidy-11 --checks=-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling
echo "No errors!"
}
make_format() {
find . -path ./cross -prune -false -o -iname *.h -o -iname *.c -exec clang-format-11 -i {} \;
}
make_clean() {
#rm -rf build/
$MAKE clean
}
if [ "${mode}" = "cross" ]; then
make_cross
elif [ "${mode}" = "build" ]; then
make_cross
make_clean
make_build
elif [ "${mode}" = "clean" ]; then
make_clean
elif [ "${mode}" = "lint" ]; then
make_lint
elif [ "${mode}" = "format" ]; then
make_format
elif [ "${mode}" = "again" ]; then
make_test
elif [ "${mode}" = "disasm" ]; then
make_disasm "$2" "$3"
elif [ "${mode}" = "addr" ]; then
make_addr "$2" "$3"
elif [ "${mode}" = "cloc" ]; then
make_cloc
elif [ "${mode}" = "sync" ]; then
make_sync
elif [ "${mode}" = "disk" ]; then
make_disk
elif [ "${mode}" = "debug" ]; then
make_cross
make_clean
make_build
make_sync &
make_debug
elif [ "${mode}" = "test" ] || [ "${mode}" = "" ]; then
make_cross
make_clean
make_build
make_sync &
make_test
make_clean
else
echo "Usage: ./run {cross | clean | build | test | debug | again | disasm | addr | sync | disk} [-y]"
printf "\nDescription of options:\n"
printf "cross\t\tBuilds the cross compiler\n"
printf "clean\t\tRemoves the compiled files\n"
printf "lint\t\tLint the entire project using clang-tidy\n"
printf "format\t\tFormat the entire project using clang-format\n"
printf "build\t\tBuilds the whole project (cross+clean)\n"
printf "test\t\tRuns the Melvix unit tests with QEMU (cross+clean+build)\n"
printf "debug\t\tEmulates Melvix with QEMU and debug options (cross+clean+build)\n"
printf "again\t\tOpens QEMU again using the previous build\n"
printf "disasm\t\tDisassembles a given part of Melvix\n"
printf "addr\t\tResolves an address to a line of code\n"
printf "cloc\t\tCount the total lines of code\n"
printf "sync\t\tSyncs the 'tags' and 'compile_commands.json' file\n"
printf "disk\t\tPrepares the userspace disk (e.g. fonts)\n"
printf "*\t\tAnything else prints this help\n"
printf "\t\tWhen no option is set, Melvix gets built and emulated using QEMU (cross+clean+build)\n\n"
echo "You can set the environment variable 'MELVIX_CONFIG' to a config group defined in '.build.mk'"
echo "Set the environment variable 'MELVIX_MAKE=\"CONFIG_FOO=bar\"' to override build configs"
fi