1e5c89e4eSSatish Balay /* 2e5c89e4eSSatish Balay Routines for opening dynamic link libraries (DLLs), keeping a searchable 3e5c89e4eSSatish Balay path of DLLs, obtaining remote DLLs via a URL and opening them locally. 4e5c89e4eSSatish Balay */ 5e5c89e4eSSatish Balay 6af0996ceSBarry Smith #include <petsc/private/petscimpl.h> 7e5c89e4eSSatish Balay 8e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 9e5c89e4eSSatish Balay /* 10e5c89e4eSSatish Balay Code to maintain a list of opened dynamic libraries and load symbols 11e5c89e4eSSatish Balay */ 12e5bd5246SBarry Smith struct _n_PetscDLLibrary { 13e5bd5246SBarry Smith PetscDLLibrary next; 14ebd79076SLisandro Dalcin PetscDLHandle handle; 15e5c89e4eSSatish Balay char libname[PETSC_MAX_PATH_LEN]; 16e5c89e4eSSatish Balay }; 17e5c89e4eSSatish Balay 189371c9d4SSatish Balay PetscErrorCode PetscDLLibraryPrintPath(PetscDLLibrary libs) { 19e5c89e4eSSatish Balay PetscFunctionBegin; 20e5c89e4eSSatish Balay while (libs) { 21e5c89e4eSSatish Balay PetscErrorPrintf(" %s\n", libs->libname); 22e5c89e4eSSatish Balay libs = libs->next; 23e5c89e4eSSatish Balay } 24e5c89e4eSSatish Balay PetscFunctionReturn(0); 25e5c89e4eSSatish Balay } 26e5c89e4eSSatish Balay 27e5c89e4eSSatish Balay /*@C 28e5c89e4eSSatish Balay PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 29e5c89e4eSSatish Balay (if it is remote), indicates if it exits and its local name. 30e5c89e4eSSatish Balay 31d083f849SBarry Smith Collective 32e5c89e4eSSatish Balay 33e5c89e4eSSatish Balay Input Parameters: 34e5c89e4eSSatish Balay + comm - processors that are opening the library 35e5c89e4eSSatish Balay - libname - name of the library, can be relative or absolute 36e5c89e4eSSatish Balay 37d8d19677SJose E. Roman Output Parameters: 382d53ad75SBarry Smith + name - actual name of file on local filesystem if found 392d53ad75SBarry Smith . llen - length of the name buffer 402d53ad75SBarry Smith - found - true if the file exists 41e5c89e4eSSatish Balay 42e5c89e4eSSatish Balay Level: developer 43e5c89e4eSSatish Balay 44e5c89e4eSSatish Balay Notes: 45e5c89e4eSSatish Balay [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 46e5c89e4eSSatish Balay 47e5c89e4eSSatish Balay ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 48a5b23f4aSJose E. Roman occurring in directoryname and filename will be replaced with appropriate values. 49e5c89e4eSSatish Balay @*/ 509371c9d4SSatish Balay PetscErrorCode PetscDLLibraryRetrieve(MPI_Comm comm, const char libname[], char *lname, size_t llen, PetscBool *found) { 51d46cf212SLisandro Dalcin char *buf, *par2, suffix[16], *gz, *so; 52d46cf212SLisandro Dalcin size_t len; 53e5c89e4eSSatish Balay 54e5c89e4eSSatish Balay PetscFunctionBegin; 55e5c89e4eSSatish Balay /* 56a523d312SBarry Smith make copy of library name and replace $PETSC_ARCH etc 57e5c89e4eSSatish Balay so we can add to the end of it to look for something like .so.1.0 etc. 58e5c89e4eSSatish Balay */ 599566063dSJacob Faibussowitsch PetscCall(PetscStrlen(libname, &len)); 602f613bf5SBarry Smith len = PetscMax(4 * len, PETSC_MAX_PATH_LEN); 619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len, &buf)); 62d46cf212SLisandro Dalcin par2 = buf; 639566063dSJacob Faibussowitsch PetscCall(PetscStrreplace(comm, libname, par2, len)); 64e5c89e4eSSatish Balay 65d46cf212SLisandro Dalcin /* temporarily remove .gz if it ends library name */ 669566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(par2, ".gz", &gz)); 67e5c89e4eSSatish Balay if (gz) { 689566063dSJacob Faibussowitsch PetscCall(PetscStrlen(gz, &len)); 6902c9f0b5SLisandro Dalcin if (len != 3) gz = NULL; /* do not end (exactly) with .gz */ 70d46cf212SLisandro Dalcin else *gz = 0; /* ends with .gz, so remove it */ 71e5c89e4eSSatish Balay } 723fa76a5bSLisandro Dalcin /* strip out .a from it if user put it in by mistake */ 739566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par2, &len)); 743fa76a5bSLisandro Dalcin if (par2[len - 1] == 'a' && par2[len - 2] == '.') par2[len - 2] = 0; 753fa76a5bSLisandro Dalcin 769566063dSJacob Faibussowitsch PetscCall(PetscFileRetrieve(comm, par2, lname, llen, found)); 778ce0dc28SMatthew G Knepley if (!(*found)) { 78e5c89e4eSSatish Balay /* see if library name does already not have suffix attached */ 799566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 809566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 819566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(par2, suffix, &so)); 82d46cf212SLisandro Dalcin /* and attach the suffix if it is not there */ 839566063dSJacob Faibussowitsch if (!so) PetscCall(PetscStrcat(par2, suffix)); 84e5c89e4eSSatish Balay 85d46cf212SLisandro Dalcin /* restore the .gz suffix if it was there */ 869566063dSJacob Faibussowitsch if (gz) PetscCall(PetscStrcat(par2, ".gz")); 87d46cf212SLisandro Dalcin 88d46cf212SLisandro Dalcin /* and finally retrieve the file */ 899566063dSJacob Faibussowitsch PetscCall(PetscFileRetrieve(comm, par2, lname, llen, found)); 902d53ad75SBarry Smith } 91d46cf212SLisandro Dalcin 929566063dSJacob Faibussowitsch PetscCall(PetscFree(buf)); 93e5c89e4eSSatish Balay PetscFunctionReturn(0); 94e5c89e4eSSatish Balay } 95e5c89e4eSSatish Balay 96e5c89e4eSSatish Balay /*@C 97ebd79076SLisandro Dalcin PetscDLLibraryOpen - Opens a PETSc dynamic link library 98e5c89e4eSSatish Balay 99d083f849SBarry Smith Collective 100e5c89e4eSSatish Balay 101e5c89e4eSSatish Balay Input Parameters: 102e5c89e4eSSatish Balay + comm - processors that are opening the library 1030f31fb7fSLisandro Dalcin - path - name of the library, can be relative or absolute 104e5c89e4eSSatish Balay 105e5c89e4eSSatish Balay Output Parameter: 1060f31fb7fSLisandro Dalcin . entry - a PETSc dynamic link library entry 107e5c89e4eSSatish Balay 108e5c89e4eSSatish Balay Level: developer 109e5c89e4eSSatish Balay 110e5c89e4eSSatish Balay Notes: 111bb84e0fdSBarry Smith [[<http,ftp>://hostname]/directoryname/]libbasename[.so.1.0] 112bb84e0fdSBarry Smith 113bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 114bb84e0fdSBarry Smith when the library is opened. 115e5c89e4eSSatish Balay 116a5b23f4aSJose E. Roman ${PETSC_ARCH} occurring in directoryname and filename 117e5c89e4eSSatish Balay will be replaced with the appropriate value. 118bb84e0fdSBarry Smith 119db781477SPatrick Sanan .seealso: `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()` 120e5c89e4eSSatish Balay @*/ 1219371c9d4SSatish Balay PetscErrorCode PetscDLLibraryOpen(MPI_Comm comm, const char path[], PetscDLLibrary *entry) { 122ace3abfcSBarry Smith PetscBool foundlibrary, match; 123b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN], par2[PETSC_MAX_PATH_LEN], suffix[16], *s; 124b3bb0f5eSLisandro Dalcin char *basename, registername[128]; 1255673baf8SLisandro Dalcin PetscDLHandle handle; 126607a6623SBarry Smith PetscErrorCode (*func)(void) = NULL; 127e5c89e4eSSatish Balay 128e5c89e4eSSatish Balay PetscFunctionBegin; 12982a51d08SSatish Balay PetscValidCharPointer(path, 2); 1305673baf8SLisandro Dalcin PetscValidPointer(entry, 3); 131ebd79076SLisandro Dalcin 1320298fd71SBarry Smith *entry = NULL; 133e5c89e4eSSatish Balay 134b3bb0f5eSLisandro Dalcin /* retrieve the library */ 1359566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Retrieving %s\n", path)); 1369566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(comm, path, par2, PETSC_MAX_PATH_LEN, &foundlibrary)); 13728b400f6SJacob Faibussowitsch PetscCheck(foundlibrary, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate dynamic library:\n %s", path); 138e2e64c6bSBarry Smith /* Eventually ./configure should determine if the system needs an executable dynamic library */ 139e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO 140e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO) 1419566063dSJacob Faibussowitsch PetscCall(PetscTestFile(par2, 'x', &foundlibrary)); 14228b400f6SJacob Faibussowitsch PetscCheck(foundlibrary, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Dynamic library is not executable:\n %s\n %s", path, par2); 143e5c89e4eSSatish Balay #endif 144e5c89e4eSSatish Balay 1453fa76a5bSLisandro Dalcin /* copy path and setup shared library suffix */ 1469566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libname, path, PETSC_MAX_PATH_LEN)); 1479566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 1489566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 1493fa76a5bSLisandro Dalcin /* remove wrong suffixes from libname */ 1509566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, ".gz", &s)); 1513fa76a5bSLisandro Dalcin if (s && s[3] == 0) s[0] = 0; 1529566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, ".a", &s)); 1533fa76a5bSLisandro Dalcin if (s && s[2] == 0) s[0] = 0; 1543fa76a5bSLisandro Dalcin /* remove shared suffix from libname */ 1559566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, suffix, &s)); 156b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 157b3bb0f5eSLisandro Dalcin 1585673baf8SLisandro Dalcin /* open the dynamic library */ 1599566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Opening dynamic library %s\n", libname)); 1609566063dSJacob Faibussowitsch PetscCall(PetscDLOpen(par2, PETSC_DL_DECIDE, &handle)); 161b3bb0f5eSLisandro Dalcin 162b3bb0f5eSLisandro Dalcin /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */ 1639566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(libname, '/', &basename)); /* XXX Windows ??? */ 164b3bb0f5eSLisandro Dalcin if (!basename) basename = libname; 1659566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(basename, "lib", 3, &match)); 166a297a907SKarl Rupp if (match) basename = basename + 3; 167*48a46eb9SPierre Jolivet else PetscCall(PetscInfo(NULL, "Dynamic library %s does not have lib prefix\n", libname)); 1689371c9d4SSatish Balay for (s = basename; *s; s++) 1699371c9d4SSatish Balay if (*s == '-') *s = '_'; 1709566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(registername, "PetscDLLibraryRegister_", sizeof(registername))); 1719566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(registername, basename, sizeof(registername))); 1729566063dSJacob Faibussowitsch PetscCall(PetscDLSym(handle, registername, (void **)&func)); 173b3bb0f5eSLisandro Dalcin if (func) { 1749566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Loading registered routines from %s\n", libname)); 1759566063dSJacob Faibussowitsch PetscCall((*func)()); 176b3bb0f5eSLisandro Dalcin } else { 1779566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Dynamic library %s does not have symbol %s\n", libname, registername)); 178b3bb0f5eSLisandro Dalcin } 1795673baf8SLisandro Dalcin 1809566063dSJacob Faibussowitsch PetscCall(PetscNew(entry)); 18102c9f0b5SLisandro Dalcin (*entry)->next = NULL; 182b3bb0f5eSLisandro Dalcin (*entry)->handle = handle; 1839566063dSJacob Faibussowitsch PetscCall(PetscStrcpy((*entry)->libname, libname)); 184e5c89e4eSSatish Balay PetscFunctionReturn(0); 185e5c89e4eSSatish Balay } 186e5c89e4eSSatish Balay 187e5c89e4eSSatish Balay /*@C 188e5c89e4eSSatish Balay PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 189e5c89e4eSSatish Balay 190d083f849SBarry Smith Collective 191e5c89e4eSSatish Balay 192d8d19677SJose E. Roman Input Parameters: 193e5bd5246SBarry Smith + comm - communicator that will open the library 1940298fd71SBarry Smith . outlist - list of already open libraries that may contain symbol (can be NULL and only the executable is searched for the function) 19530a1dd1fSBarry Smith . path - optional complete library name (if provided checks here before checking outlist) 196e5c89e4eSSatish Balay - insymbol - name of symbol 197e5c89e4eSSatish Balay 198e5c89e4eSSatish Balay Output Parameter: 1990298fd71SBarry Smith . value - if symbol not found then this value is set to NULL 200e5c89e4eSSatish Balay 201e5c89e4eSSatish Balay Level: developer 202e5c89e4eSSatish Balay 20395452b02SPatrick Sanan Notes: 20495452b02SPatrick Sanan Symbol can be of the form 205e5c89e4eSSatish Balay [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 206e5c89e4eSSatish Balay 207e5c89e4eSSatish Balay Will attempt to (retrieve and) open the library if it is not yet been opened. 208e5c89e4eSSatish Balay 209e5c89e4eSSatish Balay @*/ 2109371c9d4SSatish Balay PetscErrorCode PetscDLLibrarySym(MPI_Comm comm, PetscDLLibrary *outlist, const char path[], const char insymbol[], void **value) { 211b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN], suffix[16], *symbol, *s; 2120298fd71SBarry Smith PetscDLLibrary nlist, prev, list = NULL; 213e5c89e4eSSatish Balay 214e5c89e4eSSatish Balay PetscFunctionBegin; 215340b11eeSBarry Smith if (outlist) PetscValidPointer(outlist, 2); 2165673baf8SLisandro Dalcin if (path) PetscValidCharPointer(path, 3); 2175673baf8SLisandro Dalcin PetscValidCharPointer(insymbol, 4); 2185673baf8SLisandro Dalcin PetscValidPointer(value, 5); 2195673baf8SLisandro Dalcin 220340b11eeSBarry Smith if (outlist) list = *outlist; 22102c9f0b5SLisandro Dalcin *value = NULL; 222e5c89e4eSSatish Balay 2239566063dSJacob Faibussowitsch PetscCall(PetscStrchr(insymbol, '(', &s)); 2242d53ad75SBarry Smith if (s) { 225e5c89e4eSSatish Balay /* make copy of symbol so we can edit it in place */ 2269566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(insymbol, &symbol)); 227b3bb0f5eSLisandro Dalcin /* If symbol contains () then replace with a NULL, to support functionname() */ 2289566063dSJacob Faibussowitsch PetscCall(PetscStrchr(symbol, '(', &s)); 2292d53ad75SBarry Smith s[0] = 0; 230a297a907SKarl Rupp } else symbol = (char *)insymbol; 231e5c89e4eSSatish Balay 232e5c89e4eSSatish Balay /* 233e5c89e4eSSatish Balay Function name does include library 234e5c89e4eSSatish Balay ------------------------------------- 235e5c89e4eSSatish Balay */ 236e5c89e4eSSatish Balay if (path && path[0] != '\0') { 237b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 2389566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libname, path, PETSC_MAX_PATH_LEN)); 2399566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 2409566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 2419566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, suffix, &s)); 242b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 2435673baf8SLisandro Dalcin /* Look if library is already opened and in path */ 24402c9f0b5SLisandro Dalcin prev = NULL; 245b3bb0f5eSLisandro Dalcin nlist = list; 246e5c89e4eSSatish Balay while (nlist) { 247ace3abfcSBarry Smith PetscBool match; 2489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(nlist->libname, libname, &match)); 2495673baf8SLisandro Dalcin if (match) goto done; 250e5c89e4eSSatish Balay prev = nlist; 251e5c89e4eSSatish Balay nlist = nlist->next; 252e5c89e4eSSatish Balay } 253b3bb0f5eSLisandro Dalcin /* open the library and append it to path */ 2549566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryOpen(comm, path, &nlist)); 2559566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Appending %s to dynamic library search path\n", path)); 256a297a907SKarl Rupp if (prev) prev->next = nlist; 2579371c9d4SSatish Balay else { 2589371c9d4SSatish Balay if (outlist) *outlist = nlist; 2599371c9d4SSatish Balay } 260e5c89e4eSSatish Balay 261e5c89e4eSSatish Balay done:; 2629566063dSJacob Faibussowitsch PetscCall(PetscDLSym(nlist->handle, symbol, value)); 263*48a46eb9SPierre Jolivet if (*value) PetscCall(PetscInfo(NULL, "Loading function %s from dynamic library %s\n", insymbol, path)); 264e5c89e4eSSatish Balay 265e5c89e4eSSatish Balay /* 266e5c89e4eSSatish Balay Function name does not include library so search path 267e5c89e4eSSatish Balay ----------------------------------------------------- 268e5c89e4eSSatish Balay */ 269e5c89e4eSSatish Balay } else { 270e5c89e4eSSatish Balay while (list) { 2719566063dSJacob Faibussowitsch PetscCall(PetscDLSym(list->handle, symbol, value)); 272e5c89e4eSSatish Balay if (*value) { 2739566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Loading symbol %s from dynamic library %s\n", symbol, list->libname)); 274e5c89e4eSSatish Balay break; 275e5c89e4eSSatish Balay } 276e5c89e4eSSatish Balay list = list->next; 277e5c89e4eSSatish Balay } 278e5c89e4eSSatish Balay if (!*value) { 2799566063dSJacob Faibussowitsch PetscCall(PetscDLSym(NULL, symbol, value)); 280*48a46eb9SPierre Jolivet if (*value) PetscCall(PetscInfo(NULL, "Loading symbol %s from object code\n", symbol)); 281e5c89e4eSSatish Balay } 282e5c89e4eSSatish Balay } 283e5c89e4eSSatish Balay 284*48a46eb9SPierre Jolivet if (symbol != insymbol) PetscCall(PetscFree(symbol)); 285e5c89e4eSSatish Balay PetscFunctionReturn(0); 286e5c89e4eSSatish Balay } 287e5c89e4eSSatish Balay 288e5c89e4eSSatish Balay /*@C 289e5c89e4eSSatish Balay PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 290e5c89e4eSSatish Balay of the search path. 291e5c89e4eSSatish Balay 292d083f849SBarry Smith Collective 293e5c89e4eSSatish Balay 294e5c89e4eSSatish Balay Input Parameters: 295e5c89e4eSSatish Balay + comm - MPI communicator 2960f31fb7fSLisandro Dalcin - path - name of the library 297e5c89e4eSSatish Balay 298e5c89e4eSSatish Balay Output Parameter: 299e5c89e4eSSatish Balay . outlist - list of libraries 300e5c89e4eSSatish Balay 301e5c89e4eSSatish Balay Level: developer 302e5c89e4eSSatish Balay 30395452b02SPatrick Sanan Notes: 30495452b02SPatrick Sanan if library is already in path will not add it. 305bb84e0fdSBarry Smith 306bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 307bb84e0fdSBarry Smith when the library is opened. 308bb84e0fdSBarry Smith 309db781477SPatrick Sanan .seealso: `PetscDLLibraryOpen()` 310e5c89e4eSSatish Balay @*/ 3119371c9d4SSatish Balay PetscErrorCode PetscDLLibraryAppend(MPI_Comm comm, PetscDLLibrary *outlist, const char path[]) { 312e5bd5246SBarry Smith PetscDLLibrary list, prev; 313e5c89e4eSSatish Balay size_t len; 314ace3abfcSBarry Smith PetscBool match, dir; 315b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN], found[8 * PETSC_MAX_PATH_LEN]; 316b3bb0f5eSLisandro Dalcin char *libname, suffix[16], *s; 3179c9d3cfdSBarry Smith PetscToken token; 318e5c89e4eSSatish Balay 319e5c89e4eSSatish Balay PetscFunctionBegin; 320b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist, 2); 321e5c89e4eSSatish Balay 322b3bb0f5eSLisandro Dalcin /* is path a directory? */ 3239566063dSJacob Faibussowitsch PetscCall(PetscTestDirectory(path, 'r', &dir)); 324e5c89e4eSSatish Balay if (dir) { 3259566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Checking directory %s for dynamic libraries\n", path)); 3269566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(program, path, sizeof(program))); 3279566063dSJacob Faibussowitsch PetscCall(PetscStrlen(program, &len)); 328e5c89e4eSSatish Balay if (program[len - 1] == '/') { 3299566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "*.", sizeof(program))); 330e5c89e4eSSatish Balay } else { 3319566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "/*.", sizeof(program))); 332e5c89e4eSSatish Balay } 3339566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, PETSC_SLSUFFIX, sizeof(program))); 334e5c89e4eSSatish Balay 3359566063dSJacob Faibussowitsch PetscCall(PetscLs(comm, program, found, 8 * PETSC_MAX_PATH_LEN, &dir)); 336e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 337e5c89e4eSSatish Balay } else { 3389566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(found, path, PETSC_MAX_PATH_LEN)); 339e5c89e4eSSatish Balay } 3409566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 3419566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 342e5c89e4eSSatish Balay 3439566063dSJacob Faibussowitsch PetscCall(PetscTokenCreate(found, '\n', &token)); 3449566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 345b3bb0f5eSLisandro Dalcin while (libname) { 346b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 3479566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, suffix, &s)); 348e5c89e4eSSatish Balay if (s) s[0] = 0; 349e5c89e4eSSatish Balay /* see if library was already open then we are done */ 350e5c89e4eSSatish Balay list = prev = *outlist; 351e5c89e4eSSatish Balay match = PETSC_FALSE; 352e5c89e4eSSatish Balay while (list) { 3539566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(list->libname, libname, &match)); 354e5c89e4eSSatish Balay if (match) break; 355e5c89e4eSSatish Balay prev = list; 356e5c89e4eSSatish Balay list = list->next; 357e5c89e4eSSatish Balay } 358b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 359b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 360e5c89e4eSSatish Balay if (!match) { 3615673baf8SLisandro Dalcin /* open the library and add to end of list */ 3629566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryOpen(comm, libname, &list)); 3639566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Appending %s to dynamic library search path\n", libname)); 364a297a907SKarl Rupp if (!*outlist) *outlist = list; 365a297a907SKarl Rupp else prev->next = list; 366e5c89e4eSSatish Balay } 3679566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 368e5c89e4eSSatish Balay } 3699566063dSJacob Faibussowitsch PetscCall(PetscTokenDestroy(&token)); 370e5c89e4eSSatish Balay PetscFunctionReturn(0); 371e5c89e4eSSatish Balay } 372e5c89e4eSSatish Balay 373e5c89e4eSSatish Balay /*@C 374e5c89e4eSSatish Balay PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 375e5c89e4eSSatish Balay the search path. 376e5c89e4eSSatish Balay 377d083f849SBarry Smith Collective 378e5c89e4eSSatish Balay 379e5c89e4eSSatish Balay Input Parameters: 380e5c89e4eSSatish Balay + comm - MPI communicator 3810f31fb7fSLisandro Dalcin - path - name of the library 382e5c89e4eSSatish Balay 383e5c89e4eSSatish Balay Output Parameter: 384e5c89e4eSSatish Balay . outlist - list of libraries 385e5c89e4eSSatish Balay 386e5c89e4eSSatish Balay Level: developer 387e5c89e4eSSatish Balay 38895452b02SPatrick Sanan Notes: 38995452b02SPatrick Sanan If library is already in path will remove old reference. 390e5c89e4eSSatish Balay 391e5c89e4eSSatish Balay @*/ 3929371c9d4SSatish Balay PetscErrorCode PetscDLLibraryPrepend(MPI_Comm comm, PetscDLLibrary *outlist, const char path[]) { 393e5bd5246SBarry Smith PetscDLLibrary list, prev; 394e5c89e4eSSatish Balay size_t len; 395ace3abfcSBarry Smith PetscBool match, dir; 396b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN], found[8 * PETSC_MAX_PATH_LEN]; 397b3bb0f5eSLisandro Dalcin char *libname, suffix[16], *s; 3985b096c79SMatthew Knepley PetscToken token; 399e5c89e4eSSatish Balay 400e5c89e4eSSatish Balay PetscFunctionBegin; 401b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist, 2); 402e5c89e4eSSatish Balay 403b3bb0f5eSLisandro Dalcin /* is path a directory? */ 4049566063dSJacob Faibussowitsch PetscCall(PetscTestDirectory(path, 'r', &dir)); 405e5c89e4eSSatish Balay if (dir) { 4069566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Checking directory %s for dynamic libraries\n", path)); 4079566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(program, path, sizeof(program))); 4089566063dSJacob Faibussowitsch PetscCall(PetscStrlen(program, &len)); 409e5c89e4eSSatish Balay if (program[len - 1] == '/') { 4109566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "*.", sizeof(program))); 411e5c89e4eSSatish Balay } else { 4129566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "/*.", sizeof(program))); 413e5c89e4eSSatish Balay } 4149566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, PETSC_SLSUFFIX, sizeof(program))); 415e5c89e4eSSatish Balay 4169566063dSJacob Faibussowitsch PetscCall(PetscLs(comm, program, found, 8 * PETSC_MAX_PATH_LEN, &dir)); 417e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 418e5c89e4eSSatish Balay } else { 4199566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(found, path, PETSC_MAX_PATH_LEN)); 420e5c89e4eSSatish Balay } 421e5c89e4eSSatish Balay 4229566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 4239566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 424e5c89e4eSSatish Balay 4259566063dSJacob Faibussowitsch PetscCall(PetscTokenCreate(found, '\n', &token)); 4269566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 427b3bb0f5eSLisandro Dalcin while (libname) { 428b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 4299566063dSJacob Faibussowitsch PetscCall(PetscStrstr(libname, suffix, &s)); 430e5c89e4eSSatish Balay if (s) s[0] = 0; 431e5c89e4eSSatish Balay /* see if library was already open and move it to the front */ 43202c9f0b5SLisandro Dalcin prev = NULL; 433b3bb0f5eSLisandro Dalcin list = *outlist; 434e5c89e4eSSatish Balay match = PETSC_FALSE; 435e5c89e4eSSatish Balay while (list) { 4369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(list->libname, libname, &match)); 437e5c89e4eSSatish Balay if (match) { 4389566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Moving %s to begin of dynamic library search path\n", libname)); 439e5c89e4eSSatish Balay if (prev) prev->next = list->next; 440b3bb0f5eSLisandro Dalcin if (prev) list->next = *outlist; 441e5c89e4eSSatish Balay *outlist = list; 442e5c89e4eSSatish Balay break; 443e5c89e4eSSatish Balay } 444e5c89e4eSSatish Balay prev = list; 445e5c89e4eSSatish Balay list = list->next; 446e5c89e4eSSatish Balay } 447b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 448b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 449e5c89e4eSSatish Balay if (!match) { 4505673baf8SLisandro Dalcin /* open the library and add to front of list */ 4519566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryOpen(comm, libname, &list)); 4529566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Prepending %s to dynamic library search path\n", libname)); 453ebd79076SLisandro Dalcin list->next = *outlist; 454e5c89e4eSSatish Balay *outlist = list; 455e5c89e4eSSatish Balay } 4569566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 457e5c89e4eSSatish Balay } 4589566063dSJacob Faibussowitsch PetscCall(PetscTokenDestroy(&token)); 459e5c89e4eSSatish Balay PetscFunctionReturn(0); 460e5c89e4eSSatish Balay } 461e5c89e4eSSatish Balay 462e5c89e4eSSatish Balay /*@C 463e5c89e4eSSatish Balay PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 464e5c89e4eSSatish Balay 465e5c89e4eSSatish Balay Collective on PetscDLLibrary 466e5c89e4eSSatish Balay 467e5c89e4eSSatish Balay Input Parameter: 4683fa76a5bSLisandro Dalcin . head - library list 469e5c89e4eSSatish Balay 470e5c89e4eSSatish Balay Level: developer 471e5c89e4eSSatish Balay 472e5c89e4eSSatish Balay @*/ 4739371c9d4SSatish Balay PetscErrorCode PetscDLLibraryClose(PetscDLLibrary list) { 474ace3abfcSBarry Smith PetscBool done = PETSC_FALSE; 4750f31fb7fSLisandro Dalcin PetscDLLibrary prev, tail; 476e5c89e4eSSatish Balay 477e5c89e4eSSatish Balay PetscFunctionBegin; 4780f31fb7fSLisandro Dalcin if (!list) PetscFunctionReturn(0); 4793fa76a5bSLisandro Dalcin /* traverse the list in reverse order */ 4803fa76a5bSLisandro Dalcin while (!done) { 4810f31fb7fSLisandro Dalcin if (!list->next) done = PETSC_TRUE; 4820f31fb7fSLisandro Dalcin prev = tail = list; 4833fa76a5bSLisandro Dalcin while (tail->next) { 4843fa76a5bSLisandro Dalcin prev = tail; 4853fa76a5bSLisandro Dalcin tail = tail->next; 486e5c89e4eSSatish Balay } 48702c9f0b5SLisandro Dalcin prev->next = NULL; 4883fa76a5bSLisandro Dalcin /* close the dynamic library and free the space in entry data-structure*/ 4899566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Closing dynamic library %s\n", tail->libname)); 4909566063dSJacob Faibussowitsch PetscCall(PetscDLClose(&tail->handle)); 4919566063dSJacob Faibussowitsch PetscCall(PetscFree(tail)); 492a297a907SKarl Rupp } 493e5c89e4eSSatish Balay PetscFunctionReturn(0); 494e5c89e4eSSatish Balay } 495