diff --git a/doc/planning/x86_64.md b/doc/planning/x86_64.md index ed5ae08c..6322d9f3 100644 --- a/doc/planning/x86_64.md +++ b/doc/planning/x86_64.md @@ -337,8 +337,6 @@ dependencies. The x86-64 bootstrap retains its explicit startup sequence. Unused working-directory wrappers moved from `io.stdio` into `io.directory`, which explicitly depends on VFS. Existing in-repository callers need no changes. -Every normal build runs `toolchain/check_arch_boundaries.py` to reject CPU -conditionals in shared units and direct architecture imports in migrated units. Existing `DEBUG_LMM` allocator guards and architecture-local fault-injection build flags remain; these are feature/test options, not architecture selection. @@ -351,3 +349,21 @@ The final adapter build also passes the 6 GiB VirtualBox bootstrap, including physical memory above 4 GiB and all 162 string, 17 console, 15 descriptor, and 17 lifecycle/container checks. VM RAM and optical media were restored; the VM is powered off. + +Source search paths are discovered recursively from shared roots and the selected +architecture tree, with other architectures excluded. Both targets use the same +compiler invocation; `target.sh` loads compiler options and entry points from +`toolchain/targets/.sh`. +Directory arguments are NUL-delimited, sorted, and passed as an array so new +subdirectories and spaces in names do not require compile-script edits. Full +i386 and x86-64 builds pass using this discovery path. + +All shared build steps now consume the selected profile: pipeline stages, +assembler format and source roots, C/Pascal compiler options, linker format, +entry points, output locations, optional compiler runtime, and image validation. +`target.sh` loads the profile by filename instead of keeping an architecture +switch. Assembly files, object files, and static libraries are discovered; +the configured assembly entry is linked first to preserve the Multiboot header. +Initialization-table, icon, LVGL, version, and checksum generation use target +settings too. Full i386 and x86-64 builds and VirtualBox boot checks validate +this pipeline; the i386 boot includes normal mounts and existing storage tests. diff --git a/toolchain/check_arch_boundaries.py b/toolchain/check_arch_boundaries.py deleted file mode 100644 index c5a749a5..00000000 --- a/toolchain/check_arch_boundaries.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2026 Aaron Hance -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Prevent shared Pascal units from selecting architecture implementations.""" -from pathlib import Path -import re -import sys - -cpu_directive = re.compile(r"\{\$\s*if(?:def|ndef)?\b[^}]*\bCPU\w*", re.I) -arch_import = re.compile(r"\barch\.(?:x86|x86_64)\.", re.I) -errors = [] -for path in sorted(Path("src").rglob("*")): - if path.suffix not in (".pas", ".inc"): - continue - if path.parts[1] == "arch" and path.parts[2] != "common": - continue - source = path.read_text(encoding="utf-8") - # Ignore prose comments but retain compiler directives. - source = re.sub(r"\{(?!\$).*?\}|\(\*.*?\*\)|//[^\n]*", "", source, flags=re.S) - if cpu_directive.search(source): - errors.append(f"{path}: CPU conditional belongs in build selection") - # Existing i386-only services outside the port still import their drivers. - # The migrated units must depend on stable platform names instead. - migrated = path.as_posix() in { - "src/core/core.util.pas", "src/core/strings/core.strings.pas", - "src/io/io.stdio.pas", "src/proc/proc.mgr.pas", - "src/memory/memory.heap.pas", "src/memory/memory.raw.pas", - } or path.parts[1:3] == ("arch", "common") - if migrated and arch_import.search(source): - errors.append(f"{path}: shared unit imports an architecture implementation") -if errors: - print("\n".join(errors), file=sys.stderr) - sys.exit(1) -print("Shared architecture boundaries verified.") diff --git a/toolchain/compile.sh b/toolchain/compile.sh index ac81b0fa..a68949c0 100644 --- a/toolchain/compile.sh +++ b/toolchain/compile.sh @@ -1,73 +1,30 @@ #!/usr/bin/env bash -# Multi-architecture build updates: Copyright 2026 Aaron Hance. -ERRCOUNT=0 -echo " " -echo "=======================" -echo " " -echo "Asuro Compilation" -echo " " - +# Copyright 2026 Aaron Hance +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +set -e TOOLCHAIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$TOOLCHAIN_DIR/target.sh" mkdir -p "$OBJ_DIR" "$BIN_DIR" -# Clean only this target's generated objects; preserve other architectures. +# Preserve generated objects belonging to other targets. find "$OBJ_DIR" -maxdepth 1 -type f \( -name '*.o' -o -name '*.ppu' -o -name '*.a' \) -delete -runOrFail() { - local binary=$1 - local errorText=$2 - if $binary; then - echo "Success." - else - echo "$errorText" - ERRCOUNT=$((ERRCOUNT+1)) - fi -} - -declare -a run_steps=( - "compile_stub.sh" "Failed to compile stub!" - "compile_vergen.sh" "Versions failed to compile" - "compile_lvgl.sh" "Failed to compile LVGL!" - "compile_icons.sh" "Failed to generate icons!" - "compile_wasuro.sh" "Failed to pull Wasuro!" - "compile_sources.sh" "Failed to compile FPC Sources!" - "compile_initcalls.sh" "Failed to generate INITFINAL table!" - "compile_link.sh" "Failed linking!" - "compile_isogen.sh" "Failed to create ISO!" - "compile_docs.sh" "Failed to generate documentation!" -) - -if [ "$ASURO_ARCH" = x86_64 ]; then - # Bootstrap milestone: no desktop/runtime dependencies until they are ported. - run_steps=( - "compile_stub.sh" "Failed to compile stub!" - "compile_sources.sh" "Failed to compile FPC Sources!" - "compile_link.sh" "Failed linking!" - "compile_isogen.sh" "Failed to create ISO!" - ) -fi - -for ((i=0; i<${#run_steps[@]}; i+=2)) -do - if [ "$ERRCOUNT" -eq "0" ] - then - script="${TOOLCHAIN_DIR}/${run_steps[$i]}" - message="${run_steps[$i+1]}" - runOrFail "$script" "$message" - fi +for step in "${BUILD_STEPS[@]}"; do + if bash "$TOOLCHAIN_DIR/compile_$step.sh"; then + echo "Success." + else + echo "Failed build step: $step" >&2 + if [ -n "$FINISH_SCRIPT" ]; then bash "$TOOLCHAIN_DIR/$FINISH_SCRIPT" failed; fi + exit 1 + fi done - -#Call generate final artifacts based on failure or success of the above. -if [ "$ASURO_ARCH" = x86_64 ]; then - if [ "$ERRCOUNT" -ne 0 ]; then exit 1; fi - echo "No errors. Bootstrap image: $ISO_FILE" - exit 0 -fi -if [ "$ERRCOUNT" -ne "0" ] -then - . "${TOOLCHAIN_DIR}/compile_finish.sh" "failed" -else - . "${TOOLCHAIN_DIR}/compile_finish.sh" "success" -fi - -cd .. +if [ -n "$FINISH_SCRIPT" ]; then bash "$TOOLCHAIN_DIR/$FINISH_SCRIPT" success; fi +echo "No errors. Image: $ISO_FILE" diff --git a/toolchain/compile_icons.sh b/toolchain/compile_icons.sh index 41e571c0..45ff541e 100644 --- a/toolchain/compile_icons.sh +++ b/toolchain/compile_icons.sh @@ -3,10 +3,12 @@ # Runs gen_file_icons.py to produce asuro_icons_{32,64,128}.c in lvglh/, # then compiles each into a .o in lib/ for linking. set -e +# Target configuration updates: Copyright 2026 Aaron Hance. +source "$(dirname "${BASH_SOURCE[0]}")/target.sh" TOOLCHAIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CONF_DIR="$(pwd)/lvglh" -OUT_DIR="$(pwd)/lib" +OUT_DIR="$(pwd)/$OBJ_DIR" FONT_CACHE="$(pwd)/img" LVGL_DIR="/tmp/lvgl" CACHE_DIR="/code/lvgl" @@ -20,8 +22,8 @@ else LVGL_INC="${CACHE_DIR}" fi -CC="gcc" -CFLAGS="-m32 -march=i686 -ffreestanding \ +CC="$C_COMPILER" +CFLAGS="-ffreestanding \ -fno-builtin -fno-stack-protector -fno-pic -fno-pie \ -O2 -Wall -Wno-unused-function -Wno-unused-variable \ -I${CONF_DIR} \ @@ -44,7 +46,7 @@ for src in "${CONF_DIR}"/asuro_icons_*.c; do [ -f "$src" ] || continue base="$(basename "${src%.c}")" echo " Compiling ${base}.c ..." - if ! $CC $CFLAGS -c "$src" -o "${OUT_DIR}/${base}.o" 2>&1; then + if ! "$CC" "${C_TARGET_OPTIONS[@]}" $CFLAGS -c "$src" -o "${OUT_DIR}/${base}.o" 2>&1; then echo " FAILED: ${base}.c" ERRORS=$((ERRORS + 1)) fi diff --git a/toolchain/compile_initcalls.sh b/toolchain/compile_initcalls.sh index 58b4bdc3..f1e550f2 100644 --- a/toolchain/compile_initcalls.sh +++ b/toolchain/compile_initcalls.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Target configuration updates: Copyright 2026 Aaron Hance. +set -e +source "$(dirname "${BASH_SOURCE[0]}")/target.sh" echo " " echo "=======================" echo " " @@ -18,11 +21,9 @@ echo " " INIT_SYMBOLS=() -for obj in lib/*.o; do - # Skip non-FPC objects that will never contain Pascal init sections - case "$(basename "$obj")" in - stub.o|splash_tga.o|initcalls.o) continue ;; - esac +for obj in "$OBJ_DIR/"*.o; do + [ -f "$obj" ] || continue + [ "$obj" = "$OBJ_DIR/initcalls.o" ] && continue # nm --defined-only: only symbols defined in this object (not extern refs) # grep ' T INIT\$_\$': global text symbols matching FPC's naming convention @@ -35,7 +36,7 @@ done COUNT=${#INIT_SYMBOLS[@]} echo "Found $COUNT unit initialization section(s)." -CFILE="/tmp/initcalls.c" +CFILE="$BIN_DIR/initcalls.c" # ---- Generate the C source file ---- @@ -99,6 +100,6 @@ cat "$CFILE" echo "--- End of generated C source ---" echo " " -# Compile to a 32-bit ELF object file -gcc -m32 -c -fno-pic -ffreestanding -o lib/initcalls.o "$CFILE" -echo "Compiled lib/initcalls.o" +# Compile for the selected target +"$C_COMPILER" "${C_TARGET_OPTIONS[@]}" -c -fno-pic -ffreestanding -o "$OBJ_DIR/initcalls.o" "$CFILE" +echo "Compiled $OBJ_DIR/initcalls.o" diff --git a/toolchain/compile_isogen.sh b/toolchain/compile_isogen.sh index b39b9be8..0729f2f7 100644 --- a/toolchain/compile_isogen.sh +++ b/toolchain/compile_isogen.sh @@ -1,15 +1,21 @@ #!/usr/bin/env bash -# Multi-architecture build updates: Copyright 2026 Aaron Hance. +# Copyright 2026 Aaron Hance +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. set -e source "$(dirname "${BASH_SOURCE[0]}")/target.sh" -echo " " -echo "=======================" -echo " " echo "Creating ISO..." -echo " " mkdir -p "$ISO_ROOT/boot/grub" -if [ "$ASURO_ARCH" != x86 ]; then - cp iso/boot/grub/grub.cfg "$ISO_ROOT/boot/grub/grub.cfg" +if [ "$(realpath "$GRUB_CONFIG")" != "$(realpath "$ISO_ROOT/boot/grub/grub.cfg")" ]; then + cp "$GRUB_CONFIG" "$ISO_ROOT/boot/grub/grub.cfg" fi cp "$BIN_DIR/kernel.bin" "$ISO_ROOT/boot/asuro.bin" grub-mkrescue -o "$ISO_FILE" "$ISO_ROOT" diff --git a/toolchain/compile_link.sh b/toolchain/compile_link.sh index 0140d802..60803b18 100644 --- a/toolchain/compile_link.sh +++ b/toolchain/compile_link.sh @@ -1,31 +1,32 @@ #!/usr/bin/env bash -# Multi-architecture build updates: Copyright 2026 Aaron Hance. +# Copyright 2026 Aaron Hance +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. set -e source "$(dirname "${BASH_SOURCE[0]}")/target.sh" -echo " " -echo "=======================" -echo " " echo "Linking..." -echo " " -if [ "$ASURO_ARCH" = x86_64 ]; then - ld -m "$LD_FORMAT" --gc-sections --no-warn-execstack \ - -T"$LINKER_SCRIPT" -o "$BIN_DIR/kernel.bin" "$OBJ_DIR/"*.o - grub-file --is-x86-multiboot "$BIN_DIR/kernel.bin" - exit +objects=() +boot_object="$OBJ_DIR/${ASM_ENTRY//\//_}" +boot_object="${boot_object%.asm}.o" +objects+=("$boot_object") +while IFS= read -r -d '' object; do + if [ "$object" != "$boot_object" ]; then objects+=("$object"); fi +done < <(find "$OBJ_DIR" -maxdepth 1 -type f -name '*.o' -print0 | LC_ALL=C sort -z) +libraries=() +while IFS= read -r -d '' library; do libraries+=("$library"); done \ + < <(find "$OBJ_DIR" -maxdepth 1 -type f -name '*.a' -print0 | LC_ALL=C sort -z) +if "$LINK_COMPILER_RUNTIME"; then + libraries+=("$("$C_COMPILER" "${C_TARGET_OPTIONS[@]}" -print-libgcc-file-name)") fi -objstring=""; -for object in `find lib/ -maxdepth 1 -name "*.o"`; do - if [ "$object" != "lib/stub.o" ] - then - objstring=$objstring$object" "; - fi -done; -objstring=lib/stub.o" "$objstring -echo "Object Files: "$objstring -echo " " - -# Find libgcc for i386 (needed by LVGL compiled with gcc) -LIBGCC=$(gcc -m32 -print-libgcc-file-name) -echo "libgcc: ${LIBGCC}" - -ld -m elf_i386 -s --gc-sections --no-warn-execstack -Ttoolchain/linker.script -o bin/kernel.bin $objstring --start-group lib/liblvgl.a ${LIBGCC} --end-group +ld -m "$LD_FORMAT" "${LINK_OPTIONS[@]}" --gc-sections --no-warn-execstack \ + -T"$LINKER_SCRIPT" -o "$BIN_DIR/kernel.bin" "${objects[@]}" \ + --start-group "${libraries[@]}" --end-group +"${KERNEL_VALIDATOR[@]}" "$BIN_DIR/kernel.bin" diff --git a/toolchain/compile_lvgl.sh b/toolchain/compile_lvgl.sh index 4632fb60..01b487fe 100644 --- a/toolchain/compile_lvgl.sh +++ b/toolchain/compile_lvgl.sh @@ -3,17 +3,19 @@ # Clone & compile in /tmp (fast container-local fs). # Cache liblvgl.a on host mount (/code/lvgl/) to skip rebuild. set -e +# Target configuration updates: Copyright 2026 Aaron Hance. +source "$(dirname "${BASH_SOURCE[0]}")/target.sh" LVGL_VERSION="v9.2.2" LVGL_REPO="https://github.com/lvgl/lvgl.git" LVGL_DIR="/tmp/lvgl" -OBJ_DIR="/tmp/lvgl_obj" +LVGL_OBJ_DIR="/tmp/lvgl_obj_$ASURO_ARCH" CONF_DIR="$(pwd)/lvglh" -OUT_DIR="$(pwd)/lib" +OUT_DIR="$(pwd)/$OBJ_DIR" CACHE_DIR="/code/lvgl" -CC="gcc" -CFLAGS="-m32 -march=i686 -ffreestanding \ +CC="$C_COMPILER" +CFLAGS="-ffreestanding \ -fno-builtin -fno-stack-protector -fno-pic -fno-pie \ -O2 -Wall -Wno-unused-function -Wno-unused-variable \ -I${CONF_DIR} \ @@ -28,9 +30,9 @@ echo "Compiling LVGL..." echo " " # If cached liblvgl.a exists on host mount, just copy it and skip everything -if [ -f "${CACHE_DIR}/liblvgl.a" ]; then +if [ -f "${CACHE_DIR}/${LVGL_CACHE_NAME}" ]; then echo "Found cached liblvgl.a in ${CACHE_DIR}, copying to ${OUT_DIR}..." - cp "${CACHE_DIR}/liblvgl.a" "${OUT_DIR}/liblvgl.a" + cp "${CACHE_DIR}/${LVGL_CACHE_NAME}" "${OUT_DIR}/liblvgl.a" echo "(Delete lvgl/liblvgl.a to force a full rebuild.)" echo " " echo "LVGL compilation complete (cached)." @@ -50,18 +52,18 @@ TOTAL=$(echo "$SOURCES" | wc -l) echo "Found ${TOTAL} LVGL source files." # Compile each .c file to .o (container-local) -rm -rf "$OBJ_DIR" -mkdir -p "$OBJ_DIR" +rm -rf "$LVGL_OBJ_DIR" +mkdir -p "$LVGL_OBJ_DIR" COUNT=0 ERRORS=0 for src in $SOURCES; do COUNT=$((COUNT + 1)) rel="${src#${LVGL_DIR}/src/}" - obj_path="${OBJ_DIR}/${rel%.c}.o" + obj_path="${LVGL_OBJ_DIR}/${rel%.c}.o" mkdir -p "$(dirname "$obj_path")" - if ! $CC $CFLAGS -c "$src" -o "$obj_path" 2>&1; then + if ! "$CC" "${C_TARGET_OPTIONS[@]}" $CFLAGS -c "$src" -o "$obj_path" 2>&1; then echo "FAILED: $rel" ERRORS=$((ERRORS + 1)) fi @@ -79,7 +81,7 @@ if [ "$ERRORS" -ne 0 ]; then fi # Archive into static library -OBJECTS=$(find "$OBJ_DIR" -name '*.o') +OBJECTS=$(find "$LVGL_OBJ_DIR" -name '*.o') ar rcs "${OUT_DIR}/liblvgl.a" $OBJECTS echo "Created ${OUT_DIR}/liblvgl.a" @@ -99,7 +101,7 @@ if [ -n "$LVGLH_SOURCES" ]; then obj_path="${LVGLH_OBJ_DIR}/${rel%.c}.o" mkdir -p "$(dirname "$obj_path")" echo " [lvglh] $rel" - if ! $CC $CFLAGS -c "$src" -o "$obj_path" 2>&1; then + if ! "$CC" "${C_TARGET_OPTIONS[@]}" $CFLAGS -c "$src" -o "$obj_path" 2>&1; then echo " FAILED: $rel" HERRORS=$((HERRORS + 1)) fi @@ -121,10 +123,10 @@ fi echo "Caching LVGL to host mount..." mkdir -p "$CACHE_DIR" rm -rf ${CACHE_DIR}/* ${CACHE_DIR}/.[!.]* ${CACHE_DIR}/..?* 2>/dev/null || true -cp "${OUT_DIR}/liblvgl.a" "${CACHE_DIR}/liblvgl.a" +cp "${OUT_DIR}/liblvgl.a" "${CACHE_DIR}/${LVGL_CACHE_NAME}" cp -a "$LVGL_DIR/src" "${CACHE_DIR}/src" cp -a "$LVGL_DIR"/*.h "${CACHE_DIR}/" 2>/dev/null || true -cp -a "$OBJ_DIR" "${CACHE_DIR}/obj" +cp -a "$LVGL_OBJ_DIR" "${CACHE_DIR}/obj" echo "Done." echo " " diff --git a/toolchain/compile_sources.sh b/toolchain/compile_sources.sh index c4ce1d16..c2816be3 100644 --- a/toolchain/compile_sources.sh +++ b/toolchain/compile_sources.sh @@ -7,27 +7,22 @@ echo "=======================" echo " " echo "Compiling FPC Sources..." echo " " -# The build selects one platform implementation; shared units cannot select CPUs. -python3 toolchain/check_arch_boundaries.py -# Build -Fu flags for the selected architecture and shared sources. -if [ "$ASURO_ARCH" = x86_64 ]; then - test_flags=() - case "${ASURO_BOOT_TEST:-none}" in - none) ;; - ud) test_flags=(-dASURO_TEST_UD) ;; - pf) test_flags=(-dASURO_TEST_PF) ;; - df) test_flags=(-dASURO_TEST_DF) ;; - *) echo "Unknown ASURO_BOOT_TEST" >&2; exit 1 ;; +# Discover unit directories using the existing source roots. Architecture +# filtering follows the namespace convention; no unit directory is added by hand. +source_paths=() +while IFS= read -r -d '' dir; do + case "$dir" in + src/arch/*) + namespace="${dir#src/arch/}" + namespace="${namespace%%/*}" + if [[ "$namespace" != "$ASURO_ARCH" && "$namespace" != common ]]; then + continue + fi + ;; esac - # Restrict search paths: never accidentally select the i386 system unit. - exec ppcx64 -n -O2 -Si -Sc -Sg -Xd -CX -Rintel -Tlinux \ - -Fu"src/arch/$ASURO_ARCH/platform" -Fusrc/core -Fusrc/core/strings -Fusrc/driver/storage -Fusrc/arch/x86_64/proc -Fusrc/core/ds -Fusrc/proc -Fusrc/io -Fusrc/arch/common -Fusrc/debug -Fusrc/boot -Fusrc/memory -Fusrc/arch/x86_64/memory -Fu"src/arch/x86_64" -FU"$OBJ_DIR" -FE"$BIN_DIR" "${test_flags[@]}" \ - src/arch/x86_64/arch.x86_64.boot.pas -fi -FU_PATHS="-Fusrc/arch/$ASURO_ARCH/platform -Fusrc -Fuwasuro -Fucompat" -for dir in $(find src wasuro compat -type d -not -path 'src/arch/*' 2>/dev/null) \ - $(find "src/arch/$ASURO_ARCH" src/arch/common -type d -not -path '*/platform*'); do - FU_PATHS="$FU_PATHS -Fu$dir" -done + source_paths+=("-Fu$dir") +done < <(find src wasuro compat -type d -print0 | LC_ALL=C sort -zu) -fpc -Aelf -gw -g -gl -n -v0e -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ $FU_PATHS src/asuro.pas +exec "$PASCAL_COMPILER" -n -Si -Sc -Sg -Xd -CX -Rintel -Tlinux \ + "${PASCAL_OPTIONS[@]}" "${source_paths[@]}" \ + -FU"$OBJ_DIR" -FE"$BIN_DIR" "$PASCAL_ENTRY" diff --git a/toolchain/compile_stub.sh b/toolchain/compile_stub.sh index 1a506431..aecb77e6 100644 --- a/toolchain/compile_stub.sh +++ b/toolchain/compile_stub.sh @@ -1,15 +1,21 @@ #!/usr/bin/env bash -# Multi-architecture build updates: Copyright 2026 Aaron Hance. +# Copyright 2026 Aaron Hance +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. set -e source "$(dirname "${BASH_SOURCE[0]}")/target.sh" -echo " " -echo "=======================" -echo " " -echo "Compiling Stub..." -echo " " -nasm -f "$NASM_FORMAT" "src/arch/$ASURO_ARCH/boot/stub.asm" -o "$OBJ_DIR/stub.o" -if [ "$ASURO_ARCH" = x86 ]; then - nasm -f "$NASM_FORMAT" src/boot/splash_tga.asm -o "$OBJ_DIR/splash_tga.o" -else - nasm -f "$NASM_FORMAT" src/arch/x86_64/isr/entry.asm -o "$OBJ_DIR/isr_entry.o" -fi +echo "Compiling assembly..." +# Include only standalone assembly under the target and enabled shared roots. +# Relative source paths keep equal basenames in separate directories distinct. +while IFS= read -r -d '' source_file; do + object="$OBJ_DIR/${source_file//\//_}" + nasm -f "$NASM_FORMAT" "$source_file" -o "${object%.asm}.o" +done < <(find "$ARCH_SOURCE_ROOT" "${ASM_SHARED_ROOTS[@]}" -type f -name '*.asm' -print0 | LC_ALL=C sort -z) diff --git a/toolchain/compile_sumgen.sh b/toolchain/compile_sumgen.sh index 42d4d228..f4584299 100644 --- a/toolchain/compile_sumgen.sh +++ b/toolchain/compile_sumgen.sh @@ -1,8 +1,10 @@ #!/usr/bin/env bash +# Target configuration updates: Copyright 2026 Aaron Hance. +source "$(dirname "${BASH_SOURCE[0]}")/target.sh" echo " " echo "=======================" echo " " echo "Generating Checksum Badge..." echo " " -checksum=$(md5sum Asuro.iso | awk '{print $1}') +checksum=$(md5sum "$ISO_FILE" | awk '{print $1}') wget -q https://img.shields.io/badge/checksum-$checksum-important.svg -O release/checksum.svg 2>/dev/null \ No newline at end of file diff --git a/toolchain/compile_vergen.sh b/toolchain/compile_vergen.sh index 5382c513..f852cddd 100644 --- a/toolchain/compile_vergen.sh +++ b/toolchain/compile_vergen.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash set -e +# Target configuration updates: Copyright 2026 Aaron Hance. +source "$(dirname "${BASH_SOURCE[0]}")/target.sh" TOOLCHAIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" echo " " echo "=======================" @@ -12,8 +14,8 @@ outfile="src/core/core.version.pas" file="toolchain/version" { # this script requires semver tool - wget -q https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver -O bin/semver && chmod +x bin/semver - export PATH="$(pwd)/bin:$PATH" + wget -q https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver -O "$BIN_DIR/semver" && chmod +x "$BIN_DIR/semver" + export PATH="$(pwd)/$BIN_DIR:$PATH" } tagref=$(git describe --tags) revision=$(git rev-parse --short=8 HEAD) @@ -26,7 +28,7 @@ build=$(semver get build $tagref) linecount=$("${TOOLCHAIN_DIR}/loc.sh" | awk '{print $1}') sourcecount=$(find src -type f | wc -l) drivercount=$(find src/driver -type f | wc -l) -fpcversion=$(fpc -h | grep -m 1 version | awk '{print $5}') +fpcversion=$("$PASCAL_COMPILER" -h | grep -m 1 version | awk '{print $5}') makeversion=$(make -v | grep GNU | awk '{print $3}' | grep -v GNU) nasmversion=$(nasm -v | awk '{print $3'}) compiledate=$(date +"%d/%m/%y") diff --git a/toolchain/target.sh b/toolchain/target.sh index 9f4a2f54..848497c8 100644 --- a/toolchain/target.sh +++ b/toolchain/target.sh @@ -10,27 +10,26 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# Shared target selection. Source this file from build steps. +# Load a target profile by convention rather than branching in build steps. ASURO_ARCH="${ASURO_ARCH:-x86}" -case "$ASURO_ARCH" in - x86) - OBJ_DIR=lib - BIN_DIR=bin - ISO_ROOT=iso - ISO_FILE=Asuro.iso - NASM_FORMAT=elf - LD_FORMAT=elf_i386 - LINKER_SCRIPT=toolchain/linker.script - ;; - x86_64) - OBJ_DIR=lib/x86_64 - BIN_DIR=bin/x86_64 - ISO_ROOT=bin/x86_64/iso - ISO_FILE=Asuro-x86_64.iso - NASM_FORMAT=elf64 - LD_FORMAT=elf_x86_64 - LINKER_SCRIPT=toolchain/x86_64/linker.script - ;; - *) echo "Unsupported ASURO_ARCH: $ASURO_ARCH" >&2; exit 1 ;; -esac -export ASURO_ARCH OBJ_DIR BIN_DIR ISO_ROOT ISO_FILE NASM_FORMAT LD_FORMAT LINKER_SCRIPT +if [[ ! "$ASURO_ARCH" =~ ^[a-zA-Z0-9_]+$ ]]; then + echo "Invalid ASURO_ARCH" >&2; exit 1 +fi +profile="$(dirname "${BASH_SOURCE[0]}")/targets/$ASURO_ARCH.sh" +if [ ! -f "$profile" ]; then echo "Unsupported ASURO_ARCH: $ASURO_ARCH" >&2; exit 1; fi +ARCH_SOURCE_ROOT="src/arch/$ASURO_ARCH" +TARGET_TOOLCHAIN_DIR="toolchain/$ASURO_ARCH" +OBJ_DIR="lib/$ASURO_ARCH" +BIN_DIR="bin/$ASURO_ARCH" +ISO_ROOT="$BIN_DIR/iso" +ISO_FILE="Asuro-$ASURO_ARCH.iso" +GRUB_CONFIG=iso/boot/grub/grub.cfg +ASM_ENTRY="$ARCH_SOURCE_ROOT/boot/stub.asm" +C_COMPILER=gcc +LINK_OPTIONS=() +LINK_COMPILER_RUNTIME=false +ASM_SHARED_ROOTS=() +FINISH_SCRIPT= +LVGL_CACHE_NAME="liblvgl-$ASURO_ARCH.a" +source "$profile" +export ASURO_ARCH OBJ_DIR BIN_DIR ISO_ROOT ISO_FILE diff --git a/toolchain/targets/x86.sh b/toolchain/targets/x86.sh new file mode 100644 index 00000000..1a16f43a --- /dev/null +++ b/toolchain/targets/x86.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Copyright 2026 Aaron Hance +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Legacy output locations are retained for the existing VirtualBox workflow. +OBJ_DIR=lib +BIN_DIR=bin +ISO_ROOT=iso +ISO_FILE=Asuro.iso +PASCAL_COMPILER=fpc +PASCAL_ENTRY=src/asuro.pas +PASCAL_OPTIONS=(-Aelf -gw -g -gl -v0e -O3 -OpPENTIUM3 -XXs -CfSSE -CfSSE2 -Pi386) +C_TARGET_OPTIONS=(-m32 -march=i686) +NASM_FORMAT=elf +LD_FORMAT=elf_i386 +LINKER_SCRIPT=toolchain/linker.script +LINK_OPTIONS=(-s) +LINK_COMPILER_RUNTIME=true +ASM_SHARED_ROOTS=(src/boot) +BUILD_STEPS=(stub vergen lvgl icons wasuro sources initcalls link isogen docs) +FINISH_SCRIPT=compile_finish.sh +LVGL_CACHE_NAME=liblvgl.a + +KERNEL_VALIDATOR=(grub-file --is-x86-multiboot) diff --git a/toolchain/targets/x86_64.sh b/toolchain/targets/x86_64.sh new file mode 100644 index 00000000..a1165d66 --- /dev/null +++ b/toolchain/targets/x86_64.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright 2026 Aaron Hance +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +PASCAL_COMPILER=ppcx64 +PASCAL_ENTRY="$ARCH_SOURCE_ROOT/arch.$ASURO_ARCH.boot.pas" +PASCAL_OPTIONS=(-O2) +C_TARGET_OPTIONS=(-m64) +NASM_FORMAT=elf64 +LD_FORMAT=elf_x86_64 +LINKER_SCRIPT="$TARGET_TOOLCHAIN_DIR/linker.script" +# The bootstrap does not depend on the desktop or hosted runtime. +BUILD_STEPS=(stub sources link isogen) +case "${ASURO_BOOT_TEST:-none}" in + none) ;; + ud|pf|df) PASCAL_OPTIONS+=("-dASURO_TEST_${ASURO_BOOT_TEST^^}") ;; + *) echo "Unknown ASURO_BOOT_TEST" >&2; exit 1 ;; +esac + +KERNEL_VALIDATOR=(grub-file --is-x86-multiboot)