Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package libblastrampoline for
openSUSE:Factory checked in at 2023-05-07 18:54:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libblastrampoline (Old)
and /work/SRC/openSUSE:Factory/.libblastrampoline.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libblastrampoline"
Sun May 7 18:54:37 2023 rev:3 rq:1085313 version:5.8.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/libblastrampoline/libblastrampoline.changes
2023-03-24 15:21:53.663348859 +0100
+++
/work/SRC/openSUSE:Factory/.libblastrampoline.new.1533/libblastrampoline.changes
2023-05-07 18:54:43.788174515 +0200
@@ -1,0 +2,18 @@
+Sat May 6 01:14:41 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 5.8.0:
+ * Avoid running `init_config()` more than once per process
+
+-------------------------------------------------------------------
+Mon May 1 07:59:43 UTC 2023 - Soc Virnyl Estela <[email protected]>
+
+- Update to version 5.7.0
+ * Prevent setting infinite loopback forwards
+ * Add support for ILP64 Accelerate
+ * Add fallback for when LBT_DEFAULT_LIBS is not set
+ * Eliminate exit(1) calls in LBT
+ * [windows] Fix self-path lookup on Windows
+ * Cygwin build fix
+ * Fix windows compile issue
+
+-------------------------------------------------------------------
Old:
----
libblastrampoline-5.4.0.tar.gz
New:
----
libblastrampoline-5.8.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ libblastrampoline.spec ++++++
--- /var/tmp/diff_new_pack.g3nIAV/_old 2023-05-07 18:54:44.240177037 +0200
+++ /var/tmp/diff_new_pack.g3nIAV/_new 2023-05-07 18:54:44.244177060 +0200
@@ -19,7 +19,7 @@
%global somajor 5
%global libname libblastrampoline%{somajor}
Name: libblastrampoline
-Version: 5.4.0
+Version: 5.8.0
Release: 0
Summary: BLAS/LAPACK demuxer library using PLT trampolines
License: MIT
++++++ libblastrampoline-5.4.0.tar.gz -> libblastrampoline-5.8.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/README.md
new/libblastrampoline-5.8.0/README.md
--- old/libblastrampoline-5.4.0/README.md 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/README.md 2023-05-05 22:15:24.000000000
+0200
@@ -1,4 +1,3 @@
-[](https://github.com/staticfloat/libblastrampoline/actions/workflows/ci.yml)
[](https://cloud.drone.io/staticfloat/libblastrampoline)
# libblastrampoline
@@ -26,6 +25,7 @@
Build `libblastrampoline.so`, then link your BLAS-using library against it
instead of `libblas.so`.
When `libblastrampoline` is loaded, it will inspect the `LBT_DEFAULT_LIBS`
environment variable and attempt to forward BLAS calls made to it on to that
library (this can be a list of semicolon-separated libraries if your backing
implementation is split across multiple libraries, such as in the case of
separate `BLAS` and `LAPACK` libraries).
+If `LBT_DEFAULT_LIBS` is not set, then `libblastrampoline` will fall back to
the definition of the `LBT_FALLBACK_LIBS` macro specified at compile time.
At any time, you may call `lbt_forward(libname, clear, verbose)` to redirect
forwarding to a new BLAS library.
If you set `clear` to `1` it will clear out all previous mappings before
setting new mappings, while if it is set to `0` it will leave symbols that do
not exist within the given `libname` alone.
This is used to implement layering of libraries, such as between a split BLAS
and LAPACK library:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/Make.inc
new/libblastrampoline-5.8.0/src/Make.inc
--- old/libblastrampoline-5.4.0/src/Make.inc 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/src/Make.inc 2023-05-05 22:15:24.000000000
+0200
@@ -98,6 +98,11 @@
COMPLEX_RETSTYLE_AUTODETECTION := 1
endif
+# If we're on an apple platform, we need to support symbol name trimming
+ifeq ($(OS), Darwin)
+ LBT_CFLAGS += -DSYMBOL_TRIMMING
+ SYMBOL_TRIMMING := 1
+endif
ifeq ($(VERBOSE),0)
ENDCOLOR := "\033[0m"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/Makefile
new/libblastrampoline-5.8.0/src/Makefile
--- old/libblastrampoline-5.4.0/src/Makefile 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/src/Makefile 2023-05-05 22:15:24.000000000
+0200
@@ -1,8 +1,18 @@
LBT_ROOT := $(dir $(abspath $(dir $(lastword $(MAKEFILE_LIST)))))
include $(LBT_ROOT)/src/Make.inc
+ifeq ($(OS),WINNT)
+# On Windows only build the library with the major soversion, all other copies
+# are useless and error prone.
+TARGET_LIBRARIES = $(builddir)/$(LIB_MAJOR_VERSION)
+else
+TARGET_LIBRARIES = $(builddir)/$(LIB_MAJOR_VERSION)
$(builddir)/$(LIB_FULL_VERSION) $(builddir)/libblastrampoline.$(SHLIB_EXT)
+endif
+
+maintarget=$(word 1,$(TARGET_LIBRARIES))
+
# Default target
-all: $(builddir)/libblastrampoline.$(SHLIB_EXT)
+all: $(maintarget)
# Objects we'll build
MAIN_OBJS := libblastrampoline.o dl_utils.o config.o \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/autodetection.c
new/libblastrampoline-5.8.0/src/autodetection.c
--- old/libblastrampoline-5.4.0/src/autodetection.c 2023-01-21
17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/src/autodetection.c 2023-05-05
22:15:24.000000000 +0200
@@ -2,6 +2,30 @@
#include <complex.h>
/*
+ * Some vendors (such as Accelerate) decided to trim off the trailing
underscore
+ * from the F77 symbol names when adding their ILP64 symbol names. So the
+ * symbol name `dgemm_` turns into `dgemm$NEWLAPACK$ILP64`. But of course,
+ * symbol names like `cblas_sdot` turn into `cblas_sdot$NEWLAPACK$ILP64`.
+ *
+ * So we need a way to selectively trim off the trailing underscore. We do so
+ * by shoving an ASCII "substitute character" onto the start of `$NEWLAPACK`,
+ */
+void build_symbol_name(char * out, const char *symbol_name, const char
*suffix) {
+ size_t symbol_len = strlen(symbol_name);
+#if defined(SYMBOL_TRIMMING)
+ if (suffix[0] == '\x1a') {
+ if (symbol_name[symbol_len-1] == '_') {
+ symbol_len -= 1;
+ }
+ suffix += 1;
+ }
+#endif
+
+ strncpy(out, symbol_name, MAX_SYMBOL_LEN);
+ strncpy(out + symbol_len, suffix, MAX_SYMBOL_LEN - symbol_len);
+}
+
+/*
* Search for a symbol that ends in one of the given suffixes. Returns NULL
if not found.
*/
const char * symbol_suffix_search(void * handle, const char * symbol_name,
const char ** suffixes, const int num_suffixes) {
@@ -12,7 +36,7 @@
continue;
}
- sprintf(symbol_name_suffixed, "%s%s", symbol_name,
suffixes[suffix_idx]);
+ build_symbol_name(symbol_name_suffixed, symbol_name,
suffixes[suffix_idx]);
if (lookup_symbol(handle, symbol_name_suffixed) != NULL) {
return suffixes[suffix_idx];
}
@@ -38,13 +62,23 @@
// Possibly-NULL suffix that we should search over
suffix_hint,
- // First, search for LP64-mangling suffixes, so that when we are
loading MKL from a
+ // First, search for LP64-mangling suffixes, so that when we are
loading libs from an
// CLI environment, (where suffix hints are not easy) we want to give
the most stable
// configuration by default.
"", "_", "__",
+ // Next, ILP64-mangling suffixes
+#if defined(_OS_DARWIN_) && defined(SYMBOL_TRIMMING)
+ // Once again, search for Accelerate's non-pure-suffixed names
+ "\x1a$NEWLAPACK$ILP64",
+ // Apple Accelerate has an updated LAPACK interface.
+ // Note that we are making use of our symbol trimming support here to
eliminate
+ // the F77 trailing underscore by starting the string with `\x1a`.
+ "\x1a$NEWLAPACK",
+#endif
+
// Next, search for ILP64-mangling suffixes
- "64", "64_", "_64__", "__64___",
+ "64", "_64", "64_", "_64_", "_64__", "__64___",
};
// If the suffix hint is NULL, just skip it when calling `lookup_symbol()`.
@@ -72,13 +106,19 @@
// Override `lsame_` to point to our `fake_lsame` if we're unable to
`RTLD_DEEPBIND`
if (use_deepbind == 0) {
- push_fake_lsame();
+ if (!push_fake_lsame()) {
+ // Bad LBT compile?
+ return LBT_INTERFACE_UNKNOWN;
+ }
}
int64_t max_idx = isamax(&n, X, &incx);
if (use_deepbind == 0) {
- pop_fake_lsame();
+ if (!pop_fake_lsame()) {
+ // Bad LBT compile?
+ return LBT_INTERFACE_UNKNOWN;
+ }
}
// Although we declare that `isamax` returns an `int64_t`, it may not
actually do so,
@@ -137,14 +177,14 @@
char symbol_name[MAX_SYMBOL_LEN];
// Attempt BLAS `isamax()` test
- sprintf(symbol_name, "isamax_%s", suffix);
+ build_symbol_name(symbol_name, "isamax_", suffix);
void * isamax = lookup_symbol(handle, symbol_name);
if (isamax != NULL) {
return autodetect_blas_interface(isamax);
}
// Attempt LAPACK `dpotrf()` test
- sprintf(symbol_name, "dpotrf_%s", suffix);
+ build_symbol_name(symbol_name, "dpotrf_", suffix);
void * dpotrf = lookup_symbol(handle, symbol_name);
if (dpotrf != NULL) {
return autodetect_lapack_interface(dpotrf);
@@ -158,7 +198,7 @@
int32_t autodetect_complex_return_style(void * handle, const char * suffix) {
char symbol_name[MAX_SYMBOL_LEN];
- sprintf(symbol_name, "zdotc_%s", suffix);
+ build_symbol_name(symbol_name, "zdotc_", suffix);
void * zdotc_addr = lookup_symbol(handle, symbol_name);
if (zdotc_addr == NULL) {
return LBT_COMPLEX_RETSTYLE_UNKNOWN;
@@ -203,8 +243,8 @@
int32_t autodetect_f2c(void * handle, const char * suffix) {
char symbol_name[MAX_SYMBOL_LEN];
- // Attempt BLAS `sdot_()` test
- sprintf(symbol_name, "sdot_%s", suffix);
+ // Attempt BLAS `sdot()` test
+ build_symbol_name(symbol_name, "sdot_", suffix);
void * sdot_addr = lookup_symbol(handle, symbol_name);
if (sdot_addr == NULL) {
return LBT_F2C_UNKNOWN;
@@ -240,10 +280,10 @@
int32_t autodetect_cblas_divergence(void * handle, const char * suffix) {
char symbol_name[MAX_SYMBOL_LEN];
- sprintf(symbol_name, "zdotc_%s", suffix);
+ build_symbol_name(symbol_name, "zdotc_", suffix);
if (lookup_symbol(handle, symbol_name) != NULL ) {
// If we have both `zdotc_64` and `cblas_zdotc_sub64`, it's all good:
- sprintf(symbol_name, "cblas_zdotc_sub%s", suffix);
+ build_symbol_name(symbol_name, "cblas_zdotc_sub", suffix);
if (lookup_symbol(handle, symbol_name) != NULL ) {
return LBT_CBLAS_CONFORMANT;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/config.c
new/libblastrampoline-5.8.0/src/config.c
--- old/libblastrampoline-5.4.0/src/config.c 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/src/config.c 2023-05-05 22:15:24.000000000
+0200
@@ -21,6 +21,18 @@
lbt_config.build_flags |= LBT_BUILDFLAGS_F2C_CAPABLE;
#endif
+#if defined(CBLAS_DIVERGENCE_AUTODETECTION)
+ lbt_config.build_flags |= LBT_BUILDFLAGS_CBLAS_DIVERGENCE;
+#endif
+
+#if defined(COMPLEX_RETSTYLE_AUTODETECTION)
+ lbt_config.build_flags |= LBT_BUILDFLAGS_COMPLEX_RETSTYLE;
+#endif
+
+#if defined(SYMBOL_TRIMMING)
+ lbt_config.build_flags |= LBT_BUILDFLAGS_SYMBOL_TRIMMING;
+#endif
+
lbt_config.exported_symbols = (const char **)&exported_func_names[0];
lbt_config.num_exported_symbols = NUM_EXPORTED_FUNCS;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/deepbindless.c
new/libblastrampoline-5.8.0/src/deepbindless.c
--- old/libblastrampoline-5.4.0/src/deepbindless.c 2023-01-21
17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/src/deepbindless.c 2023-05-05
22:15:24.000000000 +0200
@@ -18,14 +18,15 @@
int lsame_idx = -1;
const void *old_lsame32 = NULL, *old_lsame64 = NULL;
-void push_fake_lsame() {
+uint8_t push_fake_lsame() {
// Find `lsame_` in our symbol list (if we haven't done so before)
if (lsame_idx == -1) {
lsame_idx = find_symbol_idx("lsame_");
if (lsame_idx == -1) {
- // This is fatal as it signifies a configuration error in our
trampoline symbol list
- fprintf(stderr, "Error: Unable to find lsame_ in our symbol
list?!\n");
- exit(1);
+ fprintf(stderr, "Error: Unable to find lsame_ in our symbol list. "
+ "This signifies a libblastrampoline compilation
failure. "
+ "Aborting interface autodetection.\n");
+ return 0;
}
}
@@ -36,13 +37,15 @@
// Insert our "fake" lsame in so that we always have a half-functional copy
(*exported_func32_addrs[lsame_idx]) = &fake_lsame;
(*exported_func64_addrs[lsame_idx]) = &fake_lsame;
+ return 1;
}
-void pop_fake_lsame() {
+uint8_t pop_fake_lsame() {
if (lsame_idx == -1) {
// Did you call `pop_fake_lsame()` without calling `push_fake_lsame()`
first?!
- fprintf(stderr, "pop_fake_lsame() called with invalid `lsame_idx`!\n");
- exit(1);
+ fprintf(stderr, "Error: Invalid lsame_ index. This is an internal
libblastrampoline error. "
+ "Aborting interface autodetection.\n");
+ return 0;
}
(*exported_func32_addrs[lsame_idx]) = old_lsame32;
@@ -50,6 +53,7 @@
old_lsame32 = NULL;
old_lsame64 = NULL;
+ return 1;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/dl_utils.c
new/libblastrampoline-5.8.0/src/dl_utils.c
--- old/libblastrampoline-5.4.0/src/dl_utils.c 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/src/dl_utils.c 2023-05-05 22:15:24.000000000
+0200
@@ -31,7 +31,7 @@
wchar_t wpath[2*PATH_MAX + 1] = {0};
if (!utf8_to_wchar(path, wpath, 2*PATH_MAX)) {
fprintf(stderr, "ERROR: Unable to convert path %s to wide string!\n",
path);
- exit(1);
+ return NULL;
}
new_handle = (void *)LoadLibraryExW(wpath, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
#else
@@ -82,10 +82,11 @@
* Work around protected symbol visibility and GCC/ld.bfd bug:
* https://sourceware.org/bugzilla/show_bug.cgi?id=26815
*/
+extern void * _win32_self_handle;
void * lookup_self_symbol(const char * symbol_name) {
void * self_handle = NULL;
#if defined(_OS_WINDOWS_)
- self_handle = GetModuleHandle(NULL);
+ self_handle = _win32_self_handle;
#elif defined(_OS_DARWIN_)
self_handle = RTLD_SELF;
#elif defined(RTLD_DEFAULT)
@@ -104,16 +105,18 @@
return self_path;
}
#if defined(_OS_WINDOWS_)
- if (!GetModuleFileNameA(GetModuleHandle(NULL), self_path, PATH_MAX)) {
+ if (!GetModuleFileNameA(_win32_self_handle, self_path, PATH_MAX)) {
fprintf(stderr, "ERROR: GetModuleFileName() failed\n");
- exit(1);
+ strcpy(self_path, "<unknown>");
+ return self_path;
}
#else
// On all other platforms, use dladdr()
Dl_info info;
if (!dladdr(lookup_self_symbol("lbt_forward"), &info)) {
fprintf(stderr, "ERROR: Unable to dladdr(\"lbt_forward\"): %s\n",
dlerror());
- exit(1);
+ strcpy(self_path, "<unknown>");
+ return self_path;
}
strcpy(self_path, info.dli_fname);
#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/libblastrampoline.c
new/libblastrampoline-5.8.0/src/libblastrampoline.c
--- old/libblastrampoline-5.4.0/src/libblastrampoline.c 2023-01-21
17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/src/libblastrampoline.c 2023-05-05
22:15:24.000000000 +0200
@@ -80,7 +80,7 @@
// Report to the user that we're cblas-wrapping this one
if (verbose) {
char exported_name[MAX_SYMBOL_LEN];
- sprintf(exported_name, "%s%s",
exported_func_names[symbol_idx], interface == LBT_INTERFACE_ILP64 ? "64_" : "");
+ build_symbol_name(exported_name,
exported_func_names[symbol_idx], interface == LBT_INTERFACE_ILP64 ? "64_" : "");
printf(" - [%04d] complex(%s)\n", symbol_idx, exported_name);
}
@@ -106,7 +106,7 @@
if (verbose) {
char exported_name[MAX_SYMBOL_LEN];
- sprintf(exported_name, "%s%s",
exported_func_names[symbol_idx], interface == LBT_INTERFACE_ILP64 ? "64_" : "");
+ build_symbol_name(exported_name,
exported_func_names[symbol_idx], interface == LBT_INTERFACE_ILP64 ? "64_" : "");
printf(" - [%04d] f2c(%s)\n", symbol_idx, exported_name);
}
@@ -182,7 +182,7 @@
// Load `libname`, clearing previous mappings if `clear` is set.
LBT_DLLEXPORT int32_t lbt_forward(const char * libname, int32_t clear, int32_t
verbose, const char * suffix_hint) {
if (verbose) {
- printf("Generating forwards to %s\n", libname);
+ printf("Generating forwards to %s (clear: %d, verbose: %d,
suffix_hint: '%s')\n", libname, clear, verbose, suffix_hint);
}
// Load the library, throwing an error if we can't actually load it
@@ -274,8 +274,8 @@
printf(" -> CBLAS not found\n");
break;
default:
- printf(" -> ERROR: CBLAS DETECTION FAILED UNEXPECTEDLY\n");
- exit(1);
+ printf(" -> ERROR: Impossible CBLAS detection result:
%d\n", cblas);
+ cblas = LBT_CBLAS_UNKNOWN;
break;
}
}
@@ -353,9 +353,11 @@
}
// Look up this symbol in the given library, if it is a valid symbol,
set it!
- sprintf(symbol_name, "%s%s", exported_func_names[symbol_idx],
lib_suffix);
+ build_symbol_name(symbol_name, exported_func_names[symbol_idx],
lib_suffix);
void *addr = lookup_symbol(handle, symbol_name);
- if (addr != NULL) {
+ void *self_symbol_addr = interface == LBT_INTERFACE_ILP64 ?
exported_func64[symbol_idx] \
+ :
exported_func32[symbol_idx];
+ if (addr != NULL && addr != self_symbol_addr) {
set_forward_by_index(symbol_idx, addr, interface,
complex_retstyle, f2c, verbose);
BITFIELD_SET(forwards, symbol_idx);
nforwards++;
@@ -374,7 +376,7 @@
// Report to the user that we're cblas-wrapping this one
if (verbose) {
char exported_name[MAX_SYMBOL_LEN];
- sprintf(exported_name, "%s%s",
exported_func_names[symbol_idx], interface == LBT_INTERFACE_ILP64 ? "64_" : "");
+ build_symbol_name(exported_name,
exported_func_names[symbol_idx], interface == LBT_INTERFACE_ILP64 ? "64_" : "");
printf(" - [%04d] cblas(%s)\n", symbol_idx, exported_name);
}
@@ -395,8 +397,22 @@
return nforwards;
}
-
+/*
+ * On windows it's surprisingly difficult to get a handle to ourselves,
+ * and that's because they give it to you in `DllMain()`. ;)
+ */
+#ifdef _OS_WINDOWS_
+void * _win32_self_handle;
+BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD code, void *reserved) {
+ if (code == DLL_PROCESS_ATTACH) {
+ _win32_self_handle = (void *)hModule;
+ } else {
+ // We do not want to run our initialization more than once per process.
+ return TRUE;
+ }
+#else
__attribute__((constructor)) void init(void) {
+#endif
// Initialize config structures
init_config();
@@ -432,29 +448,71 @@
default_func =
lookup_self_symbol("lbt_default_func_print_error_and_exit");
}
- // LBT_DEFAULT_LIBS is a semicolon-separated list of paths that should be
loaded as BLAS libraries
+ // Build our lists of self-symbol addresses
+ int32_t symbol_idx;
+ char symbol_name[MAX_SYMBOL_LEN];
+ for (symbol_idx=0; exported_func_names[symbol_idx] != NULL; ++symbol_idx) {
+ exported_func32[symbol_idx] =
lookup_self_symbol(exported_func_names[symbol_idx]);
+
+ // Look up this symbol in the given library, if it is a valid symbol,
set it!
+ build_symbol_name(symbol_name, exported_func_names[symbol_idx], "64_");
+ exported_func64[symbol_idx] = lookup_self_symbol(symbol_name);
+ }
+
+ // LBT_DEFAULT_LIBS is a semicolon-separated list of paths that should be
loaded as BLAS libraries.
+ // Each library can have a `!suffix` tacked onto the end of it, providing
a library-specific
+ // suffix_hint. Example:
+ // export
LBT_DEFAULT_LIBS="libopenblas64.so!64_;/tmp/libfoo.so;/tmp/libbar.so!fastmath32"
const char * default_libs = getenv("LBT_DEFAULT_LIBS");
+#if defined(LBT_FALLBACK_LIBS)
+ if (default_libs == NULL) {
+ default_libs = LBT_FALLBACK_LIBS;
+ }
+#endif
if (default_libs != NULL) {
const char * curr_lib_start = default_libs;
int clear = 1;
char curr_lib[PATH_MAX];
+ char suffix_buffer[MAX_SYMBOL_LEN];
while (curr_lib_start[0] != '\0') {
// Find the end of this current library name
const char * end = curr_lib_start;
- while (*end != ';' && *end != '\0')
+ const char * suffix_sep = NULL;
+ while (*end != ';' && *end != '\0') {
+ if (*end == '!' && suffix_sep == NULL) {
+ suffix_sep = end;
+ }
end++;
+ }
+ const char * curr_lib_end = end;
+ if (suffix_sep != NULL) {
+ curr_lib_end = suffix_sep;
+ }
- // Copy it into a temporary location
- int len = end - curr_lib_start;
+ // Figure out if there's an embedded suffix_hint:
+ const char * suffix_hint = NULL;
+ if (suffix_sep != NULL) {
+ int len = end - (suffix_sep + 1);
+ memcpy(suffix_buffer, suffix_sep+1, len);
+ suffix_buffer[len] = '\0';
+ suffix_hint = &suffix_buffer[0];
+ }
+
+ int len = curr_lib_end - curr_lib_start;
memcpy(curr_lib, curr_lib_start, len);
curr_lib[len] = '\0';
curr_lib_start = end;
+
while (curr_lib_start[0] == ';')
curr_lib_start++;
// Load functions from this library, clearing only the first time.
- lbt_forward(curr_lib, clear, verbose, NULL);
+ lbt_forward(curr_lib, clear, verbose, suffix_hint);
clear = 0;
}
}
+
+#ifdef _OS_WINDOWS_
+ return TRUE;
+#endif
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/libblastrampoline.h
new/libblastrampoline-5.8.0/src/libblastrampoline.h
--- old/libblastrampoline-5.4.0/src/libblastrampoline.h 2023-01-21
17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/src/libblastrampoline.h 2023-05-05
22:15:24.000000000 +0200
@@ -111,8 +111,11 @@
} lbt_config_t;
// Possible values for `build_flags` in `lbt_config_t`
-#define LBT_BUILDFLAGS_DEEPBINDLESS 0x01
-#define LBT_BUILDFLAGS_F2C_CAPABLE 0x02
+#define LBT_BUILDFLAGS_DEEPBINDLESS 0x01
+#define LBT_BUILDFLAGS_F2C_CAPABLE 0x02
+#define LBT_BUILDFLAGS_CBLAS_DIVERGENCE 0x04
+#define LBT_BUILDFLAGS_COMPLEX_RETSTYLE 0x08
+#define LBT_BUILDFLAGS_SYMBOL_TRIMMING 0x10
/*
* Load the given `libname`, lookup all registered symbols within our
configured list of exported
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libblastrampoline-5.4.0/src/libblastrampoline_internal.h
new/libblastrampoline-5.8.0/src/libblastrampoline_internal.h
--- old/libblastrampoline-5.4.0/src/libblastrampoline_internal.h
2023-01-21 17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/src/libblastrampoline_internal.h
2023-05-05 22:15:24.000000000 +0200
@@ -76,6 +76,7 @@
void close_library(void * handle);
// Functions in `autodetection.c`
+void build_symbol_name(char * out, const char *symbol_name, const char
*suffix);
const char * autodetect_symbol_suffix(void * handle, const char * suffix_hint);
int32_t autodetect_blas_interface(void * isamax_addr);
int32_t autodetect_lapack_interface(void * dpotrf_addr);
@@ -92,7 +93,7 @@
#endif
// Functions in deepbindless_surrogates.c
-void push_fake_lsame();
-void pop_fake_lsame();
+uint8_t push_fake_lsame();
+uint8_t pop_fake_lsame();
int fake_lsame(char * ca, char * cb);
extern uint8_t use_deepbind;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libblastrampoline-5.4.0/src/libblastrampoline_trampdata.h
new/libblastrampoline-5.8.0/src/libblastrampoline_trampdata.h
--- old/libblastrampoline-5.4.0/src/libblastrampoline_trampdata.h
2023-01-21 17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/src/libblastrampoline_trampdata.h
2023-05-05 22:15:24.000000000 +0200
@@ -32,4 +32,20 @@
NULL
};
#undef XX
-#undef XX_64
\ No newline at end of file
+#undef XX_64
+
+// Generate list of our own function addresses, so that we can filter
+// out libraries that link against us (such as LAPACK_jll) so that we
+// don't accidentally loop back to ourselves.
+#define XX(name) NULL,
+#define XX_64(name) NULL,
+const void ** exported_func32[] = {
+ EXPORTED_FUNCS(XX)
+ NULL
+};
+const void ** exported_func64[] = {
+ EXPORTED_FUNCS(XX_64)
+ NULL
+};
+#undef XX
+#undef XX_64
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/threading.c
new/libblastrampoline-5.8.0/src/threading.c
--- old/libblastrampoline-5.4.0/src/threading.c 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/src/threading.c 2023-05-05 22:15:24.000000000
+0200
@@ -47,16 +47,18 @@
/*
* Returns the number of threads configured in all loaded libraries.
* In the event of a mismatch, returns the largest value.
+ * If no BLAS libraries with a known threading interface are loaded,
+ * returns `1`.
*/
LBT_DLLEXPORT int32_t lbt_get_num_threads() {
- int32_t max_threads = 0;
+ int32_t max_threads = 1;
const lbt_config_t * config = lbt_get_config();
for (int lib_idx=0; config->loaded_libs[lib_idx] != NULL; ++lib_idx) {
lbt_library_info_t * lib = config->loaded_libs[lib_idx];
for (int symbol_idx=0; getter_names[symbol_idx] != NULL; ++symbol_idx)
{
char symbol_name[MAX_SYMBOL_LEN];
- sprintf(symbol_name, "%s%s", getter_names[symbol_idx],
lib->suffix);
+ build_symbol_name(symbol_name, getter_names[symbol_idx],
lib->suffix);
int (*fptr)() = lookup_symbol(lib->handle, symbol_name);
if (fptr != NULL) {
int new_threads = fptr();
@@ -78,7 +80,7 @@
lbt_library_info_t * lib = config->loaded_libs[lib_idx];
for (int symbol_idx=0; setter_names[symbol_idx] != NULL; ++symbol_idx)
{
char symbol_name[MAX_SYMBOL_LEN];
- sprintf(symbol_name, "%s%s", setter_names[symbol_idx],
lib->suffix);
+ build_symbol_name(symbol_name, setter_names[symbol_idx],
lib->suffix);
void (*fptr)(int) = lookup_symbol(lib->handle, symbol_name);
if (fptr != NULL) {
fptr(nthreads);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/src/win_utils.c
new/libblastrampoline-5.8.0/src/win_utils.c
--- old/libblastrampoline-5.4.0/src/win_utils.c 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/src/win_utils.c 2023-05-05 22:15:24.000000000
+0200
@@ -31,4 +31,4 @@
if (!MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len))
return 0;
return 1;
-}
\ No newline at end of file
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/test/dpstrf_test/Makefile
new/libblastrampoline-5.8.0/test/dpstrf_test/Makefile
--- old/libblastrampoline-5.4.0/test/dpstrf_test/Makefile 1970-01-01
01:00:00.000000000 +0100
+++ new/libblastrampoline-5.8.0/test/dpstrf_test/Makefile 2023-05-05
22:15:24.000000000 +0200
@@ -0,0 +1,15 @@
+include ../../src/Make.inc
+
+all: $(prefix)/dpstrf_test$(EXE)
+
+$(prefix):
+ @mkdir -p $@
+
+$(prefix)/dpstrf_test$(EXE): dpstrf_test.c | $(prefix)
+ @$(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS)
+
+clean:
+ @rm -f $(prefix)/dpstrf_test$(EXE)
+
+run: $(prefix)/dpstrf_test$(EXE)
+ @$(prefix)/dpstrf_test$(EXE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libblastrampoline-5.4.0/test/dpstrf_test/dpstrf_test.c
new/libblastrampoline-5.8.0/test/dpstrf_test/dpstrf_test.c
--- old/libblastrampoline-5.4.0/test/dpstrf_test/dpstrf_test.c 1970-01-01
01:00:00.000000000 +0100
+++ new/libblastrampoline-5.8.0/test/dpstrf_test/dpstrf_test.c 2023-05-05
22:15:24.000000000 +0200
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef ILP64
+#define MANGLE(x) x##64_
+typedef int64_t blasint;
+#else
+#define MANGLE(x) x
+typedef int32_t blasint;
+#endif
+
+extern blasint MANGLE(dpstrf_)(char *, blasint *, double *, blasint *, blasint
*, blasint *, double *, double*, blasint *);
+
+#define N 4
+int main()
+{
+ blasint pivot[N];
+ blasint info;
+ double A[N][N];
+ double work[2*N];
+ blasint order = N;
+ blasint rank = 0;
+ blasint lda = N;
+ blasint stride = 1;
+ double tol = 0.0;
+
+
+ // Initialize `A` with known values (transposed into FORTRAN ordering)
+ A[0][0] = 3.4291134; A[1][0] = -0.61112815; A[2][0] = 0.8155207;
A[3][0] = -0.9183448;
+ A[0][1] = -0.61112815; A[1][1] = 3.1250076; A[2][1] = -0.44400603;
A[3][1] = 0.97749346;
+ A[0][2] = 0.8155207; A[1][2] = -0.44400603; A[2][2] = 0.5413656;
A[3][2] = 0.53000593;
+ A[0][3] = -0.9183448; A[1][3] = 0.97749346; A[2][3] = 0.53000593;
A[3][3] = 5.108155;
+
+ // find solution using LAPACK routine dpstrf, all the arguments have to
+ // be pointers and you have to add an underscore to the routine name
+
+ // parameters in the order as they appear in the function call
+ // order of matrix A, number of right hand sides (b), matrix A,
+ // leading dimension of A, array that records pivoting,
+ // result vector b on entry, x on exit, leading dimension of b
+ // return value
+ MANGLE(dpstrf_)("U", &order, &A[0][0], &lda, &pivot[0], &rank, &tol,
&work[0], &info);
+ if (info != 0) {
+ printf("ERROR: info == %ld!\n", info);
+ return 1;
+ }
+
+ // Print out diagonal of A
+ printf("diag(A):");
+ for (blasint j=0; j<N; j++) {
+ printf(" %8.4f", A[j][j]);
+ }
+ printf("\n");
+ return 0;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/test/runtests.jl
new/libblastrampoline-5.8.0/test/runtests.jl
--- old/libblastrampoline-5.4.0/test/runtests.jl 2023-01-21
17:45:47.000000000 +0100
+++ new/libblastrampoline-5.8.0/test/runtests.jl 2023-05-05
22:15:24.000000000 +0200
@@ -61,6 +61,13 @@
end
@test expected_return_value
+ # Expect to see the path to `libblastrampoline` within the output,
+ # since we have `LBT_VERBOSE=1` and at startup, it announces its own
path:
+ if startswith(libblas_name, "blastrampoline")
+ lbt_libdir = first(libdirs)
+ @test occursin(lbt_libdir, output)
+ end
+
# Test to make sure the test ran properly
has_expected_output = all(occursin(expected, output) for expected in
test_expected_outputs)
if !has_expected_output
@@ -81,18 +88,20 @@
end
# our tests, written in C, defined in subdirectories in `test/`
-dgemm = ("dgemm_test", ("||C||^2 is: 24.3384",),
true)
-dgemmt = ("dgemmt_test", ("||C||^2 is: 23.2952",),
true)
-sgesv = ("sgesv_test", ("||b||^2 is: 3.0000",),
true)
-sgesv_failure = ("sgesv_test", ("Error: no BLAS/LAPACK library loaded!",),
false)
-sdot = ("sdot_test", ("C is: 1.9900",),
true)
+dgemm = ("dgemm_test", ("||C||^2 is: 24.3384",),
true)
+dgemmt = ("dgemmt_test", ("||C||^2 is: 23.2952",),
true)
+dpstrf = ("dpstrf_test", ("diag(A): 2.2601 1.8067 1.6970
0.4121",), true)
+sgesv = ("sgesv_test", ("||b||^2 is: 3.0000",),
true)
+sgesv_failure = ("sgesv_test", ("Error: no BLAS/LAPACK library loaded!",),
false)
+sdot = ("sdot_test", ("C is: 1.9900",),
true)
zdotc = ("zdotc_test", (
"C (cblas) is: ( 1.4700, 3.8300)",
"C (fortran) is: ( 1.4700, 3.8300)",
), true)
# Helper function to run all the tests with the given arguments
-function run_all_tests(args...; tests = [dgemm, dgemmt, sgesv, sdot, zdotc])
+# Does not include `dgemmt` because that's MKL-only
+function run_all_tests(args...; tests = [dgemm, dpstrf, sgesv, sdot, zdotc])
for test in tests
run_test(test, args...)
end
@@ -105,13 +114,13 @@
end
openblas_jll_libname =
splitext(basename(OpenBLAS_jll.libopenblas_path)[4:end])[1]
@testset "Vanilla OpenBLAS_jll ($(openblas_interface))" begin
- run_all_tests(openblas_jll_libname, OpenBLAS_jll.LIBPATH_list,
openblas_interface, "", tests=[dgemm, sgesv, sdot, zdotc])
+ run_all_tests(openblas_jll_libname, OpenBLAS_jll.LIBPATH_list,
openblas_interface, "")
end
# Build version that links against vanilla OpenBLAS32
@testset "Vanilla OpenBLAS32_jll (LP64)" begin
# Reverse OpenBLAS32_jll's LIBPATH_list so that we get the right
openblas.so
- run_all_tests("openblas", reverse(OpenBLAS32_jll.LIBPATH_list), :LP64, "",
tests=[dgemm, sgesv, sdot, zdotc])
+ run_all_tests("openblas", reverse(OpenBLAS32_jll.LIBPATH_list), :LP64, "")
end
# Next, build a version that links against `libblastrampoline`, and tell
@@ -121,20 +130,20 @@
@testset "LBT -> OpenBLAS_jll ($(openblas_interface))" begin
libdirs = unique(vcat(lbt_dir, OpenBLAS_jll.LIBPATH_list...,
CompilerSupportLibraries_jll.LIBPATH_list...))
- run_all_tests(blastrampoline_link_name(), libdirs, openblas_interface,
OpenBLAS_jll.libopenblas_path, tests=[dgemm, sgesv, sdot, zdotc])
+ run_all_tests(blastrampoline_link_name(), libdirs, openblas_interface,
OpenBLAS_jll.libopenblas_path)
end
# And again, but this time with OpenBLAS32_jll
@testset "LBT -> OpenBLAS32_jll (LP64)" begin
libdirs = unique(vcat(lbt_dir, OpenBLAS32_jll.LIBPATH_list...,
CompilerSupportLibraries_jll.LIBPATH_list...))
- run_all_tests(blastrampoline_link_name(), libdirs, :LP64,
OpenBLAS32_jll.libopenblas_path, tests=[dgemm, sgesv, sdot, zdotc])
+ run_all_tests(blastrampoline_link_name(), libdirs, :LP64,
OpenBLAS32_jll.libopenblas_path)
end
# Test against MKL_jll using `libmkl_rt`, which is :LP64 by default
if MKL_jll.is_available()
@testset "LBT -> MKL_jll (LP64)" begin
libdirs = unique(vcat(lbt_dir, MKL_jll.LIBPATH_list...,
CompilerSupportLibraries_jll.LIBPATH_list...))
- run_all_tests(blastrampoline_link_name(), libdirs, :LP64,
MKL_jll.libmkl_rt_path)
+ run_all_tests(blastrampoline_link_name(), libdirs, :LP64,
MKL_jll.libmkl_rt_path; tests = [dgemm, dgemmt, dpstrf, sgesv, sdot, zdotc])
end
# Test that we can set MKL's interface via an environment variable to
select ILP64, and LBT detects it properly
@@ -142,7 +151,7 @@
@testset "LBT -> MKL_jll (ILP64, via env)" begin
withenv("MKL_INTERFACE_LAYER" => "ILP64") do
libdirs = unique(vcat(lbt_dir, MKL_jll.LIBPATH_list...,
CompilerSupportLibraries_jll.LIBPATH_list...))
- run_all_tests(blastrampoline_link_name(), libdirs, :ILP64,
MKL_jll.libmkl_rt_path)
+ run_all_tests(blastrampoline_link_name(), libdirs, :ILP64,
MKL_jll.libmkl_rt_path; tests = [dgemm, dgemmt, dpstrf, sgesv, sdot, zdotc])
end
end
end
@@ -161,7 +170,22 @@
# With LAPACK as well, run all tests except `dgemmt`
veclib_lapack_path =
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/libLAPACK.dylib"
@testset "LBT -> vecLib/libLAPACK" begin
- run_all_tests(blastrampoline_link_name(), [lbt_dir], :LP64,
string(veclib_blas_path, ";", veclib_lapack_path), tests=[dgemm, sgesv, sdot,
zdotc])
+ run_all_tests(blastrampoline_link_name(), [lbt_dir], :LP64,
string(veclib_blas_path, ";", veclib_lapack_path))
+ end
+
+ veclib_lapack_handle = dlopen(veclib_lapack_path)
+ if dlsym_e(veclib_lapack_handle, "dpotrf\$NEWLAPACK\$ILP64") != C_NULL
+ @testset "LBT -> vecLib/libBLAS (ILP64)" begin
+ veclib_blas_path_ilp64 =
"$(veclib_blas_path)!\x1a\$NEWLAPACK\$ILP64"
+ run_all_tests(blastrampoline_link_name(), [lbt_dir], :ILP64,
veclib_blas_path_ilp64; tests=[dgemm, sdot, zdotc])
+ end
+
+ @testset "LBT -> vecLib/libLAPACK (ILP64)" begin
+ veclib_lapack_path_ilp64 =
"$(veclib_lapack_path)!\x1a\$NEWLAPACK\$ILP64"
+ @warn("dpstrf test broken on new LAPACK in Accelerate")
+ dpstrf_broken = (dpstrf[1], "diag(A): 2.2601 1.7140 0.6206
1.1878", true)
+ run_all_tests(blastrampoline_link_name(), [lbt_dir], :ILP64,
veclib_lapack_path_ilp64; tests=[dgemm, dpstrf_broken, sgesv, sdot, zdotc])
+ end
end
end
@@ -187,7 +211,7 @@
if openblas_interface == :ILP64
inconsolable = ("inconsolable_test", ("||C||^2 is: 24.3384", "||b||^2 is:
3.0000"), true)
@testset "LBT -> OpenBLAS 32 + 64 (LP64 + ILP64)" begin
- libdirs = unique(vcat(OpenBLAS32_jll.LIBPATH_list...,
OpenBLAS_jll.LIBPATH_list..., CompilerSupportLibraries_jll.LIBPATH_list...,
lbt_dir))
+ libdirs = unique(vcat(lbt_dir, OpenBLAS32_jll.LIBPATH_list...,
OpenBLAS_jll.LIBPATH_list..., CompilerSupportLibraries_jll.LIBPATH_list...))
run_test(inconsolable, lbt_link_name, libdirs, :wild_sobbing,
"$(OpenBLAS32_jll.libopenblas_path);$(OpenBLAS_jll.libopenblas_path)")
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libblastrampoline-5.4.0/test/utils.jl
new/libblastrampoline-5.8.0/test/utils.jl
--- old/libblastrampoline-5.4.0/test/utils.jl 2023-01-21 17:45:47.000000000
+0100
+++ new/libblastrampoline-5.8.0/test/utils.jl 2023-05-05 22:15:24.000000000
+0200
@@ -22,7 +22,7 @@
return join(vcat(paths..., get(ENV, LIBPATH_env, String[])), pathsep)
end
-function capture_output(cmd::Cmd; verbose::Bool = false)
+function capture_output(cmd::Cmd; verbose::Bool = false, timeout = 10.0)
out_pipe = Pipe()
if verbose
ld_env = filter(e -> startswith(e, "LBT_") || startswith(e, "LD_") ||
startswith(e, "DYLD_"), something(cmd.env, String[]))
@@ -30,7 +30,23 @@
end
p = run(pipeline(ignorestatus(cmd), stdout=out_pipe, stderr=out_pipe),
wait=false)
close(out_pipe.in)
- output = @async read(out_pipe, String)
+ output = @async begin
+ lines = String[]
+ for line in readlines(out_pipe)
+ if verbose
+ println(line)
+ end
+ push!(lines, line)
+ end
+ return join(lines, "\n")
+ end
+ @async begin
+ sleep(timeout)
+ if process_running(p)
+ @warn("$(basename(cmd.exec[1])) timeout exceeded!")
+ kill(p)
+ end
+ end
wait(p)
return p, fetch(output)
end