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 @@
-[![GitHub Actions 
CI](https://github.com/staticfloat/libblastrampoline/actions/workflows/ci.yml/badge.svg)](https://github.com/staticfloat/libblastrampoline/actions/workflows/ci.yml)
 [![Drone Build 
Status](https://cloud.drone.io/api/badges/staticfloat/libblastrampoline/status.svg)](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

Reply via email to