diff --git a/.github/workflows/busybox-eld.yml b/.github/workflows/busybox-eld.yml new file mode 100644 index 000000000..5b9eeda0d --- /dev/null +++ b/.github/workflows/busybox-eld.yml @@ -0,0 +1,234 @@ +name: BusyBox with ELD + +on: + workflow_dispatch: + # pull_request: {} + schedule: + - cron: "0 5 * * *" + +permissions: + contents: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + fetch-clang-cross-toolchain: + if: github.repository == 'qualcomm/eld' + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + toolchain_asset: x86_64-unknown-linux-musl.tar.xz + enabled: 1 + - arch: riscv32 + toolchain_asset: riscv32-unknown-linux-musl.tar.xz + enabled: 0 + - arch: riscv64 + toolchain_asset: riscv64-unknown-linux-musl.tar.xz + enabled: 0 + - arch: arm + toolchain_asset: arm-unknown-linux-musleabi.tar.xz + enabled: 0 + - arch: aarch64 + toolchain_asset: aarch64-unknown-linux-musl.tar.xz + enabled: 0 + uses: ./.github/workflows/clang-cross-download.yml + with: + runner: ubuntu-latest + workspace: /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }} + assets: ${{ matrix.toolchain_asset }} + upload_artifact: true + artifact_name: clang-cross-${{ matrix.arch }} + enabled: ${{ matrix.enabled == 1 }} + + build-busybox-with-eld: + if: github.repository == 'qualcomm/eld' + needs: fetch-clang-cross-toolchain + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + busybox_arch: x86_64 + target_triple: x86_64-unknown-linux-musl + toolchain_dir: x86_64-unknown-linux-musl + qemu_bin: "" + enabled: 1 + - arch: riscv32 + busybox_arch: riscv + target_triple: riscv32-unknown-linux-musl + toolchain_dir: riscv32-unknown-linux-musl + qemu_bin: qemu-riscv32 + enabled: 0 + - arch: riscv64 + busybox_arch: riscv + target_triple: riscv64-unknown-linux-musl + toolchain_dir: riscv64-unknown-linux-musl + qemu_bin: qemu-riscv64 + enabled: 0 + - arch: arm + busybox_arch: arm + target_triple: arm-unknown-linux-musleabi + toolchain_dir: arm-unknown-linux-musleabi + qemu_bin: qemu-arm + enabled: 0 + - arch: aarch64 + busybox_arch: aarch64 + target_triple: aarch64-unknown-linux-musl + toolchain_dir: aarch64-unknown-linux-musl + qemu_bin: qemu-aarch64 + enabled: 0 + steps: + - name: Checkout eld + if: matrix.enabled == 1 && github.event_name != 'pull_request' + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + repository: qualcomm/eld + ref: main + fetch-depth: 1 + + - name: Checkout eld PR branch + if: matrix.enabled == 1 && github.event_name == 'pull_request' + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 1 + + - name: Configure workflow environment variables + if: matrix.enabled == 1 + uses: ./.github/workflows/ConfigureBuildWorkflowENV + + - name: Record pre-build entry + if: github.event_name == 'schedule' && matrix.enabled == 1 + uses: ./.github/workflows/BuildStatusDataRecorder + with: + enabled: true + project: "llvm-project/llvm/tools/eld" + stage: "pre-" + workflow-name: "busybox" + record-mode: "record" + status: "fail" + run-id: ${{github.run_id}} + arch-name: "${{ matrix.arch }}" + branch-name: "${{env.BUILD_BRANCH}}" + + - name: Fetch latest nightly toolset + if: matrix.enabled == 1 + uses: ./.github/workflows/FetchNightlyToolset + + - name: Download clang-cross toolchain artifact + if: matrix.enabled == 1 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c #v8.0.1 + with: + name: clang-cross-${{ matrix.arch }} + path: clang-cross + + - name: Extract clang-cross toolchain + if: matrix.enabled == 1 + shell: bash + env: + TOOLCHAIN_DIR: ${{ matrix.toolchain_dir }} + run: | + set -euo pipefail + mkdir -p "${{ github.workspace }}/${TOOLCHAIN_DIR}" + tar -xf clang-cross/clang-cross-*.tar -C "${{ github.workspace }}/${TOOLCHAIN_DIR}" --strip-components=1 + + - name: Resolve toolchain paths + if: matrix.enabled == 1 + shell: bash + env: + TARGET_TRIPLE: ${{ matrix.target_triple }} + TOOLCHAIN_DIR: ${{ matrix.toolchain_dir }} + run: | + set -euo pipefail + toolchain_base="${{ github.workspace }}/${TOOLCHAIN_DIR}" + cross_root="$(find "${toolchain_base}" -type f -path "*/bin/${TARGET_TRIPLE}-clang" -print -quit | sed 's|/bin/.*$||')" + if [[ -z "${cross_root}" ]]; then + echo "Could not find ${TARGET_TRIPLE}-clang under ${toolchain_base}" >&2 + find "${toolchain_base}" -maxdepth 4 -type d -name bin -print >&2 || true + exit 1 + fi + eld_bin="$(command -v ld.eld || true)" + if [[ -z "${eld_bin}" ]]; then + echo "Could not find ld.eld in PATH after FetchNightlyToolset" >&2 + exit 1 + fi + echo "CROSS_TOOLCHAIN_ROOT=${cross_root}" >> "${GITHUB_ENV}" + echo "ELD_BIN=${eld_bin}" >> "${GITHUB_ENV}" + echo "${cross_root}/bin" >> "${GITHUB_PATH}" + echo "Using cross toolchain root: ${cross_root}" + echo "Using ld.eld: ${eld_bin}" + + - name: Clone BusyBox + if: matrix.enabled == 1 + shell: bash + run: | + git clone https://github.com/mirror/busybox.git + + - name: Build BusyBox with ELD + if: matrix.enabled == 1 + shell: bash + env: + CROSS_TOOLCHAIN_ROOT: ${{ env.CROSS_TOOLCHAIN_ROOT }} + TARGET_TRIPLE: ${{ matrix.target_triple }} + BUSYBOX_ARCH: ${{ matrix.busybox_arch }} + ELD_BIN: ${{ env.ELD_BIN }} + run: | + set -euo pipefail + command -v "${TARGET_TRIPLE}-clang" + command -v ld.eld + "${TARGET_TRIPLE}"-clang --version + "${ELD_BIN}" --version + + SYSROOT="${CROSS_TOOLCHAIN_ROOT}/${TARGET_TRIPLE}/sysroot" + MUSL_LINKER="$(find "${SYSROOT}/lib" -name 'ld-musl-*.so.1' | head -1)" + + cd busybox + make defconfig + + make -j"$(nproc)" \ + ARCH="${BUSYBOX_ARCH}" \ + CC="${TARGET_TRIPLE}-clang --ld-path=${ELD_BIN}" \ + HOSTCC=clang \ + STRIP="${TARGET_TRIPLE}-strip" \ + LDFLAGS="-Wl,-dynamic-linker,${MUSL_LINKER} -Wl,-rpath,${SYSROOT}/lib" + + - name: Run BusyBox tests + if: matrix.enabled == 1 + timeout-minutes: 5 + shell: bash + run: | + set -euo pipefail + cd busybox/testsuite + + # env --default-signal resets all signals (including SIGPIPE) to their + # default handlers before exec-ing the shell. This is necessary because + # the GitHub Actions runner sets SIGPIPE to SIG_IGN, which is inherited + # by all child processes and causes 'yes' in md5sum.tests to spin + # forever instead of dying when the pipe is closed by 'head'. + env SKIP_KNOWN_BUGS=1 SKIP_INTERNET_TESTS=1 env --default-signal /bin/sh ./runtest 2>&1 | tee /tmp/busybox-test-output.txt || true + + - name: Validate test results with FileCheck + if: matrix.enabled == 1 + shell: bash + run: | + FileCheck --input-file=/tmp/busybox-test-output.txt "${{ github.workspace }}/test/BusyBox/${{ matrix.arch }}/test-failures.txt" + + - name: Update build entry + if: github.event_name == 'schedule' && matrix.enabled == 1 + uses: ./.github/workflows/BuildStatusDataRecorder + with: + enabled: true + project: "llvm-project/llvm/tools/eld" + stage: "post-" + workflow-name: "busybox" + record-mode: "update" + status: "pass" + run-id: ${{github.run_id}} + arch-name: "${{ matrix.arch }}" + branch-name: "${{env.BUILD_BRANCH}}" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c8846ba9..f20c8319d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ on: - '.github/workflows/ci-win.yml' - '.github/workflows/clang-cross-download.yml' - '.github/workflows/clang-cross-schedule.yml' + - '.github/workflows/busybox-eld.yml' - '.github/workflows/nightly-musl-builder.yml' - '.github/workflows/picolibc-builder.yml' - '.github/workflows/nightly-test.yml' diff --git a/.github/workflows/clang-cross-download.yml b/.github/workflows/clang-cross-download.yml index 0133e7c2b..4fc49857b 100644 --- a/.github/workflows/clang-cross-download.yml +++ b/.github/workflows/clang-cross-download.yml @@ -17,20 +17,38 @@ on: description: "Comma-separated list of asset names to download" required: true type: string + upload_artifact: + description: "Upload extracted toolchains as a GitHub artifact" + required: false + type: boolean + default: false + artifact_name: + description: "Artifact name when upload_artifact is true" + required: false + type: string + default: "clang-cross-toolchains" + enabled: + description: "Set to false to skip this job entirely (used to disable matrix entries)" + required: false + type: boolean + default: true permissions: contents: write jobs: download: + if: ${{ inputs.enabled }} runs-on: ${{ inputs.runner }} steps: - name: Download and extract release assets + id: fetch shell: bash env: WORKSPACE: ${{ inputs.workspace }} ASSETS: ${{ inputs.assets }} run: | + set -euo pipefail api_url="https://api.github.com/repos/cross-tools/clang-cross/releases/latest" release_json="$(curl -fsSL "${api_url}")" tag="$(printf '%s' "${release_json}" | jq -r '.tag_name')" @@ -114,3 +132,15 @@ jobs: echo "Symlinks in ${WORKSPACE}:" find "${WORKSPACE}" -maxdepth 1 -type l -lname "${root_dir}/*" -printf "%p -> %l\n" + + artifact_tar="${RUNNER_TEMP}/clang-cross-${tag}.tar" + tar -cf "${artifact_tar}" -C "${base_dir}" . + echo "artifact_tar=${artifact_tar}" >> "${GITHUB_OUTPUT}" + + - name: Upload extracted toolchains artifact + if: ${{ inputs.upload_artifact }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + with: + name: ${{ inputs.artifact_name }} + retention-days: 1 + path: ${{ steps.fetch.outputs.artifact_tar }} diff --git a/.github/workflows/update-build-dashboard-data.yml b/.github/workflows/update-build-dashboard-data.yml index 3ef9f4cb4..835dd1740 100644 --- a/.github/workflows/update-build-dashboard-data.yml +++ b/.github/workflows/update-build-dashboard-data.yml @@ -42,6 +42,7 @@ jobs: python3 record_builds.py --workflow reverse_iterator --emit python3 record_builds.py --workflow release --emit python3 record_builds.py --workflow windows_nightly --emit + python3 record_builds.py --workflow busybox --emit rm -f record_builds.py build-status.db rm -rf ${DASH_DIR} cd .. diff --git a/test/BusyBox/x86_64/test-failures.txt b/test/BusyBox/x86_64/test-failures.txt new file mode 100644 index 000000000..007209bd6 --- /dev/null +++ b/test/BusyBox/x86_64/test-failures.txt @@ -0,0 +1,23 @@ +#BEGIN_COMMENT +# BusyBox's awk_sub() implements gsub() by repeatedly calling regexec() while +# advancing a pointer through the string. Correctly handling anchors like +# \< (word start) on each iteration requires REG_STARTEND, a BSD/glibc regex +# extension not present in POSIX. musl's regex.h defines no REG_STARTEND, so +# the build falls back to the code path busybox's own source comments already +# flag as buggy: it reruns regexec() on the advanced pointer, so the regex +# engine treats that mid-string position as a word start too, and \