#!/usr/bin/env sh set -e cd "$(dirname "$0")" mode="${1}" no_ask="${2}" network="rtl8139" qemu_with_flags() { if [ "${mode}" = "image" ] || [ "${mode}" = "image_debug" ]; then # TODO: Find out why kvm install is incredibly slow SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-i386 -no-reboot -vga std -smp "$(nproc)" -serial mon:stdio -rtc base=localtime -m 256M -net nic,model=${network},macaddr=42:42:42:42:42:42 -net user "$@" else SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-i386 -no-reboot -vga std -serial stdio -rtc base=localtime -m 256M -net nic,model=${network},macaddr=42:42:42:42:42:42 -net user "$@" fi } make_genext2fs() { if [ "$(genext2fs -V | awk '{print $2}')" = "1.4.2" ]; then echo "genext2fs is already the newest version" else if [ "$no_ask" != "-y" ]; then printf "Melvix requires the newest genext2fs version, would you like to install it? [y/n] " read -r answer fi if [ "$answer" != "${answer#[Yy]}" ] || [ "$no_ask" = "-y" ]; then echo "Building genext2fs..." git clone --quiet https://github.com/bestouff/genext2fs.git >/dev/null cd genext2fs >/dev/null git checkout --quiet 000e369 >/dev/null mv README.md README >/dev/null touch ChangeLog >/dev/null bash autogen.sh >/dev/null ./configure >/dev/null sudo make install >/dev/null cd .. >/dev/null rm -rf genext2fs >/dev/null echo "Success!" else echo "This probably won't compile..." fi fi } make_cross() { if [ ! -d "./cross/" ]; then # Create directory mkdir -p cross cd cross DIR=$(pwd) # Get sources mkdir "${DIR}/src" && cd "${DIR}/src" echo "Downloading..." curl -sSL "https://ftp.gnu.org/gnu/binutils/binutils-2.34.tar.xz" | tar xJ curl -sSL "https://ftp.gnu.org/gnu/gcc/gcc-9.3.0/gcc-9.3.0.tar.xz" | tar xJ # Prepare compiling mkdir -p "${DIR}/opt/bin" export PREFIX="${DIR}/opt" export TARGET=i686-elf export PATH="$PREFIX/bin:$PATH" # Compile binutils mkdir "${DIR}/src/build-binutils" && cd "${DIR}/src/build-binutils" ../binutils-2.34/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror make make install # Compile GCC mkdir "${DIR}/src/build-gcc" && cd "${DIR}/src/build-gcc" ../gcc-9.3.0/configure --target="$TARGET" --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers make all-gcc make all-target-libgcc make install-gcc make install-target-libgcc cd "${DIR}/.." else # Should be sourced to take effect cd cross DIR=$(pwd) export PREFIX="${DIR}/opt" export TARGET=i686-elf export PATH="$PREFIX/bin:$PATH" cd .. fi } make_build() { mkdir -p iso/ echo "Building..." mkdir -p build/kernel/ mkdir -p build/res/ mkdir -p build/user/ cd build/ cmake .. >/dev/null make cd .. # Create ISO mkdir -p ./iso/boot/grub/ cp ./build/kernel/kernel.bin ./iso/boot/kernel.bin cp ./src/bootloader/grub.cfg ./iso/boot/grub/ grub-mkrescue -o ./build/melvix.iso ./iso/ # Check ISO if grub-file --is-x86-multiboot2 ./build/kernel/kernel.bin; then echo "Multiboot confirmed" else echo "Kernel is corrupted!" exit 1 fi # Create disk image make_genext2fs mkdir ./mnt/ mkdir -p ./mnt/etc/ mkdir -p ./mnt/usr/ mkdir -p ./mnt/bin/ # TODO: Device file touching should be in kernel mkdir -p ./mnt/dev/ touch ./mnt/dev/stdin touch ./mnt/dev/stdout touch ./mnt/dev/stderr touch ./mnt/dev/fb cp ./build/res/font.bin ./mnt/bin/font cp ./build/user/* ./mnt/bin/ echo "Hello world, ext2!" | tee -a ./mnt/etc/test /usr/local/bin/genext2fs -B 4096 -d mnt -U -N 4096 -b 65536 ./build/disk.img rm -r mnt/ printf "Build finshed successfully!\n\n" } make_test() { qemu_with_flags -cdrom ./build/melvix.iso -hda ./build/disk.img } make_debug() { qemu_with_flags -s -cdrom ./build/melvix.iso #-drive file=./build/hdd10M.img,format=raw } make_image_debug() { qemu_with_flags -cdrom ./build/melvix.iso #-drive file=./build/hdd10M.img,format=raw #qemu_with_flags -drive file=./build/hdd10M.img,format=raw } make_image() { #start=$(date +%s.%N) #qemu_with_flags -nographic -cdrom ./build/melvix.iso -drive file=./build/hdd10M.img,format=raw >install.log #end=$(date +%s.%N) #cat install.log #printf "[LOG END]\n\n" #tail install.log | grep -q "Installation successful!" && echo Booted and installed within "$(echo "$end - $start" | bc -l)" seconds || echo Installation failed! && exit 1 #rm install.log echo "This test is currently disabled" } make_sync() { rm tags compile_commands.json ctags -R --exclude=.git --exclude=build --exclude=iso --exclude=cross . mkdir -p build cd build cmake .. >/dev/null mv compile_commands.json .. cd .. } make_tidy() { find ./src -type f -name "*.sh" | xargs -l -i sh -c 'shfmt -w {}' shfmt -w ./run find ./src -type f -regex '.*\.\(c\|h\)' -exec clang-format -i {} \; find ./src -type f | xargs -l -i sh -c 'printf %s "$(< {})" > {}' } make_font() { cd ./src/resources/ sh conv.sh cd ../../ } make_clean() { #rm -rf ./build ./iso rm -rf ./iso ./build/*.img ./build/*.o ./build/*.bin } if [ "${mode}" = "cross" ]; then make_cross elif [ "${mode}" = "build" ]; then make_cross make_clean make_build elif [ "${mode}" = "clean" ]; then make_clean elif [ "${mode}" = "test" ]; then make_cross make_clean make_build make_test elif [ "${mode}" = "again" ]; then make_test elif [ "${mode}" = "debug" ]; then make_debug elif [ "${mode}" = "image_debug" ]; then make_cross make_clean make_build make_image_debug elif [ "${mode}" = "image" ]; then make_cross make_clean make_build make_image elif [ "${mode}" = "sync" ]; then make_sync elif [ "${mode}" = "tidy" ]; then make_tidy elif [ "${mode}" = "font" ]; then make_font make_tidy else echo "Please use the following syntax:" echo "./run {cross | build | clean | test | debug | image | sync | tidy | font} [-y]" fi