diff options
Diffstat (limited to 'build.sh')
| -rwxr-xr-x | build.sh | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..bb9c67a --- /dev/null +++ b/build.sh @@ -0,0 +1,231 @@ +#!/bin/bash + +set -e + +if [ -z "${CROSSCC_i686}" ]; then + CROSSCC_i686=i686-elf-gcc +fi + +if [ -z "${CROSSAS_i686}" ]; then + CROSSAS_i686=i686-elf-as +fi + +if [ -z "${CROSSCC_x8664}" ]; then + CROSSCC_x8664=x86_64-elf-gcc +fi + +if [ -z "${CROSSAS_x8664}" ]; then + CROSSAS_x8664=x86_64-elf-as +fi + +if [ -z "${CROSSLD_i686}" ]; then + CROSSLD_i686=i686-elf-ld +fi + +if [ -z "${CROSSLD_x8664}" ]; then + CROSSLD_x8664=x86_64-elf-ld +fi + +if [ -z "${STAGE1_DIR}" ]; then + STAGE1_DIR="./stage1/" +fi + +if [ -z "${STAGE2_DIR}" ]; then + STAGE2_DIR="$(pwd)/stage2" +fi + +if [ -z "${BUILD_DIR}" ]; then + BUILD_DIR="$(pwd)/build" +fi +mkdir -p "${BUILD_DIR}" + +if [ -z "${TARGET}" ]; then + TARGET="$(pwd)/bootloader" +fi + +GLOBAL_CFLAGS=(-I./include -ffreestanding -m32 -nostdlib) + +LINKER_LD="linker.ld" + +# Stage 1 + +STAGE1_LD="${STAGE1_DIR}/linker.ld" + +STAGE1_C_FILES=$(find "${STAGE1_DIR}" -name "*.c") +STAGE1_AS_FILES=$(find "${STAGE1_DIR}" -name "*.S") + +STAGE1_AS_TARGET="${BUILD_DIR}/stage1_as.o" +STAGE1_CC_TARGET="${BUILD_DIR}/stage1_cc.o" + +STAGE1_TARGET="${BUILD_DIR}/stage1.bin" + +# Stage 2 + +STAGE2_LD="${STAGE1_DIR}/linker.ld" + +STAGE2_C_FILES=$(find "${STAGE2_DIR}" -name "*.c") +STAGE2_AS_FILES=$(find "${STAGE2_DIR}" -name "*.S") + +STAGE2_AS_TARGET="${BUILD_DIR}/stage2_as.o" +STAGE2_CC_TARGET="${BUILD_DIR}/stage2_cc.o" + +STAGE1_DIR="$(pwd)/stage1" +STAGE2_DIR="$(pwd)/stage2" + +function usage { + echo -e "Custom build system." + echo -e "Available commands:" + echo -e " ${0} all" + echo -e " ${0} run" + echo -e " ${0} build_drive" + echo -e " ${0} clean" + echo -e " ${0} stage1" +} + +function build_lib { + macro="$1" + + set -e + + local lib_cfiles=$(find "./lib/" -name "*.c") + + mkdir -p "${BUILD_DIR}/lib" + for i in ${lib_cfiles[@]}; do + "${CROSSCC_i686}" -m32 -c "$i" "${GLOBAL_CFLAGS[@]}" -o "${BUILD_DIR}/${i}.o" -D${macro} + echo -e " [CC] ${i}" + done + + echo "[LIB] Compiled libraries." +} + +function stage1 { + set -e + + if [[ -e "${BUILD_DIR}/${STAGE1_DIR}" ]] && [[ -f "${BUILD_DIR}/${STAGE1_DIR}" ]]; then + mkdir -p "${BUILD_DIR}/${STAGE1_DIR}" + echo -e "Creating the stage 1 build directory ${BUILD_DIR}/${STAGE1_DIR}" + fi + + echo -e "Producing stage 1 binaries..." + + if [[ ${#STAGE1_AS_FILES[@]} -gt 0 ]] && [[ -n "${STAGE1_AS_FILES[@]}" ]]; then + echo -e "[STAGE1] Found assembly files: " + for i in ${STAGE1_AS_FILES[@]}; do + mkdir -p "${BUILD_DIR}/${i}" + "${CROSSAS_i686}" "$i" -o "${BUILD_DIR}/${i}.o" + echo -e " [AS]: $i" + done + echo -e " [AS] Assembled stage 1." + else + echo -e "[STAGE1] No assembly files were found." + fi + + if [[ ${#STAGE1_C_FILES[@]} -gt 0 ]] && [[ -n "${STAGE1_C_FILES[@]}" ]]; then + echo -e "[STAGE1] Found C files: " + for i in ${STAGE1_C_FILES[@]}; do + "${CROSSCC_i686}" -c "$i" -o "${BUILD_DIR}/${i}.o" "${GLOBAL_CFLAGS[@]}" + echo -e " [CC]: $i" + done + echo -e " [CC] Compiled stage 1." + else + echo -e "[STAGE1] No C files were found." + fi + + if [[ ${#STAGE1_C_FILES[@]} -eq 0 ]] && [[ ${#STAGE1_AS_FILES[@]} -eq 0 ]]; then + echo -e "[STAGE1] No stage1 files were found!" + exit 1 + fi + + echo -e "Stage 1 binaries completed." +} + +function stage2 { + if [[ -e "${BUILD_DIR}/${STAGE1_DIR}" ]] && [[ -f "${BUILD_DIR}/${STAGE1_DIR}" ]]; then + mkdir -p "${BUILD_DIR}/${STAGE1_DIR}" + fi + + ${CROSSAS_i686} "${STAGE2_AS_FILES}" -o "${STAGE2_AS_TARGET}" + echo -e " [AS] Assembled stage 2." + ${CROSSCC_x8664} "${STAGE2_C_FILES}" -o "${STAGE2_CC_TARGET}" + echo -e " [CC] Compiled stage 2." +} + +function link { + set -e + + local linker_files=() + + echo -e "[LINK] Linking files..." + + for i in $(find "${BUILD_DIR}" -name "*.o"); do + linker_files+=("$i") + echo -e " [L] Added: $i" + done + + "${CROSSLD_i686}" -T "${LINKER_LD}" "${linker_files[@]}" -o "${STAGE1_TARGET}" + + echo -e "[LINK] Linking complete." +} + +function clean { + if [[ -e "${BUILD_DIR}" && -d "${BUILD_DIR}" ]]; then + echo -e "[CLEAN] Deleting build/ directory..." + rm -rf "${BUILD_DIR}" + fi + + if [[ -e "$(pwd)/disk.img" && -f "$(pwd)/disk.img" ]]; then + echo -e "[CLEAN] Deleting disk.img..." + rm "$(pwd)/disk.img" + fi + echo -e "[CLEAN] Project cleaned." +} + +function build_image { + dd if="${STAGE1_TARGET}" of="$(pwd)/disk.img" bs=512 count=15 +} + +function run { + qemu-system-x86_64 -drive format=raw,file="$(pwd)/disk.img" +} + +function debug { + qemu-system-x86_64 -drive format=raw,file="$(pwd)/disk.img" -S -s +} + +function compile { + echo "[COMPILE] Compiling and preparing the entire build." + clean + mkdir -p ./build/ + build_lib "STAGE1" + stage1 + link + build_image + echo "[COMPILE] DONE" +} + +function run { + qemu-system-x86_64 -drive format=raw,file=disk.img +} + +case "$1" in + "all") compile ;; + "run") compile && run ;; + "debug") compile && debug ;; + "stage1") stage1 ;; + "build_drive") build_image ;; + "clean") clean ;; + "help"|"usage") + usage + exit 0 + ;; + "") + echo -e "You must specify a command." + echo -e "Type '${0} usage' or '${0} help' for more information." + exit 1 + ;; + *) + echo -e "Command not found: '${1}'" + usage + exit 1 + ;; +esac |
