diff --git a/.github/scripts/build-package.sh b/.github/scripts/build-package.sh index 73101d3..8774f88 100755 --- a/.github/scripts/build-package.sh +++ b/.github/scripts/build-package.sh @@ -9,15 +9,18 @@ PACKAGE_REPOSITORY=$1 CLEAN_BUILD=${CLEAN_BUILD:-0} INSTALL_PACKAGE=${INSTALL_PACKAGE:-0} NO_EXTRACT=${NO_EXTRACT:-0} +NO_CHECK=${NO_CHECK:-1} +NO_ARCHIVE=${NO_ARCHIVE:-0} ARGUMENTS="--syncdeps \ --rmdeps \ --noconfirm \ --noprogressbar \ - --nocheck \ --skippgpcheck \ --force \ $([ "$NO_EXTRACT" = 1 ] && echo "--noextract" || echo "") \ + $([ "$NO_CHECK" = 1 ] && echo "--nocheck " || echo "") \ + $([ "$NO_ARCHIVE" = 1 ] && echo "--noarchive" || echo "") \ $([ "$CLEAN_BUILD" = 1 ] && echo "--cleanbuild" || echo "") \ $([ "$INSTALL_PACKAGE" = 1 ] && echo "--install" || echo "")" diff --git a/.github/scripts/patch-dejagnu.sh b/.github/scripts/patch-dejagnu.sh new file mode 100755 index 0000000..acf858a --- /dev/null +++ b/.github/scripts/patch-dejagnu.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e # exit on error +set -x # echo on +set -o pipefail # fail of any command in pipeline is an error + +DIR="`dirname ${BASH_SOURCE[0]}`/../.." +DIR=`realpath $DIR` + +pushd / + echo "::group::Patch Dejagnu" + patch -p1 -b -i "$DIR/patches/dejagnu/0001-local-exec.patch" + echo "::endgroup::" +popd diff --git a/.github/workflows/build-and-test-mingw-w64-gcc.yml b/.github/workflows/build-and-test-mingw-w64-gcc.yml new file mode 100644 index 0000000..5d5bb95 --- /dev/null +++ b/.github/workflows/build-and-test-mingw-w64-gcc.yml @@ -0,0 +1,78 @@ +name: Build and test mingw-w64-gcc + +on: + pull_request: + workflow_dispatch: + inputs: + packages_repository: + description: "MSYS2 packages repository to build from" + type: string + default: "Windows-on-ARM-Experiments/MINGW-packages" + packages_branch: + description: "MSYS2 packages branch to build from" + type: string + default: "woarm64" + arch: + description: 'Architecture that should be built and tested' + required: false + default: 'x86_64' + tag: + description: 'Tag to use for the artifact' + required: true + gcc_module: + description: 'GCC module to test' + required: false + default: '' + gcc_test_filter: + description: 'GCC test filter' + required: false + default: '' + workflow_call: + inputs: + packages_repository: + type: string + packages_branch: + type: string + arch: + type: string + tag: + type: string + gcc_module: + type: string + gcc_test_filter: + type: string + +jobs: + build-and-test-mingw-w64-gcc: + name: Build and test mingw-w64-gcc + uses: ./.github/workflows/build-package.yml + with: + package_name: mingw-w64-gcc + packages_repository: ${{ inputs.packages_repository || 'Windows-on-ARM-Experiments/MINGW-packages' }} + packages_branch: ${{ inputs.packages_branch || 'woarm64' }} + runner_arch: ${{ inputs.arch || 'x86_64' }} + target_arch: ${{ inputs.arch || 'x86_64' }} + check: true + check_module: ${{ inputs.gcc_module || 'gcc-c' }} + check_filter: ${{ inputs.gcc_test_filter || 'compile.exp=103818.c' }} + + create-summary: + needs: build-and-test-mingw-w64-gcc + name: Create summary + runs-on: ubuntu-latest + + steps: + - name: Checkout mingw-woarm64-build repository + uses: actions/checkout@v4 + with: + repository: Windows-on-ARM-Experiments/mingw-woarm64-build + + - name: Download test results artifacts + uses: actions/download-artifact@v4 + with: + name: mingw-w64-gcc-test-results + path: ${{ github.workspace }}/test-results + + - name: Create summary + run: | + .github/scripts/toolchain/create-gcc-summary.sh ${{ github.workspace }}/test-results >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/build-package.yml b/.github/workflows/build-package.yml index ebf39a6..2aece03 100644 --- a/.github/workflows/build-package.yml +++ b/.github/workflows/build-package.yml @@ -6,6 +6,22 @@ on: package_name: description: "Package name to build" type: string + packages_repository: + description: "MSYS2 packages repository to build from" + type: string + default: "Windows-on-ARM-Experiments/MSYS2-packages" + packages_branch: + description: "MSYS2 packages branch to build from" + type: string + default: "woarm64" + runner_arch: + description: "Architecture to build on" + type: string + default: "x86_64" + target_arch: + description: "Architecture to build for" + type: string + default: "aarch64" needs: description: "Parent workflow job dependencies" type: string @@ -13,14 +29,18 @@ on: description: "Install additional dependencies" type: string default: "" - packages_repository: - description: "MSYS2 packages repository to build from" + check: + description: "Enable check step after the package is built" + type: boolean + default: false + check_module: + description: "Module to test" type: string - default: "Windows-on-ARM-Experiments/MSYS2-packages" - packages_branch: - description: "MSYS2 packages branch to build from" + default: "" + check_filter: + description: "Test filter" type: string - default: "woarm64" + default: "" defaults: run: @@ -29,14 +49,20 @@ defaults: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} CLEAN_BUILD: 1 + NO_CHECK: ${{ inputs.check && '0' || '1' }} + NO_ARCHIVE: ${{ inputs.check && '1' || '0' }} + MODULE: ${{ inputs.check_module }} + FILTER: ${{ inputs.check_filter }} jobs: build: name: Build ${{ inputs.package_name }} - runs-on: ${{ fromJson(contains(inputs.packages_repository, 'MINGW') && '["Windows", "ARM64", "Blackhex"]' || '["windows-latest"]') }} + runs-on: ${{ fromJson(inputs.runner_arch == 'aarch64' && '["Windows", "ARM64", "Blackhex"]' || '["windows-latest"]') }} + timeout-minutes: ${{ inputs.check && 720 || 180 }} steps: - name: Kill hanging processes + if: ${{ inputs.runner_arch == 'aarch64' }} shell: powershell run: | tasklist @@ -57,11 +83,13 @@ jobs: exit 0 - name: Fix Git long paths + if: ${{ inputs.runner_arch == 'aarch64' }} shell: powershell run: | git config --global core.longpaths true - name: Fix $PATH + if: ${{ inputs.runner_arch == 'aarch64' }} shell: powershell run: | Write-Output "GITHUB_PATH: $env:GITHUB_PATH" @@ -71,40 +99,54 @@ jobs: timeout-minutes: 10 with: msystem: ${{ contains(inputs.packages_repository, 'MINGW') && 'MINGW64' || 'MSYS' }} - update: false - cache: false + update: ${{ inputs.runner_arch == 'x86_64' }} + cache: ${{ inputs.runner_arch == 'x86_64' }} - name: Checkout repository uses: actions/checkout@v4 + - name: Checkout ${{ inputs.packages_repository }} repository + uses: actions/checkout@v4 + with: + repository: ${{ inputs.packages_repository }} + ref: ${{ inputs.packages_branch }} + sparse-checkout: ${{ inputs.package_name }} + path: ${{ github.workspace }}/packages + - name: Pacman hang workaround + if: ${{ inputs.runner_arch == 'aarch64' }} run: | `cygpath "${{ github.workspace }}"`/.github/scripts/pacman-workaround.sh - name: First MSYS2 update + if: ${{ inputs.runner_arch == 'aarch64' }} shell: powershell run: | msys2 -c 'pacman -Syuu --noconfirm' exit 0 - name: Second MSYS2 update + if: ${{ inputs.runner_arch == 'aarch64' }} shell: powershell run: | msys2 -c 'pacman -Syuu --noconfirm' - name: Setup packages repository + if: ${{ inputs.target_arch == 'aarch64' }} run: | `cygpath "${{ github.workspace }}"`/.github/scripts/setup-repository.sh - name: Install dependencies run: | + echo '${{ inputs.check }}' pacman -S --noconfirm \ git \ mingw-w64-x86_64-github-cli \ mingw-w64-x86_64-jq \ base-devel \ - ${{ contains(inputs.packages_repository, 'MINGW') && - 'mingw-w64-cross-gcc mingw-w64-cross-windows-default-manifest mingw-w64-x86_64-gcc-libs' || '' }} \ + ${{ contains(inputs.packages_repository, 'MINGW') && format('{0}-{1}-{2}', 'mingw-w64', inputs.target_arch, 'gcc') || '' }} \ + ${{ contains(inputs.packages_repository, 'MINGW') && (inputs.target_arch == 'aarch64') && 'mingw-w64-cross-windows-default-manifest mingw-w64-x86_64-gcc-libs' || '' }} \ + ${{ inputs.check && 'dejagnu' || '' }} \ ${{ inputs.dependencies }} - name: Download artifacts @@ -122,16 +164,13 @@ jobs: run: | `cygpath "${{ github.workspace }}"`/.github/scripts/pthread-headers-hack-before.sh - - name: Checkout ${{ inputs.packages_repository }} repository - uses: actions/checkout@v4 - with: - repository: ${{ inputs.packages_repository }} - ref: ${{ inputs.packages_branch }} - sparse-checkout: ${{ inputs.package_name }} - path: ${{ github.workspace }}/packages + - name: Patch Dejagnu + if: ${{ inputs.check }} + run: | + `cygpath "${{ github.workspace }}"`/.github/scripts/patch-dejagnu.sh - name: Setup cross-compilation environment - if: ${{ contains(inputs.packages_repository, 'MINGW') }} + if: ${{ inputs.target_arch == 'aarch64' }} run: | `cygpath "${{ github.workspace }}"`/.github/scripts/setup-cross-compilation.sh @@ -147,7 +186,7 @@ jobs: key: main-ccache-${{ steps.enable-ccache.outputs.timestamp }} restore-keys: main-ccache- - - name: Build ${{ inputs.package_name }} + - name: Build ${{ inputs.check && 'and test' || '' }} ${{ inputs.package_name }} working-directory: ${{ github.workspace }}/packages/${{ inputs.package_name }} run: | `cygpath "${{ github.workspace }}"`/.github/scripts/build-package.sh ${{ inputs.packages_repository }} @@ -160,12 +199,21 @@ jobs: key: main-ccache-${{ steps.enable-ccache.outputs.timestamp }} - name: Upload ${{ inputs.package_name }} + if: ${{ !inputs.check }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.package_name }} retention-days: 1 path: ${{ github.workspace }}/packages/${{ inputs.package_name }}/*.pkg.tar.zst + - name: Upload ${{ inputs.package_name }} test results + if: ${{ inputs.check }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.package_name }}-test-results + retention-days: 14 + path: ${{ github.workspace }}/packages/${{ inputs.package_name }}/src/test-results + - name: Upload build folder if: failure() uses: actions/upload-artifact@v4 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c468c92..e3f1d3c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,7 +4,6 @@ on: push: branches: - main - pull_request: workflow_dispatch: inputs: msys2_packages_branch: diff --git a/patches/dejagnu/0001-local-exec.patch b/patches/dejagnu/0001-local-exec.patch new file mode 100644 index 0000000..86d664b --- /dev/null +++ b/patches/dejagnu/0001-local-exec.patch @@ -0,0 +1,159 @@ +--- a/usr/share/dejagnu/remote.exp ++++ b/usr/share/dejagnu/remote.exp +@@ -164,14 +164,7 @@ + # ignore SIGHUP. + global errorInfo + if { $inp eq "" && $outp eq "" } { +- set id -1 +- set result [catch "eval spawn -ignore SIGHUP \{${commandline}\}" pid] +- if { $result == 0 } { +- set result2 0 +- } else { +- set pid 0 +- set result2 5 +- } ++ set status [catch "exec timeout -k 5 10 $commandline" output] + } else { + # Use a command pipeline with open. + if { $inp ne "" } { +@@ -205,78 +198,80 @@ + } + set pid [pid $id] + set result [catch "spawn -ignore SIGHUP -leaveopen $id" result2] +- } +- # Prepend "-" to each pid, to generate the "process group IDs" needed by +- # kill. +- set pgid "-[join $pid { -}]" +- verbose "pid is $pid $pgid" +- if { $result != 0 || $result2 != 0 } { +- # This shouldn't happen. +- if {[info exists errorInfo]} { +- set foo $errorInfo +- } else { +- set foo "" ++ ++ # Prepend "-" to each pid, to generate the "process group IDs" needed by ++ # kill. ++ set pgid "-[join $pid { -}]" ++ verbose "pid is $pid $pgid" ++ if { $result != 0 || $result2 != 0 } { ++ # This shouldn't happen. ++ if {[info exists errorInfo]} { ++ set foo $errorInfo ++ } else { ++ set foo "" ++ } ++ verbose "spawn -open $id failed, $result $result2, $foo" ++ catch "close $id" ++ return [list -1 "spawn failed"] + } +- verbose "spawn -open $id failed, $result $result2, $foo" +- catch "close $id" +- return [list -1 "spawn failed"] +- } + +- set got_eof 0 +- set output "" ++ set got_eof 0 ++ set output "" + +- # Wait for either $timeout seconds to elapse, or for the program to +- # exit. +- expect { +- -i $spawn_id -timeout $timeout -re ".+" { +- append output $expect_out(buffer) +- exp_continue -continue_timer +- } +- timeout { +- warning "program timed out" +- } +- eof { +- set got_eof 1 ++ # Wait for either $timeout seconds to elapse, or for the program to ++ # exit. ++ expect { ++ -i $spawn_id -timeout $timeout -re ".+" { ++ append output $expect_out(buffer) ++ exp_continue -continue_timer ++ } ++ timeout { ++ warning "program timed out" ++ } ++ eof { ++ set got_eof 1 ++ } + } +- } + +- # If we didn't get EOF, we have to kill the poor defenseless program. +- if { $got_eof } { +- set pid -1 +- } +- set r2 [close_wait_program $spawn_id $pid wres] +- if { $id > 0 } { +- if { $pid > 0 } { +- # If timed-out, don't wait for all the processes associated +- # with the pipeline to terminate as a stuck one would cause +- # us to hang. +- catch {fconfigure $id -blocking false} ++ # If we didn't get EOF, we have to kill the poor defenseless program. ++ if { $got_eof } { ++ set pid -1 + } +- set r2 [catch "close $id" res] +- } else { +- verbose "waitres is $wres" 2 +- if { $r2 == 0 } { +- set r2 [lindex $wres 3] +- if { [llength $wres] > 4 } { +- if { [lindex $wres 4] eq "CHILDKILLED" } { +- set r2 1 +- } ++ set r2 [close_wait_program $spawn_id $pid wres] ++ if { $id > 0 } { ++ if { $pid > 0 } { ++ # If timed-out, don't wait for all the processes associated ++ # with the pipeline to terminate as a stuck one would cause ++ # us to hang. ++ catch {fconfigure $id -blocking false} + } +- if { $r2 != 0 } { +- set res $wres ++ set r2 [catch "close $id" res] ++ } else { ++ verbose "waitres is $wres" 2 ++ if { $r2 == 0 } { ++ set r2 [lindex $wres 3] ++ if { [llength $wres] > 4 } { ++ if { [lindex $wres 4] eq "CHILDKILLED" } { ++ set r2 1 ++ } ++ } ++ if { $r2 != 0 } { ++ set res $wres ++ } else { ++ set res "" ++ } + } else { +- set res "" ++ set res "wait failed" + } ++ } ++ if { $r2 != 0 || $res ne "" || ! $got_eof } { ++ verbose "close result is $res" ++ set status 1 + } else { +- set res "wait failed" ++ set status 0 + } + } +- if { $r2 != 0 || $res ne "" || ! $got_eof } { +- verbose "close result is $res" +- set status 1 +- } else { +- set status 0 +- } ++ + verbose "output is $output status $status" + if { $outp eq "" || $outp eq "|& cat" } { + return [list $status $output]