Skip to content

MRG: Refactor build_openblas script #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 36 additions & 58 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# This is a basic workflow to help you get started with Actions

name: Windows build

defaults:
run:
shell: bash

on:
push:
branches: [ master ]
Expand All @@ -15,13 +9,16 @@ on:
env:
OPENBLAS_COMMIT: "bfd9c1b58cd3"
OPENBLAS_ROOT: "c:\\opt"
# Preserve working directory for calls into bash
CHERE_INVOKING: "yes"
BASH_PATH: "c:\\rtools40\\usr\\bin\\bash"

jobs:
build:
strategy:
matrix:
BUILD_BITS: [64, 32]
INTERFACE64: ['1', '']
INTERFACE64: ['1', '0']
os: [windows-latest]
exclude:
- BUILD_BITS: 32
Expand All @@ -31,65 +28,46 @@ jobs:

steps:
- uses: actions/checkout@v2
- uses: ilammy/msvc-dev-cmd@v1

- name: Setup
- name: install-rtools
run: |
BITS=${{ matrix.BUILD_BITS }}
echo "BUILD_BITS=$BITS" >> $GITHUB_ENV;
if [ "$BITS" == "32" ]; then
echo "PLAT=i686" >> $GITHUB_ENV;
else
echo "PLAT=x86_64" >> $GITHUB_ENV;
fi
echo "START_DIR=$PWD" >> $GITHUB_ENV;
choco install -y zip

- run: |
choco install -y mingw --forcex86 --force --version=8.1.0
choco install -y make
name: Install 32-bit mingw
shell: powershell
if: ${{ matrix.BUILD_BITS == '32' }}
choco install rtools --no-progress

- run: |
# see https://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg586184.html
if [ "${{ matrix.BUILD_BITS }}" == "64" ]; then
include=/c/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/avx512fintrin.h
else
include=/c/ProgramData/Chocolatey/lib/mingw/tools/install/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/avx512fintrin.h
fi
sed -i -e"s/_mm512_abs_pd (__m512 __A)/_mm512_abs_pd (__m512d __A)/" $include
name: Fix gcc bug
- name: Set env variables
run: |
echo "START_DIR=$PWD" >> $env:GITHUB_ENV
$BITS = ${{ matrix.BUILD_BITS }}
echo "BUILD_BITS=$BITS" >> $env:GITHUB_ENV
# For interpretation of MSYSTEM, see:
# https://sourceforge.net/p/msys2/discussion/general/thread/b7dfdac8/#3939
if ($BITS -eq 32) {
echo "PLAT=i686" >> $env:GITHUB_ENV
echo "MSYSTEM=MINGW32" >> $env:GITHUB_ENV
echo "LDFLAGS=-static -static-libgcc" >> $env:GITHUB_ENV
} else {
echo "PLAT=x86_64" >> $env:GITHUB_ENV
echo "MSYSTEM=UCRT64" >> $env:GITHUB_ENV
echo "LDFLAGS=-lucrt -static -static-libgcc" >> $env:GITHUB_ENV
}
if ( ${{ matrix.INTERFACE64 }} -eq 1 ) {
echo "INTERFACE64=1" >> $env:GITHUB_ENV
}

- name: Build
run: |
BITS=${{ matrix.BUILD_BITS }}
if [ "${{ matrix.INTERFACE64 }}" == "1" ]; then
export INTERFACE64=1
fi
if [ "$BITS" == "32" ]; then
export PATH=/c/ProgramData/chocolatey/lib/mingw/tools/install/mingw32/bin:$PATH
fi
echo $PATH
git submodule update --init --recursive
tools/build_openblas.sh
& $env:BASH_PATH -lc tools/build_openblas.sh

- name: Test
run: |
BITS=${{ matrix.BUILD_BITS }}
if [ "$BITS" == "32" ]; then
export PATH=/c/ProgramData/chocolatey/lib/mingw/tools/install/mingw32/bin:$PATH
fi
if [ "${{ matrix.INTERFACE64 }}" == "1" ]; then
export INTERFACE64=1
fi
tools/build_gfortran.sh
cp test.exe builds
cp test_dyn.exe builds
./test.exe
cp $(cygpath $OPENBLAS_ROOT)/$BITS/bin/*.dll .
./test_dyn.exe
& $env:BASH_PATH -lc tools/build_gfortran.sh
echo "Static test"
.\for_test\test.exe
echo "Dynamic test"
.\for_test\test_dyn.exe

- name: Copy
run: |
cp for_test\test*.exe builds

- uses: actions/upload-artifact@v3
with:
Expand All @@ -100,4 +78,4 @@ jobs:
OPENBLAS_LIBS_STAGING_UPLOAD_TOKEN: ${{ secrets.MULTIBUILD_WHEELS_STAGING_ACCESS }}
run: |
pip install -q git+https://github.com/Anaconda-Platform/anaconda-client@1.8.0
tools/upload_to_anaconda_staging.sh
& $env:BASH_PATH -lc tools/upload_to_anaconda_staging.sh
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ builds/
*~
*.pyc
*.swp
test.exe
for_test/
2 changes: 1 addition & 1 deletion OpenBLAS
17 changes: 12 additions & 5 deletions tools/build_gfortran.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@

set -e

cd $(cygpath "$START_DIR")
rm -rf for_test
mkdir for_test
cd for_test

repo_path=$(cygpath "$START_DIR")
OBP=$(cygpath $OPENBLAS_ROOT\\$BUILD_BITS)

static_libname=$(find $OBP/lib -maxdepth 1 -type f -name '*.a' \! -name '*.dll.a' | tail -1)
dynamic_libname=$(find $OBP/lib -maxdepth 1 -type f -name '*.dll.a' | tail -1)
dll_name=$(echo $dynamic_libname | sed 's#/lib/#/bin/#' | sed 's/.a$//')

cp $dll_name .

if [ "$INTERFACE64" == "1" ]; then
gfortran -I $OBP/include -fdefault-integer-8 -o test.exe test64_.f90 $static_libname
gfortran -I $OBP/include -fdefault-integer-8 -o test_dyn.exe test64_.f90 $dynamic_libname
gfortran -I $OBP/include -fdefault-integer-8 -o test.exe ${repo_path}/test64_.f90 $static_libname
gfortran -I $OBP/include -fdefault-integer-8 -o test_dyn.exe ${repo_path}/test64_.f90 $dynamic_libname
else
gfortran -I $OBP/include -o test.exe test.f90 $static_libname
gfortran -I $OBP/include -o test_dyn.exe test.f90 $dynamic_libname
gfortran -I $OBP/include -o test.exe ${repo_path}/test.f90 $static_libname
gfortran -I $OBP/include -o test_dyn.exe ${repo_path}/test.f90 $dynamic_libname
fi
108 changes: 69 additions & 39 deletions tools/build_openblas.sh
Original file line number Diff line number Diff line change
@@ -1,40 +1,62 @@
#!/bin/bash
# Build script for OpenBLAS on Windows
# Expects environment variables:
# OPENBLAS_ROOT
# OPENBLAS_COMMIT
# BUILD_BITS
# START_DIR
# Expects "lib.exe" and "gcc" to be on the path
#
# Usage: build_openblas.sh [openblas_root [build_bits [if_bits]]]
#
# e.g build_openblas.sh c:\\opt 64 32
#
# Uses the optional environment variables. We always prefer command line argument
# values above to environment variable values:
#
# OPENBLAS_ROOT (default directory root for binaries, unspecified -> c:\opt).
# BUILD_BITS (default binary architecture, 32 or 64, unspec -> 64).
# INTERFACE64 (1 for 64-bit interface, anything else or undefined for 32,
# This gives the default value if if_bits not specified above).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to make the connection between the command line if_bits and the INTERFACE64 environment variable more explicit. What happens if I specify if_bits==32 like in the example above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above was meant to cover that, unless I misunderstood:

# Uses the optional environment variables. We always prefer command line argument

# START_DIR (directory containing OpenBLAS source, unspec -> .. from here)
# OPENBLAS_COMMIT (unspec -> current submodule commit)
# LDFLAGS (example: "-lucrt -static -static-libgcc")
#
# Expects at leasts these binaries on the PATH:
# realpath, cygpath, zip, gcc, make, ar, dlltool
# usually as part of an msys installation.

set -ex
# Convert to Unix-style path
openblas_root="$(cygpath ${1:-${OPENBLAS_ROOT:-c:\\opt}})"
build_bits="${2:-${BUILD_BITS:-64}}"
if [ "$INTERFACE64" == "1" ]; then if_default=64; else if_default=32; fi
if_bits=${3:-${if_default}}
# Our directory for later copying
if [ -z "$START_DIR" ]; then
our_wd="$(realpath $(dirname "${BASH_SOURCE[0]}")/..)"
else
our_wd=$(cygpath "$START_DIR")
fi

# Paths in Unix format
OPENBLAS_ROOT=$(cygpath "$OPENBLAS_ROOT")
echo "Building from $our_wd, to $openblas_root"
echo "Binaries are $build_bits bit, interface is $if_bits bit"
echo "Using gcc at $(which gcc), --version:"
gcc --version

# Our directory for later copying
our_wd=$(cygpath "$START_DIR")
cd $our_wd
# Make output directory for build artifacts
rm -rf builds
mkdir builds
builds_dir="$our_wd/builds"
rm -rf $builds_dir
mkdir $builds_dir

cd OpenBLAS
cd "${our_wd}/OpenBLAS"
git submodule update --init --recursive

# Check which gcc we're using
which gcc
gcc --version

# Get / clean code
git fetch origin
git checkout $OPENBLAS_COMMIT
if [ -n "$OPENBLAS_COMMIT" ]; then
git checkout $OPENBLAS_COMMIT
fi
git clean -fxd
git reset --hard
rm -rf $OPENBLAS_ROOT/$BUILD_BITS
rm -rf $openblas_root/$build_bits

# Set architecture flags
if [ "$BUILD_BITS" == 64 ]; then
if [ "$build_bits" == 64 ]; then
march="x86-64"
# https://csharp.wekeepcoding.com/article/10463345/invalid+register+for+.seh_savexmm+in+Cygwin
extra="-fno-asynchronous-unwind-tables"
Expand All @@ -51,9 +73,9 @@ cflags="-O2 -march=$march -mtune=generic $extra"
fflags="$fextra $cflags -frecursive -ffpe-summary=invalid,zero"

# Set suffixed-ILP64 flags
if [ "$INTERFACE64" == "1" ]; then
interface64_flags="INTERFACE64=1 SYMBOLSUFFIX=64_"
SYMBOLSUFFIX=64_
if [ "$if_bits" == "64" ]; then
SYMBOLSUFFIX="64_"
interface64_flags="INTERFACE64=1 SYMBOLSUFFIX=${SYMBOLSUFFIX}"
# We override FCOMMON_OPT, so we need to set default integer manually
fflags="$fflags -fdefault-integer-8"
else
Expand All @@ -66,42 +88,50 @@ OPENBLAS_VERSION=$(git describe --tags)
# Build OpenBLAS
# Variable used in creating output libraries
export LIBNAMESUFFIX=${OPENBLAS_VERSION}-${GCC_TAG}
make BINARY=$BUILD_BITS DYNAMIC_ARCH=1 USE_THREAD=1 USE_OPENMP=0 \
make BINARY=$build_bits DYNAMIC_ARCH=1 USE_THREAD=1 USE_OPENMP=0 \
NUM_THREADS=24 NO_WARMUP=1 NO_AFFINITY=1 CONSISTENT_FPCSR=1 \
BUILD_LAPACK_DEPRECATED=1 TARGET=PRESCOTT BUFFERSIZE=20\
LDFLAGS="$LDFLAGS" \
COMMON_OPT="$cflags" \
FCOMMON_OPT="$fflags" \
MAX_STACK_ALLOC=2048 \
$interface64_flags
make PREFIX=$OPENBLAS_ROOT/$BUILD_BITS $interface64_flags install
make PREFIX=$openblas_root/$build_bits $interface64_flags install
DLL_BASENAME=libopenblas${SYMBOLSUFFIX}_${LIBNAMESUFFIX}
if [ "$INTERFACE64" == "1" ]; then
if [ "$if_bits" == "64" ]; then
# OpenBLAS does not build a symbol-suffixed static library on Windows:
# do it ourselves
set -x # echo commands
static_libname=$(find . -maxdepth 1 -type f -name '*.a' \! -name '*.dll.a' | tail -1)
make -C exports $interface64_flags objcopy.def
objcopy --redefine-syms exports/objcopy.def "${static_libname}" "${static_libname}.renamed"
cp -f "${static_libname}.renamed" "$OPENBLAS_ROOT/$BUILD_BITS/lib/${static_libname}"
cp -f "${static_libname}.renamed" "$OPENBLAS_ROOT/$BUILD_BITS/lib/${DLL_BASENAME}.a"
cp -f "${static_libname}.renamed" "$openblas_root/$build_bits/lib/${static_libname}"
cp -f "${static_libname}.renamed" "$openblas_root/$build_bits/lib/${DLL_BASENAME}.a"
set +x
fi
cd $OPENBLAS_ROOT
cd $openblas_root
# Copy library link file for custom name
cd $BUILD_BITS/lib
cd $build_bits/lib
cp ${our_wd}/OpenBLAS/exports/${DLL_BASENAME}.def ${DLL_BASENAME}.def
# At least for the mingwpy wheel, we have to use the VC tools to build the
# export library. Maybe fixed in later binutils by patch referred to in
# https://sourceware.org/ml/binutils/2016-02/msg00002.html
cp ${our_wd}/OpenBLAS/exports/${DLL_BASENAME}.def ${DLL_BASENAME}.def
"lib.exe" /machine:${vc_arch} /def:${DLL_BASENAME}.def
# "lib.exe" /machine:${vc_arch} /def:${DLL_BASENAME}.def
# Maybe this will now work (after 2016 patch above).
dlltool --input-def ${DLL_BASENAME}.def \
--output-exp ${DLL_BASENAME}.exp \
--dllname ${DLL_BASENAME}.dll \
--output-lib ${DLL_BASENAME}.lib
# Replace the DLL name with the generated name.
sed -i "s/ -lopenblas$/ -l${DLL_BASENAME:3}/g" pkgconfig/openblas.pc
cd ../..
# Build template site.cfg for using this build
cat > ${BUILD_BITS}/site.cfg.template << EOF
cat > ${build_bits}/site.cfg.template << EOF
[openblas${SYMBOLSUFFIX}]
libraries = $DLL_BASENAME
library_dirs = {openblas_root}\\${BUILD_BITS}\\lib
include_dirs = {openblas_root}\\${BUILD_BITS}\\include
library_dirs = {openblas_root}\\${build_bits}\\lib
include_dirs = {openblas_root}\\${build_bits}\\include
EOF
ZIP_NAME="openblas${SYMBOLSUFFIX}-${OPENBLAS_VERSION}-${plat_tag}-${GCC_TAG}.zip"
zip -r $ZIP_NAME $BUILD_BITS
cp $ZIP_NAME $our_wd/builds
zip_name="openblas${SYMBOLSUFFIX}-${OPENBLAS_VERSION}-${plat_tag}-${GCC_TAG}.zip"
zip -r $zip_name $build_bits
cp $zip_name ${builds_dir}