diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..f910d53 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,13 @@ +# Default owners +* @strombetta + +# CI / release workflows +/.github/workflows/ @strombetta + +# Build system and scripts +/Makefile @strombetta +/Makefile.check @strombetta +/Makefile.help @strombetta +/make/ @strombetta +/scripts/ @strombetta +/config/ @strombetta diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5673923..36a87c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,7 @@ on: push: tags: - "v*" + workflow_dispatch: jobs: build: @@ -15,12 +16,10 @@ jobs: include: - arch: x86_64 runs-on: ubuntu-latest - target: x86_64 triple: x86_64-bugleos-linux-musl label: x86_64 - arch: aarch64 - runs-on: arm64 - target: aarch64 + runs-on: ubuntu-24.04-arm triple: aarch64-bugleos-linux-musl label: aarch64 permissions: @@ -31,6 +30,26 @@ jobs: with: fetch-depth: 0 + - name: Read package versions + shell: bash + run: | + set -euo pipefail + binutils_version="$(awk -F ' := ' '/^BINUTILS_VERSION/ {print $2; exit}' make/binutils-stage1.mk)" + gcc_version="$(awk -F ' := ' '/^GCC_VERSION/ {print $2; exit}' make/gcc-stage1.mk)" + musl_version="$(awk -F ' := ' '/^MUSL_VERSION/ {print $2; exit}' make/musl.mk)" + linux_version="$(awk -F ' := ' '/^LINUX_VERSION/ {print $2; exit}' make/linux-headers.mk)" + + if [ -z "$binutils_version" ] || [ -z "$gcc_version" ] || [ -z "$musl_version" ] || [ -z "$linux_version" ]; then + echo "Failed to read one or more package versions." >&2 + exit 1 + fi + + echo "BINUTILS_VERSION=${binutils_version}" >> "$GITHUB_ENV" + echo "GCC_VERSION=${gcc_version}" >> "$GITHUB_ENV" + echo "MUSL_VERSION=${musl_version}" >> "$GITHUB_ENV" + echo "LINUX_VERSION=${linux_version}" >> "$GITHUB_ENV" + echo "VERSIONS_KEY=binutils-${binutils_version}-gcc-${gcc_version}-musl-${musl_version}-linux-${linux_version}" >> "$GITHUB_ENV" + - name: Validate tag format run: | set -euo pipefail @@ -49,6 +68,24 @@ jobs: build-essential binutils bash coreutils tar gzip xz-utils bison flex texinfo gawk file curl wget gpg \ libgmp-dev libmpfr-dev libmpc-dev python3 + - name: Restore download cache + uses: actions/cache@v4 + with: + path: | + downloads/ + sources/ + key: downloads-${{ runner.os }}-${{ matrix.arch }}-${{ env.VERSIONS_KEY }} + + - name: Restore build cache + uses: actions/cache@v4 + with: + path: | + builds/ + out/progress/ + out/toolchain/ + out/toolchain-stage1/ + key: build-${{ runner.os }}-${{ matrix.arch }}-${{ env.VERSIONS_KEY }}-${{ hashFiles('Makefile', 'make/*.mk', 'config/*.mk', 'scripts/*.sh') }} + - name: Fetch sources run: | set -euo pipefail @@ -59,10 +96,35 @@ jobs: set -euo pipefail ./scripts/verify-checksums.sh - - name: Build ${{ matrix.arch }} toolchain + - name: Build binutils stage1 + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} binutils-stage1 + + - name: Build Linux headers + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} linux-headers + + - name: Build GCC stage1 run: | set -euo pipefail - make ${{ matrix.target }} + make TARGET=${{ matrix.triple }} gcc-stage1 + + - name: Build musl + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} musl + + - name: Build binutils stage2 + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} binutils-stage2 + + - name: Build GCC stage2 + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} gcc-stage2 - name: Upload build logs if: always() @@ -92,6 +154,39 @@ jobs: path: dist/bugleos-toolchain-${{ env.VERSION }}-${{ matrix.label }}.tar.gz if-no-files-found: error + hash-artifacts: + name: Prepare SLSA subjects + runs-on: ubuntu-latest + needs: build + outputs: + base64_subjects: ${{ steps.hashes.outputs.base64_subjects }} + steps: + - name: Download toolchain tarballs + uses: actions/download-artifact@v4 + with: + path: dist + + - name: Compute base64 subjects + id: hashes + shell: bash + run: | + set -euo pipefail + mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) + if [ "${#files[@]}" -eq 0 ]; then + echo "No toolchain tarballs found under dist/." >&2 + exit 1 + fi + + tmp="$(mktemp)" + for f in "${files[@]}"; do + hash="$(sha256sum "$f" | awk '{print $1}')" + name="$(basename "$f")" + printf '%s %s\n' "$hash" "$name" >> "$tmp" + done + + sort "$tmp" | base64 -w0 > "$tmp.b64" + echo "base64_subjects=$(cat "$tmp.b64")" >> "$GITHUB_OUTPUT" + publish: name: Publish Release runs-on: ubuntu-latest @@ -115,6 +210,71 @@ jobs: echo "PRERELEASE=false" >> "$GITHUB_ENV" fi + - name: Install signing tools + run: | + sudo apt-get update + sudo apt-get install -y minisign gnupg + + - name: Install SBOM tool (syft) + run: | + set -euo pipefail + curl -sSfL https://get.anchore.io/syft | sh -s -- -b /usr/local/bin + syft version + + - name: Generate SBOMs (SPDX + CycloneDX) + run: | + set -euo pipefail + mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) + if [ "${#files[@]}" -eq 0 ]; then + echo "No toolchain tarballs found under dist/." >&2 + exit 1 + fi + + for f in "${files[@]}"; do + base="$(basename "$f" .tar.gz)" + workdir="$(mktemp -d)" + tar -C "$workdir" -xzf "$f" + syft "dir:$workdir" -o spdx-json > "dist/${base}.spdx.json" + syft "dir:$workdir" -o cyclonedx-json > "dist/${base}.cdx.json" + rm -rf "$workdir" + done + + - name: Generate SHA256SUMS and signatures + env: + MINISIGN_KEY: ${{ secrets.MINISIGN_KEY }} + MINISIGN_PUB: ${{ secrets.MINISIGN_PUB }} + run: | + set -euo pipefail + + if [ -z "${MINISIGN_KEY:-}" ] || [ -z "${MINISIGN_PUB:-}" ]; then + echo "Missing minisign secrets (MINISIGN_KEY / MINISIGN_PUB)." >&2 + exit 1 + fi + + mkdir -p out dist + printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key + printf '%s' "$MINISIGN_PUB" | base64 -d > out/minisign.pub + chmod 600 out/minisign.key + cp out/minisign.pub dist/minisign.pub + + mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) + if [ "${#files[@]}" -eq 0 ]; then + echo "No toolchain tarballs found under dist/." >&2 + exit 1 + fi + + mapfile -d '' sboms < <(find dist -maxdepth 1 \( -name 'bugleos-toolchain-*.spdx.json' -o -name 'bugleos-toolchain-*.cdx.json' \) -print0 | sort -z) + if [ "${#sboms[@]}" -eq 0 ]; then + echo "No SBOM files found under dist/." >&2 + exit 1 + fi + + sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS + minisign -S -s out/minisign.key -m dist/SHA256SUMS + for f in "${files[@]}"; do + minisign -S -s out/minisign.key -m "$f" + done + - name: Publish GitHub Release uses: softprops/action-gh-release@v2 with: @@ -123,11 +283,44 @@ jobs: draft: false prerelease: ${{ env.PRERELEASE }} body: | - Supported architectures: - Architecture | Download Link - ------------ | ------------- - x86_64 | [bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz](dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz) - aarch64 | [bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz](dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz) + # Supported architectures + + ## ![64-bit architecture (x86_64)](https://img.shields.io/badge/arch-x86__64-blue) + - Toolchain: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz + - Signature (minisign): https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig + + ## ![ARM64 architecture (aarch64)](https://img.shields.io/badge/arch-aarch64-green) + - Toolchain: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz + - Signature (minisign): https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig + + ## Verification + - Public key: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/minisign.pub + - Checksums: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/SHA256SUMS + - Checksums signature: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/SHA256SUMS.minisig + files: | dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz + dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz + dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig + dist/bugleos-toolchain-${{ env.VERSION }}-x86_64.spdx.json + dist/bugleos-toolchain-${{ env.VERSION }}-aarch64.spdx.json + dist/bugleos-toolchain-${{ env.VERSION }}-x86_64.cdx.json + dist/bugleos-toolchain-${{ env.VERSION }}-aarch64.cdx.json + dist/SHA256SUMS + dist/SHA256SUMS.minisig + dist/minisign.pub + + provenance: + name: Generate SLSA provenance + needs: [hash-artifacts, publish] + permissions: + actions: read + id-token: write + contents: write + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + with: + base64-subjects: "${{ needs.hash-artifacts.outputs.base64_subjects }}" + upload-assets: true + upload-tag-name: ${{ github.ref_name }} + provenance-name: bugleos-toolchain-${{ github.ref_name }}.intoto.jsonl diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..fa3f0c1 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,66 @@ +# Code of Conduct + +## Our Pledge + +We as contributors and maintainers pledge to make participation in this project +a harassment-free experience for everyone, regardless of age, body size, +visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to a positive environment include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes +- Focusing on what is best for the community + +Examples of unacceptable behavior include: + +- Sexualized language or imagery, and sexual attention or advances +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without explicit permission +- Other conduct which could reasonably be considered inappropriate + +## Enforcement Responsibilities + +Project maintainers are responsible for clarifying and enforcing standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior they deem inappropriate, threatening, offensive, or +harmful. + +## Scope + +This Code of Conduct applies within all project spaces and also applies when an +individual is officially representing the project in public spaces. + +## Reporting + +Report incidents to the maintainers by contacting the repository owner via the +email listed on their GitHub profile. If you are unable to use email, open a +private GitHub discussion (if enabled) or request a private contact channel +through a maintainer. + +We will acknowledge receipt within 5 business days and will keep you informed +about the process when possible. + +## Enforcement Guidelines + +Maintainers will follow these Community Impact Guidelines in determining the +consequences for any action they deem in violation of this Code of Conduct: + +1. **Correction**: A private, written warning with clarification. +2. **Warning**: A formal warning with consequences for continued behavior. +3. **Temporary Ban**: A temporary ban from participation. +4. **Permanent Ban**: Permanent removal from the community. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 2.1. +For details, see: +https://www.contributor-covenant.org/version/2/1/code_of_conduct.html diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000..aac6a3f --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,21 @@ +# Maintainers + +This document lists the active maintainers for the BugleOS Cross Toolchain +repository and their areas of responsibility. + +## Active Maintainers + +- Sebastiano Trombetta (@strombetta) — Lead Maintainer + - Toolchain build system (Makefiles, scripts) + - Release process and artifacts + - CI/CD workflows + +## Contact + +For questions or support, see SUPPORT.md. +For security issues, follow SECURITY.md. + +## Changes to This File + +Updates to this file should be made via pull request and require approval from +an existing maintainer. diff --git a/Makefile b/Makefile index 3c693e4..266ddf1 100644 --- a/Makefile +++ b/Makefile @@ -20,29 +20,24 @@ # SOFTWARE. include config/paths.mk -include config/versions.mk +include make/helpers.mk -MAKEFLAGS += --no-print-directory +ROOT_DIR := $(abspath $(ROOT_DIR)) + +include Makefile.help -ARCHES := aarch64 x86_64 -load_target = $(strip $(shell awk -F':=' '/^TARGET/ {gsub(/[ \t]/,"",$$2);print $$2}' config/arch/$(1).mk)) +MAKEFLAGS += --no-print-directory -.PHONY: $(ARCHES) toolchain binutils-stage1 linux-headers gcc-stage1 musl binutils-stage2 gcc-stage2 verify-toolchain clean distclean check help sanity +TRIPLET ?= $(TARGET) -help: - @echo "BugleOS Cross-compiling Toolchain Builder" - @echo - @echo "Targets:" - @echo " make help Show this help message" - @echo " make toolchain Build BugleOS cross-compiling toolchain for host architecture" - @echo " make x86_64 Build BugleOS cross-compiling toolchain for x86_64 architecture" - @echo " make aarch64 Build BugleOS cross-compiling toolchain for aarch64 architecture" - @echo " make clean Remove builds and logs" - @echo " make distclean Full cleanup" - @echo " make check TARGET= Sanity-check an existing toolchain" +BINUTILS_TOOLS := addr2line ar as c++filt elfedit gprof ld ld.bfd ld.gold nm objcopy objdump ranlib readelf size strings strip +GCC_TOOLS := gcc g++ cpp gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool +MUSL_LIBS := libc libm libpthread librt libdl libutil libxnet libresolv libcrypt -$(ARCHES): - @$(MAKE) TARGET=$(call load_target,$@) toolchain +.PHONY: toolchain binutils-stage1 linux-headers gcc-stage1 musl binutils-stage2 gcc-stage2 verify-toolchain \ + clean-toolchain clean-binutils clean-gcc clean-musl clean-kheaders \ + clean-binutils-stage2 clean-gcc-stage2 \ + clean check sanity guard-%: @test -n "$($*)" || { echo "ERROR: $* is not set"; exit 1; } @@ -72,13 +67,136 @@ verify-toolchain: guard-TARGET toolchain: binutils-stage1 linux-headers gcc-stage1 musl binutils-stage2 gcc-stage2 -clean: - @rm -rf $(BUILDS_DIR) $(LOGS_DIR) - -distclean: clean - @rm -rf $(OUT_DIR) - -check: verify-toolchain +clean: clean-toolchain ## Remove toolchain output for the current triplet (plus logs/output cleanup) + +clean-toolchain: clean-binutils clean-gcc clean-musl clean-kheaders clean-binutils-stage2 clean-gcc-stage2 ## Remove toolchain output for the current triplet (plus logs/output cleanup) + $(call do_clean,toolchain) + $(call do_safe_remove,$(LOGS_DIR)) + $(call do_safe_remove,$(OUT_DIR)) + $(call do_safe_remove,$(TOOLCHAIN_TARGET_DIR)) + $(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)) + +clean-binutils: clean-gcc ## Remove binutils build directories + $(call do_clean,binutils) + $(call do_safe_remove,$(BINUTILS1_BUILD_DIR)) + $(call do_safe_remove,$(BINUTILS2_BUILD_DIR)) + $(call do_safe_remove_glob,$(SOURCES_DIR),binutils-*) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),.binutils-*-verified) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),binutils-*.tar.xz) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),binutils-*.tar.xz.sig) + $(call do_safe_remove,$(DOWNLOADS_DIR)/gnu-keyring.gpg) + $(call do_safe_remove_glob,$(LOGS_DIR),binutils-stage1-*.log) + $(call do_safe_remove_glob,$(LOGS_DIR),binutils-stage2-*.log) + $(foreach tool,$(BINUTILS_TOOLS),$(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/bin/$(TARGET)-$(tool))) + $(foreach tool,$(BINUTILS_TOOLS),$(call do_safe_remove,$(TOOLCHAIN_ROOT)/bin/$(TARGET)-$(tool))) + $(call do_safe_remove_glob,$(STAGE1_TOOLCHAIN_ROOT)/lib,libbfd.*) + $(call do_safe_remove_glob,$(STAGE1_TOOLCHAIN_ROOT)/lib,libopcodes.*) + $(call do_safe_remove_glob,$(STAGE1_TOOLCHAIN_ROOT)/lib,libiberty.*) + $(call do_safe_remove_glob,$(STAGE1_TOOLCHAIN_ROOT)/lib,libctf.*) + $(call do_safe_remove_glob,$(STAGE1_TOOLCHAIN_ROOT)/lib,libctf-nobfd.*) + $(call do_safe_remove_glob,$(STAGE1_TOOLCHAIN_ROOT)/lib,libgprofng.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libbfd.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libopcodes.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libiberty.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libctf.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libctf-nobfd.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libgprofng.*) + +clean-binutils-stage2: + $(call do_clean,binutils-stage2) + $(call do_safe_remove,$(BINUTILS2_BUILD_DIR)) + $(call do_safe_remove_glob,$(LOGS_DIR),binutils-stage2-*.log) + $(foreach tool,$(BINUTILS_TOOLS),$(call do_safe_remove,$(TOOLCHAIN_ROOT)/bin/$(TARGET)-$(tool))) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libbfd.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libopcodes.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libiberty.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libctf.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libctf-nobfd.*) + $(call do_safe_remove_glob,$(TOOLCHAIN_ROOT)/lib,libgprofng.*) + +clean-gcc: clean-musl ## Remove GCC build directory + $(call do_clean,gcc) + $(call do_safe_remove,$(GCC_BUILD_DIR)) + $(call do_safe_remove_glob,$(SOURCES_DIR),gcc-*) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),.gcc-*-verified) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),gcc-*.tar.xz) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),gcc-*.tar.xz.sig) + $(call do_safe_remove,$(DOWNLOADS_DIR)/gnu-keyring.gpg) + $(call do_safe_remove_glob,$(LOGS_DIR),gcc-stage1-*.log) + $(call do_safe_remove_glob,$(LOGS_DIR),gcc-stage2-*.log) + $(foreach tool,$(GCC_TOOLS),$(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/bin/$(TARGET)-$(tool))) + $(foreach tool,$(GCC_TOOLS),$(call do_safe_remove,$(TOOLCHAIN_ROOT)/bin/$(TARGET)-$(tool))) + $(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/lib/gcc/$(TARGET)) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/lib/gcc/$(TARGET)) + $(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/libexec/gcc/$(TARGET)) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/libexec/gcc/$(TARGET)) + $(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/$(TARGET)/lib) + $(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/$(TARGET)/lib64) + $(call do_safe_remove,$(STAGE1_TOOLCHAIN_ROOT)/$(TARGET)/include) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/$(TARGET)/lib) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/$(TARGET)/lib64) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/$(TARGET)/include) + +clean-gcc-stage2: + $(call do_clean,gcc-stage2) + $(call do_safe_remove_glob,$(LOGS_DIR),gcc-stage2-*.log) + $(foreach tool,$(GCC_TOOLS),$(call do_safe_remove,$(TOOLCHAIN_ROOT)/bin/$(TARGET)-$(tool))) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/lib/gcc/$(TARGET)) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/libexec/gcc/$(TARGET)) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/$(TARGET)/lib) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/$(TARGET)/lib64) + $(call do_safe_remove,$(TOOLCHAIN_ROOT)/$(TARGET)/include) + +clean-musl: clean-binutils-stage2 clean-gcc-stage2 ## Remove musl build directory + $(call do_clean,musl) + $(call do_safe_remove,$(MUSL_BUILD_DIR)) + $(call do_safe_remove_glob,$(SOURCES_DIR),musl-*) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),.musl-*-verified) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),musl-*.tar.gz) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),musl-*.tar.gz.asc) + $(call do_safe_remove,$(DOWNLOADS_DIR)/musl.pub) + $(call do_safe_remove_glob,$(LOGS_DIR),musl-*.log) + $(foreach lib,$(MUSL_LIBS),$(call do_safe_remove_glob,$(SYSROOT)/lib,$(lib).*)) + $(foreach lib,$(MUSL_LIBS),$(call do_safe_remove_glob,$(SYSROOT)/usr/lib,$(lib).*)) + $(call do_safe_remove,$(SYSROOT)/lib/$(MUSL_LDSO)) + $(call do_safe_remove,$(SYSROOT)/usr/lib/$(MUSL_LDSO)) + $(call do_safe_remove,$(SYSROOT)/lib/crt1.o) + $(call do_safe_remove,$(SYSROOT)/lib/crti.o) + $(call do_safe_remove,$(SYSROOT)/lib/crtn.o) + $(call do_safe_remove,$(SYSROOT)/usr/lib/crt1.o) + $(call do_safe_remove,$(SYSROOT)/usr/lib/crti.o) + $(call do_safe_remove,$(SYSROOT)/usr/lib/crtn.o) + @include_dir="$(SYSROOT)/usr/include"; \ + abs="$(abspath $(SYSROOT)/usr/include)"; \ + repo="$(ROOT_DIR)"; \ + if [ -z "$$include_dir" ] || [ -z "$$abs" ] || [ "$$abs" = "/" ] || [ "$$abs" = "$$repo" ]; then \ + echo "ERROR: Refusing to remove unsafe path '$$abs'."; \ + exit 1; \ + fi; \ + case "$$abs" in "$$repo"|"$$repo"/*) ;; \ + *) echo "ERROR: Refusing to remove $$abs (outside $$repo)."; exit 1;; \ + esac; \ + if [ -d "$$abs" ]; then \ + echo " removing musl headers under $$abs (preserving linux/asm/asm-generic)"; \ + find "$$abs" -mindepth 1 -maxdepth 1 \ + ! -name linux ! -name asm ! -name asm-generic \ + -exec rm -rf -- {} +; \ + fi + +clean-kheaders: clean-gcc ## Remove Linux UAPI headers build directory + $(call do_clean,linux-headers) + $(call do_safe_remove,$(LINUX_HEADERS_BUILD_DIR)) + $(call do_safe_remove_glob,$(SOURCES_DIR),linux-*) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),.linux-*-verified) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),linux-*.tar.xz) + $(call do_safe_remove_glob,$(DOWNLOADS_DIR),linux-*.tar.sign) + $(call do_safe_remove_glob,$(LOGS_DIR),linux-headers-*.log) + $(call do_safe_remove,$(SYSROOT)/usr/include/linux) + $(call do_safe_remove,$(SYSROOT)/usr/include/asm) + $(call do_safe_remove,$(SYSROOT)/usr/include/asm-generic) + +check: guard-TARGET + @$(MAKE) -f Makefile.check TARGET=$(TARGET) check sanity: - @true \ No newline at end of file + @true diff --git a/Makefile.check b/Makefile.check new file mode 100644 index 0000000..beda1d2 --- /dev/null +++ b/Makefile.check @@ -0,0 +1,38 @@ +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include config/paths.mk +include make/helpers.mk + +ROOT_DIR := $(abspath $(ROOT_DIR)) + +MAKEFLAGS += --no-print-directory + +.PHONY: check + +guard-%: + @test -n "$($*)" || { echo "ERROR: $* is not set"; exit 1; } + +check: guard-TARGET + @ROOT_DIR=$(ROOT_DIR) TARGET=$(TARGET) TOOLCHAIN_ROOT=$(TOOLCHAIN_ROOT) TOOLCHAIN_TARGET_DIR=$(TOOLCHAIN_TARGET_DIR) \ + SYSROOT=$(SYSROOT) PREFIX=$(TOOLCHAIN_ROOT) \ + PATH="$(TOOLCHAIN_ROOT)/bin:$(TOOLCHAIN_TARGET_DIR)/bin:$$PATH" \ + $(ROOT_DIR)/scripts/check-toolchain.sh diff --git a/Makefile.help b/Makefile.help new file mode 100644 index 0000000..d5076b7 --- /dev/null +++ b/Makefile.help @@ -0,0 +1,68 @@ +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +HELP_COL_WIDTH ?= 24 +HELP_FILES = $(strip $(firstword $(MAKEFILE_LIST)) $(MAKEFILE_LIST) $(MAKEFILES) $(INCLUDES) $(MK_FILES)) +HELP_FILES_EXISTING = $(strip $(foreach f,$(HELP_FILES),$(wildcard $(f)))) +HELP_HOST_TARGET := $(if $(HOST_TARGET),$(HOST_TARGET),unknown) +HELP_TARGET := $(firstword $(strip \ + $(if $(filter command\ line environment environment\ override,$(origin TARGET)),$(TARGET)) \ + $(if $(filter command\ line environment environment\ override,$(origin RECIPE)),$(RECIPE)) \ +)) + +.PHONY: help +ifneq ($(HELP_TARGET),) +help: + @case "$(HELP_TARGET)" in \ + toolchain) \ + echo "Usage: make toolchain [options]"; \ + echo " Build cross-compiling toolchain."; \ + echo; \ + echo "Options:"; \ + echo " TARGET= Specify for what architecture to build (default: $(HELP_HOST_TARGET))."; \ + echo " WITH_LINUX_HEADERS=1 Install Linux UAPI headers into SYSROOT (default: 0)."; \ + echo " JOBS= Parallel build jobs (default: auto-detected)."; \ + echo " TOOLCHAIN_ROOT= Override toolchain output root (default: out/toolchain)."; \ + ;; \ + help) \ + echo "Usage: make help [options]"; \ + echo " Show this help message."; \ + echo; \ + echo "Options:"; \ + echo " TARGET= Show further information about a target."; \ + ;; \ + *) \ + echo "Usage: make $(HELP_TARGET) [options]"; \ + echo " No help available for '$(HELP_TARGET)'."; \ + ;; \ + esac +else +help: + @echo "BugleOS Cross-compiling Toolchain Builder" + @echo + @echo "Available targets:" + @echo " make toolchain Build cross-compiling toolchain." + @echo " make clean Remove toolchain output." + @echo " make check Check an existing toolchain." + @echo " make help Show this help message." + @echo + @echo "See 'make help TARGET=' for details." +endif diff --git a/README.md b/README.md index 8f06a49..6a0f4b8 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ BugleOS Cross Toolchain builds deterministic cross-compilers and system headers ## Repository layout - `Makefile`: entry point orchestrating staged builds per architecture. -- `config/`: central version and path definitions, plus per-architecture target triples. +- `config/`: path definitions and per-architecture target triples. - `make/`: stage-specific makefiles for binutils, GCC, and musl. - `scripts/`: helper utilities for fetching sources, verifying checksums, loading the environment, and emitting metadata files. - `patches/`: placeholder for local patches to upstream sources. @@ -29,23 +29,28 @@ scripts/fetch-sources.sh scripts/verify-checksums.sh ``` -Build a toolchain for a specific architecture: +Build a toolchain for a specific architecture by overriding `TARGET` on the command line. The umbrella target `toolchain` builds the current `TARGET` from `config/paths.mk` or an override passed on the command line. By default, `TARGET` matches the host architecture when it is supported: ``` -make x86_64 -make aarch64 +make TARGET=aarch64-bugleos-linux-musl toolchain ``` -The umbrella target `toolchain` builds the current `TARGET` from `config/paths.mk` or an override passed on the command line. By default, `TARGET` matches the host architecture when it is supported: +To list optional variables for a specific target, pass the target name via `TARGET`: ``` -make TARGET=aarch64-bugleos-linux-musl toolchain +make help TARGET=toolchain ``` -To install Linux UAPI headers into the sysroot, set `WITH_LINUX_HEADERS=1` and update `LINUX_VERSION`/`LINUX_SHA256` in `config/versions.mk`: +To install Linux UAPI headers into the sysroot, set `WITH_LINUX_HEADERS=1` and update `LINUX_VERSION`/`LINUX_SHA256` in `make/linux-headers.mk`: ``` -make WITH_LINUX_HEADERS=1 x86_64 +make WITH_LINUX_HEADERS=1 TARGET=x86_64-bugleos-linux-musl toolchain +``` + +You can override build parallelism and the toolchain output root: + +``` +make JOBS=8 TOOLCHAIN_ROOT=/opt/bugleos/toolchain TARGET=x86_64-bugleos-linux-musl toolchain ``` ## Using the toolchain environment @@ -72,10 +77,27 @@ To validate an existing build and ensure the compiler never falls back to host h make TARGET=aarch64-bugleos-linux-musl verify-toolchain ``` -## Cleaning +## Validation: make check + +Run the toolchain validation target to assert that the installed binaries, sysroot, musl loader/libc, and kernel headers are present and match the requested target triplet and architecture: + +``` +make TARGET=aarch64-bugleos-linux-musl check +``` + +## Cleaning / Resetting + +The Makefile provides a safe, explicit cleaning interface focused on per-package build artifacts and toolchain outputs. Use `TRIPLET=` (or `TARGET=`) to scope to a specific architecture. Destructive targets require `FORCE=1`. + +Per-package build cleans (they also remove downstream toolchain stages that depend on the selected package, following the `toolchain` build order): + - `make clean-binutils` removes binutils build trees, logs, sources, archives/stamps, and installed toolchain outputs. + - `make clean-gcc` removes GCC build trees, logs, sources, archives/stamps, and installed toolchain outputs. + - `make clean-musl` removes musl build trees, logs, sources, archives/stamps, and musl-installed sysroot headers/libs (preserving Linux UAPI headers). + - `make clean-kheaders` removes Linux UAPI header builds, logs, sources, archives/stamps, and the installed Linux headers under the sysroot. + +Destructive targets (require `FORCE=1`): -- `make clean` removes `builds/` and `logs/` only. -- `make distclean` additionally removes `out/` while preserving downloads. +- `make clean-toolchain FORCE=1` removes toolchain outputs (`out/toolchain/` and `out/toolchain-stage1`). ## Continuous Integration diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..67d7ae8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,61 @@ +# Security Policy + +This document describes how to report security issues for BugleOS Cross Toolchain. + +## Supported Versions + +We currently support the latest released version and the `main` branch. + +| Version | Supported | +| --- | --- | +| latest | :white_check_mark: | +| older releases | :x: | + +## Reporting a Vulnerability + +Please report security issues **privately**. + +Preferred method: +1. Open a private GitHub Security Advisory: + https://github.com/strombetta/bugleos-make-toolchain/security/advisories + +If you cannot use GitHub Security Advisories, contact the maintainer privately +via the email listed in the maintainer's GitHub profile or commit metadata. + +### What to Include + +Please include: +- A clear description of the vulnerability and impact +- Steps to reproduce (proof-of-concept if possible) +- Affected versions/commits +- Any suggested fixes or mitigations + +## Response Timeline + +We aim to: +- Acknowledge receipt within **2 business days** +- Provide a status update within **7 days** +- Coordinate a fix and disclosure schedule as appropriate + +Timelines may vary based on complexity and upstream coordination needs. + +## Scope + +In scope: +- Build scripts, CI workflows, release artifacts, and integrity checks +- Supply-chain or signing/verification issues +- Toolchain configuration that could compromise build outputs + +Out of scope: +- Vulnerabilities in upstream projects (binutils/GCC/musl/Linux) + unless introduced or amplified by this repository + +## Coordinated Disclosure + +Please do not open public issues or disclose details until a fix or mitigation +is available. We will coordinate disclosure with you. + +## Security Updates + +Security fixes will be released as new versions. Release notes will reference +the advisory and provide upgrade guidance. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..c64b281 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,34 @@ +# Support + +This document describes how to get help with BugleOS Cross Toolchain. + +## What We Support + +We can help with: +- Build failures in this repository +- Reproducibility issues and validation checks +- Documentation clarity and usage questions +- Feature requests related to the build system + +## What We Do Not Support + +- Bugs in upstream projects (binutils, GCC, musl, Linux) unless caused by + configuration or patches in this repository +- General operating system setup outside the documented prerequisites + +## How to Get Help + +1. **Check the docs first** + - README.md and CONTRIBUTING.md +2. **Collect diagnostics** + - Host OS and tool versions + - Target triplet + - Logs from `logs/` +3. **Choose the right channel** + - Questions: GitHub Discussions (if enabled) + - Bugs/feature requests: GitHub Issues with clear reproduction steps + +## Security Issues + +Please do not file public issues for security vulnerabilities. +Follow SECURITY.md for private reporting. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0.0 diff --git a/VERSIONING.md b/VERSIONING.md new file mode 100644 index 0000000..b022a38 --- /dev/null +++ b/VERSIONING.md @@ -0,0 +1,38 @@ +# Versioning Policy + +BugleOS Cross Toolchain follows Semantic Versioning 2.0.0. + +## Version Format + +`MAJOR.MINOR.PATCH` stored in the `VERSION` file. + +- **MAJOR**: incompatible changes (build outputs, flags, toolchain layout) +- **MINOR**: backward-compatible feature additions +- **PATCH**: backward-compatible bug fixes and reproducibility fixes + +## Tags + +Release tags follow: + +`vMAJOR.MINOR.PATCH` +or +`vMAJOR.MINOR.PATCH-PRERELEASE` + +Examples: +- `v1.2.3` +- `v1.2.3-rc.1` + +## Release Process + +1. Update `VERSION` with the next `MAJOR.MINOR.PATCH`. +2. Create an annotated tag using the `Tag from VERSION` workflow. +3. CI builds artifacts, verifies checksums, and publishes the release. + +## Pre-releases + +Pre-releases are allowed (e.g., `-rc.1`, `-beta.1`) and are published as +pre-release tags in GitHub. + +## Hotfixes + +Hotfixes increment **PATCH** and follow the same release process. diff --git a/config/arch/aarch64.mk b/config/arch/aarch64.mk index 27584a5..34e3683 100644 --- a/config/arch/aarch64.mk +++ b/config/arch/aarch64.mk @@ -1,7 +1,22 @@ -## -# Copyright (c) 2025 Sebastiano Trombetta -# SPDX-License-Identifier: MIT -# Licensed under the MIT License. See LICENSE file for details. -## +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. TARGET := aarch64-bugleos-linux-musl diff --git a/config/arch/x86_64.mk b/config/arch/x86_64.mk index c86fa6a..7d3b680 100644 --- a/config/arch/x86_64.mk +++ b/config/arch/x86_64.mk @@ -1,7 +1,22 @@ -## -# Copyright (c) 2025 Sebastiano Trombetta -# SPDX-License-Identifier: MIT -# Licensed under the MIT License. See LICENSE file for details. -## +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. TARGET := x86_64-bugleos-linux-musl diff --git a/config/paths.mk b/config/paths.mk index 123c88f..d1de155 100644 --- a/config/paths.mk +++ b/config/paths.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,6 +25,8 @@ SOURCES_DIR ?= $(ROOT_DIR)/sources BUILDS_DIR ?= $(ROOT_DIR)/builds OUT_DIR ?= $(ROOT_DIR)/out LOGS_DIR ?= $(ROOT_DIR)/logs +MINISIGN_KEY ?= $(OUT_DIR)/minisign.key +MINISIGN_PUB ?= $(OUT_DIR)/minisign.pub HOST_ARCH := $(shell uname -m) HOST_TARGET := $(shell \ @@ -44,9 +46,6 @@ LINUX_ARCH := $(TARGET_ARCH) endif MUSL_LDSO := ld-musl-$(TARGET_ARCH).so.1 -HOST_PATH := /usr/bin:/bin:$(PATH) -CROSS_PATH := $(TOOLCHAIN_ROOT)/bin:$(TOOLCHAIN_TARGET_DIR)/bin:$(STAGE1_TOOLCHAIN_ROOT)/bin:$(STAGE1_TOOLCHAIN_ROOT)/$(TARGET)/bin - TOOLCHAIN_ROOT ?= $(OUT_DIR)/toolchain TOOLCHAIN_TARGET_DIR ?= $(TOOLCHAIN_ROOT)/$(TARGET) SYSROOT ?= $(TOOLCHAIN_TARGET_DIR)/sysroot diff --git a/config/versions.mk b/config/versions.mk deleted file mode 100644 index c75e59d..0000000 --- a/config/versions.mk +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) Sebastiano Trombetta. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -BINUTILS_VERSION := 2.45.1 -BINUTILS_URL := https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz -BINUTILS_SIG_URL := https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz.sig -BINUTILS_SHA256 := 5fe101e6fe9d18fdec95962d81ed670fdee5f37e3f48f0bef87bddf862513aa5 - -LINUX_VERSION := 6.18.2 -LINUX_URL := https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$(LINUX_VERSION).tar.xz -LINUX_SIG_URL := https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$(LINUX_VERSION).tar.sign -LINUX_KEYRING_URL := https://www.kernel.org/keys.html -LINUX_KEYRING_FPRS := 647F28654894E3BD457199BE38DBBDC86092693E,F41BDF16F35CD80D9E56735BF38153E276D54749,ABAF11C65A2970B130ABE3C479BE3E4300411886,AEE416F7DCCB753BB3D5609D88BCE80F012F54CA -LINUX_SHA256 := 558c6bbab749492b34f99827fe807b0039a744693c21d3a7e03b3a48edaab96a - -GCC_VERSION := 15.2.0 -GCC_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz -GCC_SIG_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz.sig -GCC_SHA256 := 438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e -GNU_KEYRING_URL := https://ftp.gnu.org/gnu/gnu-keyring.gpg -GNU_KEYRING_FPRS := 1397 5A70 E63C 361C 73AE 69EF 6EEB 81F8 981C 74C7 - -MUSL_VERSION := 1.2.4 -MUSL_URL := https://musl.libc.org/releases/musl-$(MUSL_VERSION).tar.gz -MUSL_SIG_URL := https://musl.libc.org/releases/musl-$(MUSL_VERSION).tar.gz.asc -MUSL_SHA256 := 7a35eae33d5372a7c0da1188de798726f68825513b7ae3ebe97aaaa52114f039 -MUSL_PUBKEY_URL := https://musl.libc.org/musl.pub -MUSL_PUBKEY_FPR := 8364 8929 0BB6 B70F 99FF DA05 56BC DB59 3020 450F diff --git a/make/binutils-stage1.mk b/make/binutils-stage1.mk index 7bfe089..cf134c2 100644 --- a/make/binutils-stage1.mk +++ b/make/binutils-stage1.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,23 +19,30 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +BINUTILS_VERSION := 2.45.1 +BINUTILS_URL := https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz +BINUTILS_SIG_URL := https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz.sig +BINUTILS_SHA256 := 5fe101e6fe9d18fdec95962d81ed670fdee5f37e3f48f0bef87bddf862513aa5 + +GNU_KEYRING_URL := https://ftp.gnu.org/gnu/gnu-keyring.gpg +GNU_KEYRING_FPRS := 1397 5A70 E63C 361C 73AE 69EF 6EEB 81F8 981C 74C7 + THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/common.mk) +include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/helpers.mk) .PHONY: all all: binutils-stage1 .PHONY: binutils-stage1 -binutils-stage1: ensure-dirs $(BINUTILS1_BUILD_DIR)/.built-stage1 +binutils-stage1: $(PROGRESS_DIR)/.binutils-stage1-done -$(BINUTILS1_BUILD_DIR)/.built-stage1: $(BINUTILS_STAMP) +$(PROGRESS_DIR)/.binutils-stage1-done: $(PROGRESS_DIR)/.binutils-stage1-built + $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage1-built: $(PROGRESS_DIR)/.binutils-stage1-unpacked $(Q)rm -rf $(BINUTILS1_BUILD_DIR) $(Q)mkdir -p $(BINUTILS1_BUILD_DIR) - $(call do_step,EXTRACT,binutils-stage1, \ - $(MAKE) -f $(THIS_MAKEFILE) unpack-binutils, \ - binutils-stage1-extract) - $(call do_step,CONFIG,binutils-stage1, \ $(call with_host_env, cd "$(BINUTILS1_BUILD_DIR)" && "$(BINUTILS_SRC_DIR)/configure" \ --target="$(TARGET)" \ @@ -62,4 +69,20 @@ $(BINUTILS1_BUILD_DIR)/.built-stage1: $(BINUTILS_STAMP) "$(STAGE1_TOOLCHAIN_ROOT)/bin/$(TARGET)-ld" -v >/dev/null 2>&1', \ binutils-stage1-check) - $(Q)touch $@ \ No newline at end of file + $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage1-unpacked: $(PROGRESS_DIR)/.binutils-stage1-verified + $(call do_unpack,binutils, \ + $(call with_host_env, \ + rm -rf "$(BINUTILS_SRC_DIR)"; \ + "$(TAR)" -xf "$(BINUTILS_ARCHIVE)" -C "$(SOURCES_DIR)"), \ + binutils-stage1-unpack) + $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage1-verified: $(PROGRESS_DIR)/.binutils-stage1-downloaded + $(call do_verify,binutils,$(ROOT_DIR)/scripts/verify-checksums.sh binutils,binutils-stage1-verify) + $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage1-downloaded: | ensure-dirs + $(call do_download,binutils,$(ROOT_DIR)/scripts/fetch-sources.sh binutils,binutils-stage1-download) + $(Q)touch $@ diff --git a/make/binutils-stage2.mk b/make/binutils-stage2.mk index 57e30d4..94d2f81 100644 --- a/make/binutils-stage2.mk +++ b/make/binutils-stage2.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,23 +19,30 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +BINUTILS_VERSION := 2.45.1 +BINUTILS_URL := https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz +BINUTILS_SIG_URL := https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz.sig +BINUTILS_SHA256 := 5fe101e6fe9d18fdec95962d81ed670fdee5f37e3f48f0bef87bddf862513aa5 + +GNU_KEYRING_URL := https://ftp.gnu.org/gnu/gnu-keyring.gpg +GNU_KEYRING_FPRS := 1397 5A70 E63C 361C 73AE 69EF 6EEB 81F8 981C 74C7 + THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/common.mk) +include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/helpers.mk) .PHONY: all all: binutils-stage2 .PHONY: binutils-stage2 -binutils-stage2: ensure-dirs $(BINUTILS2_BUILD_DIR)/.built-stage2 +binutils-stage2: $(PROGRESS_DIR)/.binutils-stage2-done + +$(PROGRESS_DIR)/.binutils-stage2-done: $(PROGRESS_DIR)/.binutils-stage2-built + $(Q)touch $@ -$(BINUTILS2_BUILD_DIR)/.built-stage2: $(BINUTILS_STAMP) +$(PROGRESS_DIR)/.binutils-stage2-built: $(PROGRESS_DIR)/.binutils-stage2-unpacked $(Q)rm -rf "$(BINUTILS2_BUILD_DIR)" $(Q)mkdir -p "$(BINUTILS2_BUILD_DIR)" - $(call do_step,EXTRACT,binutils-stage2, \ - $(MAKE) -f $(THIS_MAKEFILE) unpack-binutils, \ - binutils-stage2-extract) - $(call do_step,CONFIG,binutils-stage2, \ $(call with_cross_env, \ cd "$(BINUTILS2_BUILD_DIR)" && \ @@ -74,3 +81,19 @@ $(BINUTILS2_BUILD_DIR)/.built-stage2: $(BINUTILS_STAMP) binutils-stage2-check) $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage2-unpacked: $(PROGRESS_DIR)/.binutils-stage2-verified + $(call do_unpack,binutils, \ + $(call with_host_env, \ + rm -rf "$(BINUTILS_SRC_DIR)"; \ + "$(TAR)" -xf "$(BINUTILS_ARCHIVE)" -C "$(SOURCES_DIR)"), \ + binutils-stage2-unpack) + $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage2-verified: $(PROGRESS_DIR)/.binutils-stage2-downloaded + $(call do_verify,binutils,$(ROOT_DIR)/scripts/verify-checksums.sh binutils,binutils-stage2-verify) + $(Q)touch $@ + +$(PROGRESS_DIR)/.binutils-stage2-downloaded: | ensure-dirs + $(call do_download,binutils,$(ROOT_DIR)/scripts/fetch-sources.sh binutils,binutils-stage2-download) + $(Q)touch $@ diff --git a/make/gcc-stage1.mk b/make/gcc-stage1.mk index ce40a21..4b5b86a 100644 --- a/make/gcc-stage1.mk +++ b/make/gcc-stage1.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,22 +19,30 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +GCC_VERSION := 15.2.0 +GCC_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz +GCC_SIG_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz.sig +GCC_SHA256 := 438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e + +GNU_KEYRING_URL := https://ftp.gnu.org/gnu/gnu-keyring.gpg +GNU_KEYRING_FPRS := 1397 5A70 E63C 361C 73AE 69EF 6EEB 81F8 981C 74C7 + THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/common.mk) +include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/helpers.mk) .PHONY: all all: gcc-stage1 .PHONY: gcc-stage1 -gcc-stage1: ensure-dirs $(GCC_BUILD_DIR)/.built-stage1 +gcc-stage1: $(PROGRESS_DIR)/.gcc-stage1-done + +$(PROGRESS_DIR)/.gcc-stage1-done: $(PROGRESS_DIR)/.gcc-stage1-built + $(Q)touch $@ -$(GCC_BUILD_DIR)/.built-stage1: $(GCC_STAMP) +$(PROGRESS_DIR)/.gcc-stage1-built: $(PROGRESS_DIR)/.gcc-stage1-unpacked $(Q)rm -rf $(GCC_BUILD_DIR) $(Q)mkdir -p $(GCC_BUILD_DIR) - $(call do_step,EXTRACT,gcc-stage1, $(MAKE) -f $(THIS_MAKEFILE) unpack-gcc, \ - gcc-stage1-extract) - $(call do_step,EXTRACT,gcc-stage1-prerequisites, \ $(call with_host_env,cd "$(GCC_SRC_DIR)" && ./contrib/download_prerequisites), \ gcc-stage1-prereqs) @@ -102,3 +110,19 @@ $(GCC_BUILD_DIR)/.built-stage1: $(GCC_STAMP) gcc-stage1-check) $(Q)touch $@ + +$(PROGRESS_DIR)/.gcc-stage1-unpacked: $(PROGRESS_DIR)/.gcc-stage1-verified + $(call do_unpack,gcc, \ + $(call with_host_env, \ + rm -rf "$(GCC_SRC_DIR)"; \ + "$(TAR)" -xf "$(GCC_ARCHIVE)" -C "$(SOURCES_DIR)"), \ + gcc-stage1-unpack) + $(Q)touch $@ + +$(PROGRESS_DIR)/.gcc-stage1-verified: $(PROGRESS_DIR)/.gcc-stage1-downloaded + $(call do_verify,gcc,$(ROOT_DIR)/scripts/verify-checksums.sh gcc,gcc-stage1-verify) + $(Q)touch $@ + +$(PROGRESS_DIR)/.gcc-stage1-downloaded: | ensure-dirs + $(call do_download,gcc,$(ROOT_DIR)/scripts/fetch-sources.sh gcc,gcc-stage1-download) + $(Q)touch $@ diff --git a/make/gcc-stage2.mk b/make/gcc-stage2.mk index 36a841c..ede74d3 100644 --- a/make/gcc-stage2.mk +++ b/make/gcc-stage2.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,23 +19,30 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +GCC_VERSION := 15.2.0 +GCC_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz +GCC_SIG_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz.sig +GCC_SHA256 := 438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e + +GNU_KEYRING_URL := https://ftp.gnu.org/gnu/gnu-keyring.gpg +GNU_KEYRING_FPRS := 1397 5A70 E63C 361C 73AE 69EF 6EEB 81F8 981C 74C7 + THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/common.mk) +include $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/helpers.mk) .PHONY: all all: gcc-stage2 .PHONY: gcc-stage2 -gcc-stage2: ensure-dirs $(GCC_BUILD_DIR)/.built-gcc-stage2 +gcc-stage2: $(PROGRESS_DIR)/.gcc-stage2-done + +$(PROGRESS_DIR)/.gcc-stage2-done: $(PROGRESS_DIR)/.gcc-stage2-built + $(Q)touch $@ -$(GCC_BUILD_DIR)/.built-gcc-stage2: $(GCC_STAMP) +$(PROGRESS_DIR)/.gcc-stage2-built: $(PROGRESS_DIR)/.gcc-stage2-unpacked $(Q)rm -rf "$(GCC_BUILD_DIR)" $(Q)mkdir -p "$(GCC_BUILD_DIR)" - $(call do_step,EXTRACT,gcc-stage2, \ - $(MAKE) -f $(THIS_MAKEFILE) unpack-gcc, \ - gcc-stage2-extract) - $(call do_step,EXTRACT,gcc-stage2-prerequisites, \ $(call with_host_env, \ cd "$(GCC_SRC_DIR)" && ./contrib/download_prerequisites \ @@ -103,3 +110,19 @@ $(GCC_BUILD_DIR)/.built-gcc-stage2: $(GCC_STAMP) gcc-stage2-check) $(Q)touch $@ + +$(PROGRESS_DIR)/.gcc-stage2-unpacked: $(PROGRESS_DIR)/.gcc-stage2-verified + $(call do_unpack,gcc, \ + $(call with_host_env, \ + rm -rf "$(GCC_SRC_DIR)"; \ + "$(TAR)" -xf "$(GCC_ARCHIVE)" -C "$(SOURCES_DIR)"), \ + gcc-stage2-unpack) + $(Q)touch $@ + +$(PROGRESS_DIR)/.gcc-stage2-verified: $(PROGRESS_DIR)/.gcc-stage2-downloaded + $(call do_verify,gcc,$(ROOT_DIR)/scripts/verify-checksums.sh gcc,gcc-stage2-verify) + $(Q)touch $@ + +$(PROGRESS_DIR)/.gcc-stage2-downloaded: | ensure-dirs + $(call do_download,gcc,$(ROOT_DIR)/scripts/fetch-sources.sh gcc,gcc-stage2-download) + $(Q)touch $@ diff --git a/make/common.mk b/make/helpers.mk similarity index 60% rename from make/common.mk rename to make/helpers.mk index 4c1b7f7..02275cf 100644 --- a/make/common.mk +++ b/make/helpers.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,7 +21,6 @@ ROOT_DIR ?= $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..) include $(ROOT_DIR)/config/paths.mk -include $(ROOT_DIR)/config/versions.mk # define comma COMMA := "," @@ -41,6 +40,48 @@ define do_step exit 1; } endef +define do_safe_remove + @target="$(1)"; \ + abs="$(abspath $(1))"; \ + repo="$(ROOT_DIR)"; \ + if [ -z "$$target" ] || [ -z "$$abs" ] || [ "$$abs" = "/" ]; then \ + echo "ERROR: Refusing to remove unsafe path '$$abs'."; \ + exit 1; \ + fi; \ + if [ "$$abs" = "$$repo" ]; then \ + echo "ERROR: Refusing to remove repository root '$$abs'."; \ + exit 1; \ + fi; \ + case "$$abs" in "$$repo"|"$$repo"/*) ;; \ + *) echo "ERROR: Refusing to remove $$abs (outside $$repo)."; exit 1;; \ + esac; \ + rm -rf -- "$$abs" +endef + +define do_safe_remove_glob + @dir="$(1)"; \ + pattern="$(2)"; \ + abs="$(abspath $(1))"; \ + repo="$(ROOT_DIR)"; \ + if [ -z "$$dir" ] || [ -z "$$abs" ] || [ "$$abs" = "/" ]; then \ + echo "ERROR: Refusing to remove unsafe path '$$abs'."; \ + exit 1; \ + fi; \ + if [ "$$abs" = "$$repo" ]; then \ + echo "ERROR: Refusing to remove repository root '$$abs'."; \ + exit 1; \ + fi; \ + case "$$abs" in "$$repo"|"$$repo"/*) ;; \ + *) echo "ERROR: Refusing to remove $$abs (outside $$repo)."; exit 1;; \ + esac; \ + rm -rf -- "$$abs"/$$pattern +endef + +# $(call do_clean, LABEL) +define do_clean + $(Q)printf " %-8s %s\n" "CLEAN" "$(1)" +endef + # $(call do_download, LABEL, COMMAND, LOGFILE) define do_download $(call do_step,DOWNLOAD,$(1),$(2),$(3)) @@ -51,6 +92,11 @@ define do_verify $(call do_step,VERIFY,$(1),$(2),$(3)) endef +# $(call do_unpack, LABEL, COMMAND, LOGFILE) +define do_unpack + $(call do_step,UNPACK,$(1),$(2),$(3)) +endef + # Quote a shell string safely for: sh -c '' # It wraps the whole command in single quotes and escapes any embedded single quote. # Example: abc'def -> 'abc'"'"'def' @@ -72,26 +118,16 @@ define with_cross_env sh -eu -c $(call sh_quote,$(1)) endef -# PATH baseline (host tools) -HOST_PATH := /usr/bin:/bin:$(PATH) -# PATH to discover cross tools (prefixed) when needed -CROSS_PATH := $(TOOLCHAIN_ROOT)/bin:$(TOOLCHAIN_ROOT)/$(TARGET)/bin:$(STAGE1_TOOLCHAIN_ROOT)/bin:$(STAGE1_TOOLCHAIN_ROOT)/$(TARGET)/bin - -HOST ?= $(shell uname -m)-unknown-linux-gnu -PKGDIR ?= $(ROOT_DIR)/patches +PROGRESS_DIR ?= $(OUT_DIR)/progress BINUTILS_ARCHIVE := $(DOWNLOADS_DIR)/binutils-$(BINUTILS_VERSION).tar.xz BINUTILS_SRC_DIR := $(SOURCES_DIR)/binutils-$(BINUTILS_VERSION) -BINUTILS_STAMP := $(DOWNLOADS_DIR)/.binutils-$(BINUTILS_VERSION)-verified LINUX_ARCHIVE := $(DOWNLOADS_DIR)/linux-$(LINUX_VERSION).tar.xz LINUX_SRC_DIR := $(SOURCES_DIR)/linux-$(LINUX_VERSION) -LINUX_STAMP := $(DOWNLOADS_DIR)/.linux-$(LINUX_VERSION)-verified GCC_ARCHIVE := $(DOWNLOADS_DIR)/gcc-$(GCC_VERSION).tar.xz GCC_SRC_DIR := $(SOURCES_DIR)/gcc-$(GCC_VERSION) -GCC_STAMP := $(DOWNLOADS_DIR)/.gcc-$(GCC_VERSION)-verified MUSL_ARCHIVE := $(DOWNLOADS_DIR)/musl-$(MUSL_VERSION).tar.gz MUSL_SRC_DIR := $(SOURCES_DIR)/musl-$(MUSL_VERSION) -MUSL_STAMP := $(DOWNLOADS_DIR)/.musl-$(MUSL_VERSION)-verified # Directory helpers BINUTILS1_BUILD_DIR := $(BUILDS_DIR)/binutils-stage1 @@ -102,46 +138,4 @@ LINUX_HEADERS_BUILD_DIR := $(BUILDS_DIR)/linux-headers .PHONY: ensure-dirs ensure-dirs: - @mkdir -p $(DOWNLOADS_DIR) $(SOURCES_DIR) $(BUILDS_DIR) $(OUT_DIR) $(TOOLCHAIN_ROOT) $(TOOLCHAIN) $(STAGE1_TOOLCHAIN_ROOT) $(SYSROOT) $(STAGE1_SYSROOT) $(LOGS_DIR) - -.PHONY: ensure-binutils ensure-linux ensure-gcc ensure-musl -ensure-binutils: $(BINUTILS_STAMP) -ensure-linux: $(LINUX_STAMP) -ensure-gcc: $(GCC_STAMP) -ensure-musl: $(MUSL_STAMP) - -$(BINUTILS_STAMP): | ensure-dirs - $(call do_download,binutils,$(ROOT_DIR)/scripts/fetch-sources.sh binutils,binutils-download) - $(call do_verify,binutils,$(ROOT_DIR)/scripts/verify-checksums.sh binutils,binutils-verify) - $(Q)touch $@ - -$(LINUX_STAMP): | ensure-dirs - $(call do_download,linux,$(ROOT_DIR)/scripts/fetch-sources.sh linux,linux-download) - $(call do_verify,linux,$(ROOT_DIR)/scripts/verify-checksums.sh linux,linux-verify) - $(Q)touch $@ - -$(GCC_STAMP): | ensure-dirs - $(call do_download,gcc,$(ROOT_DIR)/scripts/fetch-sources.sh gcc,gcc-download) - $(call do_verify,gcc,$(ROOT_DIR)/scripts/verify-checksums.sh gcc,gcc-verify) - $(Q)touch $@ - -$(MUSL_STAMP): | ensure-dirs - $(call do_download,musl,$(ROOT_DIR)/scripts/fetch-sources.sh musl,musl-download) - $(call do_verify,musl,$(ROOT_DIR)/scripts/verify-checksums.sh musl,musl-verify) - $(Q)touch $@ - -unpack-binutils: ensure-binutils - @rm -rf $(BINUTILS_SRC_DIR) - @$(TAR) -xf $(BINUTILS_ARCHIVE) -C $(SOURCES_DIR) - -unpack-linux: ensure-linux - @rm -rf $(LINUX_SRC_DIR) - @$(TAR) -xf $(LINUX_ARCHIVE) -C $(SOURCES_DIR) - -unpack-gcc: ensure-gcc - @rm -rf $(GCC_SRC_DIR) - @$(TAR) -xf $(GCC_ARCHIVE) -C $(SOURCES_DIR) - -unpack-musl: ensure-musl - @rm -rf $(MUSL_SRC_DIR) - @$(TAR) -xf $(MUSL_ARCHIVE) -C $(SOURCES_DIR) + @mkdir -p $(DOWNLOADS_DIR) $(SOURCES_DIR) $(BUILDS_DIR) $(OUT_DIR) $(PROGRESS_DIR) $(TOOLCHAIN_ROOT) $(TOOLCHAIN) $(STAGE1_TOOLCHAIN_ROOT) $(SYSROOT) $(STAGE1_SYSROOT) $(LOGS_DIR) diff --git a/make/linux-headers.mk b/make/linux-headers.mk index 23d6b7e..968efc6 100644 --- a/make/linux-headers.mk +++ b/make/linux-headers.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,23 +19,29 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +LINUX_VERSION := 6.18.2 +LINUX_URL := https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$(LINUX_VERSION).tar.xz +LINUX_SIG_URL := https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$(LINUX_VERSION).tar.sign +LINUX_KEYRING_URL := https://www.kernel.org/keys.html +LINUX_KEYRING_FPRS := 647F28654894E3BD457199BE38DBBDC86092693E,F41BDF16F35CD80D9E56735BF38153E276D54749,ABAF11C65A2970B130ABE3C479BE3E4300411886,AEE416F7DCCB753BB3D5609D88BCE80F012F54CA +LINUX_SHA256 := 558c6bbab749492b34f99827fe807b0039a744693c21d3a7e03b3a48edaab96a + THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -include $(abspath $(dir $(THIS_MAKEFILE))/common.mk) +include $(abspath $(dir $(THIS_MAKEFILE))/helpers.mk) .PHONY: all all: linux-headers .PHONY: linux-headers -linux-headers: ensure-dirs $(LINUX_HEADERS_BUILD_DIR)/.built-linux-headers +linux-headers: $(PROGRESS_DIR)/.linux-headers-done + +$(PROGRESS_DIR)/.linux-headers-done: $(PROGRESS_DIR)/.linux-headers-built + $(Q)touch $@ -$(LINUX_HEADERS_BUILD_DIR)/.built-linux-headers: $(LINUX_STAMP) +$(PROGRESS_DIR)/.linux-headers-built: $(PROGRESS_DIR)/.linux-headers-unpacked $(Q)rm -rf "$(LINUX_HEADERS_BUILD_DIR)" $(Q)mkdir -p "$(LINUX_HEADERS_BUILD_DIR)" - $(call do_step,EXTRACT,linux-headers, \ - $(MAKE) -f "$(THIS_MAKEFILE)" unpack-linux, \ - linux-headers-extract) - $(call do_step,INSTALL,linux-headers, \ $(call with_host_env, \ $(MAKE) -C "$(LINUX_SRC_DIR)" O="$(LINUX_HEADERS_BUILD_DIR)" \ @@ -54,3 +60,19 @@ $(LINUX_HEADERS_BUILD_DIR)/.built-linux-headers: $(LINUX_STAMP) linux-headers-check) $(Q)touch $@ + +$(PROGRESS_DIR)/.linux-headers-unpacked: $(PROGRESS_DIR)/.linux-headers-verified + $(call do_unpack,linux, \ + $(call with_host_env, \ + rm -rf "$(LINUX_SRC_DIR)"; \ + "$(TAR)" -xf "$(LINUX_ARCHIVE)" -C "$(SOURCES_DIR)"), \ + linux-headers-unpack) + $(Q)touch $@ + +$(PROGRESS_DIR)/.linux-headers-verified: $(PROGRESS_DIR)/.linux-headers-downloaded + $(call do_verify,linux,$(ROOT_DIR)/scripts/verify-checksums.sh linux,linux-headers-verify) + $(Q)touch $@ + +$(PROGRESS_DIR)/.linux-headers-downloaded: | ensure-dirs + $(call do_download,linux,$(ROOT_DIR)/scripts/fetch-sources.sh linux,linux-headers-download) + $(Q)touch $@ diff --git a/make/musl.mk b/make/musl.mk index b480e51..5f41f6f 100644 --- a/make/musl.mk +++ b/make/musl.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2025 Sebastiano Trombetta +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +7,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,23 +19,29 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +MUSL_VERSION := 1.2.4 +MUSL_URL := https://musl.libc.org/releases/musl-$(MUSL_VERSION).tar.gz +MUSL_SIG_URL := https://musl.libc.org/releases/musl-$(MUSL_VERSION).tar.gz.asc +MUSL_SHA256 := 7a35eae33d5372a7c0da1188de798726f68825513b7ae3ebe97aaaa52114f039 +MUSL_PUBKEY_URL := https://musl.libc.org/musl.pub +MUSL_PUBKEY_FPR := 8364 8929 0BB6 B70F 99FF DA05 56BC DB59 3020 450F + THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -include $(abspath $(dir $(THIS_MAKEFILE))/common.mk) +include $(abspath $(dir $(THIS_MAKEFILE))/helpers.mk) .PHONY: all all: musl .PHONY: musl -musl: ensure-dirs $(MUSL_BUILD_DIR)/.built-musl +musl: $(PROGRESS_DIR)/.musl-done + +$(PROGRESS_DIR)/.musl-done: $(PROGRESS_DIR)/.musl-built + $(Q)touch $@ -$(MUSL_BUILD_DIR)/.built-musl: $(MUSL_STAMP) +$(PROGRESS_DIR)/.musl-built: $(PROGRESS_DIR)/.musl-unpacked $(Q)rm -rf "$(MUSL_BUILD_DIR)" $(Q)mkdir -p "$(MUSL_BUILD_DIR)" - $(call do_step,EXTRACT,musl, \ - $(MAKE) -f "$(THIS_MAKEFILE)" unpack-musl, \ - musl-extract) - $(call do_step,CONFIG,musl, \ $(call with_cross_env,cd "$(MUSL_BUILD_DIR)" && \ "$(MUSL_SRC_DIR)/configure" \ @@ -91,3 +97,19 @@ $(MUSL_BUILD_DIR)/.built-musl: $(MUSL_STAMP) musl-check) $(Q)touch $@ + +$(PROGRESS_DIR)/.musl-unpacked: $(PROGRESS_DIR)/.musl-verified + $(call do_unpack,musl, \ + $(call with_host_env, \ + rm -rf "$(MUSL_SRC_DIR)"; \ + "$(TAR)" -xf "$(MUSL_ARCHIVE)" -C "$(SOURCES_DIR)"), \ + musl-unpack) + $(Q)touch $@ + +$(PROGRESS_DIR)/.musl-verified: $(PROGRESS_DIR)/.musl-downloaded + $(call do_verify,musl,$(ROOT_DIR)/scripts/verify-checksums.sh musl,musl-verify) + $(Q)touch $@ + +$(PROGRESS_DIR)/.musl-downloaded: | ensure-dirs + $(call do_download,musl,$(ROOT_DIR)/scripts/fetch-sources.sh musl,musl-download) + $(Q)touch $@ diff --git a/scripts/check-toolchain.sh b/scripts/check-toolchain.sh new file mode 100755 index 0000000..bdacd1c --- /dev/null +++ b/scripts/check-toolchain.sh @@ -0,0 +1,199 @@ +#!/bin/sh +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +set -eu + +ROOT_DIR=${ROOT_DIR:-$(cd "$(dirname "$0")/.." && pwd)} +TARGET=${TARGET:-x86_64-bugleos-linux-musl} +TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT:-$ROOT_DIR/out/toolchain} +TOOLCHAIN_TARGET_DIR=${TOOLCHAIN_TARGET_DIR:-$TOOLCHAIN_ROOT/$TARGET} +DEFAULT_SYSROOT="$TOOLCHAIN_TARGET_DIR/sysroot" +SYSROOT=${SYSROOT:-$DEFAULT_SYSROOT} +PREFIX=${PREFIX:-$TOOLCHAIN_ROOT} + +fail() { + echo "[check-toolchain] ERROR: $*" >&2 + exit 1 +} + +print_check() { + printf " %-8s %s\n" "CHECK" "$1" +} + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || fail "$1 not found in PATH" +} + +resolve_tool() { + tool="$1" + for dir in "$PREFIX/bin" "$TOOLCHAIN_TARGET_DIR/bin"; do + candidate="$dir/$TARGET-$tool" + if [ -x "$candidate" ]; then + printf "%s\n" "$candidate" + return 0 + fi + done + return 1 +} + +normalize() { + printf "%s" "${1%/}" +} + +select_toolchain_target() { + if [ -d "$SYSROOT" ]; then + return 0 + fi + if [ "$SYSROOT" != "$DEFAULT_SYSROOT" ]; then + fail "missing sysroot directory: $SYSROOT" + fi + + candidates="" + candidate_count=0 + for dir in "$TOOLCHAIN_ROOT"/*; do + [ -d "$dir" ] || continue + [ -d "$dir/sysroot" ] || continue + target=$(basename "$dir") + candidates="$candidates $target" + candidate_count=$((candidate_count + 1)) + done + + if [ "$candidate_count" -eq 0 ]; then + fail "no toolchain sysroot found under $TOOLCHAIN_ROOT (expected $DEFAULT_SYSROOT)" + fi + if [ "$candidate_count" -gt 1 ]; then + fail "multiple toolchain targets found under $TOOLCHAIN_ROOT: $candidates (set TARGET to select one)" + fi + + detected=${candidates# } + detected=${detected%% *} + if [ "$detected" != "$TARGET" ]; then + echo "[check-toolchain] INFO: using detected toolchain target $detected instead of TARGET=$TARGET" >&2 + fi + TARGET="$detected" + TOOLCHAIN_TARGET_DIR="$TOOLCHAIN_ROOT/$TARGET" + DEFAULT_SYSROOT="$TOOLCHAIN_TARGET_DIR/sysroot" + SYSROOT="$DEFAULT_SYSROOT" +} + +select_toolchain_target + +PATH="$PREFIX/bin:$TOOLCHAIN_TARGET_DIR/bin:$PATH" + +TARGET_ARCH=${TARGET%%-*} +[ -n "$TARGET_ARCH" ] || fail "unable to determine target architecture from TARGET=$TARGET" + +case "$TARGET_ARCH" in + x86_64) + EXPECTED_MACHINE="Advanced Micro Devices X86-64" + ;; + aarch64) + EXPECTED_MACHINE="AArch64" + ;; + *) + fail "unsupported target architecture for ELF validation: $TARGET_ARCH" + ;; +esac + +case "$(normalize "$SYSROOT")" in + ""|"/") + fail "unsafe sysroot path: $SYSROOT" + ;; +esac + +[ -d "$SYSROOT" ] || fail "missing sysroot directory: $SYSROOT" + +for tool in ld as ar ranlib strip readelf; do + tool_path="$(resolve_tool "$tool")" || tool_path="" + [ -n "$tool_path" ] || fail "missing toolchain binary: $TARGET-$tool (searched $PREFIX/bin and $TOOLCHAIN_TARGET_DIR/bin)" +done +print_check "binutils" + +tool_path="$(resolve_tool gcc)" || tool_path="" +[ -n "$tool_path" ] || fail "missing toolchain binary: $TARGET-gcc (searched $PREFIX/bin and $TOOLCHAIN_TARGET_DIR/bin)" + +require_cmd "$TARGET-gcc" +require_cmd "$TARGET-readelf" + +DUMPMACHINE=$("$TARGET"-gcc -dumpmachine 2>/dev/null || true) +[ "$DUMPMACHINE" = "$TARGET" ] || fail "gcc -dumpmachine returned '$DUMPMACHINE' (expected '$TARGET')" + +if ! "$TARGET"-gcc -v 2>&1 | grep -F "Target: $TARGET" >/dev/null; then + fail "gcc -v does not report Target: $TARGET" +fi + +EXPECTED_SYSROOT=$(normalize "$SYSROOT") +PRINTED_SYSROOT=$(normalize "$("$TARGET"-gcc --print-sysroot 2>/dev/null || true)") +[ "$PRINTED_SYSROOT" = "$EXPECTED_SYSROOT" ] || fail "gcc --print-sysroot returned '$PRINTED_SYSROOT' (expected '$EXPECTED_SYSROOT')" +print_check "gcc" + +for dir in "$SYSROOT/usr/include" "$SYSROOT/usr/lib" "$SYSROOT/lib"; do + [ -d "$dir" ] || fail "missing sysroot directory: $dir" +done + +KERNEL_HEADER="" +if [ -f "$SYSROOT/usr/include/linux/version.h" ]; then + KERNEL_HEADER="$SYSROOT/usr/include/linux/version.h" +elif [ -f "$SYSROOT/usr/include/linux/utsrelease.h" ]; then + KERNEL_HEADER="$SYSROOT/usr/include/linux/utsrelease.h" +fi +[ -n "$KERNEL_HEADER" ] || fail "missing kernel headers under $SYSROOT/usr/include/linux" +print_check "linux-headers" + +ldso_name="ld-musl-${TARGET_ARCH}.so.1" +ldso_path="" +if [ -e "$SYSROOT/lib/$ldso_name" ]; then + ldso_path="$SYSROOT/lib/$ldso_name" +elif [ -e "$SYSROOT/usr/lib/$ldso_name" ]; then + ldso_path="$SYSROOT/usr/lib/$ldso_name" +else + for candidate in "$SYSROOT/lib"/ld-musl-*.so.1 "$SYSROOT/usr/lib"/ld-musl-*.so.1; do + if [ -e "$candidate" ]; then + ldso_path="$candidate" + break + fi + done +fi +[ -n "$ldso_path" ] || fail "missing musl loader (expected $SYSROOT/lib/$ldso_name or $SYSROOT/usr/lib/$ldso_name)" + +libc_path="" +for candidate in "$SYSROOT/lib/libc.so" "$SYSROOT/usr/lib/libc.so" "$SYSROOT/lib/libc.a" "$SYSROOT/usr/lib/libc.a"; do + if [ -e "$candidate" ]; then + libc_path="$candidate" + break + fi +done +[ -n "$libc_path" ] || fail "missing musl libc artifact under $SYSROOT/lib or $SYSROOT/usr/lib" +print_check "musl" + +TARGET_BIN_DIR="$PREFIX/$TARGET/bin" +if [ -d "$TARGET_BIN_DIR" ]; then + if [ -z "$(ls "$TARGET_BIN_DIR")" ]; then + fail "target bin directory is empty: $TARGET_BIN_DIR" + fi +fi + +if ! LC_ALL=C "$TARGET"-readelf -h "$ldso_path" 2>/dev/null | grep -F "Machine:" | grep -F "$EXPECTED_MACHINE" >/dev/null; then + fail "unexpected ELF machine for $ldso_path (expected $EXPECTED_MACHINE)" +fi + +print_check "sysroot" diff --git a/scripts/enter-env.sh b/scripts/enter-env.sh index ef4f074..cdeb121 100755 --- a/scripts/enter-env.sh +++ b/scripts/enter-env.sh @@ -1,9 +1,25 @@ #!/usr/bin/env bash -## -# Copyright (c) 2025 Sebastiano Trombetta -# SPDX-License-Identifier: MIT -# Licensed under the MIT License. See LICENSE file for details. -## +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + set -euo pipefail ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" diff --git a/scripts/fetch-sources.sh b/scripts/fetch-sources.sh index ee733ba..e27aeab 100755 --- a/scripts/fetch-sources.sh +++ b/scripts/fetch-sources.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash -# Copyright (c) 2025 Sebastiano Trombetta +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -7,10 +8,10 @@ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: - +# # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. - +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,14 +25,10 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" DOWNLOADS_DIR="${DOWNLOADS_DIR:-$ROOT_DIR/downloads}" -version_of() { - local var="$1" - awk -F':=' -v name="$var" '$1 ~ "^"name"" {gsub(/[ \t]/,"",$2); print $2}' "$ROOT_DIR/config/versions.mk" -} - -url_of() { - local var="$1" - awk -F':=' -v name="$var" '$1 ~ "^"name"" {sub(/^ /,"",$2); print $2}' "$ROOT_DIR/config/versions.mk" +value_of() { + local mk_file="$1" + local var="$2" + awk -F':=' -v name="$var" '$1 ~ "^"name"" {sub(/^[ \t]+/,"",$2); print $2; exit}' "$mk_file" } expand_make_vars() { @@ -65,26 +62,32 @@ fetch() { fi } -BINUTILS_VERSION=$(version_of BINUTILS_VERSION) -LINUX_VERSION=$(version_of LINUX_VERSION) -GCC_VERSION=$(version_of GCC_VERSION) -MUSL_VERSION=$(version_of MUSL_VERSION) - -BINUTILS_URL=$(url_of BINUTILS_URL) -BINUTILS_SIG_URL=$(url_of BINUTILS_SIG_URL) -LINUX_URL=$(url_of LINUX_URL) -LINUX_SIG_URL=$(url_of LINUX_SIG_URL) -GCC_URL=$(url_of GCC_URL) -GCC_SIG_URL=$(url_of GCC_SIG_URL) -GNU_KEYRING_URL=$(url_of GNU_KEYRING_URL) -MUSL_URL=$(url_of MUSL_URL) -MUSL_SIG_URL=$(url_of MUSL_SIG_URL) -MUSL_PUBKEY_URL=$(url_of MUSL_PUBKEY_URL) +BINUTILS_MK="$ROOT_DIR/make/binutils-stage1.mk" +LINUX_MK="$ROOT_DIR/make/linux-headers.mk" +GCC_MK="$ROOT_DIR/make/gcc-stage1.mk" +MUSL_MK="$ROOT_DIR/make/musl.mk" + +BINUTILS_VERSION=$(value_of "$BINUTILS_MK" BINUTILS_VERSION) +LINUX_VERSION=$(value_of "$LINUX_MK" LINUX_VERSION) +GCC_VERSION=$(value_of "$GCC_MK" GCC_VERSION) +MUSL_VERSION=$(value_of "$MUSL_MK" MUSL_VERSION) + +BINUTILS_URL=$(value_of "$BINUTILS_MK" BINUTILS_URL) +BINUTILS_SIG_URL=$(value_of "$BINUTILS_MK" BINUTILS_SIG_URL) +LINUX_URL=$(value_of "$LINUX_MK" LINUX_URL) +LINUX_SIG_URL=$(value_of "$LINUX_MK" LINUX_SIG_URL) +GCC_URL=$(value_of "$GCC_MK" GCC_URL) +GCC_SIG_URL=$(value_of "$GCC_MK" GCC_SIG_URL) +MUSL_URL=$(value_of "$MUSL_MK" MUSL_URL) +MUSL_SIG_URL=$(value_of "$MUSL_MK" MUSL_SIG_URL) +MUSL_PUBKEY_URL=$(value_of "$MUSL_MK" MUSL_PUBKEY_URL) fetch_binutils() { + local gnu_keyring_url + gnu_keyring_url=$(value_of "$BINUTILS_MK" GNU_KEYRING_URL) fetch "binutils-${BINUTILS_VERSION}.tar.xz" "$(expand_url "$BINUTILS_URL")" fetch "binutils-${BINUTILS_VERSION}.tar.xz.sig" "$(expand_url "$BINUTILS_SIG_URL")" - fetch "gnu-keyring.gpg" "$(expand_url "$GNU_KEYRING_URL")" + fetch "gnu-keyring.gpg" "$(expand_url "$gnu_keyring_url")" } fetch_linux() { @@ -93,9 +96,11 @@ fetch_linux() { } fetch_gcc() { + local gnu_keyring_url + gnu_keyring_url=$(value_of "$GCC_MK" GNU_KEYRING_URL) fetch "gcc-${GCC_VERSION}.tar.xz" "$(expand_url "$GCC_URL")" fetch "gcc-${GCC_VERSION}.tar.xz.sig" "$(expand_url "$GCC_SIG_URL")" - fetch "gnu-keyring.gpg" "$(expand_url "$GNU_KEYRING_URL")" + fetch "gnu-keyring.gpg" "$(expand_url "$gnu_keyring_url")" } fetch_musl() { diff --git a/scripts/verify-checksums.sh b/scripts/verify-checksums.sh index d7382e0..61eb1cd 100755 --- a/scripts/verify-checksums.sh +++ b/scripts/verify-checksums.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash -# Copyright (c) 2025 Sebastiano Trombetta +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -25,30 +26,38 @@ ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" DOWNLOADS_DIR="${DOWNLOADS_DIR:-$ROOT_DIR/downloads}" value_of() { - local var="$1" - awk -F':=' -v name="$var" '$1 ~ "^"name"" {gsub(/[ \t]/,"",$2); print $2}' "$ROOT_DIR/config/versions.mk" + local mk_file="$1" + local var="$2" + awk -F':=' -v name="$var" '$1 ~ "^"name"" {gsub(/[ \t]/,"",$2); print $2; exit}' "$mk_file" } -BINUTILS_VERSION=$(value_of BINUTILS_VERSION) -GCC_VERSION=$(value_of GCC_VERSION) -MUSL_VERSION=$(value_of MUSL_VERSION) -LINUX_VERSION=$(value_of LINUX_VERSION) +BINUTILS_MK="$ROOT_DIR/make/binutils-stage1.mk" +LINUX_MK="$ROOT_DIR/make/linux-headers.mk" +GCC_MK="$ROOT_DIR/make/gcc-stage1.mk" +MUSL_MK="$ROOT_DIR/make/musl.mk" + +BINUTILS_VERSION=$(value_of "$BINUTILS_MK" BINUTILS_VERSION) +GCC_VERSION=$(value_of "$GCC_MK" GCC_VERSION) +MUSL_VERSION=$(value_of "$MUSL_MK" MUSL_VERSION) +LINUX_VERSION=$(value_of "$LINUX_MK" LINUX_VERSION) -BINUTILS_SHA=$(value_of BINUTILS_SHA256) -GCC_SHA=$(value_of GCC_SHA256) -MUSL_SHA=$(value_of MUSL_SHA256) -LINUX_SHA=$(value_of LINUX_SHA256) +BINUTILS_SHA=$(value_of "$BINUTILS_MK" BINUTILS_SHA256) +GCC_SHA=$(value_of "$GCC_MK" GCC_SHA256) +MUSL_SHA=$(value_of "$MUSL_MK" MUSL_SHA256) +LINUX_SHA=$(value_of "$LINUX_MK" LINUX_SHA256) -LINUX_KEYRING_FPRS=$(value_of LINUX_KEYRING_FPRS) -GNU_KEYRING_FPRS=$(value_of GNU_KEYRING_FPRS) -MUSL_PUBKEY_FPR=$(value_of MUSL_PUBKEY_FPR) +LINUX_KEYRING_FPRS=$(value_of "$LINUX_MK" LINUX_KEYRING_FPRS) +GNU_KEYRING_FPRS_BINUTILS=$(value_of "$BINUTILS_MK" GNU_KEYRING_FPRS) +GNU_KEYRING_FPRS_GCC=$(value_of "$GCC_MK" GNU_KEYRING_FPRS) +MUSL_PUBKEY_FPR=$(value_of "$MUSL_MK" MUSL_PUBKEY_FPR) ensure_checksum_set() { local name="$1" local value="$2" + local file="$3" if [[ $value =~ ^SHA256_PLACEHOLDER ]]; then - echo "Checksum for $name is missing. Please update config/versions.mk with the real SHA256 before verifying." >&2 + echo "Checksum for $name is missing. Please update $file with the real SHA256 before verifying." >&2 exit 1 fi } @@ -56,9 +65,10 @@ ensure_checksum_set() { ensure_fpr_set() { local name="$1" local value="$2" + local file="$3" if [[ -z "$value" || $value =~ FPR_PLACEHOLDER ]]; then - echo "Fingerprint for $name is missing. Please update config/versions.mk before verifying." >&2 + echo "Fingerprint for $name is missing. Please update $file before verifying." >&2 exit 1 fi } @@ -170,14 +180,16 @@ trap cleanup EXIT gpg_common_args=(--homedir "$GNUPGHOME_TMP" --batch --no-tty) import_gnu_keyring() { + local expected_fprs="$1" + local source_file="$2" ensure_file_present "$GNU_KEYRING" "GNU project keyring" - ensure_fpr_set "GNU_KEYRING_FPRS" "$GNU_KEYRING_FPRS" - verify_key_fprs "$GNU_KEYRING" "$GNU_KEYRING_FPRS" "GNU keyring" + ensure_fpr_set "GNU_KEYRING_FPRS" "$expected_fprs" "$source_file" + verify_key_fprs "$GNU_KEYRING" "$expected_fprs" "GNU keyring" gpg "${gpg_common_args[@]}" --import "$GNU_KEYRING" >/dev/null } import_linux_keys() { - ensure_fpr_set "LINUX_KEYRING_FPRS" "$LINUX_KEYRING_FPRS" + ensure_fpr_set "LINUX_KEYRING_FPRS" "$LINUX_KEYRING_FPRS" "$LINUX_MK" if [[ -f "$LINUX_KEYRING" ]]; then verify_key_fprs "$LINUX_KEYRING" "$LINUX_KEYRING_FPRS" "Linux kernel signing keyring" gpg "${gpg_common_args[@]}" --import "$LINUX_KEYRING" >/dev/null @@ -208,7 +220,7 @@ import_linux_keys() { import_musl_pubkey() { ensure_file_present "$MUSL_PUBKEY" "musl public key" - ensure_fpr_set "MUSL_PUBKEY_FPR" "$MUSL_PUBKEY_FPR" + ensure_fpr_set "MUSL_PUBKEY_FPR" "$MUSL_PUBKEY_FPR" "$MUSL_MK" verify_key_fprs "$MUSL_PUBKEY" "$MUSL_PUBKEY_FPR" "musl public key" gpg "${gpg_common_args[@]}" --import "$MUSL_PUBKEY" >/dev/null } @@ -230,10 +242,10 @@ verify_checksum() { } verify_binutils() { - ensure_checksum_set "binutils" "$BINUTILS_SHA" + ensure_checksum_set "binutils" "$BINUTILS_SHA" "$BINUTILS_MK" ensure_file_present "$DOWNLOADS_DIR/$SIG_BINUTILS" "binutils signature file" ensure_file_present "$DOWNLOADS_DIR/binutils-${BINUTILS_VERSION}.tar.xz" "binutils source archive" - import_gnu_keyring + import_gnu_keyring "$GNU_KEYRING_FPRS_BINUTILS" "$BINUTILS_MK" echo "Verifying binutils signature..." verify_signature "$SIG_BINUTILS" "binutils-${BINUTILS_VERSION}.tar.xz" echo "Verifying binutils checksum..." @@ -241,7 +253,7 @@ verify_binutils() { } verify_linux() { - ensure_checksum_set "linux" "$LINUX_SHA" + ensure_checksum_set "linux" "$LINUX_SHA" "$LINUX_MK" ensure_file_present "$DOWNLOADS_DIR/$SIG_LINUX" "Linux source signature file" ensure_file_present "$DOWNLOADS_DIR/linux-${LINUX_VERSION}.tar.xz" "Linux source archive" @@ -258,10 +270,10 @@ verify_linux() { } verify_gcc() { - ensure_checksum_set "GCC" "$GCC_SHA" + ensure_checksum_set "GCC" "$GCC_SHA" "$GCC_MK" ensure_file_present "$DOWNLOADS_DIR/$SIG_GCC" "GCC signature file" ensure_file_present "$DOWNLOADS_DIR/gcc-${GCC_VERSION}.tar.xz" "GCC source archive" - import_gnu_keyring + import_gnu_keyring "$GNU_KEYRING_FPRS_GCC" "$GCC_MK" echo "Verifying GCC signature..." verify_signature "$SIG_GCC" "gcc-${GCC_VERSION}.tar.xz" echo "Verifying GCC checksum..." @@ -269,7 +281,7 @@ verify_gcc() { } verify_musl() { - ensure_checksum_set "musl" "$MUSL_SHA" + ensure_checksum_set "musl" "$MUSL_SHA" "$MUSL_MK" ensure_file_present "$DOWNLOADS_DIR/$SIG_MUSL" "musl signature file" ensure_file_present "$DOWNLOADS_DIR/musl-${MUSL_VERSION}.tar.gz" "musl source archive" import_musl_pubkey diff --git a/scripts/verify-toolchain.sh b/scripts/verify-toolchain.sh index 6ebf276..08980da 100755 --- a/scripts/verify-toolchain.sh +++ b/scripts/verify-toolchain.sh @@ -1,4 +1,25 @@ #!/usr/bin/env bash +# +# Copyright (c) Sebastiano Trombetta. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + set -euo pipefail ROOT_DIR="${ROOT_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"