1e5c89e4eSSatish Balay #define PETSC_DLL 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay Routines for opening dynamic link libraries (DLLs), keeping a searchable 4e5c89e4eSSatish Balay path of DLLs, obtaining remote DLLs via a URL and opening them locally. 5e5c89e4eSSatish Balay */ 6e5c89e4eSSatish Balay 7e5c89e4eSSatish Balay #include "petsc.h" 8e5c89e4eSSatish Balay #include "petscsys.h" 9*b3bb0f5eSLisandro Dalcin #include "src/sys/dll/dlimpl.h" 10e5c89e4eSSatish Balay 11e5c89e4eSSatish Balay /* 12e5c89e4eSSatish Balay Contains the list of registered CCA components 13e5c89e4eSSatish Balay */ 14e5c89e4eSSatish Balay PetscFList CCAList = 0; 15e5c89e4eSSatish Balay 16e5c89e4eSSatish Balay 17e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 18e5c89e4eSSatish Balay /* 19e5c89e4eSSatish Balay Code to maintain a list of opened dynamic libraries and load symbols 20e5c89e4eSSatish Balay */ 21e5bd5246SBarry Smith struct _n_PetscDLLibrary { 22e5bd5246SBarry Smith PetscDLLibrary next; 23ebd79076SLisandro Dalcin PetscDLHandle handle; 24e5c89e4eSSatish Balay char libname[PETSC_MAX_PATH_LEN]; 25e5c89e4eSSatish Balay }; 26e5c89e4eSSatish Balay 27*b3bb0f5eSLisandro Dalcin /* 28*b3bb0f5eSLisandro Dalcin This is the list used by the PetscDLLibrary register routines 29*b3bb0f5eSLisandro Dalcin */ 30*b3bb0f5eSLisandro Dalcin PetscDLLibrary DLLibrariesLoaded = 0; 31*b3bb0f5eSLisandro Dalcin 32*b3bb0f5eSLisandro Dalcin 33e5c89e4eSSatish Balay #undef __FUNCT__ 34e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrintPath" 355673baf8SLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrintPath(PetscDLLibrary libs) 36e5c89e4eSSatish Balay { 37e5c89e4eSSatish Balay PetscFunctionBegin; 38e5c89e4eSSatish Balay while (libs) { 39e5c89e4eSSatish Balay PetscErrorPrintf(" %s\n",libs->libname); 40e5c89e4eSSatish Balay libs = libs->next; 41e5c89e4eSSatish Balay } 42e5c89e4eSSatish Balay PetscFunctionReturn(0); 43e5c89e4eSSatish Balay } 44e5c89e4eSSatish Balay 45e5c89e4eSSatish Balay #undef __FUNCT__ 46e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryRetrieve" 47e5c89e4eSSatish Balay /*@C 48e5c89e4eSSatish Balay PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 49e5c89e4eSSatish Balay (if it is remote), indicates if it exits and its local name. 50e5c89e4eSSatish Balay 51e5c89e4eSSatish Balay Collective on MPI_Comm 52e5c89e4eSSatish Balay 53e5c89e4eSSatish Balay Input Parameters: 54e5c89e4eSSatish Balay + comm - processors that are opening the library 55e5c89e4eSSatish Balay - libname - name of the library, can be relative or absolute 56e5c89e4eSSatish Balay 57e5c89e4eSSatish Balay Output Parameter: 58e5c89e4eSSatish Balay . handle - library handle 59e5c89e4eSSatish Balay 60e5c89e4eSSatish Balay Level: developer 61e5c89e4eSSatish Balay 62e5c89e4eSSatish Balay Notes: 63e5c89e4eSSatish Balay [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 64e5c89e4eSSatish Balay 65e5c89e4eSSatish Balay ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 66e5c89e4eSSatish Balay occuring in directoryname and filename will be replaced with appropriate values. 67e5c89e4eSSatish Balay @*/ 68300a7f5bSBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,size_t llen,PetscTruth *found) 69e5c89e4eSSatish Balay { 70*b3bb0f5eSLisandro Dalcin char *par2,suffix[16],*gz,*so; 71e5c89e4eSSatish Balay PetscErrorCode ierr; 72e5c89e4eSSatish Balay size_t len1,len2,len; 73e5c89e4eSSatish Balay PetscTruth tflg,flg; 74e5c89e4eSSatish Balay 75e5c89e4eSSatish Balay PetscFunctionBegin; 76e5c89e4eSSatish Balay /* 77a523d312SBarry Smith make copy of library name and replace $PETSC_ARCH etc 78e5c89e4eSSatish Balay so we can add to the end of it to look for something like .so.1.0 etc. 79e5c89e4eSSatish Balay */ 80e5c89e4eSSatish Balay ierr = PetscStrlen(libname,&len);CHKERRQ(ierr); 81e5c89e4eSSatish Balay len = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 82e5c89e4eSSatish Balay ierr = PetscMalloc(len*sizeof(char),&par2);CHKERRQ(ierr); 83e5c89e4eSSatish Balay ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr); 84e5c89e4eSSatish Balay 85e5c89e4eSSatish Balay /* 86e5c89e4eSSatish Balay Remove any file: header 87e5c89e4eSSatish Balay */ 88e5c89e4eSSatish Balay ierr = PetscStrncmp(par2,"file:",5,&tflg);CHKERRQ(ierr); 89e5c89e4eSSatish Balay if (tflg) { 90*b3bb0f5eSLisandro Dalcin /* XXX BUG: overlapping buffers, undefined */ 91e5c89e4eSSatish Balay ierr = PetscStrcpy(par2,par2+5);CHKERRQ(ierr); 92e5c89e4eSSatish Balay } 93e5c89e4eSSatish Balay 94e5c89e4eSSatish Balay /* strip out .a from it if user put it in by mistake */ 95e5c89e4eSSatish Balay ierr = PetscStrlen(par2,&len);CHKERRQ(ierr); 96e5c89e4eSSatish Balay if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0; 97e5c89e4eSSatish Balay 98e5c89e4eSSatish Balay /* remove .gz if it ends library name */ 99e5c89e4eSSatish Balay ierr = PetscStrstr(par2,".gz",&gz);CHKERRQ(ierr); 100e5c89e4eSSatish Balay if (gz) { 101e5c89e4eSSatish Balay ierr = PetscStrlen(gz,&len);CHKERRQ(ierr); 102e5c89e4eSSatish Balay if (len == 3) { 103e5c89e4eSSatish Balay *gz = 0; 104e5c89e4eSSatish Balay } 105e5c89e4eSSatish Balay } 106e5c89e4eSSatish Balay 107e5c89e4eSSatish Balay /* see if library name does already not have suffix attached */ 108*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 109*b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 110*b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(par2,suffix,&so);CHKERRQ(ierr); 111*b3bb0f5eSLisandro Dalcin if (so) { 112*b3bb0f5eSLisandro Dalcin ierr = PetscStrlen(so,&len1);CHKERRQ(ierr); 113*b3bb0f5eSLisandro Dalcin ierr = PetscStrlen(suffix,&len2);CHKERRQ(ierr); 114*b3bb0f5eSLisandro Dalcin flg = (PetscTruth) (len1 != len2); 115e5c89e4eSSatish Balay } else { 116e5c89e4eSSatish Balay flg = PETSC_TRUE; 117e5c89e4eSSatish Balay } 118e5c89e4eSSatish Balay if (flg) { 119e5c89e4eSSatish Balay ierr = PetscStrcat(par2,".");CHKERRQ(ierr); 120e5c89e4eSSatish Balay ierr = PetscStrcat(par2,PETSC_SLSUFFIX);CHKERRQ(ierr); 121e5c89e4eSSatish Balay } 122e5c89e4eSSatish Balay 123e5c89e4eSSatish Balay /* put the .gz back on if it was there */ 124e5c89e4eSSatish Balay if (gz) { 125e5c89e4eSSatish Balay ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr); 126e5c89e4eSSatish Balay } 127e5c89e4eSSatish Balay ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr); 128e5c89e4eSSatish Balay ierr = PetscFree(par2);CHKERRQ(ierr); 129e5c89e4eSSatish Balay PetscFunctionReturn(0); 130e5c89e4eSSatish Balay } 131e5c89e4eSSatish Balay 132e5c89e4eSSatish Balay 133e5c89e4eSSatish Balay #undef __FUNCT__ 134e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryOpen" 135e5c89e4eSSatish Balay /*@C 136ebd79076SLisandro Dalcin PetscDLLibraryOpen - Opens a PETSc dynamic link library 137e5c89e4eSSatish Balay 138e5c89e4eSSatish Balay Collective on MPI_Comm 139e5c89e4eSSatish Balay 140e5c89e4eSSatish Balay Input Parameters: 141e5c89e4eSSatish Balay + comm - processors that are opening the library 142e5c89e4eSSatish Balay - libname - name of the library, can be relative or absolute 143e5c89e4eSSatish Balay 144e5c89e4eSSatish Balay Output Parameter: 145e5c89e4eSSatish Balay . handle - library handle 146e5c89e4eSSatish Balay 147e5c89e4eSSatish Balay Level: developer 148e5c89e4eSSatish Balay 149e5c89e4eSSatish Balay Notes: 150e5c89e4eSSatish Balay [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 151e5c89e4eSSatish Balay 152e5c89e4eSSatish Balay ${PETSC_ARCH} occuring in directoryname and filename 153e5c89e4eSSatish Balay will be replaced with the appropriate value. 154e5c89e4eSSatish Balay @*/ 155*b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryOpen(MPI_Comm comm,const char path[],PetscDLLibrary *entry) 156e5c89e4eSSatish Balay { 157e5c89e4eSSatish Balay PetscErrorCode ierr; 158*b3bb0f5eSLisandro Dalcin PetscTruth foundlibrary,match; 159*b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],par2[PETSC_MAX_PATH_LEN],suffix[16],*s; 160*b3bb0f5eSLisandro Dalcin char *basename,registername[128]; 1615673baf8SLisandro Dalcin PetscDLHandle handle; 162e5c89e4eSSatish Balay PetscErrorCode (*func)(const char*) = NULL; 163e5c89e4eSSatish Balay size_t len; 164e5c89e4eSSatish Balay 165e5c89e4eSSatish Balay PetscFunctionBegin; 1665673baf8SLisandro Dalcin PetscValidCharPointer(libname,2); 1675673baf8SLisandro Dalcin PetscValidPointer(entry,3); 168ebd79076SLisandro Dalcin 1695673baf8SLisandro Dalcin *entry = PETSC_NULL; 170e5c89e4eSSatish Balay 171*b3bb0f5eSLisandro Dalcin /* retrieve the library */ 172*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Retrieving %s\n",path);CHKERRQ(ierr); 173*b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryRetrieve(comm,path,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr); 174*b3bb0f5eSLisandro Dalcin if (!foundlibrary) SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s\n",path); 175e5c89e4eSSatish Balay /* Eventually config/configure.py should determine if the system needs an executable dynamic library */ 176e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO 177e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO) 178e5c89e4eSSatish Balay ierr = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr); 179*b3bb0f5eSLisandro Dalcin if (!foundlibrary) SETERRQ2(PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s\n",path,par2); 180e5c89e4eSSatish Balay #endif 181e5c89e4eSSatish Balay 182*b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 183*b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 184*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 185*b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 186*b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 187*b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 188*b3bb0f5eSLisandro Dalcin 1895673baf8SLisandro Dalcin /* open the dynamic library */ 190*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Opening dynamic library %s\n",libname);CHKERRQ(ierr); 191*b3bb0f5eSLisandro Dalcin ierr = PetscDLOpen(par2,PETSC_DL_DECIDE,&handle);CHKERRQ(ierr); 192*b3bb0f5eSLisandro Dalcin 193*b3bb0f5eSLisandro Dalcin /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */ 194*b3bb0f5eSLisandro Dalcin ierr = PetscStrrchr(libname,'/',&basename);CHKERRQ(ierr); /* XXX Windows ??? */ 195*b3bb0f5eSLisandro Dalcin if (!basename) basename = libname; 196*b3bb0f5eSLisandro Dalcin ierr = PetscStrncmp(basename,"lib",3,&match);CHKERRQ(ierr); 197*b3bb0f5eSLisandro Dalcin if (match) { 198*b3bb0f5eSLisandro Dalcin basename = basename + 3; 199*b3bb0f5eSLisandro Dalcin } else { 200*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Dynamic library %s do not have lib prefix\n",libname);CHKERRQ(ierr); 201e5c89e4eSSatish Balay } 202*b3bb0f5eSLisandro Dalcin ierr = PetscStrlen(basename,&len);CHKERRQ(ierr); 203*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr); 204*b3bb0f5eSLisandro Dalcin ierr = PetscStrncat(registername,basename,len);CHKERRQ(ierr); 205*b3bb0f5eSLisandro Dalcin ierr = PetscDLSym(handle,registername,(void**)&func);CHKERRQ(ierr); 206*b3bb0f5eSLisandro Dalcin if (func) { 2075673baf8SLisandro Dalcin ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr); 2085673baf8SLisandro Dalcin ierr = (*func)(libname);CHKERRQ(ierr); 209*b3bb0f5eSLisandro Dalcin } else { 210*b3bb0f5eSLisandro Dalcin ierr = PetscInfo2(0,"Dynamic library %s do not have symbol %s\n",libname,registername);CHKERRQ(ierr); 211*b3bb0f5eSLisandro Dalcin } 2125673baf8SLisandro Dalcin 2135673baf8SLisandro Dalcin ierr = PetscNew(struct _n_PetscDLLibrary,entry);CHKERRQ(ierr); 2145673baf8SLisandro Dalcin (*entry)->next = 0; 215*b3bb0f5eSLisandro Dalcin (*entry)->handle = handle; 216*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy((*entry)->libname,libname);CHKERRQ(ierr); 2175673baf8SLisandro Dalcin 218e5c89e4eSSatish Balay PetscFunctionReturn(0); 219e5c89e4eSSatish Balay } 220e5c89e4eSSatish Balay 221e5c89e4eSSatish Balay #undef __FUNCT__ 222e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibrarySym" 223e5c89e4eSSatish Balay /*@C 224e5c89e4eSSatish Balay PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay Collective on MPI_Comm 227e5c89e4eSSatish Balay 228e5c89e4eSSatish Balay Input Parameter: 229e5bd5246SBarry Smith + comm - communicator that will open the library 230e5bd5246SBarry Smith . inlist - list of already open libraries that may contain symbol (checks here before path) 231e5bd5246SBarry Smith . path - optional complete library name 232e5c89e4eSSatish Balay - insymbol - name of symbol 233e5c89e4eSSatish Balay 234e5c89e4eSSatish Balay Output Parameter: 235e5c89e4eSSatish Balay . value 236e5c89e4eSSatish Balay 237e5c89e4eSSatish Balay Level: developer 238e5c89e4eSSatish Balay 239e5c89e4eSSatish Balay Notes: Symbol can be of the form 240e5c89e4eSSatish Balay [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 241e5c89e4eSSatish Balay 242e5c89e4eSSatish Balay Will attempt to (retrieve and) open the library if it is not yet been opened. 243e5c89e4eSSatish Balay 244e5c89e4eSSatish Balay @*/ 245*b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *outlist,const char path[],const char insymbol[],void **value) 246e5c89e4eSSatish Balay { 247*b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],suffix[16],*symbol,*s; 248e5c89e4eSSatish Balay size_t len; 249e5bd5246SBarry Smith PetscDLLibrary nlist,prev,list; 250*b3bb0f5eSLisandro Dalcin PetscErrorCode ierr; 251e5c89e4eSSatish Balay 252e5c89e4eSSatish Balay PetscFunctionBegin; 253*b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 2545673baf8SLisandro Dalcin if (path) PetscValidCharPointer(path,3); 2555673baf8SLisandro Dalcin PetscValidCharPointer(insymbol,4); 2565673baf8SLisandro Dalcin PetscValidPointer(value,5); 2575673baf8SLisandro Dalcin 258*b3bb0f5eSLisandro Dalcin list = *outlist; 259e5c89e4eSSatish Balay *value = 0; 260e5c89e4eSSatish Balay 261e5c89e4eSSatish Balay /* make copy of symbol so we can edit it in place */ 262e5c89e4eSSatish Balay ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr); 263e5c89e4eSSatish Balay ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr); 264e5c89e4eSSatish Balay ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr); 265*b3bb0f5eSLisandro Dalcin /* If symbol contains () then replace with a NULL, to support functionname() */ 266*b3bb0f5eSLisandro Dalcin ierr = PetscStrchr(symbol,'(',&s);CHKERRQ(ierr); 267*b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 268e5c89e4eSSatish Balay 269e5c89e4eSSatish Balay /* 270e5c89e4eSSatish Balay Function name does include library 271e5c89e4eSSatish Balay ------------------------------------- 272e5c89e4eSSatish Balay */ 273e5c89e4eSSatish Balay if (path && path[0] != '\0') { 274*b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 275*b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 276*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 277*b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 278*b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 279*b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 2805673baf8SLisandro Dalcin /* Look if library is already opened and in path */ 281e5c89e4eSSatish Balay prev = 0; 282*b3bb0f5eSLisandro Dalcin nlist = list; 283e5c89e4eSSatish Balay while (nlist) { 284e5c89e4eSSatish Balay PetscTruth match; 285*b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(nlist->libname,libname,&match);CHKERRQ(ierr); 2865673baf8SLisandro Dalcin if (match) goto done; 287e5c89e4eSSatish Balay prev = nlist; 288e5c89e4eSSatish Balay nlist = nlist->next; 289e5c89e4eSSatish Balay } 290*b3bb0f5eSLisandro Dalcin /* open the library and append it to path */ 2915673baf8SLisandro Dalcin ierr = PetscDLLibraryOpen(comm,path,&nlist);CHKERRQ(ierr); 292ae15b995SBarry Smith ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr); 2935673baf8SLisandro Dalcin if (prev) { prev->next = nlist; } 294*b3bb0f5eSLisandro Dalcin else { *outlist = nlist; } 295e5c89e4eSSatish Balay 296e5c89e4eSSatish Balay done:; 2975673baf8SLisandro Dalcin ierr = PetscDLSym(nlist->handle,symbol,value);CHKERRQ(ierr); 298e5c89e4eSSatish Balay if (!*value) { 299e5c89e4eSSatish Balay SETERRQ2(PETSC_ERR_PLIB,"Unable to locate function %s in dynamic library %s",insymbol,path); 300e5c89e4eSSatish Balay } 301ae15b995SBarry Smith ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr); 302e5c89e4eSSatish Balay 303e5c89e4eSSatish Balay /* 304e5c89e4eSSatish Balay Function name does not include library so search path 305e5c89e4eSSatish Balay ----------------------------------------------------- 306e5c89e4eSSatish Balay */ 307e5c89e4eSSatish Balay } else { 308e5c89e4eSSatish Balay while (list) { 309ebd79076SLisandro Dalcin ierr = PetscDLSym(list->handle,symbol,value);CHKERRQ(ierr); 310e5c89e4eSSatish Balay if (*value) { 311*b3bb0f5eSLisandro Dalcin ierr = PetscInfo2(0,"Loading symbol %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr); 312e5c89e4eSSatish Balay break; 313e5c89e4eSSatish Balay } 314e5c89e4eSSatish Balay list = list->next; 315e5c89e4eSSatish Balay } 316e5c89e4eSSatish Balay if (!*value) { 317ebd79076SLisandro Dalcin ierr = PetscDLSym(PETSC_NULL,symbol,value);CHKERRQ(ierr); 318e5c89e4eSSatish Balay if (*value) { 319*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Loading symbol %s from object code\n",symbol);CHKERRQ(ierr); 320e5c89e4eSSatish Balay } 321e5c89e4eSSatish Balay } 322e5c89e4eSSatish Balay } 323e5c89e4eSSatish Balay 324e5c89e4eSSatish Balay ierr = PetscFree(symbol);CHKERRQ(ierr); 325e5c89e4eSSatish Balay PetscFunctionReturn(0); 326e5c89e4eSSatish Balay } 327e5c89e4eSSatish Balay 328e5c89e4eSSatish Balay #undef __FUNCT__ 329e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryAppend" 330e5c89e4eSSatish Balay /*@C 331e5c89e4eSSatish Balay PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 332e5c89e4eSSatish Balay of the search path. 333e5c89e4eSSatish Balay 334e5c89e4eSSatish Balay Collective on MPI_Comm 335e5c89e4eSSatish Balay 336e5c89e4eSSatish Balay Input Parameters: 337e5c89e4eSSatish Balay + comm - MPI communicator 338e5c89e4eSSatish Balay - libname - name of the library 339e5c89e4eSSatish Balay 340e5c89e4eSSatish Balay Output Parameter: 341e5c89e4eSSatish Balay . outlist - list of libraries 342e5c89e4eSSatish Balay 343e5c89e4eSSatish Balay Level: developer 344e5c89e4eSSatish Balay 345e5c89e4eSSatish Balay Notes: if library is already in path will not add it. 346e5c89e4eSSatish Balay @*/ 347*b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 348e5c89e4eSSatish Balay { 349e5bd5246SBarry Smith PetscDLLibrary list,prev; 350e5c89e4eSSatish Balay PetscErrorCode ierr; 351e5c89e4eSSatish Balay size_t len; 352e5c89e4eSSatish Balay PetscTruth match,dir; 353*b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 354*b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 3559c9d3cfdSBarry Smith PetscToken token; 356e5c89e4eSSatish Balay 357e5c89e4eSSatish Balay PetscFunctionBegin; 358*b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 359e5c89e4eSSatish Balay 360*b3bb0f5eSLisandro Dalcin /* is path a directory? */ 361*b3bb0f5eSLisandro Dalcin ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr); 362e5c89e4eSSatish Balay if (dir) { 363*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr); 364*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(program,path);CHKERRQ(ierr); 365e5c89e4eSSatish Balay ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 366e5c89e4eSSatish Balay if (program[len-1] == '/') { 367e5c89e4eSSatish Balay ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 368e5c89e4eSSatish Balay } else { 369e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 370e5c89e4eSSatish Balay } 371e5c89e4eSSatish Balay ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 372e5c89e4eSSatish Balay 373*b3bb0f5eSLisandro Dalcin ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 374e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 375e5c89e4eSSatish Balay } else { 376*b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 377e5c89e4eSSatish Balay } 378e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 379e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 380e5c89e4eSSatish Balay 381e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 382*b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 383*b3bb0f5eSLisandro Dalcin while (libname) { 384*b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 385*b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 386e5c89e4eSSatish Balay if (s) s[0] = 0; 387e5c89e4eSSatish Balay /* see if library was already open then we are done */ 388e5c89e4eSSatish Balay list = prev = *outlist; 389e5c89e4eSSatish Balay match = PETSC_FALSE; 390e5c89e4eSSatish Balay while (list) { 391*b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr); 392e5c89e4eSSatish Balay if (match) break; 393e5c89e4eSSatish Balay prev = list; 394e5c89e4eSSatish Balay list = list->next; 395e5c89e4eSSatish Balay } 396*b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 397*b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 398e5c89e4eSSatish Balay if (!match) { 3995673baf8SLisandro Dalcin /* open the library and add to end of list */ 400*b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr); 401*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname);CHKERRQ(ierr); 402e5c89e4eSSatish Balay if (!*outlist) { 403e5c89e4eSSatish Balay *outlist = list; 404e5c89e4eSSatish Balay } else { 405e5c89e4eSSatish Balay prev->next = list; 406e5c89e4eSSatish Balay } 407e5c89e4eSSatish Balay } 408*b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 409e5c89e4eSSatish Balay } 410e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 411e5c89e4eSSatish Balay PetscFunctionReturn(0); 412e5c89e4eSSatish Balay } 413e5c89e4eSSatish Balay 414e5c89e4eSSatish Balay #undef __FUNCT__ 415e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrepend" 416e5c89e4eSSatish Balay /*@C 417e5c89e4eSSatish Balay PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 418e5c89e4eSSatish Balay the search path. 419e5c89e4eSSatish Balay 420e5c89e4eSSatish Balay Collective on MPI_Comm 421e5c89e4eSSatish Balay 422e5c89e4eSSatish Balay Input Parameters: 423e5c89e4eSSatish Balay + comm - MPI communicator 424e5c89e4eSSatish Balay - libname - name of the library 425e5c89e4eSSatish Balay 426e5c89e4eSSatish Balay Output Parameter: 427e5c89e4eSSatish Balay . outlist - list of libraries 428e5c89e4eSSatish Balay 429e5c89e4eSSatish Balay Level: developer 430e5c89e4eSSatish Balay 431e5c89e4eSSatish Balay Notes: If library is already in path will remove old reference. 432e5c89e4eSSatish Balay 433e5c89e4eSSatish Balay @*/ 434*b3bb0f5eSLisandro Dalcin PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 435e5c89e4eSSatish Balay { 436e5bd5246SBarry Smith PetscDLLibrary list,prev; 437e5c89e4eSSatish Balay PetscErrorCode ierr; 438e5c89e4eSSatish Balay size_t len; 439e5c89e4eSSatish Balay PetscTruth match,dir; 440*b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 441*b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 4425b096c79SMatthew Knepley PetscToken token; 443e5c89e4eSSatish Balay 444e5c89e4eSSatish Balay PetscFunctionBegin; 445*b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 446e5c89e4eSSatish Balay 447*b3bb0f5eSLisandro Dalcin /* is path a directory? */ 448*b3bb0f5eSLisandro Dalcin ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr); 449e5c89e4eSSatish Balay if (dir) { 450*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr); 451*b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(program,path);CHKERRQ(ierr); 452e5c89e4eSSatish Balay ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 453e5c89e4eSSatish Balay if (program[len-1] == '/') { 454e5c89e4eSSatish Balay ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 455e5c89e4eSSatish Balay } else { 456e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 457e5c89e4eSSatish Balay } 458e5c89e4eSSatish Balay ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 459e5c89e4eSSatish Balay 460*b3bb0f5eSLisandro Dalcin ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 461e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 462e5c89e4eSSatish Balay } else { 463*b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 464e5c89e4eSSatish Balay } 465e5c89e4eSSatish Balay 466e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 467e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 468e5c89e4eSSatish Balay 469e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 470*b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 471*b3bb0f5eSLisandro Dalcin while (libname) { 472*b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 473*b3bb0f5eSLisandro Dalcin ierr = PetscStrstr(libname,suffix,&s);CHKERRQ(ierr); 474e5c89e4eSSatish Balay if (s) s[0] = 0; 475e5c89e4eSSatish Balay /* see if library was already open and move it to the front */ 476e5c89e4eSSatish Balay prev = 0; 477*b3bb0f5eSLisandro Dalcin list = *outlist; 478e5c89e4eSSatish Balay match = PETSC_FALSE; 479e5c89e4eSSatish Balay while (list) { 480*b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr); 481e5c89e4eSSatish Balay if (match) { 482*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Moving %s to begin of dynamic library search path\n",libname);CHKERRQ(ierr); 483e5c89e4eSSatish Balay if (prev) prev->next = list->next; 484*b3bb0f5eSLisandro Dalcin if (prev) list->next = *outlist; 485e5c89e4eSSatish Balay *outlist = list; 486e5c89e4eSSatish Balay break; 487e5c89e4eSSatish Balay } 488e5c89e4eSSatish Balay prev = list; 489e5c89e4eSSatish Balay list = list->next; 490e5c89e4eSSatish Balay } 491*b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 492*b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 493e5c89e4eSSatish Balay if (!match) { 4945673baf8SLisandro Dalcin /* open the library and add to front of list */ 495*b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr); 496*b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname);CHKERRQ(ierr); 497ebd79076SLisandro Dalcin list->next = *outlist; 498e5c89e4eSSatish Balay *outlist = list; 499e5c89e4eSSatish Balay } 500*b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 501e5c89e4eSSatish Balay } 502e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 503e5c89e4eSSatish Balay PetscFunctionReturn(0); 504e5c89e4eSSatish Balay } 505e5c89e4eSSatish Balay 506e5c89e4eSSatish Balay #undef __FUNCT__ 507e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryClose" 508e5c89e4eSSatish Balay /*@C 509e5c89e4eSSatish Balay PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 510e5c89e4eSSatish Balay 511e5c89e4eSSatish Balay Collective on PetscDLLibrary 512e5c89e4eSSatish Balay 513e5c89e4eSSatish Balay Input Parameter: 514e5c89e4eSSatish Balay . next - library list 515e5c89e4eSSatish Balay 516e5c89e4eSSatish Balay Level: developer 517e5c89e4eSSatish Balay 518e5c89e4eSSatish Balay @*/ 519e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryClose(PetscDLLibrary next) 520e5c89e4eSSatish Balay { 521e5bd5246SBarry Smith PetscDLLibrary prev; 522e5c89e4eSSatish Balay PetscErrorCode ierr; 523e5c89e4eSSatish Balay 524e5c89e4eSSatish Balay PetscFunctionBegin; 525e5c89e4eSSatish Balay while (next) { 526e5c89e4eSSatish Balay prev = next; 527e5c89e4eSSatish Balay next = next->next; 528ebd79076SLisandro Dalcin /* close the dynamic library */ 529ebd79076SLisandro Dalcin ierr = PetscDLClose(&prev->handle);CHKERRQ(ierr); 530e5c89e4eSSatish Balay /* free the space in the prev data-structure */ 531e5c89e4eSSatish Balay ierr = PetscFree(prev);CHKERRQ(ierr); 532e5c89e4eSSatish Balay } 533e5c89e4eSSatish Balay PetscFunctionReturn(0); 534e5c89e4eSSatish Balay } 535e5c89e4eSSatish Balay 536e5c89e4eSSatish Balay #undef __FUNCT__ 537e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryCCAAppend" 538e5c89e4eSSatish Balay /*@C 539e5c89e4eSSatish Balay PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end 540e5c89e4eSSatish Balay of the search path. 541e5c89e4eSSatish Balay 542e5c89e4eSSatish Balay Collective on MPI_Comm 543e5c89e4eSSatish Balay 544e5c89e4eSSatish Balay Input Parameters: 545e5c89e4eSSatish Balay + comm - MPI communicator 546e5c89e4eSSatish Balay - libname - name of directory to check 547e5c89e4eSSatish Balay 548e5c89e4eSSatish Balay Output Parameter: 549e5c89e4eSSatish Balay . outlist - list of libraries 550e5c89e4eSSatish Balay 551e5c89e4eSSatish Balay Level: developer 552e5c89e4eSSatish Balay 553e5c89e4eSSatish Balay Notes: if library is already in path will not add it. 554e5c89e4eSSatish Balay @*/ 555e5bd5246SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[]) 556e5c89e4eSSatish Balay { 557e5c89e4eSSatish Balay PetscErrorCode ierr; 558e5c89e4eSSatish Balay size_t l; 559e5c89e4eSSatish Balay PetscTruth dir; 560e5c89e4eSSatish Balay char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2; 561e5c89e4eSSatish Balay char *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib; 562e5c89e4eSSatish Balay FILE *fp; 5635b096c79SMatthew Knepley PetscToken token1, token2; 564ed9cf6e9SBarry Smith int err; 565e5c89e4eSSatish Balay 566e5c89e4eSSatish Balay PetscFunctionBegin; 567e5c89e4eSSatish Balay /* is dirname a directory? */ 568e5c89e4eSSatish Balay ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr); 569e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 570e5c89e4eSSatish Balay 571ae15b995SBarry Smith ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr); 572e5c89e4eSSatish Balay ierr = PetscStrcpy(program,dirname);CHKERRQ(ierr); 573e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.cca");CHKERRQ(ierr); 574e5c89e4eSSatish Balay 575e5c89e4eSSatish Balay ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 576e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 577e5c89e4eSSatish Balay 578e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 579e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 580e5c89e4eSSatish Balay ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr); 581e5c89e4eSSatish Balay ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 582e5c89e4eSSatish Balay while (libname1) { 583e5c89e4eSSatish Balay fp = fopen(libname1,"r"); if (!fp) continue; 584e5c89e4eSSatish Balay while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) { 585e5c89e4eSSatish Balay if (found[0] == '!') continue; 586e5c89e4eSSatish Balay ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr); 587e5c89e4eSSatish Balay if (f2) { /* found library name */ 588e5c89e4eSSatish Balay if (found[0] == '/') { 589e5c89e4eSSatish Balay lib = found; 590e5c89e4eSSatish Balay } else { 591e5c89e4eSSatish Balay ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr); 592e5c89e4eSSatish Balay ierr = PetscStrlen(libname,&l);CHKERRQ(ierr); 593e5c89e4eSSatish Balay if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);} 594e5c89e4eSSatish Balay ierr = PetscStrcat(libname,found);CHKERRQ(ierr); 595e5c89e4eSSatish Balay lib = libname; 596e5c89e4eSSatish Balay } 597e5c89e4eSSatish Balay ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr); 598e5c89e4eSSatish Balay } else { 599ae15b995SBarry Smith ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr); 600e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr); 601e5c89e4eSSatish Balay ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr); 602e5c89e4eSSatish Balay ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr); 603e5c89e4eSSatish Balay ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr); 604e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token2);CHKERRQ(ierr); 605e5c89e4eSSatish Balay } 606e5c89e4eSSatish Balay } 607ed9cf6e9SBarry Smith err = fclose(fp); 608ed9cf6e9SBarry Smith if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file"); 609e5c89e4eSSatish Balay ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 610e5c89e4eSSatish Balay } 611e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token1);CHKERRQ(ierr); 612e5c89e4eSSatish Balay PetscFunctionReturn(0); 613e5c89e4eSSatish Balay } 614