Skip to content
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

WIP: patch OpenBLAS build for quadmath symbols #85

Closed

Conversation

matthew-brett
Copy link
Contributor

Apply Carl's patch to OpenBLAS export build of library, to remove
libquatmath symbol.

See:
#82 (comment)

Disabled for 32-bit (symbol missing).

We should try and apply this for Unix builds.

@mattip
Copy link
Collaborator

mattip commented Jul 30, 2024

@matthew-brett I am going to push forward with this to solve numpy/numpy#27080. How can I make sure no quadmath symbols are used in the static compilation of libscipy-openblas.dll?

@matthew-brett
Copy link
Contributor Author

@carlkl - this was your patch - any thoughts on - for example - debugging or upstreaming to OpenBLAS?

@carlkl
Copy link

carlkl commented Jul 31, 2024

This patch should be reworked or better replaced by a different PR.

In a static compilation of libscipy-openblas.dll all references to libquadmath symbols should disappear. This behaviour can be proved by linking with a linking map. I've done this a while ago.

I'm using now a different patchset for Openblas for binary size reduction. I can take a look at this the next days I there is interest.

@mattip
Copy link
Collaborator

mattip commented Jul 31, 2024

The changes in the patch still are valid, although the line numbers have changed a bit. I tried it and the library builds, so it would be nice to put this in for windows, especially in light of the different licensing of quadmath (LGPL) which makes the static linking on windows problematic, see numpy/numpy#27080

matthew-brett and others added 3 commits July 31, 2024 22:16
Apply Carl's patch to OpenBLAS export build of library, to remove
libquatmath symbol.

See:
MacPython#82 (comment)
@mattip
Copy link
Collaborator

mattip commented Jul 31, 2024

I rebased off main and updated the line numbers in the patch.

@mattip
Copy link
Collaborator

mattip commented Aug 1, 2024

The dynamic link command is failing since $dynamic_libname is empty, somehow the build is not creating the expected *.dll.a anymore. This line in the changeset seems relevant, I wonder why it is not creating the import library. I will try to reproduce locally.

@carlkl
Copy link

carlkl commented Aug 1, 2024

This patch was supplied myself several years ago, either as part of an issue or privately per EMail. (I can't remember).
In the meantime reworked this patch several times a little bit.
EDIT: found it: #82 (comment)

Regarding libquadmath symbols: some time ago I investigated whether libquadmath symbols are actually used in a statically linked OpenBLAS binary. This is not the case, as can be seen by examining the linker map, at least if -Wl,s is used as well.
EDIT: -Wl,--defsym,quadmath_snprintf=snprintf is not necessary in case of static linking

However, I won't have time before the weekend to go into further details.

@carlkl
Copy link

carlkl commented Aug 1, 2024

You may tryout something like this:

# On Windows, we only generate a DLL without a version suffix.  This is because
# applications which link against the dynamic library reference a fixed DLL name
# in their import table.  By instead using a stable name it is possible to
# upgrade between library versions, without needing to re-link an application.
# For more details see: https://github.com/xianyi/OpenBLAS/issues/127.
ifeq ($(DEBUG), 1)
../$(LIBDLLNAME) : ../$(LIBNAME) $(LIBPREFIX).def dllinit.$(SUFFIX)
	$(RANLIB) ../$(LIBNAME)
	$(CC) $(CFLAGS) $(LDFLAGS) $(LIBPREFIX).def dllinit.$(SUFFIX) \
	-shared -static -static-libgfortran -o ../$(LIBDLLNAME) -Wl,--out-implib,../$(IMPLIBNAME) \
	-Wl,--whole-archive ../$(LIBNAME) -Wl,--no-whole-archive $(FEXTRALIB) $(EXTRALIB)
else
../$(LIBDLLNAME) : ../$(LIBNAME) $(LIBPREFIX).def dllinit.$(SUFFIX)
	$(RANLIB) ../$(LIBNAME)
	$(CC) $(CFLAGS) $(LDFLAGS) $(LIBPREFIX).def dllinit.$(SUFFIX) \
	-shared -static -static-libgfortran -o ../$(LIBDLLNAME) -Wl,--out-implib,../$(IMPLIBNAME) \
	-Wl,-gc-sections -Wl,-s \
	-Wl,--whole-archive ../$(LIBNAME) -Wl,--no-whole-archive $(FEXTRALIB) $(EXTRALIB)
endif

Something was not working with the DEBUG case as far as I remember, so you can also simply try:

# On Windows, we only generate a DLL without a version suffix.  This is because
# applications which link against the dynamic library reference a fixed DLL name
# in their import table.  By instead using a stable name it is possible to
# upgrade between library versions, without needing to re-link an application.
# For more details see: https://github.com/xianyi/OpenBLAS/issues/127.
../$(LIBDLLNAME) : ../$(LIBNAME) $(LIBPREFIX).def dllinit.$(SUFFIX)
	$(RANLIB) ../$(LIBNAME)
	$(CC) $(CFLAGS) $(LDFLAGS) $(LIBPREFIX).def dllinit.$(SUFFIX) \
	-shared -static -static-libgfortran -o ../$(LIBDLLNAME) -Wl,--out-implib,../$(IMPLIBNAME) \
	-Wl,-gc-sections -Wl,-s \
	-Wl,--whole-archive ../$(LIBNAME) -Wl,--no-whole-archive $(FEXTRALIB) $(EXTRALIB)

Another hint: some years ago creation the creation of the .dll.a import library only works correct with dlltool.exe
With newer binutils and gcc versions it works as expected.

@carlkl
Copy link

carlkl commented Aug 4, 2024

@mattip, @matthew-brett
I changed my mind about my proposed OpenBLAS patch, see #85 (comment). Did you took this into account?

@mattip
Copy link
Collaborator

mattip commented Aug 4, 2024

Sorry, I am not sure I understand. What is the difference between the latest suggestion and the patch?

@carlkl
Copy link

carlkl commented Aug 4, 2024

The replacement of the quadmath_snprintf symbol is not needed. My fault, I proposed it without further estimation at time.

@mattip
Copy link
Collaborator

mattip commented Aug 4, 2024

Are you sure? When I changed FEXTRALIBS to exlude -lquadmath, OpenBLAS no longer linked (on windows), quadmath_snprintf was missing. Here is the diff I used:

diff --git a/f_check b/f_check
index 93c5962de..ce326b614 100755
--- a/f_check
+++ b/f_check
@@ -380,7 +380,7 @@ if [ -n "$link" ]; then
         case "$flag" in -l*)
             case "$flag" in
                 *ibrary*|*gfortranbegin*|*flangmain*|*frtbegin*|*pathfstart*|\
-                    *crt[0-9]*|*gcc*|*user32*|*kernel32*|*advapi32*|*shell32*|\
+                    *crt[0-9]*|*gcc*|*user32*|*kernel32*|*advapi32*|*shell32*|quadmath*|\
                     -l) ;;
                 *omp*)
                     case "$vendor" in

Currently the patch includes -Wl,--defsym,quadmath_snprintf=snprintf, but does not modify f_check.

@carlkl
Copy link

carlkl commented Aug 4, 2024

at least it doesn't harm. In some years one may ask why this was necessary...

During the linking stage libquadmath is necessary to resolve quadmath_snprintf, as this symbol is needed by libgfortran (compiled with quadmath support). However, with -Wl,-gc-sections -Wl,-s alls symbols are sorted out, that are not needed by libquadmath.dll. If quadmath_snprintf is part of the dll at the end can be checked with -Wl,-Map,output.map.
For libquadmath.dll this is not the case, hence we don't have a dependancy on the quadmath library.

@mattip
Copy link
Collaborator

mattip commented Aug 5, 2024

Thanks, that helps clear up what is going on.

If quadmath_snprintf is part of the dll at the end can be checked with -Wl,-Map,output.map

Cool. I will see if I can make this part of the build script.

@mattip mattip force-pushed the drop-quadmath-symbol branch 2 times, most recently from 6b8258c to 849965d Compare August 6, 2024 06:56
@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

I would like to merge this and get scipy-openblas wheels built for consideration in the upcoming NumPy 2.1 release, to mitigate issue numpy/numpy#27080. Any objections?

@matthew-brett
Copy link
Contributor Author

Do we currently trigger uses of the relevant snprintf calls in tests? Just to check if they crash or produce wrong output?

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

Do we currently trigger uses of the relevant snprintf calls in tests?

No idea. Any thoughts how to check it?

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

Maybe via a LD_PRELOAD stub shared object on linux that exports quadmath_snprintf (since on linux we dynamically link)?

@carlkl
Copy link

carlkl commented Aug 7, 2024

Some years ago I replaced quadmath_snprintf with abort, but it never hits.

The symbol quadmath_snprintf is an dependancy you will get with gfortran in almost every non-trivial program, as the gfortran print routines are linked against libquadmath. But you need the functionality only if you use quadmath floating point values. In this case you will need much more symbols from libquadmath aside quadmath_snprintf .

@matthew-brett
Copy link
Contributor Author

Would we be better placed to make a stub quadmath_snprintf implementation ourselves, that generates a suitable warning?

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

I am not so concerned that the slight differences between _snprinf and the UCRT snprintf will cause problems. Only on 32-bits _snprintf is used, and NumPy does not even have a complex256 dtype on windows64, much less on the seldom-used windows32.

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

Some years ago I replaced quadmath_snprintf with abort, but it never hits.

Is that code still around?

@carlkl
Copy link

carlkl commented Aug 7, 2024

This is the full list of all symbols libquadmath.dll (gcc-ucrt 64bit) depends on:
(quadmath_snprintf replaced by snprintf)

list of libquadmath.dll dependencies
  1, 0x18d5728, KERNEL32.dll, CloseHandle, 149
  2, 0x18d5730, KERNEL32.dll, CreateEventA, 206
  3, 0x18d5738, KERNEL32.dll, CreateFileA, 213
  4, 0x18d5740, KERNEL32.dll, CreateSemaphoreA, 252
  5, 0x18d5748, KERNEL32.dll, CreateThread, 261
  6, 0x18d5750, KERNEL32.dll, DeleteCriticalSection, 293
  7, 0x18d5758, KERNEL32.dll, DuplicateHandle, 323
  8, 0x18d5760, KERNEL32.dll, EnterCriticalSection, 331
  9, 0x18d5768, KERNEL32.dll, GetCurrentProcess, 565
 10, 0x18d5770, KERNEL32.dll, GetCurrentProcessId, 566
 11, 0x18d5778, KERNEL32.dll, GetCurrentThread, 569
 12, 0x18d5780, KERNEL32.dll, GetCurrentThreadId, 570
 13, 0x18d5788, KERNEL32.dll, GetEnvironmentVariableA, 601
 14, 0x18d5790, KERNEL32.dll, GetFileAttributesA, 611
 15, 0x18d5798, KERNEL32.dll, GetFileInformationByHandle, 618
 16, 0x18d57a0, KERNEL32.dll, GetHandleInformation, 640
 17, 0x18d57a8, KERNEL32.dll, GetLastError, 644
 18, 0x18d57b0, KERNEL32.dll, GetModuleFileNameA, 664
 19, 0x18d57b8, KERNEL32.dll, GetModuleHandleA, 666
 20, 0x18d57c0, KERNEL32.dll, GetProcAddress, 726
 21, 0x18d57c8, KERNEL32.dll, GetProcessAffinityMask, 727
 22, 0x18d57d0, KERNEL32.dll, GetProcessTimes, 743
 23, 0x18d57d8, KERNEL32.dll, GetSystemInfo, 781
 24, 0x18d57e0, KERNEL32.dll, GetSystemTimeAsFileTime, 787
 25, 0x18d57e8, KERNEL32.dll, GetTempPathA, 801
 26, 0x18d57f0, KERNEL32.dll, GetThreadContext, 803
 27, 0x18d57f8, KERNEL32.dll, GetThreadPriority, 814
 28, 0x18d5800, KERNEL32.dll, GetTickCount, 821
 29, 0x18d5808, KERNEL32.dll, GetVersion, 841
 30, 0x18d5810, KERNEL32.dll, InitializeCriticalSection, 914
 31, 0x18d5818, KERNEL32.dll, IsDebuggerPresent, 942
 32, 0x18d5820, KERNEL32.dll, IsProcessorFeaturePresent, 950
 33, 0x18d5828, KERNEL32.dll, LeaveCriticalSection, 1008
 34, 0x18d5830, KERNEL32.dll, OpenProcess, 1093
 35, 0x18d5838, KERNEL32.dll, OutputDebugStringA, 1102
 36, 0x18d5840, KERNEL32.dll, QueryPerformanceCounter, 1157
 37, 0x18d5848, KERNEL32.dll, QueryPerformanceFrequency, 1158
 38, 0x18d5850, KERNEL32.dll, RaiseException, 1180
 39, 0x18d5858, KERNEL32.dll, ReleaseSemaphore, 1224
 40, 0x18d5860, KERNEL32.dll, ResetEvent, 1242
 41, 0x18d5868, KERNEL32.dll, ResumeThread, 1249
 42, 0x18d5870, KERNEL32.dll, RtlCaptureContext, 1251
 43, 0x18d5878, KERNEL32.dll, RtlLookupFunctionEntry, 1259
 44, 0x18d5880, KERNEL32.dll, RtlUnwindEx, 1265
 45, 0x18d5888, KERNEL32.dll, RtlVirtualUnwind, 1266
 46, 0x18d5890, KERNEL32.dll, SetEndOfFile, 1330
 47, 0x18d5898, KERNEL32.dll, SetEvent, 1336
 48, 0x18d58a0, KERNEL32.dll, SetLastError, 1365
 49, 0x18d58a8, KERNEL32.dll, SetProcessAffinityMask, 1376
 50, 0x18d58b0, KERNEL32.dll, SetThreadContext, 1402
 51, 0x18d58b8, KERNEL32.dll, SetThreadPriority, 1412
 52, 0x18d58c0, KERNEL32.dll, Sleep, 1444
 53, 0x18d58c8, KERNEL32.dll, SuspendThread, 1453
 54, 0x18d58d0, KERNEL32.dll, SwitchToThread, 1455
 55, 0x18d58d8, KERNEL32.dll, TerminateProcess, 1460
 56, 0x18d58e0, KERNEL32.dll, TerminateThread, 1461
 57, 0x18d58e8, KERNEL32.dll, TlsAlloc, 1478
 58, 0x18d58f0, KERNEL32.dll, TlsGetValue, 1480
 59, 0x18d58f8, KERNEL32.dll, TlsSetValue, 1481
 60, 0x18d5900, KERNEL32.dll, TryEnterCriticalSection, 1487
 61, 0x18d5908, KERNEL32.dll, VirtualAlloc, 1521
 62, 0x18d5910, KERNEL32.dll, VirtualFree, 1524
 63, 0x18d5918, KERNEL32.dll, VirtualProtect, 1527
 64, 0x18d5920, KERNEL32.dll, VirtualQuery, 1529
 65, 0x18d5928, KERNEL32.dll, WaitForMultipleObjects, 1536
 66, 0x18d5930, KERNEL32.dll, WaitForSingleObject, 1538
 
 67, 0x18d5940, api-ms-win-crt-conio-l1-1-0.dll (ucrtbase.dll), __conio_common_vcprintf, 1
 
 68, 0x18d5950, api-ms-win-crt-convert-l1-1-0.dll (ucrtbase.dll), atoi, 87
 69, 0x18d5958, api-ms-win-crt-convert-l1-1-0.dll (ucrtbase.dll), mbrtowc, 95
 70, 0x18d5960, api-ms-win-crt-convert-l1-1-0.dll (ucrtbase.dll), wcrtomb, 109
 
 71, 0x18d5970, api-ms-win-crt-environment-l1-1-0.dll (ucrtbase.dll), __p__environ, 1
 72, 0x18d5978, api-ms-win-crt-environment-l1-1-0.dll (ucrtbase.dll), __p__wenviron, 2
 73, 0x18d5980, api-ms-win-crt-environment-l1-1-0.dll (ucrtbase.dll), getenv, 19
 
 74, 0x18d5990, api-ms-win-crt-filesystem-l1-1-0.dll (ucrtbase.dll), _fstat64, 24
 75, 0x18d5998, api-ms-win-crt-filesystem-l1-1-0.dll (ucrtbase.dll), _lock_file, 32
 76, 0x18d59a0, api-ms-win-crt-filesystem-l1-1-0.dll (ucrtbase.dll), _stat64, 44
 77, 0x18d59a8, api-ms-win-crt-filesystem-l1-1-0.dll (ucrtbase.dll), _unlock_file, 52
 78, 0x18d59b0, api-ms-win-crt-filesystem-l1-1-0.dll (ucrtbase.dll), remove, 85
 
 79, 0x18d59c0, api-ms-win-crt-heap-l1-1-0.dll (ucrtbase.dll), _set_new_mode, 24
 80, 0x18d59c8, api-ms-win-crt-heap-l1-1-0.dll (ucrtbase.dll), calloc, 25
 81, 0x18d59d0, api-ms-win-crt-heap-l1-1-0.dll (ucrtbase.dll), free, 26
 82, 0x18d59d8, api-ms-win-crt-heap-l1-1-0.dll (ucrtbase.dll), malloc, 27
 83, 0x18d59e0, api-ms-win-crt-heap-l1-1-0.dll (ucrtbase.dll), realloc, 28
 
 84, 0x18d59f0, api-ms-win-crt-locale-l1-1-0.dll (ucrtbase.dll), localeconv, 20
 85, 0x18d59f8, api-ms-win-crt-locale-l1-1-0.dll (ucrtbase.dll), setlocale, 21
 
 86, 0x18d5a08, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), atan2, 96
 87, 0x18d5a10, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), atan2f, 97
 88, 0x18d5a18, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), cos, 155
 89, 0x18d5a20, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), cosf, 156
 90, 0x18d5a28, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), cosh, 157
 91, 0x18d5a30, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), exp, 189
 92, 0x18d5a38, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), expf, 193
 93, 0x18d5a40, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), frexp, 214
 94, 0x18d5a48, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), hypot, 215
 95, 0x18d5a50, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), log, 229
 96, 0x18d5a58, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), log10, 230
 97, 0x18d5a60, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), log10f, 231
 98, 0x18d5a68, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), logf, 241
 99, 0x18d5a70, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), lround, 245
100, 0x18d5a78, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), lroundf, 246
101, 0x18d5a80, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), pow, 265
102, 0x18d5a88, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), powf, 266
103, 0x18d5a90, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), sin, 285
104, 0x18d5a98, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), sinf, 286
105, 0x18d5aa0, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), sinh, 287
106, 0x18d5aa8, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), sqrt, 289
107, 0x18d5ab0, api-ms-win-crt-math-l1-1-0.dll (ucrtbase.dll), sqrtf, 290

108, 0x18d5ac0, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), __C_specific_handler, 16
109, 0x18d5ac8, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), __intrinsic_setjmpex, 40
110, 0x18d5ad0, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), longjmp, 1141
111, 0x18d5ad8, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), memcmp, 1143
112, 0x18d5ae0, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), memcpy, 1144
113, 0x18d5ae8, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), memmove, 1145
114, 0x18d5af0, api-ms-win-crt-private-l1-1-0.dll (ucrtbase.dll), strchr, 1148

115, 0x18d5b00, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), __p___argc, 5
116, 0x18d5b08, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), __p___argv, 6
117, 0x18d5b10, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), __p___wargv, 7
118, 0x18d5b18, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), __p__pgmptr, 9
119, 0x18d5b20, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _assert, 19
120, 0x18d5b28, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _beginthreadex, 21
121, 0x18d5b30, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _configure_narrow_argv, 25
122, 0x18d5b38, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _configure_wide_argv, 26
123, 0x18d5b40, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _crt_at_quick_exit, 30
124, 0x18d5b48, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _crt_atexit, 31
125, 0x18d5b50, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _endthreadex, 34
126, 0x18d5b58, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _errno, 35
127, 0x18d5b60, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _execute_onexit_table, 36
128, 0x18d5b68, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _exit, 37
129, 0x18d5b70, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _fpreset, 39
130, 0x18d5b78, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _getpid, 52
131, 0x18d5b80, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _initialize_narrow_environment, 54
132, 0x18d5b88, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _initialize_onexit_table, 55
133, 0x18d5b90, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _initialize_wide_environment, 56
134, 0x18d5b98, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _initterm, 57
135, 0x18d5ba0, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), _register_onexit_function, 63
136, 0x18d5ba8, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), abort, 88
137, 0x18d5bb0, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), exit, 89
138, 0x18d5bb8, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), raise, 101
139, 0x18d5bc0, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), signal, 103
140, 0x18d5bc8, api-ms-win-crt-runtime-l1-1-0.dll (ucrtbase.dll), strerror, 104

141, 0x18d5bd8, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), __acrt_iob_func, 1
142, 0x18d5be0, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), __stdio_common_vfprintf, 4
143, 0x18d5be8, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), __stdio_common_vfwprintf, 8
144, 0x18d5bf0, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), __stdio_common_vsprintf, 14
145, 0x18d5bf8, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _close, 25
146, 0x18d5c00, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _dup, 31
147, 0x18d5c08, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _get_osfhandle, 69
148, 0x18d5c10, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _isatty, 83
149, 0x18d5c18, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _lseeki64, 89
150, 0x18d5c20, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _open, 94
151, 0x18d5c28, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _read, 106
152, 0x18d5c30, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _sopen, 116
153, 0x18d5c38, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _setmode, 113
154, 0x18d5c40, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), _write, 139
155, 0x18d5c48, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), fflush, 151
156, 0x18d5c50, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), fputc, 159
157, 0x18d5c58, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), fwrite, 170
158, 0x18d5c60, api-ms-win-crt-stdio-l1-1-0.dll (ucrtbase.dll), puts, 179

159, 0x18d5c70, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), _strdup, 54
160, 0x18d5c78, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), _strnicmp, 65
161, 0x18d5c80, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), isalnum, 129
162, 0x18d5c88, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), memset, 160
163, 0x18d5c90, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), strcat, 161
164, 0x18d5c98, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), strcmp, 163
165, 0x18d5ca0, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), strlen, 168
166, 0x18d5ca8, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), strncmp, 171
167, 0x18d5cb0, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), strncpy, 172
168, 0x18d5cb8, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), tolower, 179
169, 0x18d5cc0, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), toupper, 180
170, 0x18d5cc8, api-ms-win-crt-string-l1-1-0.dll (ucrtbase.dll), wcslen, 191

171, 0x18d5cd8, api-ms-win-crt-time-l1-1-0.dll (ucrtbase.dll), __daylight, 10
172, 0x18d5ce0, api-ms-win-crt-time-l1-1-0.dll (ucrtbase.dll), __timezone, 14
173, 0x18d5ce8, api-ms-win-crt-time-l1-1-0.dll (ucrtbase.dll), __tzname, 15
174, 0x18d5cf0, api-ms-win-crt-time-l1-1-0.dll (ucrtbase.dll), _tzset, 61

175, 0x18d5d00, api-ms-win-crt-utility-l1-1-0.dll (ucrtbase.dll), bsearch, 20
176, 0x18d5d08, api-ms-win-crt-utility-l1-1-0.dll (ucrtbase.dll), rand, 31
177, 0x18d5d10, api-ms-win-crt-utility-l1-1-0.dll (ucrtbase.dll), rand_s, 32

@matthew-brett
Copy link
Contributor Author

Sorry to be confusing - my worry was rather that we somehow generate a segfault or similar with this relinking, triggered when some BLAS / LAPACK routine ends up calling quad_snprintf, and that we'll only find out when we hit a code path where that happens. I guess we'd need to find out where in the Fortran code quad_snprintf is being called, and work out some way of hitting that code.

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

Ahh. There is some test code for quadmath. We could

  • get that to work under linux, and use ltrace -l quadmath to see if anything there calls quadmath_snprinf
  • then get that running under mingw, and then use the same link flag to replace the symbol, and make sure tests pass

But I think your analysis when you replaced quadmath_snprintf is correct: there is a vanishingly small possibility code will hit that code path. NumPy/SciPy do not use quadmath at all. In order to hit the code path someone would need to write their own code that uses quadmath, but not call any quadmath routines other than quadmath_snprintf (since all the other routines are not linked into the dll), build a python library out of it, still use the OpenBLAS dll from NumPy/Scipy, and run that code on windows

@matthew-brett
Copy link
Contributor Author

Thanks for the analysis. My suggestion before was to write some stub that would catch that very rare case and give some informative error, just in case.

@carlkl
Copy link

carlkl commented Aug 7, 2024

A stub with warning is a good idea IMHO.

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

OK, let's see how hard it is to add a stub that prints a warning to stderr and calls snprintf/_snprintf.

@rgommers
Copy link
Collaborator

rgommers commented Aug 7, 2024

Hey all. Unless the stub is like <= 1hr of work and can be finished today, I would strongly suggest that it's way more important to get new wheels up than mitigate some very low-probability event with a better error message. NumPy 2.1.x just branched 2.5 hours ago and if we miss the boat there we both have the potential license concern being unresolved and may cause an extra numpy RC to be needed, delaying the rollout for Python 3.13 support.

@carlkl
Copy link

carlkl commented Aug 7, 2024

Another analysis:

if you link OpenBLAS non-static, you will get te following additional dependencies:

1, 0x188d4e0, libgcc_s_seh-1.dll, __emutls_get_address, 46
2, 0x188d4e8, libgcc_s_seh-1.dll, __powidf2, 115
3, 0x188d4f0, libgcc_s_seh-1.dll, __powisf2, 116

4, 0x188d500, libgfortran-5.dll, _gfortran_concat_string, 194
5, 0x188d508, libgfortran-5.dll, _gfortran_etime, 294

the reason you need libquadmath.dll relies on the fact that libgfortran-5.dll depends on libquadmath.

@carlkl
Copy link

carlkl commented Aug 7, 2024

AFAIK mingw64 has no __noop (MSVC specific), but can define a function simply with

(void)0

or with the help of asm something like that:

.text
.global quadmath_snprintf
quadmath_snprintf:
  ret

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

Sorry, I don't follow. Are you suggesting we replace quadmath_snprintf with a segfault or noop? I thought you wanted a warning?

@carlkl
Copy link

carlkl commented Aug 7, 2024

I'm sure, that quadmath_snprintf is used only by gfortran itself, so there is no codepath within OpenBLAS possible.

I found another way for a detailed analysis: Using -Wl,--trace-symbol=<symbolname>

i.e. if you use i.e. -Wl,--trace-symbol=cos the linker print out the following:

C:/Users/devel/AppData/Local/pool/msys2/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ../libopenblasp-r0.3.28dev.a(dorbdb.o): reference to cos
C:/Users/devel/AppData/Local/pool/msys2/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ../libopenblasp-r0.3.28dev.a(zunbdb.o): reference to cos
C:/Users/devel/AppData/Local/pool/msys2/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ../libopenblasp-r0.3.28dev.a(dlarnv.o): reference to cos
C:/Users/devel/AppData/Local/pool/msys2/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ../libopenblasp-r0.3.28dev.a(dlarnd.o): reference to cos

but with -Wl,--trace-symbol=quadmath_snprintf I got nothing! Not to say that this symbol is not exported in every case.

My conclusion is: replace `quadmath_snprintf`` with a no-op operation.

@mattip
Copy link
Collaborator

mattip commented Aug 7, 2024

Not to say that this symbol is not exported in every case.
My conclusion is: replace `quadmath_snprintf`` with a no-op operation.

If I understand correctly, then it really doesn't matter what replaces quadmath_snprintf, it will not be called in the current win64/win32 builds of OpenBLAS. So what is the difference between adding a no-op function and using the current code (which replaces it with snprintf/_snprintf_c)?

@carlkl
Copy link

carlkl commented Aug 7, 2024

If I understand correctly, then it really doesn't matter what replaces quadmath_snprintf, it will not be called in the current win64/win32 builds of OpenBLAS. So what is the difference between adding a no-op function and using the current code (which replaces it with snprintf/_snprintf_c)?

Yes, correctly. The result is the same.

@mattip
Copy link
Collaborator

mattip commented Aug 11, 2024

Closing, this was merged in the v0.3.28 builds in #178 and backported to the v0.3.27 builds, thanks to @carlkl and @matthew-brett for the original patches and for mentoring the progress.

@mattip mattip closed this Aug 11, 2024
@mattip
Copy link
Collaborator

mattip commented Aug 11, 2024

It may be interesting to see how numpy/numpy-user-dtypes#98 progresses, and if it makes us rethink using quadmathlib on windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants