diff options
| -rw-r--r-- | .github/workflows/circleci.yml | 2 | ||||
| -rw-r--r-- | .github/workflows/wheels.yml | 13 | ||||
| -rw-r--r-- | .travis.yml | 2 | ||||
| -rw-r--r-- | azure-pipelines.yml | 31 | ||||
| -rw-r--r-- | azure-steps-windows.yml | 33 | ||||
| -rw-r--r-- | numpy/distutils/command/build_ext.py | 7 | ||||
| -rw-r--r-- | numpy/lib/tests/test_format.py | 1 | ||||
| -rw-r--r-- | tools/openblas_support.py | 107 | ||||
| -rwxr-xr-x | tools/travis-test.sh | 1 | ||||
| -rw-r--r-- | tools/wheels/cibw_before_build.sh | 35 | ||||
| -rw-r--r-- | tools/wheels/cibw_test_command.sh | 20 | ||||
| -rw-r--r-- | tools/wheels/gfortran_utils.sh | 75 |
12 files changed, 175 insertions, 152 deletions
diff --git a/.github/workflows/circleci.yml b/.github/workflows/circleci.yml index df5b8c8b9..de191d068 100644 --- a/.github/workflows/circleci.yml +++ b/.github/workflows/circleci.yml @@ -2,6 +2,8 @@ # # if: github.repository == 'numpy/numpy' +name: CircleCI artifact redirector + permissions: contents: read # to fetch code (actions/checkout) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index cca807435..0c9f2dad8 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -108,14 +108,13 @@ jobs: with: python-version: "3.x" - - name: Configure mingw for 32-bit builds + - name: setup rtools for 32-bit run: | - # Force 32-bit mingw - choco uninstall mingw - choco install -y mingw --forcex86 --force --version=7.3.0 - echo "C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw32\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - refreshenv - if: ${{ env.IS_32_BIT == 'true' }} + echo "PLAT=i686" >> $env:GITHUB_ENV + echo "MSYSTEM=MINGW32" >> $env:GITHUB_ENV + echo "PATH=$env:RTOOLS40_HOME\mingw32\bin;$env:PATH" >> $env:GITHUB_ENV + gfortran --version + if: ${{ matrix.buildplat[1] == 'win32' }} - name: Build wheels uses: pypa/cibuildwheel@v2.11.2 diff --git a/.travis.yml b/.travis.yml index 1c219a6d1..4f9ac48fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ jobs: env: # use OpenBLAS build, not system ATLAS - DOWNLOAD_OPENBLAS=1 - - NPY_USE_BLAS_ILP64=1 + # - NPY_USE_BLAS_ILP64=1 # the openblas build fails - ATLAS=None # VSX4 still not supported by ubuntu/gcc-11 - EXPECT_CPU_FEATURES="VSX VSX2 VSX3" diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d393077b8..89a5fc1ae 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -113,6 +113,7 @@ stages: echo CFLAGS \$CFLAGS && \ python3 -m pip install -v . && \ python3 runtests.py -n --debug-info --mode=full -- -rsx --junitxml=junit/test-results.xml && \ + python3 -m pip install threadpoolctl && \ python3 tools/openblas_support.py --check_version" displayName: 'Run 32-bit manylinux2014 Docker Build / Tests' - task: PublishTestResults@2 @@ -150,28 +151,14 @@ stages: [ -n "$USE_XCODE_10" ] && /bin/bash -c "sudo xcode-select -s /Applications/Xcode_10.app/Contents/Developer" clang --version displayName: 'report clang version' - # NOTE: might be better if we could avoid installing - # two C compilers, but with homebrew looks like we're - # now stuck getting the full gcc toolchain instead of - # just pulling in gfortran + - script: | - set -xe - # same version of gfortran as the open-libs and numpy-wheel builds - curl -L https://github.com/MacPython/gfortran-install/raw/master/archives/gfortran-4.9.0-Mavericks.dmg -o gfortran.dmg - GFORTRAN_SHA256=$(shasum -a 256 gfortran.dmg) - KNOWN_SHA256="d2d5ca5ba8332d63bbe23a07201c4a0a5d7e09ee56f0298a96775f928c3c4b30 gfortran.dmg" - if [ "$GFORTRAN_SHA256" != "$KNOWN_SHA256" ]; then - echo sha256 mismatch - exit 1 + if [[ $PLATFORM == "macosx-arm64" ]]; then + PLAT="arm64" fi - hdiutil attach -mountpoint /Volumes/gfortran gfortran.dmg - sudo installer -pkg /Volumes/gfortran/gfortran.pkg -target / - otool -L /usr/local/gfortran/lib/libgfortran.3.dylib - # Manually symlink gfortran-4.9 to plain gfortran for f2py. - # No longer needed after Feb 13 2020 as gfortran is already present - # and the attempted link errors. Keep this for future reference. - # ln -s /usr/local/bin/gfortran-4.9 /usr/local/bin/gfortran - displayName: 'make libgfortran available on mac os for openblas' + source tools/wheels/gfortran_utils.sh + install_gfortran + displayName: 'install gfortran' # use the pre-built openblas binary that most closely # matches our MacOS wheel builds -- currently based # primarily on file size / name details @@ -227,7 +214,9 @@ stages: env: # gfortran installed above adds -lSystem, so this is needed to find it (gh-22043) LIBRARY_PATH: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib - - bash: python tools/openblas_support.py --check_version + - bash: | + python -m pip install threadpoolctl + python tools/openblas_support.py --check_version displayName: 'Verify OpenBLAS version' condition: eq(variables['USE_OPENBLAS'], '1') # import doesn't work when in numpy src directory , so do a pip dev install of build lib to test diff --git a/azure-steps-windows.yml b/azure-steps-windows.yml index 671e01c5b..8fe677eab 100644 --- a/azure-steps-windows.yml +++ b/azure-steps-windows.yml @@ -32,21 +32,21 @@ steps: displayName: 'Install dependencies; some are optional to avoid test skips' - powershell: | - choco install -y mingw --forcex86 --force --version=7.3.0 + choco install -y rtools refreshenv - displayName: 'Install 32-bit mingw for 32-bit builds' - condition: eq(variables['BITS'], 32) + displayName: 'Install rtools' - powershell: | $ErrorActionPreference = "Stop" - # Download and get the path to "openblas.a". We cannot copy it + # Download and get the path to "openblas". We cannot copy it # to $PYTHON_EXE's directory since that is on a different drive which # mingw does not like. Instead copy it to a directory and set OPENBLAS, # since OPENBLAS will be picked up by the openblas discovery $target = $(python tools/openblas_support.py) mkdir openblas echo "Copying $target to openblas/" - cp $target openblas/ + cp -r $target/* openblas/ + $env:OPENBLAS = $target displayName: 'Download / Install OpenBLAS' # NOTE: for Windows builds it seems much more tractable to use runtests.py @@ -57,7 +57,11 @@ steps: If ($(BITS) -eq 32) { $env:CFLAGS = "-m32" $env:LDFLAGS = "-m32" - $env:PATH = "C:\\ProgramData\\chocolatey\\lib\\mingw\\tools\\install\\mingw$(BITS)\\bin;" + $env:PATH + $env:PATH = "$env:RTOOLS40_HOME\\mingw32\\bin;$env:PATH" + } + Else + { + $env:PATH = "$env:RTOOLS40_HOME\\mingw64\\bin;$env:PATH" } If ( Test-Path env:NPY_USE_BLAS_ILP64 ) { $env:OPENBLAS64_ = "openblas" @@ -72,7 +76,22 @@ steps: } displayName: 'Build NumPy' -- script: python runtests.py -n --show-build-log --mode=$(TEST_MODE) -- -rsx --junitxml=junit/test-results.xml +- script: | + python -m pip install threadpoolctl + python tools/openblas_support.py --check_version + displayName: 'Check OpenBLAS version' + +- powershell: | + If ($(BITS) -eq 32) { + $env:CFLAGS = "-m32" + $env:LDFLAGS = "-m32" + $env:PATH = "$env:RTOOLS40_HOME\\mingw32\\bin;$env:PATH" + } + Else + { + $env:PATH = "$env:RTOOLS40_HOME\\mingw64\\bin;$env:PATH" + } + python runtests.py -n --show-build-log --mode=$(TEST_MODE) -- -rsx --junitxml=junit/test-results.xml displayName: 'Run NumPy Test Suite' - task: PublishTestResults@2 diff --git a/numpy/distutils/command/build_ext.py b/numpy/distutils/command/build_ext.py index 8b568c159..6dc6b4265 100644 --- a/numpy/distutils/command/build_ext.py +++ b/numpy/distutils/command/build_ext.py @@ -586,6 +586,13 @@ class build_ext (old_build_ext): # not using fcompiler linker self._libs_with_msvc_and_fortran( fcompiler, libraries, library_dirs) + if ext.runtime_library_dirs: + # gcc adds RPATH to the link. On windows, copy the dll into + # self.extra_dll_dir instead. + for d in ext.runtime_library_dirs: + for f in glob(d + '/*.dll'): + copy_file(f, self.extra_dll_dir) + ext.runtime_library_dirs = [] elif ext.language in ['f77', 'f90'] and fcompiler is not None: linker = fcompiler.link_shared_object diff --git a/numpy/lib/tests/test_format.py b/numpy/lib/tests/test_format.py index ab9472020..6f6406cf8 100644 --- a/numpy/lib/tests/test_format.py +++ b/numpy/lib/tests/test_format.py @@ -923,6 +923,7 @@ def test_large_file_support(tmpdir): assert_array_equal(r, d) +@pytest.mark.skipif(IS_PYPY, reason="flaky on PyPy") @pytest.mark.skipif(np.dtype(np.intp).itemsize < 8, reason="test requires 64-bit system") @pytest.mark.slow diff --git a/tools/openblas_support.py b/tools/openblas_support.py index ce677f9a5..ed43804af 100644 --- a/tools/openblas_support.py +++ b/tools/openblas_support.py @@ -13,8 +13,8 @@ from tempfile import mkstemp, gettempdir from urllib.request import urlopen, Request from urllib.error import HTTPError -OPENBLAS_V = '0.3.20' -OPENBLAS_LONG = 'v0.3.20' +OPENBLAS_V = '0.3.21' +OPENBLAS_LONG = 'v0.3.21' BASE_LOC = 'https://anaconda.org/multibuild-wheels-staging/openblas-libs' BASEURL = f'{BASE_LOC}/{OPENBLAS_LONG}/download' SUPPORTED_PLATFORMS = [ @@ -54,13 +54,10 @@ def get_ilp64(): def get_manylinux(arch): - if arch in ('x86_64', 'i686'): - default = '2010' - else: - default = '2014' + default = '2014' ret = os.environ.get("MB_ML_VER", default) # XXX For PEP 600 this can be a glibc version - assert ret in ('1', '2010', '2014', '_2_24'), f'invalid MB_ML_VER {ret}' + assert ret in ('2010', '2014', '_2_24'), f'invalid MB_ML_VER {ret}' return ret @@ -77,16 +74,16 @@ def download_openblas(target, plat, ilp64): suffix = f'manylinux{ml_ver}_{arch}.tar.gz' typ = 'tar.gz' elif plat == 'macosx-x86_64': - suffix = 'macosx_10_9_x86_64-gf_1becaaa.tar.gz' + suffix = 'macosx_10_9_x86_64-gf_c469a42.tar.gz' typ = 'tar.gz' elif plat == 'macosx-arm64': - suffix = 'macosx_11_0_arm64-gf_f26990f.tar.gz' + suffix = 'macosx_11_0_arm64-gf_5272328.tar.gz' typ = 'tar.gz' elif osname == 'win': if plat == "win-32": - suffix = 'win32-gcc_8_1_0.zip' + suffix = 'win32-gcc_8_3_0.zip' else: - suffix = 'win_amd64-gcc_8_1_0.zip' + suffix = 'win_amd64-gcc_10_3_0.zip' typ = 'zip' if not suffix: @@ -102,11 +99,11 @@ def download_openblas(target, plat, ilp64): if response.status != 200: print(f'Could not download "{filename}"', file=sys.stderr) return None - print(f"Downloading {length} from {filename}", file=sys.stderr) + # print(f"Downloading {length} from {filename}", file=sys.stderr) data = response.read() # Verify hash key = os.path.basename(filename) - print("Saving to file", file=sys.stderr) + # print("Saving to file", file=sys.stderr) with open(target, 'wb') as fid: fid.write(data) return typ @@ -133,28 +130,34 @@ def setup_openblas(plat=get_plat(), ilp64=get_ilp64()): if osname == 'win': if not typ == 'zip': return f'expecting to download zipfile on windows, not {typ}' - return unpack_windows_zip(tmp) + return unpack_windows_zip(tmp, plat) else: if not typ == 'tar.gz': return 'expecting to download tar.gz, not %s' % str(typ) return unpack_targz(tmp) -def unpack_windows_zip(fname): +def unpack_windows_zip(fname, plat): + unzip_base = os.path.join(gettempdir(), 'openblas') + if not os.path.exists(unzip_base): + os.mkdir(unzip_base) with zipfile.ZipFile(fname, 'r') as zf: - # Get the openblas.a file, but not openblas.dll.a nor openblas.dev.a - lib = [x for x in zf.namelist() if OPENBLAS_LONG in x and - x.endswith('a') and not x.endswith('dll.a') and - not x.endswith('dev.a')] - if not lib: - return 'could not find libopenblas_%s*.a ' \ - 'in downloaded zipfile' % OPENBLAS_LONG - if get_ilp64() is None: - target = os.path.join(gettempdir(), 'openblas.a') - else: - target = os.path.join(gettempdir(), 'openblas64_.a') - with open(target, 'wb') as fid: - fid.write(zf.read(lib[0])) + zf.extractall(unzip_base) + if plat == "win-32": + target = os.path.join(unzip_base, "32") + else: + target = os.path.join(unzip_base, "64") + # Copy the lib to openblas.lib. Once we can properly use pkg-config + # this will not be needed + lib = glob.glob(os.path.join(target, 'lib', '*.lib')) + assert len(lib) == 1 + for f in lib: + shutil.copy(f, os.path.join(target, 'lib', 'openblas.lib')) + shutil.copy(f, os.path.join(target, 'lib', 'openblas64_.lib')) + # Copy the dll from bin to lib so system_info can pick it up + dll = glob.glob(os.path.join(target, 'bin', '*.dll')) + for f in dll: + shutil.copy(f, os.path.join(target, 'lib')) return target @@ -235,7 +238,8 @@ def make_init(dirname): def test_setup(plats): ''' - Make sure all the downloadable files exist and can be opened + Make sure all the downloadable files needed for wheel building + exist and can be opened ''' def items(): """ yields all combinations of arch, ilp64 @@ -243,19 +247,8 @@ def test_setup(plats): for plat in plats: yield plat, None osname, arch = plat.split("-") - if arch not in ('i686', 'arm64', '32'): + if arch not in ('i686', '32'): yield plat, '64_' - if osname == "linux" and arch in ('i686', 'x86_64'): - oldval = os.environ.get('MB_ML_VER', None) - os.environ['MB_ML_VER'] = '1' - yield plat, None - # Once we create x86_64 and i686 manylinux2014 wheels... - # os.environ['MB_ML_VER'] = '2014' - # yield arch, None, False - if oldval: - os.environ['MB_ML_VER'] = oldval - else: - os.environ.pop('MB_ML_VER') errs = [] for plat, ilp64 in items(): @@ -273,7 +266,7 @@ def test_setup(plats): continue if not target: raise RuntimeError(f'Could not setup {plat}') - print(target) + print('success with', plat, ilp64) if osname == 'win': if not target.endswith('.a'): raise RuntimeError("Not .a extracted!") @@ -291,32 +284,24 @@ def test_setup(plats): raise errs[0] -def test_version(expected_version, ilp64=get_ilp64()): +def test_version(expected_version=None): """ Assert that expected OpenBLAS version is - actually available via NumPy + actually available via NumPy. Requires threadpoolctl """ import numpy - import ctypes + import threadpoolctl - dll = ctypes.CDLL(numpy.core._multiarray_umath.__file__) - if ilp64 == "64_": - get_config = dll.openblas_get_config64_ - else: - get_config = dll.openblas_get_config - get_config.restype = ctypes.c_char_p - res = get_config() - print('OpenBLAS get_config returned', str(res)) + data = threadpoolctl.threadpool_info() + if len(data) != 1: + raise ValueError(f"expected single threadpool_info result, got {data}") if not expected_version: expected_version = OPENBLAS_V - check_str = b'OpenBLAS %s' % expected_version.encode() - print(check_str) - assert check_str in res, f'{expected_version} not found in {res}' - if ilp64: - assert b"USE64BITINT" in res - else: - assert b"USE64BITINT" not in res - + if data[0]['version'] != expected_version: + raise ValueError( + f"expected OpenBLAS version {expected_version}, got {data}" + ) + print("OK") if __name__ == '__main__': import argparse diff --git a/tools/travis-test.sh b/tools/travis-test.sh index 96bc33926..eeeefe2eb 100755 --- a/tools/travis-test.sh +++ b/tools/travis-test.sh @@ -143,6 +143,7 @@ EOF fi if [ -n "$CHECK_BLAS" ]; then + $PYTHON -m pip install threadpoolctl $PYTHON ../tools/openblas_support.py --check_version fi diff --git a/tools/wheels/cibw_before_build.sh b/tools/wheels/cibw_before_build.sh index 5cf7d8088..ad76b330f 100644 --- a/tools/wheels/cibw_before_build.sh +++ b/tools/wheels/cibw_before_build.sh @@ -26,33 +26,22 @@ if [[ $RUNNER_OS == "Linux" || $RUNNER_OS == "macOS" ]] ; then elif [[ $RUNNER_OS == "Windows" ]]; then PYTHONPATH=tools python -c "import openblas_support; openblas_support.make_init('numpy')" target=$(python tools/openblas_support.py) + ls /tmp mkdir -p openblas - cp $target openblas + # bash on windows does not like cp -r $target/* openblas + for f in $(ls $target); do + cp -r $target/$f openblas + done + ls openblas fi -# Install GFortran if [[ $RUNNER_OS == "macOS" ]]; then - # same version of gfortran as the openblas-libs and numpy-wheel builds - curl -L https://github.com/MacPython/gfortran-install/raw/master/archives/gfortran-4.9.0-Mavericks.dmg -o gfortran.dmg - GFORTRAN_SHA256=$(shasum -a 256 gfortran.dmg) - KNOWN_SHA256="d2d5ca5ba8332d63bbe23a07201c4a0a5d7e09ee56f0298a96775f928c3c4b30 gfortran.dmg" - if [ "$GFORTRAN_SHA256" != "$KNOWN_SHA256" ]; then - echo sha256 mismatch - exit 1 - fi - - hdiutil attach -mountpoint /Volumes/gfortran gfortran.dmg - sudo installer -pkg /Volumes/gfortran/gfortran.pkg -target / - otool -L /usr/local/gfortran/lib/libgfortran.3.dylib - - # arm64 stuff from gfortran_utils + # Install same version of gfortran as the openblas-libs builds if [[ $PLATFORM == "macosx-arm64" ]]; then - source $PROJECT_DIR/tools/wheels/gfortran_utils.sh - install_arm64_cross_gfortran + PLAT="arm64" fi - - # Manually symlink gfortran-4.9 to plain gfortran for f2py. - # No longer needed after Feb 13 2020 as gfortran is already present - # and the attempted link errors. Keep this for future reference. - # ln -s /usr/local/bin/gfortran-4.9 /usr/local/bin/gfortran + source $PROJECT_DIR/tools/wheels/gfortran_utils.sh + install_gfortran + # Try a newer version of delocate that knows about /usr/local/lib + pip install git+https://github.com/isuruf/delocate@search_usr_local#egg=delocate fi diff --git a/tools/wheels/cibw_test_command.sh b/tools/wheels/cibw_test_command.sh index cbc735fc0..589033e10 100644 --- a/tools/wheels/cibw_test_command.sh +++ b/tools/wheels/cibw_test_command.sh @@ -5,19 +5,27 @@ set -xe PROJECT_DIR="$1" +python -m pip install threadpoolctl python -c "import numpy; numpy.show_config()" if [[ $RUNNER_OS == "Windows" ]]; then # GH 20391 PY_DIR=$(python -c "import sys; print(sys.prefix)") mkdir $PY_DIR/libs fi - +if [[ $RUNNER_OS == "macOS" && $RUNNER_ARCH == "X64" ]]; then + # Not clear why this is needed but it seems on x86_64 this is not the default + # and without it f2py tests fail + export DYLD_LIBRARY_PATH=/usr/local/lib +fi # Set available memory value to avoid OOM problems on aarch64. # See gh-22418. export NPY_AVAILABLE_MEM="4 GB" -python -c "import sys; import numpy; sys.exit(not numpy.test('full'))" - -python $PROJECT_DIR/tools/wheels/check_license.py -if [[ $UNAME == "Linux" || $UNAME == "Darwin" ]] ; then - python $PROJECT_DIR/tools/openblas_support.py --check_version +if [[ $(python -c "import sys; print(sys.implementation.name)") == "pypy" ]]; then + # make PyPy more verbose, try to catc a segfault in + # numpy/lib/tests/test_function_base.py + python -c "import sys; import numpy; sys.exit(not numpy.test(label='full', verbose=2))" +else + python -c "import sys; import numpy; sys.exit(not numpy.test(label='full'))" fi +python $PROJECT_DIR/tools/wheels/check_license.py +python $PROJECT_DIR/tools/openblas_support.py --check_version diff --git a/tools/wheels/gfortran_utils.sh b/tools/wheels/gfortran_utils.sh index e0c7054a5..39357b3fe 100644 --- a/tools/wheels/gfortran_utils.sh +++ b/tools/wheels/gfortran_utils.sh @@ -26,7 +26,6 @@ # Bash utilities for use with gfortran -GF_LIB_URL="https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com" ARCHIVE_SDIR="${ARCHIVE_SDIR:-archives}" GF_UTIL_DIR=$(dirname "${BASH_SOURCE[0]}") @@ -52,9 +51,8 @@ function get_distutils_platform { echo "manylinux1_$plat" return fi - # macOS 32-bit arch is i386 - [ "$plat" == "i686" ] && plat="i386" - local target=$(echo $MACOSX_DEPLOYMENT_TARGET | tr .- _) + # The gfortran downloads build for macos 10.9 + local target="10_9" echo "macosx_${target}_${plat}" } @@ -78,15 +76,14 @@ function get_distutils_platform_ex { echo "manylinux${mb_ml_ver}_${plat}" return fi - # macOS 32-bit arch is i386 - [ "$plat" == "i686" ] && plat="i386" - local target=$(echo $MACOSX_DEPLOYMENT_TARGET | tr .- _) + # The gfortran downloads build for macos 10.9 + local target="10_9" echo "macosx_${target}_${plat}" } function get_macosx_target { # Report MACOSX_DEPLOYMENT_TARGET as given by distutils get_platform. - python -c "import sysconfig as s; print(s.get_config_vars()['MACOSX_DEPLOYMENT_TARGET'])" + python3 -c "import sysconfig as s; print(s.get_config_vars()['MACOSX_DEPLOYMENT_TARGET'])" } function check_gfortran { @@ -107,9 +104,6 @@ function get_gf_lib_for_suf { if [ -n "$suffix" ]; then suffix="-$suffix"; fi local fname="$prefix-${plat_tag}${suffix}.tar.gz" local out_fname="${ARCHIVE_SDIR}/$fname" - if [ ! -e "$out_fname" ]; then - curl -L "${GF_LIB_URL}/$fname" > $out_fname || (echo "Fetch of $out_fname failed"; exit 1) - fi [ -s $out_fname ] || (echo "$out_fname is empty"; exit 24) echo "$out_fname" } @@ -117,24 +111,54 @@ function get_gf_lib_for_suf { if [ "$(uname)" == "Darwin" ]; then mac_target=${MACOSX_DEPLOYMENT_TARGET:-$(get_macosx_target)} export MACOSX_DEPLOYMENT_TARGET=$mac_target - GFORTRAN_DMG="${GF_UTIL_DIR}/archives/gfortran-4.9.0-Mavericks.dmg" - export GFORTRAN_SHA="$(shasum $GFORTRAN_DMG)" - - function install_arm64_cross_gfortran { - curl -L -O https://github.com/isuruf/gcc/releases/download/gcc-10-arm-20210228/gfortran-darwin-arm64.tar.gz - export GFORTRAN_SHA=f26990f6f08e19b2ec150b9da9d59bd0558261dd - if [[ "$(shasum gfortran-darwin-arm64.tar.gz)" != "${GFORTRAN_SHA} gfortran-darwin-arm64.tar.gz" ]]; then - echo "shasum mismatch for gfortran-darwin-arm64" + # Keep this for now as some builds might depend on this being + # available before install_gfortran is called + export GFORTRAN_SHA=c469a420d2d003112749dcdcbe3c684eef42127e + # Set SDKROOT env variable if not set + export SDKROOT=${SDKROOT:-$(xcrun --show-sdk-path)} + + function download_and_unpack_gfortran { + local arch=$1 + local type=$2 + curl -L -O https://github.com/isuruf/gcc/releases/download/gcc-11.3.0-2/gfortran-darwin-${arch}-${type}.tar.gz + case ${arch}-${type} in + arm64-native) + export GFORTRAN_SHA=142290685240f4f86cdf359cb2030d586105d7e4 + ;; + arm64-cross) + export GFORTRAN_SHA=527232845abc5af21f21ceacc46fb19c190fe804 + ;; + x86_64-native) + export GFORTRAN_SHA=c469a420d2d003112749dcdcbe3c684eef42127e + ;; + x86_64-cross) + export GFORTRAN_SHA=107604e57db97a0ae3e7ca7f5dd722959752f0b3 + ;; + esac + if [[ "$(shasum gfortran-darwin-${arch}-${type}.tar.gz)" != "${GFORTRAN_SHA} gfortran-darwin-${arch}-${type}.tar.gz" ]]; then + echo "shasum mismatch for gfortran-darwin-${arch}-${type}" exit 1 fi sudo mkdir -p /opt/ - sudo cp "gfortran-darwin-arm64.tar.gz" /opt/gfortran-darwin-arm64.tar.gz + sudo cp "gfortran-darwin-${arch}-${type}.tar.gz" /opt/gfortran-darwin-${arch}-${type}.tar.gz pushd /opt - sudo tar -xvf gfortran-darwin-arm64.tar.gz - sudo rm gfortran-darwin-arm64.tar.gz + sudo tar -xvf gfortran-darwin-${arch}-${type}.tar.gz + sudo rm gfortran-darwin-${arch}-${type}.tar.gz popd - export FC_ARM64="$(find /opt/gfortran-darwin-arm64/bin -name "*-gfortran")" - local libgfortran="$(find /opt/gfortran-darwin-arm64/lib -name libgfortran.dylib)" + if [[ "${type}" == "native" ]]; then + # Link these into /usr/local so that there's no need to add rpath or -L + for f in libgfortran.dylib libgfortran.5.dylib libgcc_s.1.dylib libgcc_s.1.1.dylib libquadmath.dylib libquadmath.0.dylib; do + ln -sf /opt/gfortran-darwin-${arch}-${type}/lib/$f /usr/local/lib/$f + done + # Add it to PATH + ln -sf /opt/gfortran-darwin-${arch}-${type}/bin/gfortran /usr/local/bin/gfortran + fi + } + + function install_arm64_cross_gfortran { + download_and_unpack_gfortran arm64 cross + export FC_ARM64="$(find /opt/gfortran-darwin-arm64-cross/bin -name "*-gfortran")" + local libgfortran="$(find /opt/gfortran-darwin-arm64-cross/lib -name libgfortran.dylib)" local libdir=$(dirname $libgfortran) export FC_ARM64_LDFLAGS="-L$libdir -Wl,-rpath,$libdir" @@ -143,8 +167,7 @@ if [ "$(uname)" == "Darwin" ]; then fi } function install_gfortran { - hdiutil attach -mountpoint /Volumes/gfortran $GFORTRAN_DMG - sudo installer -pkg /Volumes/gfortran/gfortran.pkg -target / + download_and_unpack_gfortran $(uname -m) native check_gfortran if [[ "${PLAT:-}" == "universal2" || "${PLAT:-}" == "arm64" ]]; then install_arm64_cross_gfortran |
