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 6c6db04a5SJed Brown #include <petscsys.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 18e5c89e4eSSatish Balay #undef __FUNCT__ 19e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrintPath" 207087cfbeSBarry Smith PetscErrorCode PetscDLLibraryPrintPath(PetscDLLibrary libs) 21e5c89e4eSSatish Balay { 22e5c89e4eSSatish Balay PetscFunctionBegin; 23e5c89e4eSSatish Balay while (libs) { 24e5c89e4eSSatish Balay PetscErrorPrintf(" %s\n",libs->libname); 25e5c89e4eSSatish Balay libs = libs->next; 26e5c89e4eSSatish Balay } 27e5c89e4eSSatish Balay PetscFunctionReturn(0); 28e5c89e4eSSatish Balay } 29e5c89e4eSSatish Balay 30e5c89e4eSSatish Balay #undef __FUNCT__ 31e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryRetrieve" 32e5c89e4eSSatish Balay /*@C 33e5c89e4eSSatish Balay PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 34e5c89e4eSSatish Balay (if it is remote), indicates if it exits and its local name. 35e5c89e4eSSatish Balay 36e5c89e4eSSatish Balay Collective on MPI_Comm 37e5c89e4eSSatish Balay 38e5c89e4eSSatish Balay Input Parameters: 39e5c89e4eSSatish Balay + comm - processors that are opening the library 40e5c89e4eSSatish Balay - libname - name of the library, can be relative or absolute 41e5c89e4eSSatish Balay 42e5c89e4eSSatish Balay Output Parameter: 432d53ad75SBarry Smith + name - actual name of file on local filesystem if found 442d53ad75SBarry Smith . llen - length of the name buffer 452d53ad75SBarry Smith - found - true if the file exists 46e5c89e4eSSatish Balay 47e5c89e4eSSatish Balay Level: developer 48e5c89e4eSSatish Balay 49e5c89e4eSSatish Balay Notes: 50e5c89e4eSSatish Balay [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 51e5c89e4eSSatish Balay 52e5c89e4eSSatish Balay ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 53e5c89e4eSSatish Balay occuring in directoryname and filename will be replaced with appropriate values. 54e5c89e4eSSatish Balay @*/ 557087cfbeSBarry Smith PetscErrorCode PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,size_t llen,PetscBool *found) 56e5c89e4eSSatish Balay { 57d46cf212SLisandro Dalcin char *buf,*par2,suffix[16],*gz,*so; 58d46cf212SLisandro Dalcin size_t len; 59e5c89e4eSSatish Balay PetscErrorCode ierr; 60e5c89e4eSSatish Balay 61e5c89e4eSSatish Balay PetscFunctionBegin; 62e5c89e4eSSatish Balay /* 63a523d312SBarry Smith make copy of library name and replace $PETSC_ARCH etc 64e5c89e4eSSatish Balay so we can add to the end of it to look for something like .so.1.0 etc. 65e5c89e4eSSatish Balay */ 66e5c89e4eSSatish Balay ierr = PetscStrlen(libname,&len);CHKERRQ(ierr); 67e5c89e4eSSatish Balay len = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 68d46cf212SLisandro Dalcin ierr = PetscMalloc(len*sizeof(char),&buf);CHKERRQ(ierr); 69d46cf212SLisandro Dalcin par2 = buf; 70e5c89e4eSSatish Balay ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr); 71e5c89e4eSSatish Balay 72d46cf212SLisandro Dalcin /* temporarily remove .gz if it ends library name */ 73d46cf212SLisandro Dalcin ierr = PetscStrrstr(par2,".gz",&gz);CHKERRQ(ierr); 74e5c89e4eSSatish Balay if (gz) { 75e5c89e4eSSatish Balay ierr = PetscStrlen(gz,&len);CHKERRQ(ierr); 76d46cf212SLisandro Dalcin if (len != 3) gz = 0; /* do not end (exactly) with .gz */ 77d46cf212SLisandro Dalcin else *gz = 0; /* ends with .gz, so remove it */ 78e5c89e4eSSatish Balay } 793fa76a5bSLisandro Dalcin /* strip out .a from it if user put it in by mistake */ 803fa76a5bSLisandro Dalcin ierr = PetscStrlen(par2,&len);CHKERRQ(ierr); 813fa76a5bSLisandro Dalcin if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0; 823fa76a5bSLisandro Dalcin 832d53ad75SBarry Smith ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr); 84*8ce0dc28SMatthew G Knepley if (!(*found)) { 85e5c89e4eSSatish Balay /* see if library name does already not have suffix attached */ 86b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 87b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 88b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(par2,suffix,&so);CHKERRQ(ierr); 89d46cf212SLisandro Dalcin /* and attach the suffix if it is not there */ 90d46cf212SLisandro Dalcin if (!so) { ierr = PetscStrcat(par2,suffix);CHKERRQ(ierr); } 91e5c89e4eSSatish Balay 92d46cf212SLisandro Dalcin /* restore the .gz suffix if it was there */ 93d46cf212SLisandro Dalcin if (gz) { ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr); } 94d46cf212SLisandro Dalcin 95d46cf212SLisandro Dalcin /* and finally retrieve the file */ 96e5c89e4eSSatish Balay ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr); 972d53ad75SBarry Smith } 98d46cf212SLisandro Dalcin 99d46cf212SLisandro Dalcin ierr = PetscFree(buf);CHKERRQ(ierr); 100e5c89e4eSSatish Balay PetscFunctionReturn(0); 101e5c89e4eSSatish Balay } 102e5c89e4eSSatish Balay 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay #undef __FUNCT__ 105e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryOpen" 106e5c89e4eSSatish Balay /*@C 107ebd79076SLisandro Dalcin PetscDLLibraryOpen - Opens a PETSc dynamic link library 108e5c89e4eSSatish Balay 109e5c89e4eSSatish Balay Collective on MPI_Comm 110e5c89e4eSSatish Balay 111e5c89e4eSSatish Balay Input Parameters: 112e5c89e4eSSatish Balay + comm - processors that are opening the library 1130f31fb7fSLisandro Dalcin - path - name of the library, can be relative or absolute 114e5c89e4eSSatish Balay 115e5c89e4eSSatish Balay Output Parameter: 1160f31fb7fSLisandro Dalcin . entry - a PETSc dynamic link library entry 117e5c89e4eSSatish Balay 118e5c89e4eSSatish Balay Level: developer 119e5c89e4eSSatish Balay 120e5c89e4eSSatish Balay Notes: 121bb84e0fdSBarry Smith [[<http,ftp>://hostname]/directoryname/]libbasename[.so.1.0] 122bb84e0fdSBarry Smith 123bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 124bb84e0fdSBarry Smith when the library is opened. 125e5c89e4eSSatish Balay 126e5c89e4eSSatish Balay ${PETSC_ARCH} occuring in directoryname and filename 127e5c89e4eSSatish Balay will be replaced with the appropriate value. 128bb84e0fdSBarry Smith 129bb84e0fdSBarry Smith .seealso: PetscLoadDynamicLibrary(), PetscDLLibraryAppend() 130e5c89e4eSSatish Balay @*/ 1317087cfbeSBarry Smith PetscErrorCode PetscDLLibraryOpen(MPI_Comm comm,const char path[],PetscDLLibrary *entry) 132e5c89e4eSSatish Balay { 133e5c89e4eSSatish Balay PetscErrorCode ierr; 134ace3abfcSBarry Smith PetscBool foundlibrary,match; 135b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],par2[PETSC_MAX_PATH_LEN],suffix[16],*s; 136b3bb0f5eSLisandro Dalcin char *basename,registername[128]; 1375673baf8SLisandro Dalcin PetscDLHandle handle; 138e5c89e4eSSatish Balay PetscErrorCode (*func)(const char*) = NULL; 139e5c89e4eSSatish Balay size_t len; 140e5c89e4eSSatish Balay 141e5c89e4eSSatish Balay PetscFunctionBegin; 14282a51d08SSatish Balay PetscValidCharPointer(path,2); 1435673baf8SLisandro Dalcin PetscValidPointer(entry,3); 144ebd79076SLisandro Dalcin 1455673baf8SLisandro Dalcin *entry = PETSC_NULL; 146e5c89e4eSSatish Balay 147b3bb0f5eSLisandro Dalcin /* retrieve the library */ 148b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Retrieving %s\n",path);CHKERRQ(ierr); 149b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryRetrieve(comm,path,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr); 150e32f2f54SBarry Smith if (!foundlibrary) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s\n",path); 151e2e64c6bSBarry Smith /* Eventually ./configure should determine if the system needs an executable dynamic library */ 152e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO 153e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO) 154e5c89e4eSSatish Balay ierr = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr); 155e32f2f54SBarry Smith if (!foundlibrary) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s\n",path,par2); 156e5c89e4eSSatish Balay #endif 157e5c89e4eSSatish Balay 1583fa76a5bSLisandro Dalcin /* copy path and setup shared library suffix */ 159b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 160b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 161b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 1623fa76a5bSLisandro Dalcin /* remove wrong suffixes from libname */ 1633fa76a5bSLisandro Dalcin ierr = PetscStrrstr(libname,".gz",&s);CHKERRQ(ierr); 1643fa76a5bSLisandro Dalcin if (s && s[3] == 0) s[0] = 0; 1653fa76a5bSLisandro Dalcin ierr = PetscStrrstr(libname,".a",&s);CHKERRQ(ierr); 1663fa76a5bSLisandro Dalcin if (s && s[2] == 0) s[0] = 0; 1673fa76a5bSLisandro Dalcin /* remove shared suffix from libname */ 168b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 169b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 170b3bb0f5eSLisandro Dalcin 1715673baf8SLisandro Dalcin /* open the dynamic library */ 172b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Opening dynamic library %s\n",libname);CHKERRQ(ierr); 173b3bb0f5eSLisandro Dalcin ierr = PetscDLOpen(par2,PETSC_DL_DECIDE,&handle);CHKERRQ(ierr); 174b3bb0f5eSLisandro Dalcin 175b3bb0f5eSLisandro Dalcin /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */ 176b3bb0f5eSLisandro Dalcin ierr = PetscStrrchr(libname,'/',&basename);CHKERRQ(ierr); /* XXX Windows ??? */ 177b3bb0f5eSLisandro Dalcin if (!basename) basename = libname; 178b3bb0f5eSLisandro Dalcin ierr = PetscStrncmp(basename,"lib",3,&match);CHKERRQ(ierr); 179b3bb0f5eSLisandro Dalcin if (match) { 180b3bb0f5eSLisandro Dalcin basename = basename + 3; 181b3bb0f5eSLisandro Dalcin } else { 182bb84e0fdSBarry Smith ierr = PetscInfo1(0,"Dynamic library %s does not have lib prefix\n",libname);CHKERRQ(ierr); 183e5c89e4eSSatish Balay } 184b3bb0f5eSLisandro Dalcin ierr = PetscStrlen(basename,&len);CHKERRQ(ierr); 185b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr); 186b3bb0f5eSLisandro Dalcin ierr = PetscStrncat(registername,basename,len);CHKERRQ(ierr); 187b3bb0f5eSLisandro Dalcin ierr = PetscDLSym(handle,registername,(void**)&func);CHKERRQ(ierr); 188b3bb0f5eSLisandro Dalcin if (func) { 1895673baf8SLisandro Dalcin ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr); 1905673baf8SLisandro Dalcin ierr = (*func)(libname);CHKERRQ(ierr); 191b3bb0f5eSLisandro Dalcin } else { 192bb84e0fdSBarry Smith ierr = PetscInfo2(0,"Dynamic library %s does not have symbol %s\n",libname,registername);CHKERRQ(ierr); 193b3bb0f5eSLisandro Dalcin } 1945673baf8SLisandro Dalcin 1955673baf8SLisandro Dalcin ierr = PetscNew(struct _n_PetscDLLibrary,entry);CHKERRQ(ierr); 1965673baf8SLisandro Dalcin (*entry)->next = 0; 197b3bb0f5eSLisandro Dalcin (*entry)->handle = handle; 198b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy((*entry)->libname,libname);CHKERRQ(ierr); 1995673baf8SLisandro Dalcin 200e5c89e4eSSatish Balay PetscFunctionReturn(0); 201e5c89e4eSSatish Balay } 202e5c89e4eSSatish Balay 203e5c89e4eSSatish Balay #undef __FUNCT__ 204e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibrarySym" 205e5c89e4eSSatish Balay /*@C 206e5c89e4eSSatish Balay PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 207e5c89e4eSSatish Balay 208e5c89e4eSSatish Balay Collective on MPI_Comm 209e5c89e4eSSatish Balay 210e5c89e4eSSatish Balay Input Parameter: 211e5bd5246SBarry Smith + comm - communicator that will open the library 212340b11eeSBarry Smith . outlist - list of already open libraries that may contain symbol (can be PETSC_NULL and only the executable is searched for the function) 21330a1dd1fSBarry Smith . path - optional complete library name (if provided checks here before checking outlist) 214e5c89e4eSSatish Balay - insymbol - name of symbol 215e5c89e4eSSatish Balay 216e5c89e4eSSatish Balay Output Parameter: 21730a1dd1fSBarry Smith . value - if symbol not found then this value is set to PETSC_NULL 218e5c89e4eSSatish Balay 219e5c89e4eSSatish Balay Level: developer 220e5c89e4eSSatish Balay 221e5c89e4eSSatish Balay Notes: Symbol can be of the form 222e5c89e4eSSatish Balay [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 223e5c89e4eSSatish Balay 224e5c89e4eSSatish Balay Will attempt to (retrieve and) open the library if it is not yet been opened. 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay @*/ 2277087cfbeSBarry Smith PetscErrorCode PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *outlist,const char path[],const char insymbol[],void **value) 228e5c89e4eSSatish Balay { 229b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],suffix[16],*symbol,*s; 230340b11eeSBarry Smith PetscDLLibrary nlist,prev,list = PETSC_NULL; 231b3bb0f5eSLisandro Dalcin PetscErrorCode ierr; 232e5c89e4eSSatish Balay 233e5c89e4eSSatish Balay PetscFunctionBegin; 234340b11eeSBarry Smith if (outlist) PetscValidPointer(outlist,2); 2355673baf8SLisandro Dalcin if (path) PetscValidCharPointer(path,3); 2365673baf8SLisandro Dalcin PetscValidCharPointer(insymbol,4); 2375673baf8SLisandro Dalcin PetscValidPointer(value,5); 2385673baf8SLisandro Dalcin 239340b11eeSBarry Smith if (outlist) list = *outlist; 240e5c89e4eSSatish Balay *value = 0; 241e5c89e4eSSatish Balay 2422d53ad75SBarry Smith 2432d53ad75SBarry Smith ierr = PetscStrchr(insymbol,'(',&s);CHKERRQ(ierr); 2442d53ad75SBarry Smith if (s) { 245e5c89e4eSSatish Balay /* make copy of symbol so we can edit it in place */ 2462d53ad75SBarry Smith ierr = PetscStrallocpy(insymbol,&symbol);CHKERRQ(ierr); 247b3bb0f5eSLisandro Dalcin /* If symbol contains () then replace with a NULL, to support functionname() */ 248b3bb0f5eSLisandro Dalcin ierr = PetscStrchr(symbol,'(',&s);CHKERRQ(ierr); 2492d53ad75SBarry Smith s[0] = 0; 2502d53ad75SBarry Smith } else { 2512d53ad75SBarry Smith symbol = (char *)insymbol; 2522d53ad75SBarry Smith } 253e5c89e4eSSatish Balay 254e5c89e4eSSatish Balay /* 255e5c89e4eSSatish Balay Function name does include library 256e5c89e4eSSatish Balay ------------------------------------- 257e5c89e4eSSatish Balay */ 258e5c89e4eSSatish Balay if (path && path[0] != '\0') { 259b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 260b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 261b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 262b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 263b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 264b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 2655673baf8SLisandro Dalcin /* Look if library is already opened and in path */ 266e5c89e4eSSatish Balay prev = 0; 267b3bb0f5eSLisandro Dalcin nlist = list; 268e5c89e4eSSatish Balay while (nlist) { 269ace3abfcSBarry Smith PetscBool match; 270b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(nlist->libname,libname,&match);CHKERRQ(ierr); 2715673baf8SLisandro Dalcin if (match) goto done; 272e5c89e4eSSatish Balay prev = nlist; 273e5c89e4eSSatish Balay nlist = nlist->next; 274e5c89e4eSSatish Balay } 275b3bb0f5eSLisandro Dalcin /* open the library and append it to path */ 2765673baf8SLisandro Dalcin ierr = PetscDLLibraryOpen(comm,path,&nlist);CHKERRQ(ierr); 277ae15b995SBarry Smith ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr); 2785673baf8SLisandro Dalcin if (prev) { prev->next = nlist; } 279b3bb0f5eSLisandro Dalcin else { *outlist = nlist; } 280e5c89e4eSSatish Balay 281e5c89e4eSSatish Balay done:; 2825673baf8SLisandro Dalcin ierr = PetscDLSym(nlist->handle,symbol,value);CHKERRQ(ierr); 28330a1dd1fSBarry Smith if (*value) { 284ae15b995SBarry Smith ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr); 28530a1dd1fSBarry Smith } 286e5c89e4eSSatish Balay 287e5c89e4eSSatish Balay /* 288e5c89e4eSSatish Balay Function name does not include library so search path 289e5c89e4eSSatish Balay ----------------------------------------------------- 290e5c89e4eSSatish Balay */ 291e5c89e4eSSatish Balay } else { 292e5c89e4eSSatish Balay while (list) { 293ebd79076SLisandro Dalcin ierr = PetscDLSym(list->handle,symbol,value);CHKERRQ(ierr); 294e5c89e4eSSatish Balay if (*value) { 295b3bb0f5eSLisandro Dalcin ierr = PetscInfo2(0,"Loading symbol %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr); 296e5c89e4eSSatish Balay break; 297e5c89e4eSSatish Balay } 298e5c89e4eSSatish Balay list = list->next; 299e5c89e4eSSatish Balay } 300e5c89e4eSSatish Balay if (!*value) { 301ebd79076SLisandro Dalcin ierr = PetscDLSym(PETSC_NULL,symbol,value);CHKERRQ(ierr); 302e5c89e4eSSatish Balay if (*value) { 303b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Loading symbol %s from object code\n",symbol);CHKERRQ(ierr); 304e5c89e4eSSatish Balay } 305e5c89e4eSSatish Balay } 306e5c89e4eSSatish Balay } 307e5c89e4eSSatish Balay 3082d53ad75SBarry Smith if (symbol != insymbol) { 309e5c89e4eSSatish Balay ierr = PetscFree(symbol);CHKERRQ(ierr); 3102d53ad75SBarry Smith } 311e5c89e4eSSatish Balay PetscFunctionReturn(0); 312e5c89e4eSSatish Balay } 313e5c89e4eSSatish Balay 314e5c89e4eSSatish Balay #undef __FUNCT__ 315e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryAppend" 316e5c89e4eSSatish Balay /*@C 317e5c89e4eSSatish Balay PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 318e5c89e4eSSatish Balay of the search path. 319e5c89e4eSSatish Balay 320e5c89e4eSSatish Balay Collective on MPI_Comm 321e5c89e4eSSatish Balay 322e5c89e4eSSatish Balay Input Parameters: 323e5c89e4eSSatish Balay + comm - MPI communicator 3240f31fb7fSLisandro Dalcin - path - name of the library 325e5c89e4eSSatish Balay 326e5c89e4eSSatish Balay Output Parameter: 327e5c89e4eSSatish Balay . outlist - list of libraries 328e5c89e4eSSatish Balay 329e5c89e4eSSatish Balay Level: developer 330e5c89e4eSSatish Balay 331e5c89e4eSSatish Balay Notes: if library is already in path will not add it. 332bb84e0fdSBarry Smith 333bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 334bb84e0fdSBarry Smith when the library is opened. 335bb84e0fdSBarry Smith 336bb84e0fdSBarry Smith .seealso: PetscDLLibraryOpen() 337e5c89e4eSSatish Balay @*/ 3387087cfbeSBarry Smith PetscErrorCode PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 339e5c89e4eSSatish Balay { 340e5bd5246SBarry Smith PetscDLLibrary list,prev; 341e5c89e4eSSatish Balay PetscErrorCode ierr; 342e5c89e4eSSatish Balay size_t len; 343ace3abfcSBarry Smith PetscBool match,dir; 344b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 345b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 3469c9d3cfdSBarry Smith PetscToken token; 347e5c89e4eSSatish Balay 348e5c89e4eSSatish Balay PetscFunctionBegin; 349b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 350e5c89e4eSSatish Balay 351b3bb0f5eSLisandro Dalcin /* is path a directory? */ 352b3bb0f5eSLisandro Dalcin ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr); 353e5c89e4eSSatish Balay if (dir) { 354b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr); 355b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(program,path);CHKERRQ(ierr); 356e5c89e4eSSatish Balay ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 357e5c89e4eSSatish Balay if (program[len-1] == '/') { 358e5c89e4eSSatish Balay ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 359e5c89e4eSSatish Balay } else { 360e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 361e5c89e4eSSatish Balay } 362e5c89e4eSSatish Balay ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 363e5c89e4eSSatish Balay 364b3bb0f5eSLisandro Dalcin ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 365e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 366e5c89e4eSSatish Balay } else { 367b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 368e5c89e4eSSatish Balay } 369e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 370e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 371e5c89e4eSSatish Balay 372e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 373b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 374b3bb0f5eSLisandro Dalcin while (libname) { 375b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 376b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 377e5c89e4eSSatish Balay if (s) s[0] = 0; 378e5c89e4eSSatish Balay /* see if library was already open then we are done */ 379e5c89e4eSSatish Balay list = prev = *outlist; 380e5c89e4eSSatish Balay match = PETSC_FALSE; 381e5c89e4eSSatish Balay while (list) { 382b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr); 383e5c89e4eSSatish Balay if (match) break; 384e5c89e4eSSatish Balay prev = list; 385e5c89e4eSSatish Balay list = list->next; 386e5c89e4eSSatish Balay } 387b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 388b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 389e5c89e4eSSatish Balay if (!match) { 3905673baf8SLisandro Dalcin /* open the library and add to end of list */ 391b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr); 392b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname);CHKERRQ(ierr); 393e5c89e4eSSatish Balay if (!*outlist) { 394e5c89e4eSSatish Balay *outlist = list; 395e5c89e4eSSatish Balay } else { 396e5c89e4eSSatish Balay prev->next = list; 397e5c89e4eSSatish Balay } 398e5c89e4eSSatish Balay } 399b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 400e5c89e4eSSatish Balay } 4018c74ee41SBarry Smith ierr = PetscTokenDestroy(&token);CHKERRQ(ierr); 402e5c89e4eSSatish Balay PetscFunctionReturn(0); 403e5c89e4eSSatish Balay } 404e5c89e4eSSatish Balay 405e5c89e4eSSatish Balay #undef __FUNCT__ 406e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrepend" 407e5c89e4eSSatish Balay /*@C 408e5c89e4eSSatish Balay PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 409e5c89e4eSSatish Balay the search path. 410e5c89e4eSSatish Balay 411e5c89e4eSSatish Balay Collective on MPI_Comm 412e5c89e4eSSatish Balay 413e5c89e4eSSatish Balay Input Parameters: 414e5c89e4eSSatish Balay + comm - MPI communicator 4150f31fb7fSLisandro Dalcin - path - name of the library 416e5c89e4eSSatish Balay 417e5c89e4eSSatish Balay Output Parameter: 418e5c89e4eSSatish Balay . outlist - list of libraries 419e5c89e4eSSatish Balay 420e5c89e4eSSatish Balay Level: developer 421e5c89e4eSSatish Balay 422e5c89e4eSSatish Balay Notes: If library is already in path will remove old reference. 423e5c89e4eSSatish Balay 424e5c89e4eSSatish Balay @*/ 4257087cfbeSBarry Smith PetscErrorCode PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 426e5c89e4eSSatish Balay { 427e5bd5246SBarry Smith PetscDLLibrary list,prev; 428e5c89e4eSSatish Balay PetscErrorCode ierr; 429e5c89e4eSSatish Balay size_t len; 430ace3abfcSBarry Smith PetscBool match,dir; 431b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 432b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 4335b096c79SMatthew Knepley PetscToken token; 434e5c89e4eSSatish Balay 435e5c89e4eSSatish Balay PetscFunctionBegin; 436b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 437e5c89e4eSSatish Balay 438b3bb0f5eSLisandro Dalcin /* is path a directory? */ 439b3bb0f5eSLisandro Dalcin ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr); 440e5c89e4eSSatish Balay if (dir) { 441b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr); 442b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(program,path);CHKERRQ(ierr); 443e5c89e4eSSatish Balay ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 444e5c89e4eSSatish Balay if (program[len-1] == '/') { 445e5c89e4eSSatish Balay ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 446e5c89e4eSSatish Balay } else { 447e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 448e5c89e4eSSatish Balay } 449e5c89e4eSSatish Balay ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 450e5c89e4eSSatish Balay 451b3bb0f5eSLisandro Dalcin ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 452e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 453e5c89e4eSSatish Balay } else { 454b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 455e5c89e4eSSatish Balay } 456e5c89e4eSSatish Balay 457e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 458e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 459e5c89e4eSSatish Balay 460e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 461b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 462b3bb0f5eSLisandro Dalcin while (libname) { 463b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 464b3bb0f5eSLisandro Dalcin ierr = PetscStrstr(libname,suffix,&s);CHKERRQ(ierr); 465e5c89e4eSSatish Balay if (s) s[0] = 0; 466e5c89e4eSSatish Balay /* see if library was already open and move it to the front */ 467e5c89e4eSSatish Balay prev = 0; 468b3bb0f5eSLisandro Dalcin list = *outlist; 469e5c89e4eSSatish Balay match = PETSC_FALSE; 470e5c89e4eSSatish Balay while (list) { 471b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr); 472e5c89e4eSSatish Balay if (match) { 473b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Moving %s to begin of dynamic library search path\n",libname);CHKERRQ(ierr); 474e5c89e4eSSatish Balay if (prev) prev->next = list->next; 475b3bb0f5eSLisandro Dalcin if (prev) list->next = *outlist; 476e5c89e4eSSatish Balay *outlist = list; 477e5c89e4eSSatish Balay break; 478e5c89e4eSSatish Balay } 479e5c89e4eSSatish Balay prev = list; 480e5c89e4eSSatish Balay list = list->next; 481e5c89e4eSSatish Balay } 482b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 483b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 484e5c89e4eSSatish Balay if (!match) { 4855673baf8SLisandro Dalcin /* open the library and add to front of list */ 486b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr); 487b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname);CHKERRQ(ierr); 488ebd79076SLisandro Dalcin list->next = *outlist; 489e5c89e4eSSatish Balay *outlist = list; 490e5c89e4eSSatish Balay } 491b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 492e5c89e4eSSatish Balay } 4938c74ee41SBarry Smith ierr = PetscTokenDestroy(&token);CHKERRQ(ierr); 494e5c89e4eSSatish Balay PetscFunctionReturn(0); 495e5c89e4eSSatish Balay } 496e5c89e4eSSatish Balay 497e5c89e4eSSatish Balay #undef __FUNCT__ 498e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryClose" 499e5c89e4eSSatish Balay /*@C 500e5c89e4eSSatish Balay PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 501e5c89e4eSSatish Balay 502e5c89e4eSSatish Balay Collective on PetscDLLibrary 503e5c89e4eSSatish Balay 504e5c89e4eSSatish Balay Input Parameter: 5053fa76a5bSLisandro Dalcin . head - library list 506e5c89e4eSSatish Balay 507e5c89e4eSSatish Balay Level: developer 508e5c89e4eSSatish Balay 509e5c89e4eSSatish Balay @*/ 5107087cfbeSBarry Smith PetscErrorCode PetscDLLibraryClose(PetscDLLibrary list) 511e5c89e4eSSatish Balay { 512ace3abfcSBarry Smith PetscBool done = PETSC_FALSE; 5130f31fb7fSLisandro Dalcin PetscDLLibrary prev,tail; 514e5c89e4eSSatish Balay PetscErrorCode ierr; 515e5c89e4eSSatish Balay 516e5c89e4eSSatish Balay PetscFunctionBegin; 5170f31fb7fSLisandro Dalcin if (!list) PetscFunctionReturn(0); 5183fa76a5bSLisandro Dalcin /* traverse the list in reverse order */ 5193fa76a5bSLisandro Dalcin while (!done) { 5200f31fb7fSLisandro Dalcin if (!list->next) done = PETSC_TRUE; 5210f31fb7fSLisandro Dalcin prev = tail = list; 5223fa76a5bSLisandro Dalcin while (tail->next) { 5233fa76a5bSLisandro Dalcin prev = tail; 5243fa76a5bSLisandro Dalcin tail = tail->next; 525e5c89e4eSSatish Balay } 5263fa76a5bSLisandro Dalcin prev->next = 0; 5273fa76a5bSLisandro Dalcin /* close the dynamic library and free the space in entry data-structure*/ 5283fa76a5bSLisandro Dalcin ierr = PetscInfo1(0,"Closing dynamic library %s\n",tail->libname);CHKERRQ(ierr); 5293fa76a5bSLisandro Dalcin ierr = PetscDLClose(&tail->handle);CHKERRQ(ierr); 5303fa76a5bSLisandro Dalcin ierr = PetscFree(tail);CHKERRQ(ierr); 5313fa76a5bSLisandro Dalcin }; 532e5c89e4eSSatish Balay PetscFunctionReturn(0); 533e5c89e4eSSatish Balay } 534e5c89e4eSSatish Balay 535