From 6c255e5b7a99b598e59462642557d82c9eb3f4f5 Mon Sep 17 00:00:00 2001 From: w-bonelli Date: Tue, 25 Jul 2023 03:06:30 -0400 Subject: [PATCH] feat: support Intel on Windows (#27) --- .github/workflows/test.yml | 47 ++++++++++++---- README.md | 2 + action.yml | 109 ++++++++++++++++++++++++++++++++----- install-intel-windows.bat | 9 +++ setup-fortran.sh | 104 +++++++++++++++++++++++++++++++++++ 5 files changed, 245 insertions(+), 26 deletions(-) create mode 100644 install-intel-windows.bat diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 71cbcbb3..e2ecef8c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,6 +76,18 @@ jobs: # {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'}} + steps: - name: Checkout repository @@ -90,26 +102,37 @@ jobs: version: ${{ matrix.toolchain.version }} - name: Check compiler version - if: ${{ steps.setup-fortran.outcome == 'success' }} + if: steps.setup-fortran.outcome == 'success' shell: bash env: FC: ${{ steps.setup-fortran.outputs.fc }} CC: ${{ steps.setup-fortran.outputs.cc }} run: | - fcv=$(${{ env.FC }} --version | head -n 1) - ccv=$(${{ env.CC }} --version | head -n 1) - - echo $fcv - echo $ccv - - fcv=$(echo "$fcv" | grep -woE '[0123456789.]+' | head -n 1) - ccv=$(echo "$ccv" | grep -woE '[0123456789.]+' | head -n 1) + 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 + + fcv=$(cat "$RUNNER_TEMP/${{ env.FC }}.ver" | head -n 1) + ccv=$(cat "$RUNNER_TEMP/${{ env.CC }}.ver" | head -n 1) + + fcv=${fcv#*Version } + fcv=${fcv%% Build*} + ccv=${ccv#*Version } + ccv=${ccv%% Build*} + else + fcv=$(${{ env.FC }} --version | head -n 1) + ccv=$(${{ env.CC }} --version | head -n 1) + + fcv=$(echo "$fcv" | grep -woE '[0123456789.]+' | head -n 1) + ccv=$(echo "$ccv" | grep -woE '[0123456789.]+' | head -n 1) + fi - [[ $fcv == ${{ matrix.toolchain.version }}* ]] || (echo "unexpected Fortran compiler version: $fcv"; exit 1) - [[ $ccv == ${{ matrix.toolchain.version }}* ]] || (echo "unexpected C compiler version: $ccv"; exit 1) + [[ "$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) - name: Test compile program (bash) - if: ${{ steps.setup-fortran.outcome == 'success' }} + if: steps.setup-fortran.outcome == 'success' shell: bash env: FC: ${{ steps.setup-fortran.outputs.fc }} diff --git a/README.md b/README.md index c6f056aa..5388230c 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,8 @@ Supported Intel toolchains: | ubuntu-\* | intel | 2023.2, 2023.1, 2023.0,
2022.2.1, 2022.2, 2022.1, 2022.0,
2021.4, 2021.3, 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 | ## License diff --git a/action.yml b/action.yml index 829d0126..b6fc225f 100644 --- a/action.yml +++ b/action.yml @@ -11,15 +11,48 @@ inputs: outputs: fc: description: "Path to Fortran compiler" - value: ${{ steps.setup.outputs.fc }} + value: ${{ steps.outputs.outputs.fc }} cc: description: "Path to C compiler" - value: ${{ steps.setup.outputs.cc }} + value: ${{ steps.outputs.outputs.cc }} runs: using: "composite" steps: - - id: setup - name: Setup toolchain + + - 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 + 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 + uses: actions/cache/restore@v3 + 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' + + - name: Setup toolchain + id: setup + if: steps.cache.outputs.cache-hit != 'true' shell: bash env: COMPILER: ${{ inputs.compiler }} @@ -49,13 +82,61 @@ runs: ;; esac - which "${FC}" - which "${CC}" - - # set outputs - echo "fc=${FC}" >> $GITHUB_OUTPUT - echo "cc=${CC}" >> $GITHUB_OUTPUT - - # persist environment variables - echo "FC=${FC}" >> $GITHUB_ENV - echo "CC=${CC}" >> $GITHUB_ENV + if ! ([ "$RUNNER_OS" == "Windows" ] && [[ "${{ inputs.compiler }}" =~ "intel" ]]); then + which "${FC}" + which "${CC}" + + # persist environment variables + echo "FC=${FC}" >> $GITHUB_ENV + echo "CC=${CC}" >> $GITHUB_ENV + fi + + - 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: | + 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%" + + - name: Set outputs and env vars + shell: bash + id: outputs + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + if [[ "${{ inputs.compiler }}" == "intel" ]]; then + echo fc=ifx>>$GITHUB_OUTPUT + echo cc=icx>>$GITHUB_OUTPUT + echo FC=ifx>>$GITHUB_ENV + echo CC=icx>>$GITHUB_ENV + elif [[ "${{ inputs.compiler }}" == "intel-classic" ]]; then + echo fc=ifort>>$GITHUB_OUTPUT + echo cc=icl>>$GITHUB_OUTPUT + echo FC=ifort>>$GITHUB_ENV + echo CC=icl>>$GITHUB_ENV + else + echo fc=$FC>>$GITHUB_OUTPUT + echo cc=$CC>>$GITHUB_OUTPUT + echo FC=$FC>>$GITHUB_ENV% + echo CC=$CC>>$GITHUB_ENV% + fi + else + echo fc=$FC>>$GITHUB_OUTPUT + echo cc=$CC>>$GITHUB_OUTPUT + echo FC=$FC>>$GITHUB_ENV + echo CC=$CC>>$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') + shell: bash + run: mv "/usr/bin/link" "$RUNNER_TEMP/link" diff --git a/install-intel-windows.bat b/install-intel-windows.bat new file mode 100644 index 00000000..ba62671f --- /dev/null +++ b/install-intel-windows.bat @@ -0,0 +1,9 @@ +@echo off + +:: download and unpack installer +curl.exe --output %TEMP%\webimage.exe --url %1 --retry 5 --retry-delay 5 +start /b /wait %TEMP%\webimage.exe -s -x -f %TEMP%\webimage_extracted --log %TEMP%\extract.log +del %TEMP%\webimage.exe + +:: run installer +%TEMP%\webimage_extracted\bootstrapper.exe -s --action install --components=intel.oneapi.win.cpp-compiler:intel.oneapi.win.ifort-compiler --eula=accept -p=NEED_VS2017_INTEGRATION=0 -p=NEED_VS2019_INTEGRATION=0 -p=NEED_VS2022_INTEGRATION=0 --log-dir=%TEMP% diff --git a/setup-fortran.sh b/setup-fortran.sh index aa026ef1..7f9cc151 100755 --- a/setup-fortran.sh +++ b/setup-fortran.sh @@ -227,6 +227,49 @@ intel_version_map_m() esac } +intel_version_map_w() +{ + local actual_version=$1 + local classic=$2 + if $classic; then + case $actual_version in + 2021.10.0 | 2021.10) + version=2023.2.0 + ;; + 2021.9.0 | 2021.9) + version=2023.1.0 + ;; + 2021.8.0 | 2021.8) + version=2023.0.0 + ;; + 2021.7.0 | 2021.7) + version=2022.3.0 + ;; + 2021.6.0 | 2021.6) + version=2022.2.0 + ;; + *) + version=$actual_version + ;; + esac + else + case $actual_version in + 2023.2 | 2023.1 | 2023.0) + version=$actual_version.0 + ;; + 2022.2.0 | 2022.2) + version=2022.3.0 + ;; + 2022.1.0 | 2022.1) + version=2022.2.0 + ;; + *) + version=$actual_version + ;; + esac + fi +} + install_intel_apt() { local version=$1 @@ -334,6 +377,58 @@ install_intel_dmg() export CXX="icpc" } +install_intel_win() +{ + local version=$1 + local classic=$2 + intel_version_map_w $version $classic + + case $version in + 2023.2.0) + WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/IRC_NAS/438527fc-7140-422c-a851-389f2791816b/w_HPCKit_p_2023.2.0.49441_offline.exe + ;; + 2023.1.0) + WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/IRC_NAS/2a13d966-fcc5-4a66-9fcc-50603820e0c9/w_HPCKit_p_2023.1.0.46357_offline.exe + ;; + 2023.0.0) + WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/19085/w_HPCKit_p_2023.0.0.25931_offline.exe + ;; + 2022.3.1) + WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/18976/w_HPCKit_p_2022.3.1.19755_offline.exe + ;; + 2022.3.0) + WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/18857/w_HPCKit_p_2022.3.0.9564_offline.exe + ;; + 2022.2.0) + WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/IRC_NAS/18680/w_HPCKit_p_2022.2.0.173_offline.exe + ;; + # the installer versions below fail + # 2022.1.2) + # WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/18529/w_HPCKit_p_2022.1.2.116_offline.exe + # ;; + # 2022.1.0) + # WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/18417/w_HPCKit_p_2022.1.0.93_offline.exe + # ;; + # 2021.4.0) + # WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/18247/w_HPCKit_p_2021.4.0.3340_offline.exe + # ;; + # 2021.3.0) + # WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/17940/w_HPCKit_p_2021.3.0.3227_offline.exe + # ;; + # 2021.2.0) + # WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/17762/w_HPCKit_p_2021.2.0.2901_offline.exe + # ;; + # 2021.1.0) + # WINDOWS_HPCKIT_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/17392/w_HPCKit_p_2021.1.0.2682_offline.exe + # ;; + *) + exit 1 + ;; + esac + + "$GITHUB_ACTION_PATH/install-intel-windows.bat" $WINDOWS_HPCKIT_URL +} + install_intel() { local platform=$1 @@ -345,6 +440,15 @@ install_intel() darwin*) install_intel_dmg $version ;; + mingw*) + install_intel_win $version $classic + ;; + msys*) + install_intel_win $version $classic + ;; + cygwin*) + install_intel_win $version $classic + ;; *) echo "Unsupported platform: $platform" exit 1