diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0400e38e..5e9f5d70 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,11 +14,181 @@ on: paths-ignore: - '**.md' schedule: - - cron: '0 6 * * *' + - cron: '0 0 1 * *' jobs: test: - name: Test compiler + name: Test latest compiler versions + if: github.event_name != 'schedule' + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-22.04 + - ubuntu-20.04 + - macos-13 + - macos-12 + - macos-11 + - windows-2022 + - windows-2019 + toolchain: + - {compiler: gcc, version: 13} + - {compiler: intel, version: '2023.2'} + - {compiler: intel-classic, version: '2021.10'} + exclude: + # ifx not available for mac + - os: macos-13 + toolchain: {compiler: intel} + - os: macos-12 + toolchain: {compiler: intel} + - os: macos-11 + toolchain: {compiler: intel} + + steps: + + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Fortran + id: setup-fortran + uses: ./ + with: + compiler: ${{ matrix.toolchain.compiler }} + version: ${{ matrix.toolchain.version }} + + - name: Check compiler version + if: steps.setup-fortran.outcome == 'success' + shell: bash + env: + FC: ${{ steps.setup-fortran.outputs.fc }} + CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} + run: | + if ([ "$RUNNER_OS" == "Windows" ] && [[ "${{ matrix.toolchain.compiler }}" =~ "intel" ]]); then + # only last line of output captured by command substitution, write to temp file instead + ${{ env.FC }} //QV > "$RUNNER_TEMP/${{ env.FC }}.ver" 2>&1 + ${{ env.CC }} //QV > "$RUNNER_TEMP/${{ env.CC }}.ver" 2>&1 + ${{ env.CXX }} //QV > "$RUNNER_TEMP/${{ env.CXX }}.ver" 2>&1 + + fcv=$(cat "$RUNNER_TEMP/${{ env.FC }}.ver" | head -n 1) + ccv=$(cat "$RUNNER_TEMP/${{ env.CC }}.ver" | head -n 1) + cxxv=$(cat "$RUNNER_TEMP/${{ env.CXX }}.ver" | head -n 1) + + fcv=${fcv#*Version } + fcv=${fcv%% Build*} + ccv=${ccv#*Version } + ccv=${ccv%% Build*} + cxxv=${cxxv#*Version } + cxxv=${cxxv%% Build*} + else + fcv=$(${{ env.FC }} --version | head -n 1) + ccv=$(${{ env.CC }} --version | head -n 1) + cxxv=$(${{ env.CXX }} --version | head -n 1) + + fcv=$(echo "$fcv" | grep -woE '[0123456789.]+' | head -n 1) + ccv=$(echo "$ccv" | grep -woE '[0123456789.]+' | head -n 1) + cxxv=$(echo "$cxxv" | grep -woE '[0123456789.]+' | head -n 1) + fi + + [[ "$fcv" == ${{ matrix.toolchain.version }}* ]] && (echo "found ${{ env.FC }} version: $fcv") || (echo "unexpected ${{ env.FC }} version: $fcv"; exit 1) + [[ "$ccv" == ${{ matrix.toolchain.version }}* ]] && (echo "found ${{ env.CC }} version: $ccv") || (echo "unexpected ${{ env.CC }} version: $ccv"; exit 1) + [[ "$cxxv" == ${{ matrix.toolchain.version }}* ]] && (echo "found ${{ env.CXX }} version: $cxxv") || (echo "unexpected ${{ env.CXX }} version: $cxxv"; exit 1) + + - name: Test compile (bash) + if: steps.setup-fortran.outcome == 'success' + shell: bash + env: + FC: ${{ steps.setup-fortran.outputs.fc }} + CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} + run: | + # macos-13/gfortran 7-9 compatibility workaround + args="" + if [ "$RUNNER_OS" == "macOS" ]; then + if [[ $(sw_vers -productVersion) == 13* ]] && \ + [[ ${{ matrix.toolchain.compiler }} == "gcc" ]] && \ + [[ ${{ matrix.toolchain.version }} =~ ^(7|8|9)$ ]] + then + args="-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" + fi + fi + + ${{ env.FC }} $args -o hw hw.f90 + output=$(./hw '2>&1') + [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected Fortran program output: $output"; exit 1) + rm hw + + # gcc/g++ 7-9 broken on macos-13, skip tests + if [[ $args == "" ]]; then + ${{ env.CC }} -o hw hw.c + output=$(./hw '2>&1') + [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected C program output: $output"; exit 1) + rm hw + + ${{ env.CXX }} -o hw hw.cpp + output=$(./hw '2>&1') + [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected C++ program output: $output"; exit 1) + rm hw + fi + + - name: Test compile Fortran (pwsh) + if: ${{ steps.setup-fortran.outcome == 'success' && runner.os == 'Windows' }} + shell: pwsh + env: + FC: ${{ steps.setup-fortran.outputs.fc }} + CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} + run: | + ${{ env.FC }} -o hw.exe hw.f90 + $output=$(& ".\hw.exe") + if ($output -match "hello world") { + write-output $output + } else { + write-output "unexpected output: $output" + exit 1 + } + rm hw.exe + + - name: Test compile (powershell) + if: ${{ steps.setup-fortran.outcome == 'success' && runner.os == 'Windows' }} + shell: powershell + env: + FC: ${{ steps.setup-fortran.outputs.fc }} + CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} + run: | + ${{ env.FC }} -o hw.exe hw.f90 + $output=$(& ".\hw.exe") + if ($output -match "hello world") { + write-output $output + } else { + write-output "unexpected output: $output" + exit 1 + } + rm hw.exe + + - name: Test compile (cmd) + if: ${{ steps.setup-fortran.outcome == 'success' && runner.os == 'Windows' }} + shell: cmd + env: + FC: ${{ steps.setup-fortran.outputs.fc }} + CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} + run: | + ${{ env.FC }} -o hw.exe hw.f90 + for /f "tokens=* usebackq" %%f in (`.\hw.exe`) do @set "OUTPUT=%%f" + if "%OUTPUT%"=="hello world" ( + echo %OUTPUT% + ) else ( + echo unexpected output: %OUTPUT% + exit 1 + ) + del hw.exe + + full_test: + name: Full compatibility test + if: github.event_name == 'schedule' runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -40,64 +210,37 @@ jobs: - {compiler: gcc, version: 8} - {compiler: gcc, version: 7} - {compiler: gcc, version: 6} - include: - - {os: ubuntu-20.04, toolchain: {compiler: intel, version: '2023.2'}} - - {os: ubuntu-20.04, toolchain: {compiler: intel, version: '2022.2.1'}} - - {os: ubuntu-20.04, toolchain: {compiler: intel, version: '2021.4'}} - - - {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2023.2'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2023.1'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2023.0'}} - - {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2022.2.1'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2022.2'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2022.1'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2022.0'}} - - {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2021.4'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2021.3'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2021.2'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2021.1.2'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel, version: '2021.1'}} - - - {os: ubuntu-20.04, toolchain: {compiler: intel-classic, version: '2021.10'}} - - {os: ubuntu-20.04, toolchain: {compiler: intel-classic, version: '2021.7.1'}} - - {os: ubuntu-20.04, toolchain: {compiler: intel-classic, version: '2021.4'}} - - - {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.10'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.9'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.8'}} - - {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.7.1'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.7'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.6'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.5'}} - - {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.4'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.3'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.2'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.1.2'}} - # {os: ubuntu-22.04, toolchain: {compiler: intel-classic, version: '2021.1'}} - - - {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.10'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.9'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.8'}} - - {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.7.1'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.7'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.6'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.5'}} - - {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.4'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.3'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.2'}} - # {os: macos-12, toolchain: {compiler: intel-classic, version: '2021.1'}} - - - {os: windows-2022, toolchain: {compiler: intel, version: '2023.2.0'}} - - {os: windows-2022, toolchain: {compiler: intel, version: '2023.1.0'}} - - {os: windows-2022, toolchain: {compiler: intel, version: '2023.0.0'}} - - {os: windows-2022, toolchain: {compiler: intel, version: '2022.2.0'}} - - {os: windows-2022, toolchain: {compiler: intel, version: '2022.1.0'}} - - - {os: windows-2022, toolchain: {compiler: intel-classic, version: '2021.10.0'}} - - {os: windows-2022, toolchain: {compiler: intel-classic, version: '2021.9.0'}} - - {os: windows-2022, toolchain: {compiler: intel-classic, version: '2021.8.0'}} - - {os: windows-2022, toolchain: {compiler: intel-classic, version: '2021.7.0'}} - - {os: windows-2022, toolchain: {compiler: intel-classic, version: '2021.6.0'}} + - {compiler: intel, version: '2023.2'} + - {compiler: intel, version: '2023.1'} + - {compiler: intel, version: '2023.0'} + - {compiler: intel, version: '2022.2.1'} + - {compiler: intel, version: '2022.2'} + - {compiler: intel, version: '2022.1'} + - {compiler: intel, version: '2022.0'} + - {compiler: intel, version: '2021.4'} + - {compiler: intel, version: '2021.2'} + - {compiler: intel, version: '2021.1.2'} + - {compiler: intel, version: '2021.1'} + - {compiler: intel-classic, version: '2021.10'} + - {compiler: intel-classic, version: '2021.9'} + - {compiler: intel-classic, version: '2021.8'} + - {compiler: intel-classic, version: '2021.7.1'} + - {compiler: intel-classic, version: '2021.7'} + - {compiler: intel-classic, version: '2021.6'} + - {compiler: intel-classic, version: '2021.5'} + - {compiler: intel-classic, version: '2021.4'} + - {compiler: intel-classic, version: '2021.3'} + - {compiler: intel-classic, version: '2021.2'} + - {compiler: intel-classic, version: '2021.1.2'} + - {compiler: intel-classic, version: '2021.1'} + exclude: + # ifx not available for mac + - os: macos-13 + toolchain: {compiler: intel} + - os: macos-12 + toolchain: {compiler: intel} + - os: macos-11 + toolchain: {compiler: intel} steps: @@ -105,7 +248,7 @@ jobs: uses: actions/checkout@v3 - name: Setup Fortran - continue-on-error: ${{ matrix.toolchain.compiler == 'gcc' }} + continue-on-error: true id: setup-fortran uses: ./ with: @@ -118,38 +261,47 @@ jobs: env: FC: ${{ steps.setup-fortran.outputs.fc }} CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} run: | if ([ "$RUNNER_OS" == "Windows" ] && [[ "${{ matrix.toolchain.compiler }}" =~ "intel" ]]); then # only last line of output captured by command substitution, write to temp file instead ${{ env.FC }} //QV > "$RUNNER_TEMP/${{ env.FC }}.ver" 2>&1 ${{ env.CC }} //QV > "$RUNNER_TEMP/${{ env.CC }}.ver" 2>&1 + ${{ env.CXX }} //QV > "$RUNNER_TEMP/${{ env.CXX }}.ver" 2>&1 fcv=$(cat "$RUNNER_TEMP/${{ env.FC }}.ver" | head -n 1) ccv=$(cat "$RUNNER_TEMP/${{ env.CC }}.ver" | head -n 1) + cxxv=$(cat "$RUNNER_TEMP/${{ env.CXX }}.ver" | head -n 1) fcv=${fcv#*Version } fcv=${fcv%% Build*} ccv=${ccv#*Version } ccv=${ccv%% Build*} + cxxv=${cxxv#*Version } + cxxv=${cxxv%% Build*} else fcv=$(${{ env.FC }} --version | head -n 1) ccv=$(${{ env.CC }} --version | head -n 1) + cxxv=$(${{ env.CXX }} --version | head -n 1) fcv=$(echo "$fcv" | grep -woE '[0123456789.]+' | head -n 1) ccv=$(echo "$ccv" | grep -woE '[0123456789.]+' | head -n 1) + cxxv=$(echo "$cxxv" | grep -woE '[0123456789.]+' | head -n 1) fi [[ "$fcv" == ${{ matrix.toolchain.version }}* ]] && (echo "found ${{ env.FC }} version: $fcv") || (echo "unexpected ${{ env.FC }} version: $fcv"; exit 1) [[ "$ccv" == ${{ matrix.toolchain.version }}* ]] && (echo "found ${{ env.CC }} version: $ccv") || (echo "unexpected ${{ env.CC }} version: $ccv"; exit 1) + [[ "$cxxv" == ${{ matrix.toolchain.version }}* ]] && (echo "found ${{ env.CXX }} version: $cxxv") || (echo "unexpected ${{ env.CXX }} version: $cxxv"; exit 1) - - name: Test compile program (bash) + - name: Test compile (bash) if: steps.setup-fortran.outcome == 'success' shell: bash env: FC: ${{ steps.setup-fortran.outputs.fc }} CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} run: | - # macos-13 / gcc 7-9 compatibility workaround + # macos-13/gfortran 7-9 compatibility workaround args="" if [ "$RUNNER_OS" == "macOS" ]; then if [[ $(sw_vers -productVersion) == 13* ]] && \ @@ -159,20 +311,33 @@ jobs: args="-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" fi fi - args="$args -o hw hw.f90" - ${{ env.FC }} $args + ${{ env.FC }} $args -o hw hw.f90 output=$(./hw '2>&1') - [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected output: $output"; exit 1) + [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected Fortran program output: $output"; exit 1) + rm hw + + # gcc/g++ 7-9 broken on macos-13, skip tests + if [[ $args == "" ]]; then + ${{ env.CC }} -o hw hw.c + output=$(./hw '2>&1') + [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected C program output: $output"; exit 1) + rm hw + + ${{ env.CXX }} -o hw hw.cpp + output=$(./hw '2>&1') + [[ "$output" == *"hello world"* ]] && echo "$output" || (echo "Unexpected C++ program output: $output"; exit 1) + rm hw + fi - - name: Test compile program (Powershell Core) + - name: Test compile Fortran (pwsh) if: ${{ steps.setup-fortran.outcome == 'success' && runner.os == 'Windows' }} shell: pwsh env: FC: ${{ steps.setup-fortran.outputs.fc }} CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} run: | - rm hw.exe ${{ env.FC }} -o hw.exe hw.f90 $output=$(& ".\hw.exe") if ($output -match "hello world") { @@ -181,15 +346,16 @@ jobs: write-output "unexpected output: $output" exit 1 } - - - name: Test compile program (Powershell Desktop) + rm hw.exe + + - name: Test compile (powershell) if: ${{ steps.setup-fortran.outcome == 'success' && runner.os == 'Windows' }} shell: powershell env: FC: ${{ steps.setup-fortran.outputs.fc }} CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} run: | - rm hw.exe ${{ env.FC }} -o hw.exe hw.f90 $output=$(& ".\hw.exe") if ($output -match "hello world") { @@ -198,15 +364,16 @@ jobs: write-output "unexpected output: $output" exit 1 } + rm hw.exe - - name: Test compile program (cmd) + - name: Test compile (cmd) if: ${{ steps.setup-fortran.outcome == 'success' && runner.os == 'Windows' }} shell: cmd env: FC: ${{ steps.setup-fortran.outputs.fc }} CC: ${{ steps.setup-fortran.outputs.cc }} + CXX: ${{ steps.setup-fortran.outputs.cxx }} run: | - del hw.exe ${{ env.FC }} -o hw.exe hw.f90 for /f "tokens=* usebackq" %%f in (`.\hw.exe`) do @set "OUTPUT=%%f" if "%OUTPUT%"=="hello world" ( @@ -215,6 +382,7 @@ jobs: echo unexpected output: %OUTPUT% exit 1 ) + del hw.exe - name: Create compatibility report shell: bash @@ -230,7 +398,6 @@ jobs: echo "$prefix,$support" >> "compat/${prefix//,/_}.csv" - name: Upload compatibility report - if: ${{ matrix.toolchain.compiler == 'gcc' }} uses: actions/upload-artifact@v3 with: name: compat @@ -238,7 +405,8 @@ jobs: compat: name: Report compatibility - needs: test + if: github.event_name == 'schedule' + needs: full_test runs-on: ubuntu-latest permissions: contents: write @@ -254,8 +422,7 @@ jobs: python-version: 3.9 - name: Install packages - run: | - pip install tabulate pandas + run: pip install tabulate pandas - name: Download reports uses: actions/download-artifact@v3 @@ -265,20 +432,11 @@ jobs: - name: Concatenate reports run: | - echo "runner,compiler,version,support" > compat_long.csv - cat compat/*.csv >> compat_long.csv + echo "runner,compiler,version,support" > long_compat.csv + cat compat/*.csv >> long_compat.csv - name: Make wide CSV and MD table - id: merge-reports - shell: python - run: | - import pandas as pd - df = pd.read_csv("compat_long.csv") - df = pd.pivot(df, index="runner", columns="version", values="support") - df = df.sort_values(by=["runner"]) - df.to_csv("compat.csv") - with open("compat.md", "w") as file: - file.write(df.to_markdown().replace("nan", "")) + run: python wide_compat_reports.py "long_compat.csv" "compat.csv" - name: Upload artifacts uses: actions/upload-artifact@v3 @@ -308,22 +466,11 @@ jobs: - name: Update README if: ${{ steps.diff.outputs.diff == 'true' && github.event_name == 'push' }} - shell: python - run: | - import re - from pathlib import Path - readme_path = Path("README.md") - readme = readme_path.open().read() - with open("compat.md", "r") as compat: - table = ''.join(compat.readlines()) - r = re.compile(r'.*', re.DOTALL) - chunk = '{}'.format('\n{}\n'.format(table)) - readme_path.open('w').write(r.sub(chunk, readme)) + run: python update_compat_table.py "compat.md" "README.md" - name: Print README diff if: ${{ steps.diff.outputs.diff == 'true' && github.event_name == 'push' }} - run: | - git diff README.md + run: git diff README.md - name: Create pull request if: ${{ steps.diff.outputs.diff == 'true' && github.event_name == 'push' }} diff --git a/README.md b/README.md index 3d180cb4..3a3fb4de 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Action to setup a Fortran compiler. This action sets up a Fortran compiler on Ubuntu, MacOS and Windows runners. +C/C++ compilers of the same toolchain/version are provided where possible, otherwise (if a standalone Fortran compiler is selected) defaulting to the preinstalled GCC. + ```yaml jobs: test: @@ -65,56 +67,45 @@ jobs: - *version*: Version of the compiler toolchain. See [runner compatibility](#runner-compatibility) charts below. - ## Outputs The action sets the following outputs: -- `cc`: C compiler executable, e.g. `gcc` - `fc`: Fortran compiler executable, e.g. `gfortran` +- `cc`: C compiler executable, e.g. `gcc` +- `cxx`: C++ compiler executable, e.g. `g++` ## Environment variables The same values are also set as environment variables: -- `CC` - `FC` +- `CC` +- `CXX` These are made available to subsequent workflow steps via the [`GITHUB_ENV` environment file mechanism](https://docs.github.com/en/actions/learn-github-actions/environment-variables#passing-values-between-steps-and-jobs-in-a-workflow). ## Runner compatibility -Support for the GCC toolchain varies across GitHub-hosted runner images. +Toolchain support varies across GitHub-hosted runner images. -| runner | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -|:-------------|:--------|:--------|:--------|:--------|:--------|:--------|:--------|:--------| -| macos-11 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| macos-12 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| macos-13 | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| ubuntu-20.04 | | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | -| ubuntu-22.04 | | | | ✓ | ✓ | ✓ | ✓ | ✓ | -| windows-2019 | | | ✓ | ✓ | ✓ | ✓ | ✓ | | -| windows-2022 | | | ✓ | ✓ | ✓ | ✓ | ✓ | | +| runner | gcc 10 | gcc 11 | gcc 12 | gcc 13 | gcc 6 | gcc 7 | gcc 8 | gcc 9 | intel-classic 2021.1.2 | intel-classic 2021.1 | intel-classic 2021.10 | intel-classic 2021.2 | intel-classic 2021.3 | intel-classic 2021.4 | intel-classic 2021.5 | intel-classic 2021.6 | intel-classic 2021.7.1 | intel-classic 2021.7 | intel-classic 2021.8 | intel-classic 2021.9 | intel 2021.1.2 | intel 2021.1 | intel 2021.2 | intel 2021.4 | intel 2022.0 | intel 2022.1 | intel 2022.2.1 | intel 2022.2 | intel 2023.0 | intel 2023.1 | intel 2023.2 | +|:-------------|:----------------|:----------------|:----------------|:----------------|:---------------|:---------------|:---------------|:---------------|:--------------------------------|:------------------------------|:-------------------------------|:------------------------------|:------------------------------|:------------------------------|:------------------------------|:------------------------------|:--------------------------------|:------------------------------|:------------------------------|:------------------------------|:------------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:------------------------|:----------------------|:----------------------|:----------------------|:----------------------| +| macos-11 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | | | | | | | | | | | +| macos-12 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | | | | | | | | | | | +| macos-13 | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | | | | | | | | | | | +| ubuntu-20.04 | ✓ | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| ubuntu-22.04 | ✓ | ✓ | ✓ | ✓ | | | | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| windows-2019 | ✓ | ✓ | ✓ | ✓ | | | ✓ | ✓ | | | ✓ | | | | | ✓ | | ✓ | ✓ | ✓ | | | | | | ✓ | | ✓ | ✓ | ✓ | ✓ | +| windows-2022 | ✓ | ✓ | ✓ | ✓ | | | ✓ | ✓ | | | ✓ | | | | | ✓ | | ✓ | ✓ | ✓ | | | | | | ✓ | | ✓ | ✓ | ✓ | ✓ | -**Note:** version 13 of the GNU toolchain is not yet available on Windows. - -**Note:** on `macos-13`, gcc 7-9 require flag `-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib`. - -Supported Intel toolchains: - -| runner | compiler | version | -| :-------- | :------------- | :------ | -| ubuntu-\* | intel | 2023.2, 2023.1, 2023.0,
2022.2.1, 2022.2, 2022.1, 2022.0,
2021.4, 2021.2, 2021.1.2, 2021.1 | -| ubuntu-\* | intel-classic | 2021.10, 2021.9, 2021.8,
2021.7.1, 2021.7, 2021.6, 2021.5,
2021.4, 2021.3, 2021.2, 2021.1.2, 2021.1 | -| macos-\* | intel-classic | 2021.10, 2021.9, 2021.8,
2021.7.1, 2021.7, 2021.6, 2021.5,
2021.4, 2021.3, 2021.2, 2021.1 | -| windows-\* | intel | 2023.2, 2023.1, 2023.0, 2022.2.0, 2022.1.0 | -| windows-\* | intel-classic | 2021.10.0, 2021.9.0, 2021.8.0, 2021.7.0, 2021.6.0 | +**Note:** on `macos-13`, `gfortran` 7-9 require flag `-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib`. -**Note:** on macOS `ifx` is not supported, so the `intel` option redirects to `intel-classic` (`ifort`). +**Note:** Intel's `ifx` compiler is not supported on macOS, so the `intel` option redirects to `intel-classic` (`ifort`). ## License diff --git a/action.yml b/action.yml index d7be569e..30630f57 100644 --- a/action.yml +++ b/action.yml @@ -2,11 +2,11 @@ name: "Setup Fortran" description: "Setup Fortran compiler and toolchain" inputs: compiler: - description: "Compiler toolchain" + description: "Toolchain or compiler to install" required: true default: "gcc" version: - description: "Version of compiler toolchain" + description: "Version of toolchain or compiler" required: false outputs: fc: @@ -15,28 +15,30 @@ outputs: cc: description: "Path to C compiler" value: ${{ steps.outputs.outputs.cc }} + cxx: + description: "Path to C++ compiler" + value: ${{ steps.outputs.outputs.cxx }} runs: using: "composite" steps: - + # On Windows runners the Intel toolchain is very slow to install, + # setup caching with daily key rotation. Steps are also needed to + # activate the oneAPI environment. - name: Set oneAPI install dir id: oneapi-root if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') shell: bash run: echo "ONEAPI_ROOT=C:\Program Files (x86)\Intel\oneAPI" >> "$GITHUB_ENV" - # GNU tar can't handle symlinks on Windows, hide it so default Windows tar is used to restore cache - name: Hide GNU tar if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') shell: bash run: mv "C:\Program Files\Git\usr\bin\tar.exe" "$RUNNER_TEMP\tar.exe" - - - name: Get Date + - name: Get date if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') id: get-date shell: bash run: echo "date=$(/bin/date -u "+%Y%m%d")" >> "$GITHUB_OUTPUT" - - name: Restore cache if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') id: cache @@ -44,12 +46,12 @@ runs: with: path: ${{ env.ONEAPI_ROOT }} key: ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.version }}-${{ steps.get-date.outputs.date }} - - name: Restore GNU tar if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') shell: bash run: mv "$RUNNER_TEMP\tar.exe" 'C:\Program Files\Git\usr\bin\tar.exe' + # Set up the selected toolchain or compiler - name: Setup toolchain id: setup if: steps.cache.outputs.cache-hit != 'true' @@ -66,7 +68,7 @@ runs: case $compiler in gcc) - version=${VERSION:-11} + version=${VERSION:-13} install_gcc $platform ;; intel-classic) @@ -82,62 +84,66 @@ runs: ;; esac - if ! ([ "$RUNNER_OS" == "Windows" ] && [[ "${{ inputs.compiler }}" =~ "intel" ]]); then - which "${FC}" - which "${CC}" - - # persist environment variables + if ! ([[ "$RUNNER_OS" == "Windows" ]] && [[ "${{ inputs.compiler }}" =~ "intel" ]]); then + # save environment variables echo "FC=${FC}" >> $GITHUB_ENV echo "CC=${CC}" >> $GITHUB_ENV + echo "CXX=${CXX}" >> $GITHUB_ENV fi + # save oneAPI cache and activate environment - name: Save cache if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') && steps.cache.outputs.cache-hit != 'true' uses: actions/cache/save@v3 with: path: ${{ env.ONEAPI_ROOT }} key: ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.version }}-${{ steps.get-date.outputs.date }} - - name: Activate oneAPI if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') shell: cmd run: | + ver | findstr /i "10\.0\.17" && set VS2019INSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise + ver | findstr /i "10\.0\.20" && set VS2022INSTALLDIR=C:\Program Files\Microsoft Visual Studio\2022\Enterprise for /f "tokens=* usebackq" %%f in (`dir /b "%ONEAPI_ROOT%\compiler\" ^| findstr /V latest ^| sort`) do @set "LATEST=%%f" :: this script fails when install location is not the default call "%ONEAPI_ROOT%\compiler\%LATEST%\env\vars.bat" set | findstr /c:"oneAPI" >> "%GITHUB_ENV%" - + # Intel compilers may have restored from cache so env vars may not be set, + # set them then set outputs for all compilers/toolchains - name: Set outputs and env vars shell: bash id: outputs run: | - if [ "$RUNNER_OS" == "Windows" ]; then + if [[ "$RUNNER_OS" == "Windows" ]]; then if [[ "${{ inputs.compiler }}" == "intel" ]]; then echo fc=ifx>>$GITHUB_OUTPUT echo cc=icx>>$GITHUB_OUTPUT + echo cxx=icx>>$GITHUB_OUTPUT echo FC=ifx>>$GITHUB_ENV echo CC=icx>>$GITHUB_ENV echo CXX=icx>>$GITHUB_ENV elif [[ "${{ inputs.compiler }}" == "intel-classic" ]]; then echo fc=ifort>>$GITHUB_OUTPUT echo cc=icl>>$GITHUB_OUTPUT + echo cxx=icl>>$GITHUB_OUTPUT echo FC=ifort>>$GITHUB_ENV echo CC=icl>>$GITHUB_ENV echo CXX=icl>>$GITHUB_ENV else echo fc=$FC>>$GITHUB_OUTPUT echo cc=$CC>>$GITHUB_OUTPUT + echo cxx=$CXX>>$GITHUB_OUTPUT fi else echo fc=$FC>>$GITHUB_OUTPUT echo cc=$CC>>$GITHUB_OUTPUT + echo cxx=$CXX>>$GITHUB_OUTPUT fi # intel oneapi flag to indicate env has been activated if [[ "${{ inputs.compiler }}" =~ "intel" ]]; then echo SETVARS_COMPLETED=1>>$GITHUB_ENV fi - # GitHub Actions prepends GNU linker to the PATH before all bash steps, hide it so MSVC linker is found - name: Hide GNU linker (Windows) if: runner.os == 'Windows' && contains(inputs.compiler, 'intel') diff --git a/compat.csv b/compat.csv index c3b19ca3..dfe9d31e 100644 --- a/compat.csv +++ b/compat.csv @@ -1,8 +1,10 @@ -runner,6,7,8,9,10,11,12,13 -macos-11,✓,✓,✓,✓,✓,✓,✓,✓ -macos-12,✓,✓,✓,✓,✓,✓,✓,✓ -macos-13,,✓,✓,✓,✓,✓,✓,✓ -ubuntu-20.04,,✓,✓,✓,✓,✓,,✓ -ubuntu-22.04,,,,✓,✓,✓,✓,✓ -windows-2019,,,✓,✓,✓,✓,✓, -windows-2022,,,✓,✓,✓,✓,✓, +compiler,gcc,gcc,gcc,gcc,gcc,gcc,gcc,gcc,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel-classic,intel,intel,intel,intel,intel,intel,intel,intel,intel,intel,intel +version,10,11,12,13,6,7,8,9,2021.1.2,2021.1,2021.10,2021.2,2021.3,2021.4,2021.5,2021.6,2021.7.1,2021.7,2021.8,2021.9,2021.1.2,2021.1,2021.2,2021.4,2022.0,2022.1,2022.2.1,2022.2,2023.0,2023.1,2023.2 +runner,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +macos-11,✓,✓,✓,✓,✓,✓,✓,✓,,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,,,,,,,,,,, +macos-12,✓,✓,✓,✓,✓,✓,✓,✓,,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,,,,,,,,,,, +macos-13,✓,✓,✓,✓,,✓,✓,✓,,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,,,,,,,,,,, +ubuntu-20.04,✓,✓,,✓,,✓,✓,✓,✓,✓,✓,✓,,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓ +ubuntu-22.04,✓,✓,✓,✓,,,,✓,✓,✓,✓,✓,,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓,✓ +windows-2019,✓,✓,✓,✓,,,✓,✓,,,✓,,,,,✓,,✓,✓,✓,,,,,,✓,,✓,✓,✓,✓ +windows-2022,✓,✓,✓,✓,,,✓,✓,,,✓,,,,,✓,,✓,✓,✓,,,,,,✓,,✓,✓,✓,✓ diff --git a/hw.c b/hw.c new file mode 100644 index 00000000..36bc20cc --- /dev/null +++ b/hw.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("hello world\n"); + return 0; +} diff --git a/hw.cpp b/hw.cpp new file mode 100644 index 00000000..2f36fe32 --- /dev/null +++ b/hw.cpp @@ -0,0 +1,6 @@ +#include + +int main() { + std::cout << "hello world\n"; + return 0; +} diff --git a/setup-fortran.sh b/setup-fortran.sh index 67b5976b..5fc4ff85 100755 --- a/setup-fortran.sh +++ b/setup-fortran.sh @@ -45,11 +45,12 @@ install_gcc_apt() { sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test sudo apt-get update - sudo apt-get install -y gcc-${version} gfortran-${version} + sudo apt-get install -y gcc-${version} gfortran-${version} g++-${version} sudo update-alternatives \ --install /usr/bin/gcc gcc /usr/bin/gcc-${version} 100 \ --slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${version} \ - --slave /usr/bin/gcov gcov /usr/bin/gcov-${version} + --slave /usr/bin/gcov gcov /usr/bin/gcov-${version} \ + --slave /usr/bin/g++ g++ /usr/bin/g++-${version} export FC="gfortran" export CC="gcc" @@ -59,6 +60,15 @@ install_gcc_apt() install_gcc_choco() { case $version in + 13) + choco install mingw --version 13.2.0 --force + # mingw 13 on Windows doesn't create shims (http://disq.us/p/2w5c5tj) + # so hide Strawberry compilers and manually add mingw bin dir to PATH + mv /c/Strawberry/c/bin/gfortran "$RUNNER_TEMP/gfortran" + mv /c/Strawberry/c/bin/gcc "$RUNNER_TEMP/gcc" + mv /c/Strawberry/c/bin/g++ "$RUNNER_TEMP/g++" + echo "C:\ProgramData\mingw64\mingw64\bin" >> $GITHUB_PATH + ;; 12) choco install mingw --version 12.2.0 --force ;; @@ -75,7 +85,7 @@ install_gcc_choco() choco install mingw --version 8.5.0 --force ;; *) - echo "Unsupported version: $version (choose 8-12)" + echo "Unsupported version: $version (choose 8-13)" exit 1 ;; esac diff --git a/update_compat_table.py b/update_compat_table.py new file mode 100644 index 00000000..a5501e18 --- /dev/null +++ b/update_compat_table.py @@ -0,0 +1,24 @@ +""" +Inserts Markdown compatibility tables +between tags in target Markdown file. +""" + +import re +import sys +from pathlib import Path + +compat_path = Path(sys.argv[1]) # path to Markdown table +update_path = Path(sys.argv[2]) # path to file to update + +assert compat_path.is_file() +assert update_path.is_file() + +with open(compat_path, "r") as compat: + table = "".join(compat.readlines()) + r = re.compile( + r".*", + re.DOTALL, + ) + ct = '{}'.format('\n{}\n'.format(table)) + readme = update_path.open().read() + update_path.open("w").write(r.sub(ct, readme)) diff --git a/wide_compat_reports.py b/wide_compat_reports.py new file mode 100644 index 00000000..1715fac9 --- /dev/null +++ b/wide_compat_reports.py @@ -0,0 +1,40 @@ +""" +Converts compatibility reports from long to wide format +and makes a Markdown table from the wide format report. +""" + +from pathlib import Path +import pandas as pd +import sys + +ip = Path(sys.argv[1]) # input file path +op = Path(sys.argv[2]) # output file path +assert ip.is_file() +assert ip.suffix == ".csv" +assert op.suffix == ".csv" + +# read long CSV +df = pd.read_csv(ip) + +# pivot and sort +df = pd.pivot_table( + df, + index="runner", + columns=["compiler", "version"], + values="support", + sort=False +).sort_values(by=["runner"]) + +# write wide CSV +df.to_csv(op) + +# write wide markdown table +with open(op.with_suffix(".md"), "w") as file: + file.write( + df.to_markdown() + .replace("nan", "") + .replace("(", "") + .replace(")", "") + .replace(",", "") + .replace("'", "") + )