diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 9f0c32b8..1bf74cf3 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -1,87 +1,263 @@ -name: Build +name: StarshipOS Build on: push: - branches: - - master + branches: [master] + pull_request: + branches: [master] + schedule: + - cron: '0 2 * * *' # 02:00 UTC nightly snapshot + workflow_dispatch: + +env: + NEXUS: https://nexus.starshipos-f18.org/repository/starshipos-releases + NEXUS_SNAP: https://nexus.starshipos-f18.org/repository/starshipos-snapshots jobs: - build-amd64-iso: + build: + name: ${{ matrix.board }} runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build kernel (amd64) - run: make -f Makefile.starkernel ARCH=amd64 - - name: Pack El Torito ISO (amd64) - run: | - set -e - BUILD_DIR=build/amd64/kernel - mkdir -p "$BUILD_DIR/iso" - dd if=/dev/zero of="$BUILD_DIR/iso/efi.img" bs=512 count=8192 - mformat -i "$BUILD_DIR/iso/efi.img" :: - mmd -i "$BUILD_DIR/iso/efi.img" ::/EFI - mmd -i "$BUILD_DIR/iso/efi.img" ::/EFI/BOOT - mcopy -i "$BUILD_DIR/iso/efi.img" "$BUILD_DIR/starkernel_loader.efi" ::/EFI/BOOT/BOOTX64.EFI - xorriso -as mkisofs -r -J -e efi.img -no-emul-boot \ - -o "$BUILD_DIR/starkernel.iso" "$BUILD_DIR/iso" - - uses: actions/upload-artifact@v3 - with: - name: lithosananke-amd64-iso - path: build/amd64/kernel/starkernel.iso - build-aarch64-iso: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + board: [qemu, pc, pi4, pi5, milkv] + include: + - board: qemu + karch: amd64 + vm_arch: amd64 + img_type: iso + efi_name: BOOTX64.EFI + - board: pc + karch: amd64 + vm_arch: amd64 + img_type: iso + efi_name: BOOTX64.EFI + - board: pi4 + karch: aarch64 + vm_arch: arm64 + img_type: iso + efi_name: BOOTAA64.EFI + - board: pi5 + karch: aarch64 + vm_arch: arm64 + img_type: iso + efi_name: BOOTAA64.EFI + - board: milkv + karch: riscv64 + vm_arch: riscv64 + img_type: img + efi_name: BOOTRISCV64.EFI + steps: - uses: actions/checkout@v4 - - name: Build kernel (aarch64) + + - name: Install toolchains + run: | + apt-get update -qq + apt-get install -y --no-install-recommends \ + build-essential make curl ca-certificates \ + gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu \ + gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu \ + mtools xorriso dosfstools gdisk + + - name: Install clang-18 (aarch64 loader) + if: matrix.karch == 'aarch64' + run: | + curl -fsSL https://apt.llvm.org/llvm.sh | bash -s -- 18 + + - name: Extract versions + id: ver + run: | + LITHOS=$(grep 'LITHOS_VERSION\s*?=' Makefile.starkernel | head -1 | sed 's/.*= *//') + SF=$(grep '^VERSION\s*?=' Makefile | head -1 | sed 's/.*= *//') + SHA=$(git rev-parse --short HEAD) + if [ "${{ github.event_name }}" = "schedule" ]; then + SUFFIX="-SNAPSHOT" + else + SUFFIX="-${SHA}" + fi + echo "lithos=${LITHOS}${SUFFIX}" >> $GITHUB_OUTPUT + echo "sf=${SF}${SUFFIX}" >> $GITHUB_OUTPUT + echo "sha=${SHA}" >> $GITHUB_OUTPUT + echo "is_snapshot=${{ github.event_name == 'schedule' }}" >> $GITHUB_OUTPUT + + - name: Build StarForth VM + run: make T=${{ matrix.board }} + + - name: Build kernel + run: | + export PATH=/usr/lib/llvm-18/bin:$PATH + make -f Makefile.starkernel T=${{ matrix.board }} + + - name: Pack ISO (amd64 / aarch64) + if: matrix.img_type == 'iso' env: - PATH: /usr/lib/llvm-18/bin:/usr/bin:/bin - run: make -f Makefile.starkernel ARCH=aarch64 - - name: Pack El Torito ISO (aarch64) + BUILD_DIR: build/${{ matrix.karch }}/kernel + EFI: ${{ matrix.efi_name }} + BOARD: ${{ matrix.board }} + VER: ${{ steps.ver.outputs.lithos }} run: | set -e - BUILD_DIR=build/aarch64/kernel mkdir -p "$BUILD_DIR/iso/EFI/BOOT" - cp "$BUILD_DIR/starkernel_loader.efi" "$BUILD_DIR/iso/EFI/BOOT/BOOTAA64.EFI" - printf "FS0:\\\\EFI\\\\BOOT\\\\BOOTAA64.EFI\r\n" > "$BUILD_DIR/iso/startup.nsh" + cp "$BUILD_DIR/starkernel_loader.efi" "$BUILD_DIR/iso/EFI/BOOT/$EFI" + printf 'FS0:\\EFI\\BOOT\\%s\r\n' "$EFI" > "$BUILD_DIR/iso/startup.nsh" dd if=/dev/zero of="$BUILD_DIR/iso/efi.img" bs=512 count=8192 mformat -i "$BUILD_DIR/iso/efi.img" :: - mmd -i "$BUILD_DIR/iso/efi.img" ::/EFI mmd -i "$BUILD_DIR/iso/efi.img" ::/EFI/BOOT - mcopy -i "$BUILD_DIR/iso/efi.img" "$BUILD_DIR/starkernel_loader.efi" ::/EFI/BOOT/BOOTAA64.EFI + mcopy -i "$BUILD_DIR/iso/efi.img" "$BUILD_DIR/starkernel_loader.efi" "::/EFI/BOOT/$EFI" xorriso -as mkisofs -r -J -e efi.img -no-emul-boot \ - -o "$BUILD_DIR/starkernel.iso" "$BUILD_DIR/iso" - - uses: actions/upload-artifact@v3 - with: - name: lithosananke-aarch64-iso - path: build/aarch64/kernel/starkernel.iso + -o "$BUILD_DIR/kernel-${VER}-${BOARD}.iso" "$BUILD_DIR/iso" - build-riscv64-img: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build kernel (riscv64) - run: make -f Makefile.starkernel ARCH=riscv64 - - name: Pack GPT/FAT32 disk image (riscv64) - # El Torito ISO and -bios QEMU mode don't work on riscv64 virt, - # so this arch ships a raw GPT disk image instead of an ISO - # (same distinction Makefile.starkernel's own qemu target makes). + - name: Pack GPT image (riscv64) + if: matrix.img_type == 'img' + env: + BUILD_DIR: build/riscv64/kernel + BOARD: ${{ matrix.board }} + VER: ${{ steps.ver.outputs.lithos }} run: | set -e - BUILD_DIR=build/riscv64/kernel - DISK="$BUILD_DIR/starkernel_rv64.img" + DISK="$BUILD_DIR/kernel-${VER}-${BOARD}.img" dd if=/dev/zero of="$DISK" bs=1M count=64 sgdisk -n 1:2048:131038 -t 1:ef00 -c 1:"EFI System" "$DISK" - dd if=/dev/zero of="$BUILD_DIR/esp_rv64.img" bs=512 count=128991 - mkfs.fat -F 32 -n "ESP" "$BUILD_DIR/esp_rv64.img" - mmd -i "$BUILD_DIR/esp_rv64.img" ::/EFI - mmd -i "$BUILD_DIR/esp_rv64.img" ::/EFI/BOOT - mcopy -i "$BUILD_DIR/esp_rv64.img" "$BUILD_DIR/starkernel_loader.efi" ::/EFI/BOOT/BOOTRISCV64.EFI - mcopy -i "$BUILD_DIR/esp_rv64.img" "$BUILD_DIR/starkernel_kernel.elf" ::/kernel.elf + dd if=/dev/zero of="$BUILD_DIR/esp.img" bs=512 count=128991 + mkfs.fat -F 32 -n "ESP" "$BUILD_DIR/esp.img" + mmd -i "$BUILD_DIR/esp.img" ::/EFI/BOOT + mcopy -i "$BUILD_DIR/esp.img" "$BUILD_DIR/starkernel_loader.efi" ::/EFI/BOOT/BOOTRISCV64.EFI + mcopy -i "$BUILD_DIR/esp.img" "$BUILD_DIR/starkernel_kernel.elf" ::/kernel.elf printf 'FS0:\\EFI\\BOOT\\BOOTRISCV64.EFI\r\n' > "$BUILD_DIR/startup.nsh" - mcopy -i "$BUILD_DIR/esp_rv64.img" "$BUILD_DIR/startup.nsh" ::/startup.nsh - dd if="$BUILD_DIR/esp_rv64.img" of="$DISK" bs=512 seek=2048 conv=notrunc - - uses: actions/upload-artifact@v3 + mcopy -i "$BUILD_DIR/esp.img" "$BUILD_DIR/startup.nsh" ::/startup.nsh + dd if="$BUILD_DIR/esp.img" of="$DISK" bs=512 seek=2048 conv=notrunc + + - name: Upload artifacts (Gitea) + uses: actions/upload-artifact@v3 with: - name: lithosananke-riscv64-img - path: build/riscv64/kernel/starkernel_rv64.img + name: starshipos-${{ matrix.board }}-${{ steps.ver.outputs.sha }} + path: | + build/${{ matrix.karch }}/kernel/starkernel_loader.efi + build/${{ matrix.karch }}/kernel/starkernel_kernel.elf + build/${{ matrix.karch }}/kernel/kernel-${{ steps.ver.outputs.lithos }}-${{ matrix.board }}.* + build/${{ matrix.vm_arch }}/fastest/starforth + + - name: Publish to Nexus + if: github.ref == 'refs/heads/master' || github.event_name == 'schedule' + env: + NEXUS_PASS: ${{ secrets.NEXUS_CI_PASSWORD }} + BOARD: ${{ matrix.board }} + KARCH: ${{ matrix.karch }} + VM_ARCH: ${{ matrix.vm_arch }} + KVER: ${{ steps.ver.outputs.lithos }} + SFVER: ${{ steps.ver.outputs.sf }} + IMG_TYPE: ${{ matrix.img_type }} + IS_SNAPSHOT: ${{ steps.ver.outputs.is_snapshot }} + run: | + set -e + REPO="${IS_SNAPSHOT:+$NEXUS_SNAP}" + REPO="${REPO:-$NEXUS}" + push() { + local coord="$1" file="$2" + echo "→ org.f18:${coord}" + curl -fsS --retry 3 \ + -u "ci-publisher:${NEXUS_PASS}" \ + -H "Content-Type: application/octet-stream" \ + -X PUT "${REPO}/org/f18/${coord}" \ + --upload-file "$file" + } + + # kernel//kernel---loader.efi + push "kernel/${KVER}/kernel-${KVER}-${BOARD}-loader.efi" \ + "build/${KARCH}/kernel/starkernel_loader.efi" + + # kernel//kernel---kernel.elf + push "kernel/${KVER}/kernel-${KVER}-${BOARD}-kernel.elf" \ + "build/${KARCH}/kernel/starkernel_kernel.elf" + + # kernel//kernel--. + push "kernel/${KVER}/kernel-${KVER}-${BOARD}.${IMG_TYPE}" \ + "build/${KARCH}/kernel/kernel-${KVER}-${BOARD}.${IMG_TYPE}" + + # starforth//starforth-- + push "starforth/${SFVER}/starforth-${SFVER}-${BOARD}" \ + "build/${VM_ARCH}/fastest/starforth" + + verify-isabelle: + name: Isabelle/HOL Proofs + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Cache Isabelle installation + uses: actions/cache@v3 + id: isabelle-install-cache + with: + path: /opt/Isabelle2024 + key: isabelle-2024-linux + + - name: Install Isabelle + if: steps.isabelle-install-cache.outputs.cache-hit != 'true' + run: | + apt-get update -qq + apt-get install -y --no-install-recommends curl ca-certificates + curl -fsSL \ + "https://isabelle.in.tum.de/dist/Isabelle2024_linux.tar.gz" \ + -o /tmp/isabelle.tar.gz + tar -xzf /tmp/isabelle.tar.gz -C /opt + rm /tmp/isabelle.tar.gz + + - name: Cache Isabelle heaps + uses: actions/cache@v3 + with: + path: ~/.isabelle/Isabelle2024 + key: isabelle-heaps-${{ hashFiles('proof/**/*.thy', 'proof/ROOT') }} + restore-keys: isabelle-heaps- + + - name: Verify StarForth proofs + run: | + export PATH=/opt/Isabelle2024/bin:$PATH + isabelle build -v -d proof StarForth 2>&1 | tee /tmp/isabelle-build.log + # Exit code reflects proof success/failure + grep -q "Finished StarForth" /tmp/isabelle-build.log + + - name: Upload proof log + if: always() + uses: actions/upload-artifact@v3 + with: + name: isabelle-proof-log-${{ github.sha }} + path: /tmp/isabelle-build.log + + build-docs: + name: Documentation + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install doc toolchain + run: | + apt-get update -qq + apt-get install -y --no-install-recommends \ + doxygen python3 \ + ruby ruby-dev build-essential \ + texlive-latex-base texlive-latex-extra \ + texlive-science texlive-fonts-recommended + gem install asciidoctor asciidoctor-latex --no-document + + - name: API docs (Doxygen → AsciiDoc) + run: make api-docs + + - name: LaTeX docs (AsciiDoc → LaTeX) + run: make docs-latex + + - name: Math companion PDF (LaTeX → PDF) + run: make math-companion + + - name: Upload documentation + if: always() + uses: actions/upload-artifact@v3 + with: + name: docs-${{ github.sha }} + path: | + docs/src/appendix/ + docs/latex/ + docs/SSRN_companion/Math_Companion_SSRN.pdf diff --git a/.gitea/workflows/nightly-docs.yml b/.gitea/workflows/nightly-docs.yml index 8abc0360..fda07f49 100644 --- a/.gitea/workflows/nightly-docs.yml +++ b/.gitea/workflows/nightly-docs.yml @@ -6,8 +6,7 @@ # classifier vol1, vol2, vol3 the formal volumes (make -C docs/formal vols) # classifier api the API reference (make -C docs/formal doxygen) # -# Gitea runs a schedule from the default branch. Until StarForth-v4.0.0 is merged to master, -# master carries a copy of this file whose checkout names that branch. +# Gitea runs a schedule from the default branch, master, so this builds master. name: Nightly documents on: diff --git a/.gitea/workflows/nightly.yml b/.gitea/workflows/nightly.yml index f7746c0e..f6029b20 100644 --- a/.gitea/workflows/nightly.yml +++ b/.gitea/workflows/nightly.yml @@ -8,8 +8,7 @@ # classifier milkv MilkV.img.xz Milk-V Mars # classifier logs logs.tar.gz this run's serial logs, proof log and DoE CSVs # -# Gitea runs a schedule from the default branch. Until StarForth-v4.0.0 is merged to master, -# master carries a copy of this file whose checkout names that branch. +# Gitea runs a schedule from the default branch, master, so this builds master. name: Nightly snapshot on: diff --git a/mk/boards.mk b/mk/boards.mk new file mode 100644 index 00000000..6e0c55d2 --- /dev/null +++ b/mk/boards.mk @@ -0,0 +1,54 @@ +# Board target table — T= selects board, sets ARCH + BOARD + BOARD_NAME. +# Included early by both Makefile and Makefile.starkernel, before arch +# normalization runs. Each Makefile applies board-specific flag overrides +# after its own arch block. +# +# Adding a new board: add an ifeq block here, then add compiler-flag +# overrides in the board-override sections of Makefile and +# Makefile.starkernel if the board needs tuning beyond the arch default. + +ifdef T + +ifeq ($(T),qemu) + ARCH ?= amd64 + BOARD := qemu + BOARD_NAME := QEMU x86_64 + CROSS_COMPILE := + +else ifeq ($(T),pc) + ARCH ?= amd64 + BOARD := pc + BOARD_NAME := x86_64 PC (native) + CROSS_COMPILE := + +else ifeq ($(T),pi4) + ARCH ?= aarch64 + BOARD := pi4 + BOARD_NAME := Raspberry Pi 4 (Cortex-A72) + CROSS_COMPILE := aarch64-linux-gnu- + +else ifeq ($(T),pi5) + ARCH ?= aarch64 + BOARD := pi5 + BOARD_NAME := Raspberry Pi 5 (Cortex-A76) + CROSS_COMPILE := aarch64-linux-gnu- + +else ifeq ($(T),milkv) + ARCH ?= riscv64 + BOARD := milkv + BOARD_NAME := Milk-V Pioneer (SG2042 RISC-V 64) + CROSS_COMPILE := riscv64-linux-gnu- + +# ── Future boards (uncomment + add flag overrides in Makefile / Makefile.starkernel) ── +# else ifeq ($(T),zynq7020) +# ARCH ?= arm +# BOARD := zynq7020 +# BOARD_NAME := Xilinx Zynq-7020 (Cortex-A9, 32-bit) +# CROSS_COMPILE := arm-linux-gnueabihf- +# # NOTE: requires removing the 32-bit guardrail and adding armhf toolchain support + +else + $(error Unknown board target T='$(T)'. Supported: qemu pc pi4 pi5 milkv) +endif + +endif # ifdef T