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 187087cfbeSBarry Smith PetscErrorCode PetscDLLibraryPrintPath(PetscDLLibrary libs) 19e5c89e4eSSatish Balay { 20e5c89e4eSSatish Balay PetscFunctionBegin; 21e5c89e4eSSatish Balay while (libs) { 22e5c89e4eSSatish Balay PetscErrorPrintf(" %s\n",libs->libname); 23e5c89e4eSSatish Balay libs = libs->next; 24e5c89e4eSSatish Balay } 25e5c89e4eSSatish Balay PetscFunctionReturn(0); 26e5c89e4eSSatish Balay } 27e5c89e4eSSatish Balay 28e5c89e4eSSatish Balay /*@C 29e5c89e4eSSatish Balay PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 30e5c89e4eSSatish Balay (if it is remote), indicates if it exits and its local name. 31e5c89e4eSSatish Balay 32d083f849SBarry Smith Collective 33e5c89e4eSSatish Balay 34e5c89e4eSSatish Balay Input Parameters: 35e5c89e4eSSatish Balay + comm - processors that are opening the library 36e5c89e4eSSatish Balay - libname - name of the library, can be relative or absolute 37e5c89e4eSSatish Balay 38d8d19677SJose E. Roman Output Parameters: 392d53ad75SBarry Smith + name - actual name of file on local filesystem if found 402d53ad75SBarry Smith . llen - length of the name buffer 412d53ad75SBarry Smith - found - true if the file exists 42e5c89e4eSSatish Balay 43e5c89e4eSSatish Balay Level: developer 44e5c89e4eSSatish Balay 45e5c89e4eSSatish Balay Notes: 46e5c89e4eSSatish Balay [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 47e5c89e4eSSatish Balay 48e5c89e4eSSatish Balay ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 49a5b23f4aSJose E. Roman occurring in directoryname and filename will be replaced with appropriate values. 50e5c89e4eSSatish Balay @*/ 517087cfbeSBarry Smith PetscErrorCode PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,size_t llen,PetscBool *found) 52e5c89e4eSSatish Balay { 53d46cf212SLisandro Dalcin char *buf,*par2,suffix[16],*gz,*so; 54d46cf212SLisandro Dalcin size_t len; 55e5c89e4eSSatish Balay 56e5c89e4eSSatish Balay PetscFunctionBegin; 57e5c89e4eSSatish Balay /* 58a523d312SBarry Smith make copy of library name and replace $PETSC_ARCH etc 59e5c89e4eSSatish Balay so we can add to the end of it to look for something like .so.1.0 etc. 60e5c89e4eSSatish Balay */ 61*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(libname,&len)); 622f613bf5SBarry Smith len = PetscMax(4*len,PETSC_MAX_PATH_LEN); 63*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(len,&buf)); 64d46cf212SLisandro Dalcin par2 = buf; 65*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrreplace(comm,libname,par2,len)); 66e5c89e4eSSatish Balay 67d46cf212SLisandro Dalcin /* temporarily remove .gz if it ends library name */ 68*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrstr(par2,".gz",&gz)); 69e5c89e4eSSatish Balay if (gz) { 70*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(gz,&len)); 7102c9f0b5SLisandro Dalcin if (len != 3) gz = NULL; /* do not end (exactly) with .gz */ 72d46cf212SLisandro Dalcin else *gz = 0; /* ends with .gz, so remove it */ 73e5c89e4eSSatish Balay } 743fa76a5bSLisandro Dalcin /* strip out .a from it if user put it in by mistake */ 75*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(par2,&len)); 763fa76a5bSLisandro Dalcin if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0; 773fa76a5bSLisandro Dalcin 78*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFileRetrieve(comm,par2,lname,llen,found)); 798ce0dc28SMatthew G Knepley if (!(*found)) { 80e5c89e4eSSatish Balay /* see if library name does already not have suffix attached */ 81*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(suffix,".",sizeof(suffix))); 82*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(suffix,PETSC_SLSUFFIX,sizeof(suffix))); 83*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrstr(par2,suffix,&so)); 84d46cf212SLisandro Dalcin /* and attach the suffix if it is not there */ 85*5f80ce2aSJacob Faibussowitsch if (!so) CHKERRQ(PetscStrcat(par2,suffix)); 86e5c89e4eSSatish Balay 87d46cf212SLisandro Dalcin /* restore the .gz suffix if it was there */ 88*5f80ce2aSJacob Faibussowitsch if (gz) CHKERRQ(PetscStrcat(par2,".gz")); 89d46cf212SLisandro Dalcin 90d46cf212SLisandro Dalcin /* and finally retrieve the file */ 91*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFileRetrieve(comm,par2,lname,llen,found)); 922d53ad75SBarry Smith } 93d46cf212SLisandro Dalcin 94*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(buf)); 95e5c89e4eSSatish Balay PetscFunctionReturn(0); 96e5c89e4eSSatish Balay } 97e5c89e4eSSatish Balay 98e5c89e4eSSatish Balay /*@C 99ebd79076SLisandro Dalcin PetscDLLibraryOpen - Opens a PETSc dynamic link library 100e5c89e4eSSatish Balay 101d083f849SBarry Smith Collective 102e5c89e4eSSatish Balay 103e5c89e4eSSatish Balay Input Parameters: 104e5c89e4eSSatish Balay + comm - processors that are opening the library 1050f31fb7fSLisandro Dalcin - path - name of the library, can be relative or absolute 106e5c89e4eSSatish Balay 107e5c89e4eSSatish Balay Output Parameter: 1080f31fb7fSLisandro Dalcin . entry - a PETSc dynamic link library entry 109e5c89e4eSSatish Balay 110e5c89e4eSSatish Balay Level: developer 111e5c89e4eSSatish Balay 112e5c89e4eSSatish Balay Notes: 113bb84e0fdSBarry Smith [[<http,ftp>://hostname]/directoryname/]libbasename[.so.1.0] 114bb84e0fdSBarry Smith 115bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 116bb84e0fdSBarry Smith when the library is opened. 117e5c89e4eSSatish Balay 118a5b23f4aSJose E. Roman ${PETSC_ARCH} occurring in directoryname and filename 119e5c89e4eSSatish Balay will be replaced with the appropriate value. 120bb84e0fdSBarry Smith 121bb84e0fdSBarry Smith .seealso: PetscLoadDynamicLibrary(), PetscDLLibraryAppend() 122e5c89e4eSSatish Balay @*/ 1237087cfbeSBarry Smith PetscErrorCode PetscDLLibraryOpen(MPI_Comm comm,const char path[],PetscDLLibrary *entry) 124e5c89e4eSSatish Balay { 125ace3abfcSBarry Smith PetscBool foundlibrary,match; 126b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],par2[PETSC_MAX_PATH_LEN],suffix[16],*s; 127b3bb0f5eSLisandro Dalcin char *basename,registername[128]; 1285673baf8SLisandro Dalcin PetscDLHandle handle; 129607a6623SBarry Smith PetscErrorCode (*func)(void) = NULL; 130e5c89e4eSSatish Balay 131e5c89e4eSSatish Balay PetscFunctionBegin; 13282a51d08SSatish Balay PetscValidCharPointer(path,2); 1335673baf8SLisandro Dalcin PetscValidPointer(entry,3); 134ebd79076SLisandro Dalcin 1350298fd71SBarry Smith *entry = NULL; 136e5c89e4eSSatish Balay 137b3bb0f5eSLisandro Dalcin /* retrieve the library */ 138*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Retrieving %s\n",path)); 139*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLLibraryRetrieve(comm,path,par2,PETSC_MAX_PATH_LEN,&foundlibrary)); 1402c71b3e2SJacob Faibussowitsch PetscCheckFalse(!foundlibrary,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s",path); 141e2e64c6bSBarry Smith /* Eventually ./configure should determine if the system needs an executable dynamic library */ 142e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO 143e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO) 144*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTestFile(par2,'x',&foundlibrary)); 1452c71b3e2SJacob Faibussowitsch PetscCheckFalse(!foundlibrary,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s",path,par2); 146e5c89e4eSSatish Balay #endif 147e5c89e4eSSatish Balay 1483fa76a5bSLisandro Dalcin /* copy path and setup shared library suffix */ 149*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN)); 150*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(suffix,".",sizeof(suffix))); 151*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(suffix,PETSC_SLSUFFIX,sizeof(suffix))); 1523fa76a5bSLisandro Dalcin /* remove wrong suffixes from libname */ 153*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrstr(libname,".gz",&s)); 1543fa76a5bSLisandro Dalcin if (s && s[3] == 0) s[0] = 0; 155*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrstr(libname,".a",&s)); 1563fa76a5bSLisandro Dalcin if (s && s[2] == 0) s[0] = 0; 1573fa76a5bSLisandro Dalcin /* remove shared suffix from libname */ 158*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrstr(libname,suffix,&s)); 159b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 160b3bb0f5eSLisandro Dalcin 1615673baf8SLisandro Dalcin /* open the dynamic library */ 162*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Opening dynamic library %s\n",libname)); 163*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLOpen(par2,PETSC_DL_DECIDE,&handle)); 164b3bb0f5eSLisandro Dalcin 165b3bb0f5eSLisandro Dalcin /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */ 166*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrchr(libname,'/',&basename)); /* XXX Windows ??? */ 167b3bb0f5eSLisandro Dalcin if (!basename) basename = libname; 168*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncmp(basename,"lib",3,&match)); 169a297a907SKarl Rupp if (match) basename = basename + 3; 170a297a907SKarl Rupp else { 171*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Dynamic library %s does not have lib prefix\n",libname)); 172e5c89e4eSSatish Balay } 173cf4b33a9SJed Brown for (s=basename; *s; s++) if (*s == '-') *s = '_'; 174*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(registername,"PetscDLLibraryRegister_",sizeof(registername))); 175*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(registername,basename,sizeof(registername))); 176*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLSym(handle,registername,(void**)&func)); 177b3bb0f5eSLisandro Dalcin if (func) { 178*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Loading registered routines from %s\n",libname)); 179*5f80ce2aSJacob Faibussowitsch CHKERRQ((*func)()); 180b3bb0f5eSLisandro Dalcin } else { 181*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Dynamic library %s does not have symbol %s\n",libname,registername)); 182b3bb0f5eSLisandro Dalcin } 1835673baf8SLisandro Dalcin 184*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(entry)); 18502c9f0b5SLisandro Dalcin (*entry)->next = NULL; 186b3bb0f5eSLisandro Dalcin (*entry)->handle = handle; 187*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy((*entry)->libname,libname)); 188e5c89e4eSSatish Balay PetscFunctionReturn(0); 189e5c89e4eSSatish Balay } 190e5c89e4eSSatish Balay 191e5c89e4eSSatish Balay /*@C 192e5c89e4eSSatish Balay PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 193e5c89e4eSSatish Balay 194d083f849SBarry Smith Collective 195e5c89e4eSSatish Balay 196d8d19677SJose E. Roman Input Parameters: 197e5bd5246SBarry Smith + comm - communicator that will open the library 1980298fd71SBarry Smith . outlist - list of already open libraries that may contain symbol (can be NULL and only the executable is searched for the function) 19930a1dd1fSBarry Smith . path - optional complete library name (if provided checks here before checking outlist) 200e5c89e4eSSatish Balay - insymbol - name of symbol 201e5c89e4eSSatish Balay 202e5c89e4eSSatish Balay Output Parameter: 2030298fd71SBarry Smith . value - if symbol not found then this value is set to NULL 204e5c89e4eSSatish Balay 205e5c89e4eSSatish Balay Level: developer 206e5c89e4eSSatish Balay 20795452b02SPatrick Sanan Notes: 20895452b02SPatrick Sanan Symbol can be of the form 209e5c89e4eSSatish Balay [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 210e5c89e4eSSatish Balay 211e5c89e4eSSatish Balay Will attempt to (retrieve and) open the library if it is not yet been opened. 212e5c89e4eSSatish Balay 213e5c89e4eSSatish Balay @*/ 2147087cfbeSBarry Smith PetscErrorCode PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *outlist,const char path[],const char insymbol[],void **value) 215e5c89e4eSSatish Balay { 216b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],suffix[16],*symbol,*s; 2170298fd71SBarry Smith PetscDLLibrary nlist,prev,list = NULL; 218e5c89e4eSSatish Balay 219e5c89e4eSSatish Balay PetscFunctionBegin; 220340b11eeSBarry Smith if (outlist) PetscValidPointer(outlist,2); 2215673baf8SLisandro Dalcin if (path) PetscValidCharPointer(path,3); 2225673baf8SLisandro Dalcin PetscValidCharPointer(insymbol,4); 2235673baf8SLisandro Dalcin PetscValidPointer(value,5); 2245673baf8SLisandro Dalcin 225340b11eeSBarry Smith if (outlist) list = *outlist; 22602c9f0b5SLisandro Dalcin *value = NULL; 227e5c89e4eSSatish Balay 228*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(insymbol,'(',&s)); 2292d53ad75SBarry Smith if (s) { 230e5c89e4eSSatish Balay /* make copy of symbol so we can edit it in place */ 231*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrallocpy(insymbol,&symbol)); 232b3bb0f5eSLisandro Dalcin /* If symbol contains () then replace with a NULL, to support functionname() */ 233*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(symbol,'(',&s)); 2342d53ad75SBarry Smith s[0] = 0; 235a297a907SKarl Rupp } else symbol = (char*)insymbol; 236e5c89e4eSSatish Balay 237e5c89e4eSSatish Balay /* 238e5c89e4eSSatish Balay Function name does include library 239e5c89e4eSSatish Balay ------------------------------------- 240e5c89e4eSSatish Balay */ 241e5c89e4eSSatish Balay if (path && path[0] != '\0') { 242b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 243*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN)); 244*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(suffix,".",sizeof(suffix))); 245*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(suffix,PETSC_SLSUFFIX,sizeof(suffix))); 246*5f80ce2aSJacob Faibussowitsch CHKERRQ(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; 253*5f80ce2aSJacob Faibussowitsch CHKERRQ(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 */ 259*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLLibraryOpen(comm,path,&nlist)); 260*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Appending %s to dynamic library search path\n",path)); 261a297a907SKarl Rupp if (prev) prev->next = nlist; 262ca43db0aSBarry Smith else {if (outlist) *outlist = nlist;} 263e5c89e4eSSatish Balay 264e5c89e4eSSatish Balay done:; 265*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLSym(nlist->handle,symbol,value)); 26630a1dd1fSBarry Smith if (*value) { 267*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Loading function %s from dynamic library %s\n",insymbol,path)); 26830a1dd1fSBarry Smith } 269e5c89e4eSSatish Balay 270e5c89e4eSSatish Balay /* 271e5c89e4eSSatish Balay Function name does not include library so search path 272e5c89e4eSSatish Balay ----------------------------------------------------- 273e5c89e4eSSatish Balay */ 274e5c89e4eSSatish Balay } else { 275e5c89e4eSSatish Balay while (list) { 276*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLSym(list->handle,symbol,value)); 277e5c89e4eSSatish Balay if (*value) { 278*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Loading symbol %s from dynamic library %s\n",symbol,list->libname)); 279e5c89e4eSSatish Balay break; 280e5c89e4eSSatish Balay } 281e5c89e4eSSatish Balay list = list->next; 282e5c89e4eSSatish Balay } 283e5c89e4eSSatish Balay if (!*value) { 284*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLSym(NULL,symbol,value)); 285e5c89e4eSSatish Balay if (*value) { 286*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Loading symbol %s from object code\n",symbol)); 287e5c89e4eSSatish Balay } 288e5c89e4eSSatish Balay } 289e5c89e4eSSatish Balay } 290e5c89e4eSSatish Balay 2912d53ad75SBarry Smith if (symbol != insymbol) { 292*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(symbol)); 2932d53ad75SBarry Smith } 294e5c89e4eSSatish Balay PetscFunctionReturn(0); 295e5c89e4eSSatish Balay } 296e5c89e4eSSatish Balay 297e5c89e4eSSatish Balay /*@C 298e5c89e4eSSatish Balay PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 299e5c89e4eSSatish Balay of the search path. 300e5c89e4eSSatish Balay 301d083f849SBarry Smith Collective 302e5c89e4eSSatish Balay 303e5c89e4eSSatish Balay Input Parameters: 304e5c89e4eSSatish Balay + comm - MPI communicator 3050f31fb7fSLisandro Dalcin - path - name of the library 306e5c89e4eSSatish Balay 307e5c89e4eSSatish Balay Output Parameter: 308e5c89e4eSSatish Balay . outlist - list of libraries 309e5c89e4eSSatish Balay 310e5c89e4eSSatish Balay Level: developer 311e5c89e4eSSatish Balay 31295452b02SPatrick Sanan Notes: 31395452b02SPatrick Sanan if library is already in path will not add it. 314bb84e0fdSBarry Smith 315bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 316bb84e0fdSBarry Smith when the library is opened. 317bb84e0fdSBarry Smith 318bb84e0fdSBarry Smith .seealso: PetscDLLibraryOpen() 319e5c89e4eSSatish Balay @*/ 3207087cfbeSBarry Smith PetscErrorCode PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 321e5c89e4eSSatish Balay { 322e5bd5246SBarry Smith PetscDLLibrary list,prev; 323e5c89e4eSSatish Balay size_t len; 324ace3abfcSBarry Smith PetscBool match,dir; 325b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 326b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 3279c9d3cfdSBarry Smith PetscToken token; 328e5c89e4eSSatish Balay 329e5c89e4eSSatish Balay PetscFunctionBegin; 330b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 331e5c89e4eSSatish Balay 332b3bb0f5eSLisandro Dalcin /* is path a directory? */ 333*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTestDirectory(path,'r',&dir)); 334e5c89e4eSSatish Balay if (dir) { 335*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Checking directory %s for dynamic libraries\n",path)); 336*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(program,path,sizeof(program))); 337*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(program,&len)); 338e5c89e4eSSatish Balay if (program[len-1] == '/') { 339*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(program,"*.",sizeof(program))); 340e5c89e4eSSatish Balay } else { 341*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(program,"/*.",sizeof(program))); 342e5c89e4eSSatish Balay } 343*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(program,PETSC_SLSUFFIX,sizeof(program))); 344e5c89e4eSSatish Balay 345*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir)); 346e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 347e5c89e4eSSatish Balay } else { 348*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(found,path,PETSC_MAX_PATH_LEN)); 349e5c89e4eSSatish Balay } 350*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(suffix,".",sizeof(suffix))); 351*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(suffix,PETSC_SLSUFFIX,sizeof(suffix))); 352e5c89e4eSSatish Balay 353*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenCreate(found,'\n',&token)); 354*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenFind(token,&libname)); 355b3bb0f5eSLisandro Dalcin while (libname) { 356b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 357*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrstr(libname,suffix,&s)); 358e5c89e4eSSatish Balay if (s) s[0] = 0; 359e5c89e4eSSatish Balay /* see if library was already open then we are done */ 360e5c89e4eSSatish Balay list = prev = *outlist; 361e5c89e4eSSatish Balay match = PETSC_FALSE; 362e5c89e4eSSatish Balay while (list) { 363*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(list->libname,libname,&match)); 364e5c89e4eSSatish Balay if (match) break; 365e5c89e4eSSatish Balay prev = list; 366e5c89e4eSSatish Balay list = list->next; 367e5c89e4eSSatish Balay } 368b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 369b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 370e5c89e4eSSatish Balay if (!match) { 3715673baf8SLisandro Dalcin /* open the library and add to end of list */ 372*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLLibraryOpen(comm,libname,&list)); 373*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Appending %s to dynamic library search path\n",libname)); 374a297a907SKarl Rupp if (!*outlist) *outlist = list; 375a297a907SKarl Rupp else prev->next = list; 376e5c89e4eSSatish Balay } 377*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenFind(token,&libname)); 378e5c89e4eSSatish Balay } 379*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenDestroy(&token)); 380e5c89e4eSSatish Balay PetscFunctionReturn(0); 381e5c89e4eSSatish Balay } 382e5c89e4eSSatish Balay 383e5c89e4eSSatish Balay /*@C 384e5c89e4eSSatish Balay PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 385e5c89e4eSSatish Balay the search path. 386e5c89e4eSSatish Balay 387d083f849SBarry Smith Collective 388e5c89e4eSSatish Balay 389e5c89e4eSSatish Balay Input Parameters: 390e5c89e4eSSatish Balay + comm - MPI communicator 3910f31fb7fSLisandro Dalcin - path - name of the library 392e5c89e4eSSatish Balay 393e5c89e4eSSatish Balay Output Parameter: 394e5c89e4eSSatish Balay . outlist - list of libraries 395e5c89e4eSSatish Balay 396e5c89e4eSSatish Balay Level: developer 397e5c89e4eSSatish Balay 39895452b02SPatrick Sanan Notes: 39995452b02SPatrick Sanan If library is already in path will remove old reference. 400e5c89e4eSSatish Balay 401e5c89e4eSSatish Balay @*/ 4027087cfbeSBarry Smith PetscErrorCode PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 403e5c89e4eSSatish Balay { 404e5bd5246SBarry Smith PetscDLLibrary list,prev; 405e5c89e4eSSatish Balay size_t len; 406ace3abfcSBarry Smith PetscBool match,dir; 407b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 408b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 4095b096c79SMatthew Knepley PetscToken token; 410e5c89e4eSSatish Balay 411e5c89e4eSSatish Balay PetscFunctionBegin; 412b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 413e5c89e4eSSatish Balay 414b3bb0f5eSLisandro Dalcin /* is path a directory? */ 415*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTestDirectory(path,'r',&dir)); 416e5c89e4eSSatish Balay if (dir) { 417*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Checking directory %s for dynamic libraries\n",path)); 418*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(program,path,sizeof(program))); 419*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(program,&len)); 420e5c89e4eSSatish Balay if (program[len-1] == '/') { 421*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(program,"*.",sizeof(program))); 422e5c89e4eSSatish Balay } else { 423*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(program,"/*.",sizeof(program))); 424e5c89e4eSSatish Balay } 425*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(program,PETSC_SLSUFFIX,sizeof(program))); 426e5c89e4eSSatish Balay 427*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir)); 428e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 429e5c89e4eSSatish Balay } else { 430*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(found,path,PETSC_MAX_PATH_LEN)); 431e5c89e4eSSatish Balay } 432e5c89e4eSSatish Balay 433*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(suffix,".",sizeof(suffix))); 434*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(suffix,PETSC_SLSUFFIX,sizeof(suffix))); 435e5c89e4eSSatish Balay 436*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenCreate(found,'\n',&token)); 437*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenFind(token,&libname)); 438b3bb0f5eSLisandro Dalcin while (libname) { 439b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 440*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrstr(libname,suffix,&s)); 441e5c89e4eSSatish Balay if (s) s[0] = 0; 442e5c89e4eSSatish Balay /* see if library was already open and move it to the front */ 44302c9f0b5SLisandro Dalcin prev = NULL; 444b3bb0f5eSLisandro Dalcin list = *outlist; 445e5c89e4eSSatish Balay match = PETSC_FALSE; 446e5c89e4eSSatish Balay while (list) { 447*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(list->libname,libname,&match)); 448e5c89e4eSSatish Balay if (match) { 449*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Moving %s to begin of dynamic library search path\n",libname)); 450e5c89e4eSSatish Balay if (prev) prev->next = list->next; 451b3bb0f5eSLisandro Dalcin if (prev) list->next = *outlist; 452e5c89e4eSSatish Balay *outlist = list; 453e5c89e4eSSatish Balay break; 454e5c89e4eSSatish Balay } 455e5c89e4eSSatish Balay prev = list; 456e5c89e4eSSatish Balay list = list->next; 457e5c89e4eSSatish Balay } 458b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 459b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 460e5c89e4eSSatish Balay if (!match) { 4615673baf8SLisandro Dalcin /* open the library and add to front of list */ 462*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLLibraryOpen(comm,libname,&list)); 463*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Prepending %s to dynamic library search path\n",libname)); 464ebd79076SLisandro Dalcin list->next = *outlist; 465e5c89e4eSSatish Balay *outlist = list; 466e5c89e4eSSatish Balay } 467*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenFind(token,&libname)); 468e5c89e4eSSatish Balay } 469*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTokenDestroy(&token)); 470e5c89e4eSSatish Balay PetscFunctionReturn(0); 471e5c89e4eSSatish Balay } 472e5c89e4eSSatish Balay 473e5c89e4eSSatish Balay /*@C 474e5c89e4eSSatish Balay PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 475e5c89e4eSSatish Balay 476e5c89e4eSSatish Balay Collective on PetscDLLibrary 477e5c89e4eSSatish Balay 478e5c89e4eSSatish Balay Input Parameter: 4793fa76a5bSLisandro Dalcin . head - library list 480e5c89e4eSSatish Balay 481e5c89e4eSSatish Balay Level: developer 482e5c89e4eSSatish Balay 483e5c89e4eSSatish Balay @*/ 4847087cfbeSBarry Smith PetscErrorCode PetscDLLibraryClose(PetscDLLibrary list) 485e5c89e4eSSatish Balay { 486ace3abfcSBarry Smith PetscBool done = PETSC_FALSE; 4870f31fb7fSLisandro Dalcin PetscDLLibrary prev,tail; 488e5c89e4eSSatish Balay 489e5c89e4eSSatish Balay PetscFunctionBegin; 4900f31fb7fSLisandro Dalcin if (!list) PetscFunctionReturn(0); 4913fa76a5bSLisandro Dalcin /* traverse the list in reverse order */ 4923fa76a5bSLisandro Dalcin while (!done) { 4930f31fb7fSLisandro Dalcin if (!list->next) done = PETSC_TRUE; 4940f31fb7fSLisandro Dalcin prev = tail = list; 4953fa76a5bSLisandro Dalcin while (tail->next) { 4963fa76a5bSLisandro Dalcin prev = tail; 4973fa76a5bSLisandro Dalcin tail = tail->next; 498e5c89e4eSSatish Balay } 49902c9f0b5SLisandro Dalcin prev->next = NULL; 5003fa76a5bSLisandro Dalcin /* close the dynamic library and free the space in entry data-structure*/ 501*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Closing dynamic library %s\n",tail->libname)); 502*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDLClose(&tail->handle)); 503*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tail)); 504a297a907SKarl Rupp } 505e5c89e4eSSatish Balay PetscFunctionReturn(0); 506e5c89e4eSSatish Balay } 507