diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 88051fb4..08ef9720 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -45,13 +45,14 @@ jobs: echo "PLAT=i686" >> $env:GITHUB_ENV echo "WHEEL_PLAT=win32" >> $env:GITHUB_ENV echo "MSYSTEM=MINGW32" >> $env:GITHUB_ENV - echo "LDFLAGS=-static -static-libgcc" >> $env:GITHUB_ENV + # No ucrt on 32-bits, so use _snprintf_c instead + echo "LDFLAGS=-static -static-libgcc -Wl,--defsym,_quadmath_snprintf=__snprintf_c" >> $env:GITHUB_ENV echo "BUILD_BITS=32" >> $env:GITHUB_ENV } else { echo "PLAT=x86_64" >> $env:GITHUB_ENV echo "WHEEL_PLAT=win_amd64" >> $env:GITHUB_ENV echo "MSYSTEM=UCRT64" >> $env:GITHUB_ENV - echo "LDFLAGS=-lucrt -static -static-libgcc" >> $env:GITHUB_ENV + echo "LDFLAGS=-lucrt -static -static-libgcc -Wl,--defsym,quadmath_snprintf=snprintf" >> $env:GITHUB_ENV echo "BUILD_BITS=64" >> $env:GITHUB_ENV } if ( ${{ matrix.INTERFACE64 }} -eq "1" ) { diff --git a/patches-windows/openblas-make-libs.patch b/patches-windows/openblas-make-libs.patch new file mode 100644 index 00000000..1e4d4aeb --- /dev/null +++ b/patches-windows/openblas-make-libs.patch @@ -0,0 +1,15 @@ +diff --git a/exports/Makefile b/exports/Makefile +index 668a4866e..956b51bf4 100644 +--- a/exports/Makefile ++++ b/exports/Makefile +@@ -126,8 +126,9 @@ dll : ../$(LIBDLLNAME) + ../$(LIBDLLNAME) : ../$(LIBNAME) $(LIBPREFIX).def dllinit.$(SUFFIX) + $(RANLIB) ../$(LIBNAME) + $(CC) $(CFLAGS) $(LDFLAGS) $(LIBPREFIX).def dllinit.$(SUFFIX) \ +- -shared -o ../$(LIBDLLNAME) -Wl,--out-implib,../$(IMPLIBNAME) \ ++ -shared -o ../$(LIBDLLNAME) -Wl,-gc-sections -Wl,-s -Wl,-Map,output.map \ + -Wl,--whole-archive ../$(LIBNAME) -Wl,--no-whole-archive $(FEXTRALIB) $(EXTRALIB) ++ dlltool -D $(LIBDLLNAME) -d $(LIBPREFIX).def -l ../$(LIBDLLNAME).a + + $(LIBPREFIX).def : $(GENSYM) + ./$(GENSYM) win2k $(ARCH) dummy $(EXPRECISION) $(NO_CBLAS) $(NO_LAPACK) $(NO_LAPACKE) $(NEED2UNDERSCORES) $(ONLY_CBLAS) "$(SYMBOLPREFIX)" "$(SYMBOLSUFFIX)" $(BUILD_LAPACK_DEPRECATED) $(BUILD_BFLOAT16) $(BUILD_SINGLE) $(BUILD_DOUBLE) $(BUILD_COMPLEX) $(BUILD_COMPLEX16) > $(@F) diff --git a/tools/build_openblas.sh b/tools/build_openblas.sh index 253c6366..f9992994 100644 --- a/tools/build_openblas.sh +++ b/tools/build_openblas.sh @@ -76,7 +76,7 @@ fflags="$fextra $cflags -frecursive -ffpe-summary=invalid,zero" # Set suffixed-ILP64 flags if [ "$if_bits" == "64" ]; then - SYMBOLSUFFIX="64_" + LIBNAMESUFFIX="64_" interface_flags="INTERFACE64=1 SYMBOLSUFFIX=64_ LIBNAMESUFFIX=64_" # We override FCOMMON_OPT, so we need to set default integer manually fflags="$fflags -fdefault-integer-8" @@ -90,8 +90,12 @@ interface_flags="$interface_flags SYMBOLPREFIX=scipy_ LIBNAMEPREFIX=scipy_ FIXED # Build name for output library from gcc version and OpenBLAS commit. GCC_TAG="gcc_$(gcc -dumpversion | tr .- _)" OPENBLAS_VERSION=$(git describe --tags --abbrev=8) + +# Patch OpenBLAS build to resolve all symbols and avoid linking +# with libquadmath +patch -p1 < ../patches-windows/openblas-make-libs.patch + # Build OpenBLAS -# Variable used in creating output libraries 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\ @@ -100,8 +104,38 @@ make BINARY=$build_bits DYNAMIC_ARCH=1 USE_THREAD=1 USE_OPENMP=0 \ FCOMMON_OPT="$fflags" \ MAX_STACK_ALLOC=2048 \ $interface_flags + +# Make sure quadmath library is not statically linked in to the DLL by checking +# the output.map generated by the linker when using `-Wl,-gc-sections -Wl,-s` +# the map will have libname(o-filename) for each function pulled out of the +# library libname +# The file itself appears in the map, so look for "libquadmath.a(". Use '-A 3' +# to show a bit of context if any symbols appear (which should not happen) +set +e +grep -A 2 "libquadmath.a(" exports/output.map +case $? in + 0) + echo "link uses libquadmath.a when it should not" + exit -1 + ;; + 1) + if [ -f exports/output.map ]; then + echo "Good, verified no 'libquadmath' used when linking" + else + echo "error occurred" + exit -1 + fi + ;; + *) + echo "grep returned $?, error occurred" + exit -1 + ;; +esac +set -e + make PREFIX=$openblas_root/$build_bits $interface_flags install -DLL_BASENAME=libscipy_openblas${SYMBOLSUFFIX}${LIBNAMESUFFIX} +DLL_BASENAME=libscipy_openblas${LIBNAMESUFFIX} +cp -f *.dll.a $openblas_root/$build_bits/lib/${DLL_BASENAME}.dll.a # OpenBLAS does not build a symbol-suffixed static library on Windows: # do it ourselves. On 32-bit builds, the objcopy.def names need a '_' prefix @@ -143,16 +177,8 @@ else sed -e "s/^Cflags.*/\0 -DBLAS_SYMBOL_PREFIX=scipy_/" -i pkgconfig/scipy-openblas.pc fi popd -# Build template site.cfg for using this build -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 -EOF - ls $openblas_root/$build_bits/lib -zip_name="openblas${SYMBOLSUFFIX}-${OPENBLAS_VERSION}-${plat_tag}-${GCC_TAG}.zip" +zip_name="openblas${LIBNAMESUFFIX}-${OPENBLAS_VERSION}-${plat_tag}-${GCC_TAG}.zip" zip -r $zip_name $build_bits cp $zip_name ${builds_dir} diff --git a/tools/windows_build.bat b/tools/windows_build.bat new file mode 100644 index 00000000..2ecc9286 --- /dev/null +++ b/tools/windows_build.bat @@ -0,0 +1,14 @@ +rem Build x86_64 OpenBLAS locally with 64-bit interfaces +rem Requires c:\rtools40 +set BASH_PATH=c:\rtools40\usr\bin\bash.exe +set BUILD_BITS=64 +set CHERE_INVOKING=yes +set INTERFACE64=1 +set LDFLAGS=-lucrt -static -static-libgcc -Wl,--defsym,quadmath_snprintf=snprintf +set MSYSTEM=UCRT64 +set PLAT=x86_64 +set START_DIR=d:\pypy_stuff\openblas-libs +set OPENBLAS_ROOT=c:\\opt +rmdir /q /s c:\opt\64 +rem %BASH_PATH% -lc tools/build_openblas.sh +rem %BASH_PATH% -lc tools/build_gfortran.sh