diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..e5530a5 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,198 @@ +# GitHub Actions Workflows for mlibc + +This directory contains GitHub Actions workflows for automating the build and release of mlibc and its GCC toolchains. + +## Workflows + +### 1. Release mlibc Source (`release.yml`) + +**Purpose**: Automatically creates source code releases for mlibc. + +**Triggers**: +- Automatically on version tags (e.g., `v1.0.0`) +- Manually via workflow dispatch with custom version + +**What it does**: +- Creates a source tarball from the repository +- Generates SHA256 checksum +- Creates a GitHub release with the source archive + +**Manual trigger**: +```bash +# Via GitHub UI: Actions -> Release mlibc Source -> Run workflow +# Or use GitHub CLI: +gh workflow run release.yml -f version=v1.0.0 +``` + +### 2. Build GCC Toolchains (`build-toolchain.yml`) + +**Purpose**: Builds GCC toolchains with mlibc for multiple architectures. + +**Triggers**: +- Automatically on version tags (e.g., `v1.0.0`) +- Manually via workflow dispatch with optional architecture selection + +**What it does**: +- Builds toolchains for selected architectures (default: all) +- Creates tarball packages for each toolchain +- Generates SHA256 checksums +- On tag push: Creates a GitHub release with all toolchain packages + +**Supported architectures**: +- `arm` - ARM Linux EABI (arm-linux-eabi) +- `riscv32` - RISC-V 32-bit (riscv32-unknown-elf) +- `riscv64` - RISC-V 64-bit (riscv64-unknown-elf) +- `aarch64` - ARM 64-bit (aarch64-linux-gnu) + +**Manual trigger**: +```bash +# Build all architectures +gh workflow run build-toolchain.yml + +# Build specific architectures +gh workflow run build-toolchain.yml -f architectures=arm,riscv64 +``` + +**Build time**: Each architecture takes approximately 1-2 hours to build. + +### 3. Build Single Toolchain (`build-single-toolchain.yml`) + +**Purpose**: Quickly build a single toolchain for testing or development. + +**Triggers**: +- Manual workflow dispatch only + +**What it does**: +- Builds a toolchain for the selected architecture +- Optionally uploads as artifact (30-day retention) +- Provides build summary with toolchain version info + +**Manual trigger**: +```bash +# Via GitHub UI: Actions -> Build Single Toolchain -> Run workflow +# Select architecture: arm, riscv32, riscv64, or aarch64 + +# Or use GitHub CLI: +gh workflow run build-single-toolchain.yml -f arch=arm -f upload_artifact=true +``` + +**Use cases**: +- Testing toolchain builds for a specific architecture +- Quick validation after making changes +- Development and debugging + +## Release Process + +### Creating a New Release + +To create a new release with source code and toolchains: + +1. **Tag the release**: + ```bash + git tag -a v1.0.0 -m "Release version 1.0.0" + git push origin v1.0.0 + ``` + +2. **Automatic builds**: + - The `release.yml` workflow will create a source release + - The `build-toolchain.yml` workflow will build all toolchains (takes 2-4 hours) + +3. **Download artifacts**: + - All toolchain packages will be attached to the GitHub release + - Source tarball and checksums will be available + +### Manual Release + +If you prefer to create releases manually: + +1. **Build toolchains**: + ```bash + gh workflow run build-toolchain.yml -f version=v1.0.0 + ``` + +2. **Create source release**: + ```bash + gh workflow run release.yml -f version=v1.0.0 + ``` + +3. **Download artifacts** from the workflow runs and manually attach to release + +## Workflow Configuration + +### Environment Variables + +The workflows set the following environment variables during builds: + +- `CI_COMMIT_SHA`: Git commit hash +- `CI_JOB_ID`: GitHub run ID +- `CI_PIPELINE_ID`: GitHub run number + +These are embedded in the built toolchains for traceability. + +### Build Resources + +- **Runner**: ubuntu-latest +- **Disk space**: Workflows automatically clean up unnecessary files to free space +- **Timeout**: 480 minutes (8 hours) per architecture +- **Parallel builds**: Multiple architectures build in parallel + +### Dependencies + +The workflows install the following dependencies: + +- build-essential +- bison, flex +- file, texinfo +- wget, gawk +- chrpath, cpio, diffstat +- zstd +- libncurses5, libz-dev +- python3, python3-pip + +## Troubleshooting + +### Build Failures + +1. **Check logs**: View the workflow run logs in GitHub Actions +2. **Disk space**: Builds require ~30GB free space per architecture +3. **Timeout**: If builds timeout, they may need more resources + +### Testing Locally + +To test builds locally before running workflows: + +```bash +cd toolchain +make arch=arm abi=linux-eabi +``` + +See `toolchain/README.md` for detailed local build instructions. + +## Maintenance + +### Updating GCC/Binutils Versions + +To update toolchain component versions: + +1. Edit `toolchain/Makefile`: + - `BINUTILS_VER` + - `GCC_VER` + - `GMP_VER`, `MPC_VER`, `MPFR_VER` + +2. Test locally first +3. Update patches in `toolchain/patches/` if needed + +### Adding New Architectures + +To add support for a new architecture: + +1. Add architecture to `toolchain/Makefile` +2. Add architecture choice to `build-single-toolchain.yml` +3. Add architecture to default list in `build-toolchain.yml` +4. Update this README + +## Related Documentation + +- [Main README](../../README.md) +- [Toolchain README](../../toolchain/README.md) +- [Architecture Documentation](../../ARCH.md) diff --git a/.github/workflows/build-single-toolchain.yml b/.github/workflows/build-single-toolchain.yml new file mode 100644 index 0000000..451629f --- /dev/null +++ b/.github/workflows/build-single-toolchain.yml @@ -0,0 +1,155 @@ +name: Build Single Toolchain + +on: + workflow_dispatch: + inputs: + arch: + description: 'Architecture to build' + required: true + type: choice + options: + - arm + - riscv32 + - riscv64 + - aarch64 + upload_artifact: + description: 'Upload as artifact (keep for 30 days)' + required: false + type: boolean + default: true + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 480 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Free disk space + run: | + echo "Disk space before cleanup:" + df -h + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf /usr/local/share/boost + sudo rm -rf "$AGENT_TOOLSDIRECTORY" + echo "Disk space after cleanup:" + df -h + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + bison \ + flex \ + file \ + texinfo \ + wget \ + chrpath \ + cpio \ + diffstat \ + gawk \ + zstd \ + libncurses5 \ + libz-dev \ + python3 \ + python3-pip + + - name: Set architecture-specific variables + id: arch_vars + run: | + ARCH="${{ inputs.arch }}" + + case "$ARCH" in + arm) + echo "target=arm-linux-eabi" >> $GITHUB_OUTPUT + echo "abi=linux-eabi" >> $GITHUB_OUTPUT + ;; + riscv32) + echo "target=riscv32-unknown-elf" >> $GITHUB_OUTPUT + echo "abi=unknown-elf" >> $GITHUB_OUTPUT + ;; + riscv64) + echo "target=riscv64-unknown-elf" >> $GITHUB_OUTPUT + echo "abi=unknown-elf" >> $GITHUB_OUTPUT + ;; + aarch64) + echo "target=aarch64-linux-gnu" >> $GITHUB_OUTPUT + echo "abi=linux-gnu" >> $GITHUB_OUTPUT + ;; + *) + echo "Unknown architecture: $ARCH" + exit 1 + ;; + esac + + - name: Build toolchain for ${{ inputs.arch }} + working-directory: toolchain + env: + CI_COMMIT_SHA: ${{ github.sha }} + CI_JOB_ID: ${{ github.run_id }} + CI_PIPELINE_ID: ${{ github.run_number }} + run: | + echo "Building toolchain for ${{ inputs.arch }}" + echo "Target: ${{ steps.arch_vars.outputs.target }}" + + make arch=${{ inputs.arch }} abi=${{ steps.arch_vars.outputs.abi }} \ + CI_COMMIT_SHA="${CI_COMMIT_SHA}" \ + CI_JOB_ID="${CI_JOB_ID}" \ + CI_PIPELINE_ID="${CI_PIPELINE_ID}" + + - name: Create toolchain archive + if: ${{ inputs.upload_artifact }} + working-directory: toolchain + run: | + TARGET="${{ steps.arch_vars.outputs.target }}_for_x86_64-pc-linux-gnu" + VERSION="$(date +%Y%m%d-%H%M%S)" + TARBALL_NAME="${TARGET}-${VERSION}.tar.gz" + + echo "Creating tarball: $TARBALL_NAME" + tar -czf "$TARBALL_NAME" "$TARGET" + + # Calculate checksum + sha256sum "$TARBALL_NAME" > "$TARBALL_NAME.sha256" + + echo "TARBALL_NAME=$TARBALL_NAME" >> $GITHUB_ENV + echo "TARGET=$TARGET" >> $GITHUB_ENV + + - name: Test toolchain + working-directory: toolchain + run: | + TARGET="${{ steps.arch_vars.outputs.target }}_for_x86_64-pc-linux-gnu" + echo "Testing toolchain..." + ./${TARGET}/bin/${{ steps.arch_vars.outputs.target }}-gcc --version + + - name: Upload toolchain artifact + if: ${{ inputs.upload_artifact }} + uses: actions/upload-artifact@v4 + with: + name: toolchain-${{ inputs.arch }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + toolchain/${{ env.TARBALL_NAME }} + toolchain/${{ env.TARBALL_NAME }}.sha256 + retention-days: 30 + + - name: Build summary + run: | + echo "## Build Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Architecture:** ${{ inputs.arch }}" >> $GITHUB_STEP_SUMMARY + echo "**Target:** ${{ steps.arch_vars.outputs.target }}" >> $GITHUB_STEP_SUMMARY + echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY + echo "**Build ID:** ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Toolchain Information" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + toolchain/${{ steps.arch_vars.outputs.target }}_for_x86_64-pc-linux-gnu/bin/${{ steps.arch_vars.outputs.target }}-gcc --version >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/build-toolchain.yml b/.github/workflows/build-toolchain.yml new file mode 100644 index 0000000..98efac2 --- /dev/null +++ b/.github/workflows/build-toolchain.yml @@ -0,0 +1,243 @@ +name: Build GCC Toolchains + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + version: + description: 'Version tag (e.g., v1.0.0)' + required: false + type: string + architectures: + description: 'Comma-separated list of architectures to build (arm,riscv32,riscv64,aarch64) or leave empty for all' + required: false + type: string + default: 'arm,riscv32,riscv64,aarch64' + +permissions: + contents: write + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.set_version.outputs.version }} + matrix: ${{ steps.set_matrix.outputs.matrix }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set version + id: set_version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ -n "${{ inputs.version }}" ]; then + echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT + elif [ "${{ github.event_name }}" == "push" ]; then + echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + else + echo "version=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT + fi + + - name: Set build matrix + id: set_matrix + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ -n "${{ inputs.architectures }}" ]; then + ARCHS="${{ inputs.architectures }}" + else + ARCHS="arm,riscv32,riscv64,aarch64" + fi + + # Convert comma-separated string to JSON array for matrix + MATRIX_JSON=$(echo "$ARCHS" | jq -R -s -c 'split(",") | map(select(length > 0))') + echo "matrix={\"arch\":$MATRIX_JSON}" >> $GITHUB_OUTPUT + echo "Building for architectures: $ARCHS" + echo "Matrix JSON: $MATRIX_JSON" + + build-toolchain: + needs: prepare + runs-on: ubuntu-latest + timeout-minutes: 480 + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Free disk space + run: | + echo "Disk space before cleanup:" + df -h + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf /usr/local/share/boost + sudo rm -rf "$AGENT_TOOLSDIRECTORY" + echo "Disk space after cleanup:" + df -h + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + bison \ + flex \ + file \ + texinfo \ + wget \ + chrpath \ + cpio \ + diffstat \ + gawk \ + zstd \ + libncurses5 \ + libz-dev \ + python3 \ + python3-pip + + - name: Set architecture-specific variables + id: arch_vars + run: | + ARCH="${{ matrix.arch }}" + + case "$ARCH" in + arm) + echo "target=arm-linux-eabi" >> $GITHUB_OUTPUT + echo "abi=linux-eabi" >> $GITHUB_OUTPUT + ;; + riscv32) + echo "target=riscv32-unknown-elf" >> $GITHUB_OUTPUT + echo "abi=unknown-elf" >> $GITHUB_OUTPUT + ;; + riscv64) + echo "target=riscv64-unknown-elf" >> $GITHUB_OUTPUT + echo "abi=unknown-elf" >> $GITHUB_OUTPUT + ;; + aarch64) + echo "target=aarch64-linux-gnu" >> $GITHUB_OUTPUT + echo "abi=linux-gnu" >> $GITHUB_OUTPUT + ;; + *) + echo "Unknown architecture: $ARCH" + exit 1 + ;; + esac + + - name: Build toolchain for ${{ matrix.arch }} + working-directory: toolchain + env: + CI_COMMIT_SHA: ${{ github.sha }} + CI_JOB_ID: ${{ github.run_id }} + CI_PIPELINE_ID: ${{ github.run_number }} + run: | + echo "Building toolchain for ${{ matrix.arch }}" + echo "Target: ${{ steps.arch_vars.outputs.target }}" + + make arch=${{ matrix.arch }} abi=${{ steps.arch_vars.outputs.abi }} \ + CI_COMMIT_SHA="${CI_COMMIT_SHA}" \ + CI_JOB_ID="${CI_JOB_ID}" \ + CI_PIPELINE_ID="${CI_PIPELINE_ID}" + + - name: Create toolchain archive + working-directory: toolchain + run: | + TARGET="${{ steps.arch_vars.outputs.target }}_for_x86_64-pc-linux-gnu" + TARBALL_NAME="${TARGET}-${{ needs.prepare.outputs.version }}.tar.gz" + + echo "Creating tarball: $TARBALL_NAME" + tar -czf "$TARBALL_NAME" "$TARGET" + + # Calculate checksum + sha256sum "$TARBALL_NAME" > "$TARBALL_NAME.sha256" + + echo "TARBALL_NAME=$TARBALL_NAME" >> $GITHUB_ENV + echo "TARGET=$TARGET" >> $GITHUB_ENV + + - name: Test toolchain + working-directory: toolchain + run: | + TARGET="${{ steps.arch_vars.outputs.target }}_for_x86_64-pc-linux-gnu" + echo "Testing toolchain..." + ./${TARGET}/bin/${{ steps.arch_vars.outputs.target }}-gcc --version + + - name: Upload toolchain artifact + uses: actions/upload-artifact@v4 + with: + name: toolchain-${{ matrix.arch }}-${{ needs.prepare.outputs.version }} + path: | + toolchain/${{ env.TARGET }}-${{ needs.prepare.outputs.version }}.tar.gz + toolchain/${{ env.TARGET }}-${{ needs.prepare.outputs.version }}.tar.gz.sha256 + retention-days: 30 + + release: + needs: [prepare, build-toolchain] + runs-on: ubuntu-latest + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release files + run: | + mkdir -p release-files + find artifacts -type f \( -name "*.tar.gz" -o -name "*.sha256" \) -exec cp {} release-files/ \; + ls -lh release-files/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ needs.prepare.outputs.version }} + name: GCC Toolchains ${{ needs.prepare.outputs.version }} + draft: false + prerelease: false + files: release-files/* + body: | + ## GCC Toolchains for mlibc ${{ needs.prepare.outputs.version }} + + This release contains pre-built GCC toolchains with mlibc for the following architectures: + + ### Supported Architectures + - **ARM**: `arm-linux-eabi` + - **RISC-V 32-bit**: `riscv32-unknown-elf` + - **RISC-V 64-bit**: `riscv64-unknown-elf` + - **AArch64**: `aarch64-linux-gnu` + + ### GCC Version + - GCC 12.2.0 + - Binutils 2.39 + - mlibc version ${{ needs.prepare.outputs.version }} + + ### Installation + 1. Download the appropriate toolchain tarball for your target architecture + 2. Extract: `tar -xzf .tar.gz` + 3. Add to PATH: `export PATH=/path/to/toolchain/bin:$PATH` + + ### Usage + ```bash + # For ARM + arm-linux-eabi-gcc --version + + # For RISC-V 32-bit + riscv32-unknown-elf-gcc --version + + # For RISC-V 64-bit + riscv64-unknown-elf-gcc --version + + # For AArch64 + aarch64-linux-gnu-gcc --version + ``` + + ### Checksums + SHA256 checksums are provided for each tarball to verify integrity. + + ### Build Information + - Commit: ${{ github.sha }} + - Build: ${{ github.run_id }} + - Pipeline: ${{ github.run_number }} diff --git a/.github/workflows/compile-mlibc.yaml b/.github/workflows/compile-mlibc.yaml new file mode 100644 index 0000000..5d80dda --- /dev/null +++ b/.github/workflows/compile-mlibc.yaml @@ -0,0 +1,96 @@ +name: Mlibc Compilation + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the main branch +on: + push: + branches: [ main ] + paths-ignore: + - '**/README.md' + - '**/README_zh.md' + pull_request: + branches: [ main ] + paths-ignore: + - '**/README.md' + - '**/README_zh.md' + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + build: + runs-on: ubuntu-22.04 + name: ${{ matrix.legs.MLIBC_COMPILE }} + strategy: + fail-fast: false + matrix: + legs: + - MLIBC_COMPILE: "Mlibc Arm Compilation On Linux" + ARCH: "arm" + QEMU_BOARD: "qemu-vexpress-a9" + + - MLIBC_COMPILE: "Mlibc AArch64 Compilation On Linux" + ARCH: "aarch64" + QEMU_BOARD: "qemu-virt-aarch64" + + - MLIBC_COMPILE: "Mlibc RISCV32 Compilation On Linux" + ARCH: "riscv32" + QEMU_BOARD: "qemu-virt-riscv32" + + - MLIBC_COMPILE: "Mlibc RISCV64 Compilation On Linux" + ARCH: "riscv64" + QEMU_BOARD: "qemu-virt-riscv64" + + steps: + - uses: actions/checkout@v4 + - name: Install Arm ToolChains + if: ${{ matrix.legs.ARCH == 'arm'}} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 + sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt + /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-" >> $GITHUB_ENV + + - name: Install AArch64 ToolChains + if: ${{ matrix.legs.ARCH == 'aarch64'}} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.6/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf.tar.xz + sudo tar -xf gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf.tar.xz -C /opt + /opt/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-" >> $GITHUB_ENV + + - name: Install RV32 ToolChains + if: ${{ matrix.legs.ARCH == 'riscv32'}} + shell: bash + run: | + wget -q https://github.com/hpmicro/riscv-gnu-toolchain/releases/download/2022.05.15/riscv32-unknown-elf-newlib-multilib_2022.05.15_linux.tar.gz + sudo tar zxf riscv32-unknown-elf-newlib-multilib_2022.05.15_linux.tar.gz -C /opt + /opt/riscv32-unknown-elf-newlib-multilib/bin/riscv32-unknown-elf-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/riscv32-unknown-elf-newlib-multilib/bin/riscv32-unknown-elf-" >> $GITHUB_ENV + + - name: Install RV64 ToolChains + if: ${{ matrix.legs.ARCH == 'riscv64'}} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.4/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + sudo tar zxf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz -C /opt + /opt/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-" >> $GITHUB_ENV + + - name: Mlibc Make Compile + shell: bash + env: + ARCH : ${{ matrix.legs.ARCH }} + QEMU_BOARD : ${{ matrix.legs.QEMU_BOARD }} + run: | + make mlibc + + - name: Upload Mlibc Compilation + uses: actions/upload-artifact@v4 + with: + name: mlibc-${{ matrix.legs.ARCH }}.a + path: ./build/${{ matrix.legs.ARCH }}/libmlibc.a + if-no-files-found: error + retention-days: 7 diff --git a/.github/workflows/qemu-hello.yaml b/.github/workflows/qemu-hello.yaml new file mode 100644 index 0000000..7b7631d --- /dev/null +++ b/.github/workflows/qemu-hello.yaml @@ -0,0 +1,153 @@ +name: Qemu-hello RUN + +on: + push: + branches: [ main ] + paths-ignore: + - '**/README.md' + - '**/README_zh.md' + pull_request: + branches: [ main ] + paths-ignore: + - '**/README.md' + - '**/README_zh.md' + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-22.04 + name: ${{ matrix.platform.QEMU_HELLO }} + strategy: + fail-fast: false + matrix: + platform: + - { QEMU_BOARD: "qemu-mps3-an536" , ARCH: "arm" , QEMU_HELLO: "qemu-hello run on qemu-mps3-an536"} + - { QEMU_BOARD: "qemu-vexpress-a9" , ARCH: "arm" , QEMU_HELLO: "qemu-hello run on qemu-vexpress-a9"} + - { QEMU_BOARD: "qemu-virt-aarch64", ARCH: "aarch64" , QEMU_HELLO: "qemu-hello run on qemu-virt-aarch64"} + - { QEMU_BOARD: "qemu-virt-riscv32", ARCH: "riscv32" , QEMU_HELLO: "qemu-hello run on qemu-virt-riscv32"} + - { QEMU_BOARD: "qemu-virt-riscv64", ARCH: "riscv64" , QEMU_HELLO: "qemu-hello run on qemu-virt-riscv64"} + steps: + - uses: actions/checkout@v4 + - name: Install Qemu + shell: bash + run: | + wget -q https://github.com/Chris-godz/mlibc/releases/download/CI/qemu-9.2.2.tar.zst + cat *.tar.zst | zstd -d -T0 | tar -xf - > /dev/null 2>&1 + chmod +x ./qemu-9.2.2/qemu_install.sh + sudo ./qemu-9.2.2/qemu_install.sh + + - name: Verify QEMU installation + shell: bash + run: | + qemu-system-arm --version + + - name: Install Arm ToolChains + if: ${{ matrix.platform.ARCH == 'arm'}} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 + sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt + /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-" >> $GITHUB_ENV + + - name: Install AArch64 ToolChains + if: ${{ matrix.platform.ARCH == 'aarch64'}} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.6/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf.tar.xz + sudo tar -xf gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf.tar.xz -C /opt + /opt/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-" >> $GITHUB_ENV + + - name: Install RV32 ToolChains + if: ${{ matrix.platform.ARCH == 'riscv32'}} + shell: bash + run: | + wget -q https://github.com/hpmicro/riscv-gnu-toolchain/releases/download/2022.05.15/riscv32-unknown-elf-newlib-multilib_2022.05.15_linux.tar.gz + sudo tar zxf riscv32-unknown-elf-newlib-multilib_2022.05.15_linux.tar.gz -C /opt + /opt/riscv32-unknown-elf-newlib-multilib/bin/riscv32-unknown-elf-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/riscv32-unknown-elf-newlib-multilib/bin/riscv32-unknown-elf-" >> $GITHUB_ENV + + - name: Install RV64 ToolChains + if: ${{ matrix.platform.ARCH == 'riscv64'}} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.4/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + sudo tar zxf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz -C /opt + /opt/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc --version + echo "MLIBC_TOOLCHAIN=/opt/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-" >> $GITHUB_ENV + + - name: qemu-hello test + shell: bash + if: ${{ env.MLIBC_TOOLCHAIN != '' && success() }} + env: + ARCH : ${{ matrix.platform.ARCH }} + QEMU_BOARD : ${{ matrix.platform.QEMU_BOARD }} + run: | + if [[ "${{ matrix.platform.QEMU_BOARD }}" == "qemu-mps3-an536" ]]; then + make qemu-hello ARCH=$ARCH QEMU_BOARD=$QEMU_BOARD + qemu-system-arm -M mps3-an536 \ + -kernel ./build/$ARCH/qemu/$QEMU_BOARD/$QEMU_BOARD.elf \ + -nographic -m 512 \ + > qemu_output_$QEMU_BOARD.log 2>&1 & + + elif [[ "${{ matrix.platform.QEMU_BOARD }}" == "qemu-vexpress-a9" ]]; then + make qemu-hello ARCH=$ARCH QEMU_BOARD=$QEMU_BOARD + qemu-system-arm -M vexpress-a9 \ + -kernel ./build/$ARCH/qemu/$QEMU_BOARD/$QEMU_BOARD.elf \ + -nographic -m 512 \ + > qemu_output_$QEMU_BOARD.log 2>&1 & + + elif [[ "${{ matrix.platform.QEMU_BOARD }}" == "qemu-virt-aarch64" ]]; then + make qemu-hello ARCH=$ARCH QEMU_BOARD=$QEMU_BOARD + qemu-system-aarch64 -M virt \ + -cpu cortex-a53 \ + -kernel ./build/$ARCH/qemu/$QEMU_BOARD/$QEMU_BOARD.elf \ + -nographic -m 512 \ + > qemu_output_$QEMU_BOARD.log 2>&1 & + + elif [[ "${{ matrix.platform.QEMU_BOARD }}" == "qemu-virt-riscv32" ]]; then + make qemu-hello ARCH=$ARCH QEMU_BOARD=$QEMU_BOARD + qemu-system-riscv32 -machine virt \ + -nographic -m 256M \ + -kernel ./build/$ARCH/qemu/$QEMU_BOARD/$QEMU_BOARD.elf \ + > qemu_output_$QEMU_BOARD.log 2>&1 & + + elif [[ "${{ matrix.platform.QEMU_BOARD }}" == "qemu-virt-riscv64" ]]; then + make qemu-hello ARCH=$ARCH QEMU_BOARD=$QEMU_BOARD + qemu-system-riscv64 -machine virt \ + -nographic -m 512M \ + -kernel ./build/$ARCH/qemu/$QEMU_BOARD/$QEMU_BOARD.elf \ + > qemu_output_$QEMU_BOARD.log 2>&1 & + fi + + QEMU_PID=$! + disown $QEMU_PID + echo "QEMU_SETUP_READY=true" >> $GITHUB_ENV + + - name: Monitor qemu log + if: ${{ env.QEMU_SETUP_READY == 'true' && success() }} + shell: bash + run: | + # wait for qemu finish + sleep 10 + echo "==========================================================================================" + echo " || || " + echo " || Start automatic running of qemu-hello || " + echo " VV VV " + echo "==========================================================================================" + LAST_TWO_LINES=$(tail -n 2 qemu_output_${{ matrix.platform.QEMU_BOARD }}.log) + echo "$LAST_TWO_LINES" + + if grep -q "Uart Test" qemu_output_${{ matrix.platform.QEMU_BOARD }}.log && grep -q "Hello mlibc" qemu_output_${{ matrix.platform.QEMU_BOARD }}.log; then + echo "==========================================================================================" + echo " Succeeded: qemu-hello run completed. Exiting log monitoring " + echo "==========================================================================================" + else + echo "==========================================================================================" + echo " Failed: qemu-hello run not completed. Exiting log monitoring " + echo "==========================================================================================" + exit 1 + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1381926 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,72 @@ +name: Release mlibc Source + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + version: + description: 'Version tag (e.g., v1.0.0)' + required: true + type: string + +permissions: + contents: write + +jobs: + create-source-release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get version + id: get_version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT + else + echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + fi + + - name: Create source tarball + run: | + VERSION="${{ steps.get_version.outputs.version }}" + TARBALL_NAME="mlibc-${VERSION}-source.tar.gz" + + # Create a clean export of the repository + git archive --format=tar.gz --prefix=mlibc-${VERSION}/ HEAD > ${TARBALL_NAME} + + # Calculate checksum + sha256sum ${TARBALL_NAME} > ${TARBALL_NAME}.sha256 + + echo "TARBALL_NAME=${TARBALL_NAME}" >> $GITHUB_ENV + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ steps.get_version.outputs.version }} + name: mlibc ${{ steps.get_version.outputs.version }} + draft: false + prerelease: false + files: | + mlibc-*.tar.gz + mlibc-*.tar.gz.sha256 + body: | + ## mlibc ${{ steps.get_version.outputs.version }} Release + + ### Source Code + This release includes the source code for mlibc version ${{ steps.get_version.outputs.version }}. + + ### Downloads + - **Source tarball**: `mlibc-${{ steps.get_version.outputs.version }}-source.tar.gz` + - **SHA256 checksum**: `mlibc-${{ steps.get_version.outputs.version }}-source.tar.gz.sha256` + + ### Toolchains + Pre-built GCC toolchains for various architectures can be downloaded from the [toolchain releases](https://github.com/${{ github.repository }}/releases). + + ### Building + Please refer to the [README](https://github.com/${{ github.repository }}/blob/${{ steps.get_version.outputs.version }}/README.md) for build instructions. diff --git a/.gitignore b/.gitignore index 16b3e86..b6f72ab 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ toolchain/mpc-* toolchain/mpfr-* toolchain/log +_codeql_detected_source_root + # MacOS Cache .DS_Store @@ -23,4 +25,4 @@ toolchain/log *.table *.bat *.asm -*.gdb \ No newline at end of file +*.gdb diff --git a/Makefile b/Makefile index 9b1d2c6..47fafc3 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,9 @@ OBJ_FILES := $(patsubst %.c,$(OBJ_DIR)/%.o,$(notdir $(SRC_FILES))) CRTOBJ_FILE := $(patsubst %.c,$(CRTOBJ_DIR)/%.o,$(notdir $(CRT_FILES))) CRTOBJ_FILES := $(patsubst %.S,$(CRTOBJ_DIR)/%.o,$(CRTOBJ_FILE)) +# Include QEMU hello world build configuration +include $(PROJECT_PATH)/mkconfigs/qemu/qemu-hello.mk + # Build rules .PHONY: all all : mlibc crt @@ -111,3 +114,6 @@ else @echo ${CRTOBJ_FILES} @echo ${CRTOBJ_FILE} endif + +# Include qemu-hello target +-include $(PROJECT_PATH)/mkconfigs/qemu/qemu-hello.mk diff --git a/README.md b/README.md index 2a8edc7..a995dc2 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,41 @@ Embedded libc, a libc library adapted for embedded systems and bare metal enviro # Quick Start +## mlibc Library Compilation + +### Development Environment + +For simple C library compilation, the development environment is relatively straightforward; make and the appropriate toolchain are sufficient. + +> make + toolchain + +### Compilation Steps + +1. Configure the environment variables corresponding to the toolchain +(Please refer to the detailed steps in the "QEMU-Bare Metal Development" section below) + +**Compile the C library** + +1. Navigate to the `mlibc` folder, open the command line, and use make to compile the static library. + +``` +# Here, we use the ARM architecture static library as an example +make mlibc ARCH=arm +``` + +2. A static library named `libmlibc.a` will be generated in the `mlibc/build/arm` directory. To integrate it with the toolchain, you can rename the file to `libc.a` for use. + +**Compile crt0** + +1. Navigate to the `mlibc` folder, open the command line, and use make to compile crt0. + +``` +# Here, we use the ARM architecture crt0 as an example +make crt0 ARCH=arm +``` + +2. The generated file will be located in `mlibc/build/$(ARCH)/crtobj`, named `crt0.o`. + ## Mlibc Development/Test Environment Setup ### Running RT-Thread on QEMU @@ -66,9 +101,9 @@ Embedded libc, a libc library adapted for embedded systems and bare metal enviro Tutorial for setting up the environment on Windows: -https://github.com/RT-Thread/rt-thread/blob/master/documentation/quick-start/quick_start_qemu/quick_start_qemu_windows.md +**Note**: The original RT-Thread documentation link is outdated. Please refer to the official RT-Thread website (https://www.rt-thread.org/) or repository (https://github.com/RT-Thread/rt-thread) for the latest documentation on setting up the development environment. -By following this tutorial, you can run RT-Thread in a Windows environment. +By following the official tutorials, you can run RT-Thread in a Windows environment. ### vexpress-a9 + RT-Thread @@ -88,13 +123,27 @@ Navigate to the `rt-thread\bsp\qemu-vexpress-a9` folder, open **env**, and enter - system packages - Select the sixth option from the bottom: `mlibc: Embedded libc, especially for RISC-V` -After finishing, you can exit the configuration page and enter **scons -j12** in the command line to compile. +After finishing the menuconfig, you need to download the mlibc package before compiling: + +```bash +# Load the RT-Thread environment +. ~/.env/env.sh + +# Update packages to download mlibc +pkgs --update +``` + +This will download mlibc to `bsp/qemu-vexpress-a9/packages/mlibc-latest`. + +Then you can enter **scons -j12** in the command line to compile. + +**Note**: There are known compilation issues with vexpress-a9 + RT-Thread integration. This may be due to compatibility issues with the current RT-Thread version. Please refer to the RT-Thread repository for updates. ### Spark + RT-Thread #### Development Environment -For those unsure where to download the source code, you can refer to the above Windows environment setup tutorial. +For those unsure where to download the source code, you can refer to the official RT-Thread documentation. Navigate to the `rt-thread\bsp\stm32\stm32f407-rt-spark` directory, then open **env** and enter **menuconfig** in the command line to enter the configuration interface. @@ -120,6 +169,18 @@ Navigate to the `rt-thread\bsp\stm32\stm32f407-rt-spark` directory, then open ** - system packages - Select the sixth option from the bottom: mlibc: Embedded libc, especially for RISC-V +After finishing the menuconfig, you need to download the mlibc package before compiling: + +```bash +# Load the RT-Thread environment +. ~/.env/env.sh + +# Update packages to download mlibc +pkgs --update +``` + +This will download mlibc to the packages directory. + ### QEMU-Bare Metal Development #### Development Environment @@ -151,71 +212,81 @@ source ~/.bashrc **Windows:** Open PowerShell and replace `YOUR_PATH_TO_TOOLCHAIN` with the corresponding path of your toolchain. ``` -[System.Environment]::SetEnvironmentVariable("YOUR_PATH_TO_TOOLCHAIN", "YOUR_PATH_TO_TOOLCHAIN", "User") +[System.Environment]::SetEnvironmentVariable("MLIBC_TOOLCHAIN", "YOUR_PATH_TO_TOOLCHAIN", "User") ``` **\#**:After the configuration is completed, you need to restart the terminal for the changes to take effect. -2. Navigate to the `mlibc/helloworld/qemu/{qemu-device}` folder and open the command line. +2. Navigate to the `mlibc` root folder and open the command line. ``` # Here, we use qemu-vexpress-a9 as an example -make QEMU_BOARD=qemu-vexpress-a9 ARCH=arm +make qemu-hello QEMU_BOARD=qemu-vexpress-a9 ARCH=arm ``` -After executing the command, an executable file named qemu-vexpress-a9.elf will be generated in the `mlibc/helloworld/qemu/qemu-vexpress-a9` folder. +After executing the command, an executable file named qemu-vexpress-a9.elf will be generated in the `mlibc/build/arm/qemu/qemu-vexpress-a9` folder. -3. Run the script `qemu.bat` in the corresponding folder. +3. Run the script `qemu.bat` in the corresponding folder under `mlibc/helloworld/qemu/{qemu-device}`. ``` +# Navigate to the qemu device folder +cd helloworld/qemu/qemu-vexpress-a9 + # Enter the following command in the command line qemu.bat ``` Information for each virtual environment is as follows: -| Filename | Virtual Device | Switch Command | -| ----------------- | -------------- | -------------------------------------- | -| qemu-vexpress-a9 | vexpress-a9 | make QEMU_BOARD=qemu-vexpress-a9 ARCH=arm | -| qemu-mps3-an536 | mps3-an536 | make QEMU_BOARD=qemu-mps3-an536 ARCH=arm | -| qemu-virt-aarch64 | virt-aarch64 | make QEMU_BOARD=qemu-virt-aarch64 ARCH=aarch64 | -| qemu-virt-riscv32 | virt-riscv32 | make QEMU_BOARD=qemu-virt-riscv32 ARCH=riscv32 | -| qemu-virt-riscv64 | virt-riscv64 | make QEMU_BOARD=qemu-virt-riscv64 ARCH=riscv64 | +| Filename | Virtual Device | Build Command | +| ----------------- | -------------- | --------------------------------------------------- | +| qemu-vexpress-a9 | vexpress-a9 | make qemu-hello QEMU_BOARD=qemu-vexpress-a9 ARCH=arm | +| qemu-mps3-an536 | mps3-an536 | make qemu-hello QEMU_BOARD=qemu-mps3-an536 ARCH=arm | +| qemu-virt-aarch64 | virt-aarch64 | make qemu-hello QEMU_BOARD=qemu-virt-aarch64 ARCH=aarch64 | +| qemu-virt-riscv32 | virt-riscv32 | make qemu-hello QEMU_BOARD=qemu-virt-riscv32 ARCH=riscv32 | +| qemu-virt-riscv64 | virt-riscv64 | make qemu-hello QEMU_BOARD=qemu-virt-riscv64 ARCH=riscv64 | +## Pre-built GCC Toolchains -## mlibc Library Compilation +For convenience, we provide pre-built GCC toolchains with mlibc for multiple architectures. These toolchains are automatically built and released using GitHub Actions. -#### Development Environment +### Downloading Pre-built Toolchains -For simple C library compilation, the development environment is relatively straightforward; make and the appropriate toolchain are sufficient. +Visit the [Releases page](https://github.com/plctlab/mlibc/releases) to download pre-built toolchains: -> make + toolchain +- **ARM**: `arm-linux-eabi_for_x86_64-pc-linux-gnu-*.tar.gz` +- **RISC-V 32-bit**: `riscv32-unknown-elf_for_x86_64-pc-linux-gnu-*.tar.gz` +- **RISC-V 64-bit**: `riscv64-unknown-elf_for_x86_64-pc-linux-gnu-*.tar.gz` +- **AArch64**: `aarch64-linux-gnu_for_x86_64-pc-linux-gnu-*.tar.gz` -#### Compilation Steps +### Installation -1. Configure the environment variables corresponding to the toolchain -:Please refer to the detailed steps in the previous section) +```bash +# Download and extract +tar -xzf .tar.gz -**Compile the C library** +# Add to PATH +export PATH=/path/to/toolchain/bin:$PATH -1. Navigate to the `mlibc` folder, open the command line, and use make to compile the static library. - -``` -# Here, we use the ARM architecture static library as an example -make mlibc ARCH=arm +# Verify installation +arm-linux-eabi-gcc --version ``` -2. A static library named `libmlibc.a` will be generated in the `mlibc/build/arm` directory. To integrate it with the toolchain, you can rename the file to `libc.a` for use. +### Building Toolchains Yourself -**Compile crt0** +If you prefer to build the toolchains yourself: -1. Navigate to the `mlibc` folder, open the command line, and use make to compile crt0. +#### Using Docker (Recommended) -``` -# Here, we use the ARM architecture crt0 as an example -make crt0 ARCH=arm -``` +See [toolchain/README.md](toolchain/README.md) for detailed instructions on building with Docker. -2. The generated file will be located in `mlibc/build/$(ARCH)/crtobj`, named `crt0.o`. +#### Using GitHub Actions + +The repository includes GitHub Actions workflows for automated builds: + +- **Build all architectures**: Triggered automatically on version tags or manually via workflow dispatch +- **Build single architecture**: Use the "Build Single Toolchain" workflow for testing + +For more information, see [.github/workflows/README.md](.github/workflows/README.md). # License Agreement diff --git a/README_zh.md b/README_zh.md index f6d5954..76b73c9 100644 --- a/README_zh.md +++ b/README_zh.md @@ -60,6 +60,40 @@ Embedded libc,一个为嵌入式系统和裸机适配的libc库 # 快速上手 +## mlibc库编译 + +### 开发环境 + +对于单纯的c库编译来说,开发环境就简单一些了,具备make和对应工具链就可以 + +> make + 工具链 + +### 编译步骤 + +1. 配置工具链对应的环境变量 +(请参考下文"QEMU-裸机开发"一节的详细步骤) + +**编译c库** + +1. 进入 mlibc 文件夹,打开命令行使用 make 编译静态库 +``` +# 这里使用 arm 架构的静态库举例 +make mlibc ARCH=arm +``` + +2. 然后会在 mlibc/build/arm 目录下生成一份静态库,文件名为`libmlibc.a`(防止与工具链中的libc.a撞名,便于测试),集成工具链时可以把文件名改为`libc.a`进行使用 + +**编译crt0** + +1. 进入mlibc文件夹,打开命令行使用 make 编译 crt0 + +``` +# 这里使用 arm 架构的 crt0 举例 +make crt0 ARCH=arm +``` + +2. 生成的文件在`mlibc/build/$(ARCH)/crtobj`中,文件名为`crt0.o` + ## mlbc开发/测试环境配置 ### QEMU运行RT-Thread @@ -68,9 +102,9 @@ Embedded libc,一个为嵌入式系统和裸机适配的libc库 windows下的环境配置教程: -https://github.com/RT-Thread/rt-thread/blob/master/documentation/quick-start/quick_start_qemu/quick_start_qemu_windows.md +**注意**:原RT-Thread文档链接已失效。请参考RT-Thread官方网站(https://www.rt-thread.org/)或代码仓库(https://github.com/RT-Thread/rt-thread)获取最新的开发环境配置文档。 -通过这个教程我们就可以在 windows 环境下运行 RT-Thread 了。 +通过官方教程我们就可以在 windows 环境下运行 RT-Thread 了。 ### vexpress-a9 + RT-Thread @@ -90,13 +124,27 @@ https://github.com/RT-Thread/rt-thread/blob/master/documentation/quick-start/qui - system packages - 选中当前页面的倒数第六个选项: `mlibc: Embedded libc, especially for RISC-V` -完成之后就可以退出配置页面然后在命令行输入**scons -j12**进行编译了。 +完成menuconfig配置后,需要先下载mlibc软件包再进行编译: + +```bash +# 加载RT-Thread环境 +. ~/.env/env.sh + +# 更新软件包以下载mlibc +pkgs --update +``` + +这将会把mlibc下载到`bsp/qemu-vexpress-a9/packages/mlibc-latest`目录。 + +然后就可以在命令行输入**scons -j12**进行编译了。 + +**注意**:vexpress-a9 + RT-Thread 集成存在已知的编译问题。这可能是由于当前RT-Thread版本的兼容性问题。请关注RT-Thread代码仓库获取更新。 ### 星火一号 + RT-Thread #### 开发环境 -不知道哪里下载源码的同学可以参考上面 windows 环境配置教程 +不知道哪里下载源码的同学可以参考RT-Thread官方文档 进入`rt-thread\bsp\stm32\stm32f407-rt-spark`目录,然后打开**env**,在命令行输入**menuconfig**,进入配置界面 @@ -122,6 +170,18 @@ https://github.com/RT-Thread/rt-thread/blob/master/documentation/quick-start/qui - system packages - 选中当前页面的倒数第六个选项: mlibc: Embedded libc, especially for RISC-V +完成menuconfig配置后,需要先下载mlibc软件包再进行编译: + +```bash +# 加载RT-Thread环境 +. ~/.env/env.sh + +# 更新软件包以下载mlibc +pkgs --update +``` + +这将会把mlibc下载到packages目录。 + ### QEMU-裸机开发 #### 开发环境 @@ -151,72 +211,83 @@ echo "export MLIBC_TOOLCHAIN='YOUR_PATH_TO_TOOLCHAIN'" >> ~/.bashrc source ~/.bashrc ``` -**Windows:** 打开 PowellShell,`YOUR_PATH_TO_TOOLCHAIN`替换为你对应的工具链路径 +**Windows:** 打开 PowerShell,`YOUR_PATH_TO_TOOLCHAIN`替换为你对应的工具链路径 ``` [System.Environment]::SetEnvironmentVariable("MLIBC_TOOLCHAIN", "YOUR_PATH_TO_TOOLCHAIN", "User") ``` **\#**:配置完后需要重启终端生效 -2. 进入`mlibc/helloworld/qemu/{qemu-device}`文件夹打开命令行 +2. 进入 `mlibc` 根目录打开命令行 ``` # 这里使用 qemu-vexpress-a9 举例 -make QEMU_BOARD=qemu-vexpress-a9 ARCH=arm +make qemu-hello QEMU_BOARD=qemu-vexpress-a9 ARCH=arm ``` - 执行完命令之后,mlibc/helloworld/qemu/qemu-vexpress-a9 文件夹下会生成一份可执行文件为 qemu-vexpress-a9.elf +执行完命令之后,`mlibc/build/arm/qemu/qemu-vexpress-a9` 文件夹下会生成一份可执行文件为 qemu-vexpress-a9.elf -3. 运行对应文件夹下的脚本`qemu.bat` +3. 运行对应文件夹 `mlibc/helloworld/qemu/{qemu-device}` 下的脚本`qemu.bat` ``` +# 进入qemu设备文件夹 +cd helloworld/qemu/qemu-vexpress-a9 + # 在命令行敲入下列命令 qemu.bat ``` 各个虚拟环境对应的信息如下: -| 文件名 | 虚拟设备 | 切换命令 | -| ----------------- | ------------ | -------------------------------------- | -| qemu-vexpress-a9 | vexpress-a9 | make QEMU_BOARD=qemu-vexpress-a9 ARCH=arm | -| qemu-mps3-an536 | mps3-an536 | make QEMU_BOARD=qemu-mps3-an536 ARCH=arm | -| qemu-virt-aarch64 | virt-aarch64 | make QEMU_BOARD=qemu-virt-aarch64 ARCH=aarch64 | -| qemu-virt-riscv32 | virt-riscv32 | make QEMU_BOARD=qemu-virt-riscv32 ARCH=riscv32 | -| qemu-virt-riscv64 | virt-riscv64 | make QEMU_BOARD=qemu-virt-riscv64 ARCH=riscv64 | +| 文件名 | 虚拟设备 | 编译命令 | +| ----------------- | ------------ | --------------------------------------------------- | +| qemu-vexpress-a9 | vexpress-a9 | make qemu-hello QEMU_BOARD=qemu-vexpress-a9 ARCH=arm | +| qemu-mps3-an536 | mps3-an536 | make qemu-hello QEMU_BOARD=qemu-mps3-an536 ARCH=arm | +| qemu-virt-aarch64 | virt-aarch64 | make qemu-hello QEMU_BOARD=qemu-virt-aarch64 ARCH=aarch64 | +| qemu-virt-riscv32 | virt-riscv32 | make qemu-hello QEMU_BOARD=qemu-virt-riscv32 ARCH=riscv32 | +| qemu-virt-riscv64 | virt-riscv64 | make qemu-hello QEMU_BOARD=qemu-virt-riscv64 ARCH=riscv64 | +## 预编译的 GCC 工具链 -## mlibc库编译 +为了方便使用,我们提供了带有 mlibc 的多架构预编译 GCC 工具链。这些工具链通过 GitHub Actions 自动构建和发布。 -#### 开发环境 +### 下载预编译工具链 -对于单纯的c库编译来说,开发环境就简单一些了,具备make和对应工具链就可以 +访问 [Releases 页面](https://github.com/plctlab/mlibc/releases) 下载预编译工具链: -> make + 工具链 +- **ARM**: `arm-linux-eabi_for_x86_64-pc-linux-gnu-*.tar.gz` +- **RISC-V 32位**: `riscv32-unknown-elf_for_x86_64-pc-linux-gnu-*.tar.gz` +- **RISC-V 64位**: `riscv64-unknown-elf_for_x86_64-pc-linux-gnu-*.tar.gz` +- **AArch64**: `aarch64-linux-gnu_for_x86_64-pc-linux-gnu-*.tar.gz` -#### 编译步骤 +### 安装 -1. 配置工具链对应的环境变量 -:请参考上一节的详细步骤) +```bash +# 下载并解压 +tar -xzf .tar.gz -**编译c库** +# 添加到 PATH +export PATH=/path/to/toolchain/bin:$PATH -1. 进入 mlibc 文件夹,打开命令行使用 make 编译静态库 -``` -# 这里使用 arm 架构的静态库举例 -make mlibc ARCH=arm +# 验证安装 +arm-linux-eabi-gcc --version ``` -2. 然后会在 mlibc/build/arm 目录下生成一份静态库,文件名为`libmlibc.a`(防止与工具链中的libc.a撞名,便于测试),集成工具链时可以把文件名改为`libc.a`进行使用 +### 自行构建工具链 -**编译crt0** +如果您希望自行构建工具链: -1. 进入mlibc文件夹,打开命令行使用 make 编译 crt0 +#### 使用 Docker(推荐) -``` -# 这里使用 arm 架构的 crt0 举例 -make crt0 ARCH=arm -``` +详细说明请参见 [toolchain/README.md](toolchain/README.md)。 -2. 生成的文件在`mlibc/build/$(ARCH)/crtobj`中,文件名为`crt0.o` +#### 使用 GitHub Actions + +仓库中包含用于自动构建的 GitHub Actions 工作流: + +- **构建所有架构**:在版本标签上自动触发或通过工作流手动触发 +- **构建单个架构**:使用 "Build Single Toolchain" 工作流进行测试 + +更多信息,请参见 [.github/workflows/README.md](.github/workflows/README.md)。 # 贡献代码 diff --git a/include/signal.h b/include/signal.h index e8bae03..262c7fd 100644 --- a/include/signal.h +++ b/include/signal.h @@ -15,24 +15,48 @@ #include #include +#ifndef SIGHUP #define SIGHUP 1 +#endif +#ifndef SIGINT #define SIGINT 2 +#endif +#ifndef SIGQUIT #define SIGQUIT 3 +#endif +#ifndef SIGBUS #define SIGBUS 7 +#endif +#ifndef SIGFPE #define SIGFPE 8 +#endif +#ifndef SIGKILL #define SIGKILL 9 +#endif #ifndef SIGUSR1 #define SIGUSR1 10 #endif +#ifndef SIGSEGV #define SIGSEGV 11 +#endif #ifndef SIGUSR2 #define SIGUSR2 12 #endif +#ifndef SIGPIPE #define SIGPIPE 13 +#endif +#ifndef SIGALRM #define SIGALRM 14 +#endif +#ifndef SIGTERM #define SIGTERM 15 +#endif +#ifndef SIGSTKFLT #define SIGSTKFLT 16 +#endif +#ifndef SIGCHLD #define SIGCHLD 17 +#endif #ifndef SIGCONT #define SIGCONT 18 #endif @@ -42,83 +66,179 @@ #ifndef SIGTSTP #define SIGTSTP 20 #endif +#ifndef SIGTTIN #define SIGTTIN 21 +#endif +#ifndef SIGTTOU #define SIGTTOU 22 +#endif #ifndef SIGURG #define SIGURG 23 #endif +#ifndef SIGXCPU #define SIGXCPU 24 +#endif +#ifndef SIGXFSZ #define SIGXFSZ 25 +#endif +#ifndef SIGVTALRM #define SIGVTALRM 26 +#endif +#ifndef SIGPROF #define SIGPROF 27 +#endif +#ifndef SIGWINCH #define SIGWINCH 28 +#endif #ifndef SIGIO #define SIGIO 29 #endif #ifndef SIGPOLL #define SIGPOLL 29 #endif +#ifndef SIGPWR #define SIGPWR 30 +#endif +#ifndef SIGSYS #define SIGSYS 31 +#endif +#ifndef SIGUNUSED #define SIGUNUSED SIGSYS +#endif +#ifndef SA_NOCLDSTOP #define SA_NOCLDSTOP 1 +#endif +#ifndef SA_NOCLDWAIT #define SA_NOCLDWAIT 2 +#endif +#ifndef SA_SIGINFO #define SA_SIGINFO 4 +#endif +#ifndef SA_ONSTACK #define SA_ONSTACK 0x08000000 +#endif +#ifndef SA_RESTART #define SA_RESTART 0x10000000 +#endif +#ifndef SA_NODEFER #define SA_NODEFER 0x40000000 +#endif +#ifndef SA_RESETHAND #define SA_RESETHAND 0x80000000 +#endif +#ifndef SA_RESTORER #define SA_RESTORER 0x04000000 +#endif +#ifndef _NSIG #define _NSIG 65 +#endif +#ifndef SI_KERNEL #define SI_KERNEL 128 +#endif +#ifndef SIG_SETMASK #define SIG_SETMASK 0 /* set mask with sigprocmask() */ +#endif +#ifndef SIG_BLOCK #define SIG_BLOCK 1 /* set of signals to block */ +#endif +#ifndef SIG_UNBLOCK #define SIG_UNBLOCK 2 /* set of signals to, well, unblock */ +#endif +#ifndef _SIG_FUNC_PTR_DEFINED typedef void (*_sig_func_ptr)(int); +#define _SIG_FUNC_PTR_DEFINED +#endif + +#ifndef _SIGSET_T_DEFINED typedef unsigned long sigset_t; +#define _SIGSET_T_DEFINED +#endif +#ifndef SIG_DFL #define SIG_DFL ((_sig_func_ptr)0) /* Default action */ +#endif +#ifndef SIG_IGN #define SIG_IGN ((_sig_func_ptr)1) /* Ignore action */ +#endif +#ifndef SIG_ERR #define SIG_ERR ((_sig_func_ptr)-1) /* Error return */ +#endif +#ifndef SI_USER #define SI_USER 0x01 /* Signal sent by kill(). */ +#endif +#ifndef SI_QUEUE #define SI_QUEUE 0x02 /* Signal sent by sigqueue(). */ +#endif +#ifndef SI_TIMER #define SI_TIMER 0x03 /* Signal generated by expiration of a timer set by timer_settime(). */ +#endif +#ifndef SI_ASYNCIO #define SI_ASYNCIO 0x04 /* Signal generated by completion of an asynchronous I/O request. */ +#endif +#ifndef SI_MESGQ #define SI_MESGQ 0x05 /* Signal generated by arrival of a message on an empty message queue. */ +#endif +#ifndef CLD_EXITED #define CLD_EXITED 1 +#endif +#ifndef CLD_KILLED #define CLD_KILLED 2 +#endif +#ifndef CLD_DUMPED #define CLD_DUMPED 3 +#endif +#ifndef CLD_TRAPPED #define CLD_TRAPPED 4 +#endif +#ifndef CLD_STOPPED #define CLD_STOPPED 5 +#endif +#ifndef CLD_CONTINUED #define CLD_CONTINUED 6 +#endif +#ifndef SIGEV_SIGNAL #define SIGEV_SIGNAL 0 +#endif +#ifndef SIGEV_NONE #define SIGEV_NONE 1 +#endif +#ifndef SIGEV_THREAD #define SIGEV_THREAD 2 +#endif +#ifndef SIGEV_THREAD_ID #define SIGEV_THREAD_ID 4 +#endif +#ifndef _UNION_SIGVAL_DEFINED union sigval { int sival_int; /* Integer signal value */ void *sival_ptr; /* Pointer signal value */ }; +#define _UNION_SIGVAL_DEFINED +#endif +#ifndef _STRUCT_SIGACTION_DEFINED struct sigaction { _sig_func_ptr sa_handler; sigset_t sa_mask; int sa_flags; }; +#define _STRUCT_SIGACTION_DEFINED +#endif +#ifndef _STRUCT_SIGEVENT_DEFINED struct sigevent { union sigval sigev_value; @@ -128,7 +248,10 @@ struct sigevent /* Notification function */ void *sigev_notify_attributes; /* Notification Attributes, really pthread_attr_t */ }; +#define _STRUCT_SIGEVENT_DEFINED +#endif +#ifndef _SIGINFO_T_DEFINED typedef struct { int si_signo, si_errno, si_code; union { @@ -174,6 +297,8 @@ typedef struct { } __sigsys; } __si_fields; } siginfo_t; +#define _SIGINFO_T_DEFINED +#endif #define si_pid __si_fields.__si_common.__first.__piduid.si_pid #define si_uid __si_fields.__si_common.__first.__piduid.si_uid @@ -199,7 +324,9 @@ typedef struct { #define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0) int sigprocmask(int how, const sigset_t *set, sigset_t *oset); +#ifndef sigemptyset int sigemptyset(sigset_t *set); +#endif int sigwait(const sigset_t *set, int *sig); int raise(int sig); diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h index ff49ed5..8d89335 100644 --- a/include/sys/statvfs.h +++ b/include/sys/statvfs.h @@ -14,6 +14,9 @@ extern "C" { #endif +#define __NEED_fsblkcnt_t +#define __NEED_fsfilcnt_t + #include #include diff --git a/mlibc.ld b/mlibc.ld index f937b19..4e7c634 100644 --- a/mlibc.ld +++ b/mlibc.ld @@ -100,7 +100,7 @@ SECTIONS PROVIDE( _gp = . + 0x8000); *(.sdata .sdata.* .sdata2.*) *(.gnu.linkonce.s.*) - } >ram AT>flash :ram_init + } >ram AT>ram :ram PROVIDE(__data_start = ADDR(.data)); PROVIDE(__data_source = LOADADDR(.data)); PROVIDE(__data_end = .); diff --git a/src/internal/mem_impl.h b/src/internal/mem_impl.h index 6b5cf09..6f522dc 100644 --- a/src/internal/mem_impl.h +++ b/src/internal/mem_impl.h @@ -18,7 +18,7 @@ extern tlsf_t tlsf; extern _LOCK_T heap_lock; -#define POOL_SIZE 1728 /* size of pool head*/ +#define POOL_SIZE 4096 /* size of pool head*/ #ifdef MLIBC_RETARGETABLE_LOCKING #define INIT_HEAP_LOCK __lock_init_recursive(heap_lock)