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 Code to maintain a list of opened dynamic libraries and load symbols 10e5c89e4eSSatish Balay */ 11e5bd5246SBarry Smith struct _n_PetscDLLibrary { 12e5bd5246SBarry Smith PetscDLLibrary next; 13ebd79076SLisandro Dalcin PetscDLHandle handle; 14e5c89e4eSSatish Balay char libname[PETSC_MAX_PATH_LEN]; 15e5c89e4eSSatish Balay }; 16e5c89e4eSSatish Balay 17d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibraryPrintPath(PetscDLLibrary libs) 18d71ae5a4SJacob Faibussowitsch { 19e5c89e4eSSatish Balay PetscFunctionBegin; 20e5c89e4eSSatish Balay while (libs) { 213ba16761SJacob Faibussowitsch PetscCall(PetscErrorPrintf(" %s\n", libs->libname)); 22e5c89e4eSSatish Balay libs = libs->next; 23e5c89e4eSSatish Balay } 243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25e5c89e4eSSatish Balay } 26e5c89e4eSSatish Balay 27e5c89e4eSSatish Balay /*@C 28e5c89e4eSSatish Balay PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 29*21532e8aSBarry Smith (if it is remote), then indicates if it exits and its local name. 30e5c89e4eSSatish Balay 31d083f849SBarry Smith Collective 32e5c89e4eSSatish Balay 33e5c89e4eSSatish Balay Input Parameters: 34*21532e8aSBarry Smith + comm - MPI processes that will be opening the library 35*21532e8aSBarry Smith . libname - name of the library, can be a relative or absolute path and be a URL 36*21532e8aSBarry Smith - llen - length of the `name` buffer 37e5c89e4eSSatish Balay 38d8d19677SJose E. Roman Output Parameters: 39*21532e8aSBarry Smith + name - actual name of the file on local filesystem if `found` 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. 49*21532e8aSBarry Smith 50*21532e8aSBarry Smith .seealso: `PetscFileRetrieve()` 51e5c89e4eSSatish Balay @*/ 52d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibraryRetrieve(MPI_Comm comm, const char libname[], char *lname, size_t llen, PetscBool *found) 53d71ae5a4SJacob Faibussowitsch { 54c6a7a370SJeremy L Thompson char *buf, *par2, *gz = NULL, *so = NULL; 55c6a7a370SJeremy L Thompson size_t len, blen; 56e5c89e4eSSatish Balay 57e5c89e4eSSatish Balay PetscFunctionBegin; 58e5c89e4eSSatish Balay /* 59a523d312SBarry Smith make copy of library name and replace $PETSC_ARCH etc 60e5c89e4eSSatish Balay so we can add to the end of it to look for something like .so.1.0 etc. 61e5c89e4eSSatish Balay */ 629566063dSJacob Faibussowitsch PetscCall(PetscStrlen(libname, &len)); 63c6a7a370SJeremy L Thompson blen = PetscMax(4 * len, PETSC_MAX_PATH_LEN); 64c6a7a370SJeremy L Thompson PetscCall(PetscMalloc1(blen, &buf)); 65d46cf212SLisandro Dalcin par2 = buf; 66c6a7a370SJeremy L Thompson PetscCall(PetscStrreplace(comm, libname, par2, blen)); 67e5c89e4eSSatish Balay 68d46cf212SLisandro Dalcin /* temporarily remove .gz if it ends library name */ 699566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(par2, ".gz", &gz)); 70e5c89e4eSSatish Balay if (gz) { 719566063dSJacob Faibussowitsch PetscCall(PetscStrlen(gz, &len)); 7202c9f0b5SLisandro Dalcin if (len != 3) gz = NULL; /* do not end (exactly) with .gz */ 73d46cf212SLisandro Dalcin else *gz = 0; /* ends with .gz, so remove it */ 74e5c89e4eSSatish Balay } 753fa76a5bSLisandro Dalcin /* strip out .a from it if user put it in by mistake */ 769566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par2, &len)); 773fa76a5bSLisandro Dalcin if (par2[len - 1] == 'a' && par2[len - 2] == '.') par2[len - 2] = 0; 783fa76a5bSLisandro Dalcin 799566063dSJacob Faibussowitsch PetscCall(PetscFileRetrieve(comm, par2, lname, llen, found)); 808ce0dc28SMatthew G Knepley if (!(*found)) { 81c6a7a370SJeremy L Thompson const char suffix[] = "." PETSC_SLSUFFIX; 82c6a7a370SJeremy L Thompson 83e5c89e4eSSatish Balay /* see if library name does already not have suffix attached */ 849566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(par2, suffix, &so)); 85d46cf212SLisandro Dalcin /* and attach the suffix if it is not there */ 86c6a7a370SJeremy L Thompson if (!so) PetscCall(PetscStrlcat(par2, suffix, blen)); 87e5c89e4eSSatish Balay 88d46cf212SLisandro Dalcin /* restore the .gz suffix if it was there */ 89c6a7a370SJeremy L Thompson if (gz) PetscCall(PetscStrlcat(par2, ".gz", blen)); 90d46cf212SLisandro Dalcin 91d46cf212SLisandro Dalcin /* and finally retrieve the file */ 929566063dSJacob Faibussowitsch PetscCall(PetscFileRetrieve(comm, par2, lname, llen, found)); 932d53ad75SBarry Smith } 94d46cf212SLisandro Dalcin 959566063dSJacob Faibussowitsch PetscCall(PetscFree(buf)); 963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97e5c89e4eSSatish Balay } 98e5c89e4eSSatish Balay 99e5c89e4eSSatish Balay /*@C 100ebd79076SLisandro Dalcin PetscDLLibraryOpen - Opens a PETSc dynamic link library 101e5c89e4eSSatish Balay 102d083f849SBarry Smith Collective 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay Input Parameters: 105*21532e8aSBarry Smith + comm - MPI processes that are opening the library 106*21532e8aSBarry Smith - path - name of the library, can be a relative or absolute path 107e5c89e4eSSatish Balay 108e5c89e4eSSatish Balay Output Parameter: 1090f31fb7fSLisandro Dalcin . entry - a PETSc dynamic link library entry 110e5c89e4eSSatish Balay 111e5c89e4eSSatish Balay Level: developer 112e5c89e4eSSatish Balay 113e5c89e4eSSatish Balay Notes: 114bb84e0fdSBarry Smith [[<http,ftp>://hostname]/directoryname/]libbasename[.so.1.0] 115bb84e0fdSBarry Smith 116*21532e8aSBarry Smith If the library has the symbol `PetscDLLibraryRegister_basename()` in it then that function is automatically run 117bb84e0fdSBarry Smith when the library is opened. 118e5c89e4eSSatish Balay 119a5b23f4aSJose E. Roman ${PETSC_ARCH} occurring in directoryname and filename 120e5c89e4eSSatish Balay will be replaced with the appropriate value. 121bb84e0fdSBarry Smith 122*21532e8aSBarry Smith .seealso: `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`, `PetscDLLibraryRetrieve()`, `PetscDLLibrarySym()`, `PetscDLLibraryClose()` 123e5c89e4eSSatish Balay @*/ 124d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibraryOpen(MPI_Comm comm, const char path[], PetscDLLibrary *entry) 125d71ae5a4SJacob Faibussowitsch { 126ace3abfcSBarry Smith PetscBool foundlibrary, match; 127c6a7a370SJeremy L Thompson const char suffix[] = "." PETSC_SLSUFFIX; 128c6a7a370SJeremy L Thompson char libname[PETSC_MAX_PATH_LEN], par2[PETSC_MAX_PATH_LEN], *s; 129b3bb0f5eSLisandro Dalcin char *basename, registername[128]; 1305673baf8SLisandro Dalcin PetscDLHandle handle; 131607a6623SBarry Smith PetscErrorCode (*func)(void) = NULL; 132e5c89e4eSSatish Balay 133e5c89e4eSSatish Balay PetscFunctionBegin; 13482a51d08SSatish Balay PetscValidCharPointer(path, 2); 1355673baf8SLisandro Dalcin PetscValidPointer(entry, 3); 136ebd79076SLisandro Dalcin 1370298fd71SBarry Smith *entry = NULL; 138e5c89e4eSSatish Balay 139b3bb0f5eSLisandro Dalcin /* retrieve the library */ 1409566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Retrieving %s\n", path)); 1419566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(comm, path, par2, PETSC_MAX_PATH_LEN, &foundlibrary)); 14228b400f6SJacob Faibussowitsch PetscCheck(foundlibrary, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate dynamic library:\n %s", path); 143e2e64c6bSBarry Smith /* Eventually ./configure should determine if the system needs an executable dynamic library */ 144e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO 145e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO) 1469566063dSJacob Faibussowitsch PetscCall(PetscTestFile(par2, 'x', &foundlibrary)); 14728b400f6SJacob Faibussowitsch PetscCheck(foundlibrary, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Dynamic library is not executable:\n %s\n %s", path, par2); 148e5c89e4eSSatish Balay #endif 149e5c89e4eSSatish Balay 1503fa76a5bSLisandro Dalcin /* copy path and setup shared library suffix */ 151c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(libname, path, sizeof(libname))); 1523fa76a5bSLisandro Dalcin /* remove wrong suffixes from libname */ 1539566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, ".gz", &s)); 1543fa76a5bSLisandro Dalcin if (s && s[3] == 0) s[0] = 0; 1559566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, ".a", &s)); 1563fa76a5bSLisandro Dalcin if (s && s[2] == 0) s[0] = 0; 1573fa76a5bSLisandro Dalcin /* remove shared suffix from libname */ 1589566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, suffix, &s)); 159b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 160b3bb0f5eSLisandro Dalcin 1615673baf8SLisandro Dalcin /* open the dynamic library */ 1629566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Opening dynamic library %s\n", libname)); 1639566063dSJacob Faibussowitsch PetscCall(PetscDLOpen(par2, PETSC_DL_DECIDE, &handle)); 164b3bb0f5eSLisandro Dalcin 165b3bb0f5eSLisandro Dalcin /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */ 1669566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(libname, '/', &basename)); /* XXX Windows ??? */ 167b3bb0f5eSLisandro Dalcin if (!basename) basename = libname; 1689566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(basename, "lib", 3, &match)); 169a297a907SKarl Rupp if (match) basename = basename + 3; 17048a46eb9SPierre Jolivet else PetscCall(PetscInfo(NULL, "Dynamic library %s does not have lib prefix\n", libname)); 1719371c9d4SSatish Balay for (s = basename; *s; s++) 1729371c9d4SSatish Balay if (*s == '-') *s = '_'; 1739566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(registername, "PetscDLLibraryRegister_", sizeof(registername))); 1749566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(registername, basename, sizeof(registername))); 1759566063dSJacob Faibussowitsch PetscCall(PetscDLSym(handle, registername, (void **)&func)); 176b3bb0f5eSLisandro Dalcin if (func) { 1779566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Loading registered routines from %s\n", libname)); 1789566063dSJacob Faibussowitsch PetscCall((*func)()); 179b3bb0f5eSLisandro Dalcin } else { 1809566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Dynamic library %s does not have symbol %s\n", libname, registername)); 181b3bb0f5eSLisandro Dalcin } 1825673baf8SLisandro Dalcin 1839566063dSJacob Faibussowitsch PetscCall(PetscNew(entry)); 18402c9f0b5SLisandro Dalcin (*entry)->next = NULL; 185b3bb0f5eSLisandro Dalcin (*entry)->handle = handle; 186c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy((*entry)->libname, libname, sizeof((*entry)->libname))); 1873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 188e5c89e4eSSatish Balay } 189e5c89e4eSSatish Balay 190e5c89e4eSSatish Balay /*@C 191*21532e8aSBarry Smith PetscDLLibrarySym - Load a symbol from a list of dynamic link libraries. 192e5c89e4eSSatish Balay 193d083f849SBarry Smith Collective 194e5c89e4eSSatish Balay 195d8d19677SJose E. Roman Input Parameters: 196*21532e8aSBarry Smith + comm - the MPI communicator that will load the symbol 197*21532e8aSBarry Smith . outlist - list of already open libraries that may contain symbol (can be `NULL` and only the executable is searched for the function) 198*21532e8aSBarry Smith . path - optional complete library name (if provided it checks here before checking `outlist`) 199e5c89e4eSSatish Balay - insymbol - name of symbol 200e5c89e4eSSatish Balay 201e5c89e4eSSatish Balay Output Parameter: 202*21532e8aSBarry Smith . value - if symbol not found then this value is set to `NULL` 203e5c89e4eSSatish Balay 204e5c89e4eSSatish Balay Level: developer 205e5c89e4eSSatish Balay 20695452b02SPatrick Sanan Notes: 20795452b02SPatrick Sanan Symbol can be of the form 208e5c89e4eSSatish Balay [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 209e5c89e4eSSatish Balay 210*21532e8aSBarry Smith It will attempt to (retrieve and) open the library if it is not yet been opened. 211e5c89e4eSSatish Balay 212*21532e8aSBarry Smith .seealso: `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`, `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryClose()` 213e5c89e4eSSatish Balay @*/ 214d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibrarySym(MPI_Comm comm, PetscDLLibrary *outlist, const char path[], const char insymbol[], void **value) 215d71ae5a4SJacob Faibussowitsch { 216bbcf679cSJacob Faibussowitsch char libname[PETSC_MAX_PATH_LEN], suffix[16]; 2177864358aSSatish Balay char *symbol = NULL, *s = NULL; 218bbcf679cSJacob Faibussowitsch PetscDLLibrary list = NULL, nlist, prev; 219e5c89e4eSSatish Balay 220e5c89e4eSSatish Balay PetscFunctionBegin; 221340b11eeSBarry Smith if (outlist) PetscValidPointer(outlist, 2); 2225673baf8SLisandro Dalcin if (path) PetscValidCharPointer(path, 3); 2235673baf8SLisandro Dalcin PetscValidCharPointer(insymbol, 4); 2245673baf8SLisandro Dalcin PetscValidPointer(value, 5); 2255673baf8SLisandro Dalcin 226340b11eeSBarry Smith if (outlist) list = *outlist; 22702c9f0b5SLisandro Dalcin *value = NULL; 228e5c89e4eSSatish Balay 2299566063dSJacob Faibussowitsch PetscCall(PetscStrchr(insymbol, '(', &s)); 2302d53ad75SBarry Smith if (s) { 231e5c89e4eSSatish Balay /* make copy of symbol so we can edit it in place */ 2329566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(insymbol, &symbol)); 233b3bb0f5eSLisandro Dalcin /* If symbol contains () then replace with a NULL, to support functionname() */ 2349566063dSJacob Faibussowitsch PetscCall(PetscStrchr(symbol, '(', &s)); 2352d53ad75SBarry Smith s[0] = 0; 236a297a907SKarl Rupp } else symbol = (char *)insymbol; 237e5c89e4eSSatish Balay 238e5c89e4eSSatish Balay /* 239e5c89e4eSSatish Balay Function name does include library 240e5c89e4eSSatish Balay */ 241e5c89e4eSSatish Balay if (path && path[0] != '\0') { 242b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 2439566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libname, path, PETSC_MAX_PATH_LEN)); 2449566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 2459566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 2469566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, suffix, &s)); 247b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 2485673baf8SLisandro Dalcin /* Look if library is already opened and in path */ 24902c9f0b5SLisandro Dalcin prev = NULL; 250b3bb0f5eSLisandro Dalcin nlist = list; 251e5c89e4eSSatish Balay while (nlist) { 252ace3abfcSBarry Smith PetscBool match; 2539566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(nlist->libname, libname, &match)); 2545673baf8SLisandro Dalcin if (match) goto done; 255e5c89e4eSSatish Balay prev = nlist; 256e5c89e4eSSatish Balay nlist = nlist->next; 257e5c89e4eSSatish Balay } 258b3bb0f5eSLisandro Dalcin /* open the library and append it to path */ 2599566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryOpen(comm, path, &nlist)); 2609566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Appending %s to dynamic library search path\n", path)); 261a297a907SKarl Rupp if (prev) prev->next = nlist; 2629371c9d4SSatish Balay else { 2639371c9d4SSatish Balay if (outlist) *outlist = nlist; 2649371c9d4SSatish Balay } 265e5c89e4eSSatish Balay 266e5c89e4eSSatish Balay done:; 2679566063dSJacob Faibussowitsch PetscCall(PetscDLSym(nlist->handle, symbol, value)); 26848a46eb9SPierre Jolivet if (*value) PetscCall(PetscInfo(NULL, "Loading function %s from dynamic library %s\n", insymbol, path)); 269e5c89e4eSSatish Balay 270e5c89e4eSSatish Balay /* 271e5c89e4eSSatish Balay Function name does not include library so search path 272e5c89e4eSSatish Balay */ 273e5c89e4eSSatish Balay } else { 274e5c89e4eSSatish Balay while (list) { 2759566063dSJacob Faibussowitsch PetscCall(PetscDLSym(list->handle, symbol, value)); 276e5c89e4eSSatish Balay if (*value) { 2779566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Loading symbol %s from dynamic library %s\n", symbol, list->libname)); 278e5c89e4eSSatish Balay break; 279e5c89e4eSSatish Balay } 280e5c89e4eSSatish Balay list = list->next; 281e5c89e4eSSatish Balay } 282e5c89e4eSSatish Balay if (!*value) { 2839566063dSJacob Faibussowitsch PetscCall(PetscDLSym(NULL, symbol, value)); 28448a46eb9SPierre Jolivet if (*value) PetscCall(PetscInfo(NULL, "Loading symbol %s from object code\n", symbol)); 285e5c89e4eSSatish Balay } 286e5c89e4eSSatish Balay } 287e5c89e4eSSatish Balay 28848a46eb9SPierre Jolivet if (symbol != insymbol) PetscCall(PetscFree(symbol)); 2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 290e5c89e4eSSatish Balay } 291e5c89e4eSSatish Balay 292e5c89e4eSSatish Balay /*@C 293*21532e8aSBarry Smith PetscDLLibraryAppend - Appends another dynamic link library to the end of the search list 294e5c89e4eSSatish Balay 295d083f849SBarry Smith Collective 296e5c89e4eSSatish Balay 297e5c89e4eSSatish Balay Input Parameters: 298e5c89e4eSSatish Balay + comm - MPI communicator 2990f31fb7fSLisandro Dalcin - path - name of the library 300e5c89e4eSSatish Balay 301e5c89e4eSSatish Balay Output Parameter: 302e5c89e4eSSatish Balay . outlist - list of libraries 303e5c89e4eSSatish Balay 304e5c89e4eSSatish Balay Level: developer 305e5c89e4eSSatish Balay 306811af0c4SBarry Smith Note: 30795452b02SPatrick Sanan if library is already in path will not add it. 308bb84e0fdSBarry Smith 309bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 310bb84e0fdSBarry Smith when the library is opened. 311bb84e0fdSBarry Smith 312*21532e8aSBarry Smith .seealso: `PetscDLLibrary`, `PetscDLLibraryOpen()`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryPrepend()` 313e5c89e4eSSatish Balay @*/ 314d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibraryAppend(MPI_Comm comm, PetscDLLibrary *outlist, const char path[]) 315d71ae5a4SJacob Faibussowitsch { 316e5bd5246SBarry Smith PetscDLLibrary list, prev; 317e5c89e4eSSatish Balay size_t len; 318ace3abfcSBarry Smith PetscBool match, dir; 319b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN], found[8 * PETSC_MAX_PATH_LEN]; 320bbcf679cSJacob Faibussowitsch char *libname, suffix[16], *s = NULL; 3219c9d3cfdSBarry Smith PetscToken token; 322e5c89e4eSSatish Balay 323e5c89e4eSSatish Balay PetscFunctionBegin; 324b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist, 2); 325e5c89e4eSSatish Balay 326b3bb0f5eSLisandro Dalcin /* is path a directory? */ 3279566063dSJacob Faibussowitsch PetscCall(PetscTestDirectory(path, 'r', &dir)); 328e5c89e4eSSatish Balay if (dir) { 3299566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Checking directory %s for dynamic libraries\n", path)); 3309566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(program, path, sizeof(program))); 3319566063dSJacob Faibussowitsch PetscCall(PetscStrlen(program, &len)); 332e5c89e4eSSatish Balay if (program[len - 1] == '/') { 3339566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "*.", sizeof(program))); 334e5c89e4eSSatish Balay } else { 3359566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "/*.", sizeof(program))); 336e5c89e4eSSatish Balay } 3379566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, PETSC_SLSUFFIX, sizeof(program))); 338e5c89e4eSSatish Balay 3399566063dSJacob Faibussowitsch PetscCall(PetscLs(comm, program, found, 8 * PETSC_MAX_PATH_LEN, &dir)); 3403ba16761SJacob Faibussowitsch if (!dir) PetscFunctionReturn(PETSC_SUCCESS); 341e5c89e4eSSatish Balay } else { 3429566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(found, path, PETSC_MAX_PATH_LEN)); 343e5c89e4eSSatish Balay } 3449566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 3459566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 346e5c89e4eSSatish Balay 3479566063dSJacob Faibussowitsch PetscCall(PetscTokenCreate(found, '\n', &token)); 3489566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 349b3bb0f5eSLisandro Dalcin while (libname) { 350b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 3519566063dSJacob Faibussowitsch PetscCall(PetscStrrstr(libname, suffix, &s)); 352e5c89e4eSSatish Balay if (s) s[0] = 0; 353e5c89e4eSSatish Balay /* see if library was already open then we are done */ 354e5c89e4eSSatish Balay list = prev = *outlist; 355e5c89e4eSSatish Balay match = PETSC_FALSE; 356e5c89e4eSSatish Balay while (list) { 3579566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(list->libname, libname, &match)); 358e5c89e4eSSatish Balay if (match) break; 359e5c89e4eSSatish Balay prev = list; 360e5c89e4eSSatish Balay list = list->next; 361e5c89e4eSSatish Balay } 362b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 363b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 364e5c89e4eSSatish Balay if (!match) { 3655673baf8SLisandro Dalcin /* open the library and add to end of list */ 3669566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryOpen(comm, libname, &list)); 3679566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Appending %s to dynamic library search path\n", libname)); 368a297a907SKarl Rupp if (!*outlist) *outlist = list; 369a297a907SKarl Rupp else prev->next = list; 370e5c89e4eSSatish Balay } 3719566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 372e5c89e4eSSatish Balay } 3739566063dSJacob Faibussowitsch PetscCall(PetscTokenDestroy(&token)); 3743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 375e5c89e4eSSatish Balay } 376e5c89e4eSSatish Balay 377e5c89e4eSSatish Balay /*@C 378*21532e8aSBarry Smith PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of the search list 379e5c89e4eSSatish Balay 380d083f849SBarry Smith Collective 381e5c89e4eSSatish Balay 382e5c89e4eSSatish Balay Input Parameters: 383e5c89e4eSSatish Balay + comm - MPI communicator 3840f31fb7fSLisandro Dalcin - path - name of the library 385e5c89e4eSSatish Balay 386e5c89e4eSSatish Balay Output Parameter: 387e5c89e4eSSatish Balay . outlist - list of libraries 388e5c89e4eSSatish Balay 389e5c89e4eSSatish Balay Level: developer 390e5c89e4eSSatish Balay 391811af0c4SBarry Smith Note: 392*21532e8aSBarry Smith If library is already in the list it will remove the old reference. 393e5c89e4eSSatish Balay 394*21532e8aSBarry Smith .seealso: `PetscDLLibrary`, `PetscDLLibraryOpen()`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryAppend()` 395e5c89e4eSSatish Balay @*/ 396d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibraryPrepend(MPI_Comm comm, PetscDLLibrary *outlist, const char path[]) 397d71ae5a4SJacob Faibussowitsch { 398e5bd5246SBarry Smith PetscDLLibrary list, prev; 399e5c89e4eSSatish Balay size_t len; 400ace3abfcSBarry Smith PetscBool match, dir; 401b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN], found[8 * PETSC_MAX_PATH_LEN]; 402bbcf679cSJacob Faibussowitsch char *libname, suffix[16], *s = NULL; 4035b096c79SMatthew Knepley PetscToken token; 404e5c89e4eSSatish Balay 405e5c89e4eSSatish Balay PetscFunctionBegin; 406b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist, 2); 407e5c89e4eSSatish Balay 408b3bb0f5eSLisandro Dalcin /* is path a directory? */ 4099566063dSJacob Faibussowitsch PetscCall(PetscTestDirectory(path, 'r', &dir)); 410e5c89e4eSSatish Balay if (dir) { 4119566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Checking directory %s for dynamic libraries\n", path)); 4129566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(program, path, sizeof(program))); 4139566063dSJacob Faibussowitsch PetscCall(PetscStrlen(program, &len)); 414e5c89e4eSSatish Balay if (program[len - 1] == '/') { 4159566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "*.", sizeof(program))); 416e5c89e4eSSatish Balay } else { 4179566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, "/*.", sizeof(program))); 418e5c89e4eSSatish Balay } 4199566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(program, PETSC_SLSUFFIX, sizeof(program))); 420e5c89e4eSSatish Balay 4219566063dSJacob Faibussowitsch PetscCall(PetscLs(comm, program, found, 8 * PETSC_MAX_PATH_LEN, &dir)); 4223ba16761SJacob Faibussowitsch if (!dir) PetscFunctionReturn(PETSC_SUCCESS); 423e5c89e4eSSatish Balay } else { 4249566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(found, path, PETSC_MAX_PATH_LEN)); 425e5c89e4eSSatish Balay } 426e5c89e4eSSatish Balay 4279566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(suffix, ".", sizeof(suffix))); 4289566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(suffix, PETSC_SLSUFFIX, sizeof(suffix))); 429e5c89e4eSSatish Balay 4309566063dSJacob Faibussowitsch PetscCall(PetscTokenCreate(found, '\n', &token)); 4319566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 432b3bb0f5eSLisandro Dalcin while (libname) { 433b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 4349566063dSJacob Faibussowitsch PetscCall(PetscStrstr(libname, suffix, &s)); 435e5c89e4eSSatish Balay if (s) s[0] = 0; 436e5c89e4eSSatish Balay /* see if library was already open and move it to the front */ 43702c9f0b5SLisandro Dalcin prev = NULL; 438b3bb0f5eSLisandro Dalcin list = *outlist; 439e5c89e4eSSatish Balay match = PETSC_FALSE; 440e5c89e4eSSatish Balay while (list) { 4419566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(list->libname, libname, &match)); 442e5c89e4eSSatish Balay if (match) { 4439566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Moving %s to begin of dynamic library search path\n", libname)); 444e5c89e4eSSatish Balay if (prev) prev->next = list->next; 445b3bb0f5eSLisandro Dalcin if (prev) list->next = *outlist; 446e5c89e4eSSatish Balay *outlist = list; 447e5c89e4eSSatish Balay break; 448e5c89e4eSSatish Balay } 449e5c89e4eSSatish Balay prev = list; 450e5c89e4eSSatish Balay list = list->next; 451e5c89e4eSSatish Balay } 452b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 453b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 454e5c89e4eSSatish Balay if (!match) { 4555673baf8SLisandro Dalcin /* open the library and add to front of list */ 4569566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryOpen(comm, libname, &list)); 4579566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Prepending %s to dynamic library search path\n", libname)); 458ebd79076SLisandro Dalcin list->next = *outlist; 459e5c89e4eSSatish Balay *outlist = list; 460e5c89e4eSSatish Balay } 4619566063dSJacob Faibussowitsch PetscCall(PetscTokenFind(token, &libname)); 462e5c89e4eSSatish Balay } 4639566063dSJacob Faibussowitsch PetscCall(PetscTokenDestroy(&token)); 4643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 465e5c89e4eSSatish Balay } 466e5c89e4eSSatish Balay 467e5c89e4eSSatish Balay /*@C 468e5c89e4eSSatish Balay PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 469e5c89e4eSSatish Balay 470c3339decSBarry Smith Collective 471e5c89e4eSSatish Balay 472e5c89e4eSSatish Balay Input Parameter: 4733fa76a5bSLisandro Dalcin . head - library list 474e5c89e4eSSatish Balay 475e5c89e4eSSatish Balay Level: developer 476e5c89e4eSSatish Balay 477*21532e8aSBarry Smith .seealso: `PetscDLLibrary`, `PetscDLLibraryOpen()`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryAppend()`, 478*21532e8aSBarry Smith `PetscDLLibraryPrepend()` 479e5c89e4eSSatish Balay @*/ 480d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLLibraryClose(PetscDLLibrary list) 481d71ae5a4SJacob Faibussowitsch { 482ace3abfcSBarry Smith PetscBool done = PETSC_FALSE; 4830f31fb7fSLisandro Dalcin PetscDLLibrary prev, tail; 484e5c89e4eSSatish Balay 485e5c89e4eSSatish Balay PetscFunctionBegin; 4863ba16761SJacob Faibussowitsch if (!list) PetscFunctionReturn(PETSC_SUCCESS); 4873fa76a5bSLisandro Dalcin /* traverse the list in reverse order */ 4883fa76a5bSLisandro Dalcin while (!done) { 4890f31fb7fSLisandro Dalcin if (!list->next) done = PETSC_TRUE; 4900f31fb7fSLisandro Dalcin prev = tail = list; 4913fa76a5bSLisandro Dalcin while (tail->next) { 4923fa76a5bSLisandro Dalcin prev = tail; 4933fa76a5bSLisandro Dalcin tail = tail->next; 494e5c89e4eSSatish Balay } 49502c9f0b5SLisandro Dalcin prev->next = NULL; 4963fa76a5bSLisandro Dalcin /* close the dynamic library and free the space in entry data-structure*/ 4979566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Closing dynamic library %s\n", tail->libname)); 4989566063dSJacob Faibussowitsch PetscCall(PetscDLClose(&tail->handle)); 4999566063dSJacob Faibussowitsch PetscCall(PetscFree(tail)); 500a297a907SKarl Rupp } 5013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 502e5c89e4eSSatish Balay } 503