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> 7c6db04a5SJed Brown #include <../src/sys/dll/dlimpl.h> 8e5c89e4eSSatish Balay 9e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 10e5c89e4eSSatish Balay /* 11e5c89e4eSSatish Balay Code to maintain a list of opened dynamic libraries and load symbols 12e5c89e4eSSatish Balay */ 13e5bd5246SBarry Smith struct _n_PetscDLLibrary { 14e5bd5246SBarry Smith PetscDLLibrary next; 15ebd79076SLisandro Dalcin PetscDLHandle handle; 16e5c89e4eSSatish Balay char libname[PETSC_MAX_PATH_LEN]; 17e5c89e4eSSatish Balay }; 18e5c89e4eSSatish Balay 19e5c89e4eSSatish Balay #undef __FUNCT__ 20e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrintPath" 217087cfbeSBarry Smith PetscErrorCode PetscDLLibraryPrintPath(PetscDLLibrary libs) 22e5c89e4eSSatish Balay { 23e5c89e4eSSatish Balay PetscFunctionBegin; 24e5c89e4eSSatish Balay while (libs) { 25e5c89e4eSSatish Balay PetscErrorPrintf(" %s\n",libs->libname); 26e5c89e4eSSatish Balay libs = libs->next; 27e5c89e4eSSatish Balay } 28e5c89e4eSSatish Balay PetscFunctionReturn(0); 29e5c89e4eSSatish Balay } 30e5c89e4eSSatish Balay 31e5c89e4eSSatish Balay #undef __FUNCT__ 32e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryRetrieve" 33e5c89e4eSSatish Balay /*@C 34e5c89e4eSSatish Balay PetscDLLibraryRetrieve - Copies a PETSc dynamic library from a remote location 35e5c89e4eSSatish Balay (if it is remote), indicates if it exits and its local name. 36e5c89e4eSSatish Balay 37e5c89e4eSSatish Balay Collective on MPI_Comm 38e5c89e4eSSatish Balay 39e5c89e4eSSatish Balay Input Parameters: 40e5c89e4eSSatish Balay + comm - processors that are opening the library 41e5c89e4eSSatish Balay - libname - name of the library, can be relative or absolute 42e5c89e4eSSatish Balay 43e5c89e4eSSatish Balay Output Parameter: 44e5c89e4eSSatish Balay . handle - library handle 45e5c89e4eSSatish Balay 46e5c89e4eSSatish Balay Level: developer 47e5c89e4eSSatish Balay 48e5c89e4eSSatish Balay Notes: 49e5c89e4eSSatish Balay [[<http,ftp>://hostname]/directoryname/]filename[.so.1.0] 50e5c89e4eSSatish Balay 51e5c89e4eSSatish Balay ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 52e5c89e4eSSatish Balay occuring in directoryname and filename will be replaced with appropriate values. 53e5c89e4eSSatish Balay @*/ 547087cfbeSBarry Smith PetscErrorCode PetscDLLibraryRetrieve(MPI_Comm comm,const char libname[],char *lname,size_t llen,PetscBool *found) 55e5c89e4eSSatish Balay { 56d46cf212SLisandro Dalcin char *buf,*par2,suffix[16],*gz,*so; 57d46cf212SLisandro Dalcin size_t len; 58e5c89e4eSSatish Balay PetscErrorCode ierr; 59e5c89e4eSSatish Balay 60e5c89e4eSSatish Balay PetscFunctionBegin; 61e5c89e4eSSatish Balay /* 62a523d312SBarry Smith make copy of library name and replace $PETSC_ARCH etc 63e5c89e4eSSatish Balay so we can add to the end of it to look for something like .so.1.0 etc. 64e5c89e4eSSatish Balay */ 65e5c89e4eSSatish Balay ierr = PetscStrlen(libname,&len);CHKERRQ(ierr); 66e5c89e4eSSatish Balay len = PetscMax(4*len,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 67d46cf212SLisandro Dalcin ierr = PetscMalloc(len*sizeof(char),&buf);CHKERRQ(ierr); 68d46cf212SLisandro Dalcin par2 = buf; 69e5c89e4eSSatish Balay ierr = PetscStrreplace(comm,libname,par2,len);CHKERRQ(ierr); 70e5c89e4eSSatish Balay 71d46cf212SLisandro Dalcin /* temporarily remove .gz if it ends library name */ 72d46cf212SLisandro Dalcin ierr = PetscStrrstr(par2,".gz",&gz);CHKERRQ(ierr); 73e5c89e4eSSatish Balay if (gz) { 74e5c89e4eSSatish Balay ierr = PetscStrlen(gz,&len);CHKERRQ(ierr); 75d46cf212SLisandro Dalcin if (len != 3) gz = 0; /* do not end (exactly) with .gz */ 76d46cf212SLisandro Dalcin else *gz = 0; /* ends with .gz, so remove it */ 77e5c89e4eSSatish Balay } 783fa76a5bSLisandro Dalcin /* strip out .a from it if user put it in by mistake */ 793fa76a5bSLisandro Dalcin ierr = PetscStrlen(par2,&len);CHKERRQ(ierr); 803fa76a5bSLisandro Dalcin if (par2[len-1] == 'a' && par2[len-2] == '.') par2[len-2] = 0; 813fa76a5bSLisandro Dalcin 82e5c89e4eSSatish Balay 83e5c89e4eSSatish Balay /* see if library name does already not have suffix attached */ 84b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 85b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 86b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(par2,suffix,&so);CHKERRQ(ierr); 87d46cf212SLisandro Dalcin /* and attach the suffix if it is not there */ 88d46cf212SLisandro Dalcin if (!so) { ierr = PetscStrcat(par2,suffix);CHKERRQ(ierr); } 89e5c89e4eSSatish Balay 90d46cf212SLisandro Dalcin /* restore the .gz suffix if it was there */ 91d46cf212SLisandro Dalcin if (gz) { ierr = PetscStrcat(par2,".gz");CHKERRQ(ierr); } 92d46cf212SLisandro Dalcin 93d46cf212SLisandro Dalcin /* and finally retrieve the file */ 94e5c89e4eSSatish Balay ierr = PetscFileRetrieve(comm,par2,lname,llen,found);CHKERRQ(ierr); 95d46cf212SLisandro Dalcin 96d46cf212SLisandro Dalcin ierr = PetscFree(buf);CHKERRQ(ierr); 97e5c89e4eSSatish Balay PetscFunctionReturn(0); 98e5c89e4eSSatish Balay } 99e5c89e4eSSatish Balay 100e5c89e4eSSatish Balay 101e5c89e4eSSatish Balay #undef __FUNCT__ 102e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryOpen" 103e5c89e4eSSatish Balay /*@C 104ebd79076SLisandro Dalcin PetscDLLibraryOpen - Opens a PETSc dynamic link library 105e5c89e4eSSatish Balay 106e5c89e4eSSatish Balay Collective on MPI_Comm 107e5c89e4eSSatish Balay 108e5c89e4eSSatish Balay Input Parameters: 109e5c89e4eSSatish Balay + comm - processors that are opening the library 1100f31fb7fSLisandro Dalcin - path - name of the library, can be relative or absolute 111e5c89e4eSSatish Balay 112e5c89e4eSSatish Balay Output Parameter: 1130f31fb7fSLisandro Dalcin . entry - a PETSc dynamic link library entry 114e5c89e4eSSatish Balay 115e5c89e4eSSatish Balay Level: developer 116e5c89e4eSSatish Balay 117e5c89e4eSSatish Balay Notes: 118bb84e0fdSBarry Smith [[<http,ftp>://hostname]/directoryname/]libbasename[.so.1.0] 119bb84e0fdSBarry Smith 120bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 121bb84e0fdSBarry Smith when the library is opened. 122e5c89e4eSSatish Balay 123e5c89e4eSSatish Balay ${PETSC_ARCH} occuring in directoryname and filename 124e5c89e4eSSatish Balay will be replaced with the appropriate value. 125bb84e0fdSBarry Smith 126bb84e0fdSBarry Smith .seealso: PetscLoadDynamicLibrary(), PetscDLLibraryAppend() 127e5c89e4eSSatish Balay @*/ 1287087cfbeSBarry Smith PetscErrorCode PetscDLLibraryOpen(MPI_Comm comm,const char path[],PetscDLLibrary *entry) 129e5c89e4eSSatish Balay { 130e5c89e4eSSatish Balay PetscErrorCode ierr; 131ace3abfcSBarry Smith PetscBool foundlibrary,match; 132b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],par2[PETSC_MAX_PATH_LEN],suffix[16],*s; 133b3bb0f5eSLisandro Dalcin char *basename,registername[128]; 1345673baf8SLisandro Dalcin PetscDLHandle handle; 135e5c89e4eSSatish Balay PetscErrorCode (*func)(const char*) = NULL; 136e5c89e4eSSatish Balay size_t len; 137e5c89e4eSSatish Balay 138e5c89e4eSSatish Balay PetscFunctionBegin; 13982a51d08SSatish Balay PetscValidCharPointer(path,2); 1405673baf8SLisandro Dalcin PetscValidPointer(entry,3); 141ebd79076SLisandro Dalcin 1425673baf8SLisandro Dalcin *entry = PETSC_NULL; 143e5c89e4eSSatish Balay 144b3bb0f5eSLisandro Dalcin /* retrieve the library */ 145b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Retrieving %s\n",path);CHKERRQ(ierr); 146b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryRetrieve(comm,path,par2,PETSC_MAX_PATH_LEN,&foundlibrary);CHKERRQ(ierr); 147e32f2f54SBarry Smith if (!foundlibrary) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate dynamic library:\n %s\n",path); 148e2e64c6bSBarry Smith /* Eventually ./configure should determine if the system needs an executable dynamic library */ 149e5c89e4eSSatish Balay #define PETSC_USE_NONEXECUTABLE_SO 150e5c89e4eSSatish Balay #if !defined(PETSC_USE_NONEXECUTABLE_SO) 151e5c89e4eSSatish Balay ierr = PetscTestFile(par2,'x',&foundlibrary);CHKERRQ(ierr); 152e32f2f54SBarry Smith if (!foundlibrary) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Dynamic library is not executable:\n %s\n %s\n",path,par2); 153e5c89e4eSSatish Balay #endif 154e5c89e4eSSatish Balay 1553fa76a5bSLisandro Dalcin /* copy path and setup shared library suffix */ 156b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 157b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 158b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 1593fa76a5bSLisandro Dalcin /* remove wrong suffixes from libname */ 1603fa76a5bSLisandro Dalcin ierr = PetscStrrstr(libname,".gz",&s);CHKERRQ(ierr); 1613fa76a5bSLisandro Dalcin if (s && s[3] == 0) s[0] = 0; 1623fa76a5bSLisandro Dalcin ierr = PetscStrrstr(libname,".a",&s);CHKERRQ(ierr); 1633fa76a5bSLisandro Dalcin if (s && s[2] == 0) s[0] = 0; 1643fa76a5bSLisandro Dalcin /* remove shared suffix from libname */ 165b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 166b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 167b3bb0f5eSLisandro Dalcin 1685673baf8SLisandro Dalcin /* open the dynamic library */ 169b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Opening dynamic library %s\n",libname);CHKERRQ(ierr); 170b3bb0f5eSLisandro Dalcin ierr = PetscDLOpen(par2,PETSC_DL_DECIDE,&handle);CHKERRQ(ierr); 171b3bb0f5eSLisandro Dalcin 172b3bb0f5eSLisandro Dalcin /* look for [path/]libXXXXX.YYY and extract out the XXXXXX */ 173b3bb0f5eSLisandro Dalcin ierr = PetscStrrchr(libname,'/',&basename);CHKERRQ(ierr); /* XXX Windows ??? */ 174b3bb0f5eSLisandro Dalcin if (!basename) basename = libname; 175b3bb0f5eSLisandro Dalcin ierr = PetscStrncmp(basename,"lib",3,&match);CHKERRQ(ierr); 176b3bb0f5eSLisandro Dalcin if (match) { 177b3bb0f5eSLisandro Dalcin basename = basename + 3; 178b3bb0f5eSLisandro Dalcin } else { 179bb84e0fdSBarry Smith ierr = PetscInfo1(0,"Dynamic library %s does not have lib prefix\n",libname);CHKERRQ(ierr); 180e5c89e4eSSatish Balay } 181b3bb0f5eSLisandro Dalcin ierr = PetscStrlen(basename,&len);CHKERRQ(ierr); 182b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(registername,"PetscDLLibraryRegister_");CHKERRQ(ierr); 183b3bb0f5eSLisandro Dalcin ierr = PetscStrncat(registername,basename,len);CHKERRQ(ierr); 184b3bb0f5eSLisandro Dalcin ierr = PetscDLSym(handle,registername,(void**)&func);CHKERRQ(ierr); 185b3bb0f5eSLisandro Dalcin if (func) { 1865673baf8SLisandro Dalcin ierr = PetscInfo1(0,"Loading registered routines from %s\n",libname);CHKERRQ(ierr); 1875673baf8SLisandro Dalcin ierr = (*func)(libname);CHKERRQ(ierr); 188b3bb0f5eSLisandro Dalcin } else { 189bb84e0fdSBarry Smith ierr = PetscInfo2(0,"Dynamic library %s does not have symbol %s\n",libname,registername);CHKERRQ(ierr); 190b3bb0f5eSLisandro Dalcin } 1915673baf8SLisandro Dalcin 1925673baf8SLisandro Dalcin ierr = PetscNew(struct _n_PetscDLLibrary,entry);CHKERRQ(ierr); 1935673baf8SLisandro Dalcin (*entry)->next = 0; 194b3bb0f5eSLisandro Dalcin (*entry)->handle = handle; 195b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy((*entry)->libname,libname);CHKERRQ(ierr); 1965673baf8SLisandro Dalcin 197e5c89e4eSSatish Balay PetscFunctionReturn(0); 198e5c89e4eSSatish Balay } 199e5c89e4eSSatish Balay 200e5c89e4eSSatish Balay #undef __FUNCT__ 201e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibrarySym" 202e5c89e4eSSatish Balay /*@C 203e5c89e4eSSatish Balay PetscDLLibrarySym - Load a symbol from the dynamic link libraries. 204e5c89e4eSSatish Balay 205e5c89e4eSSatish Balay Collective on MPI_Comm 206e5c89e4eSSatish Balay 207e5c89e4eSSatish Balay Input Parameter: 208e5bd5246SBarry Smith + comm - communicator that will open the library 209*340b11eeSBarry Smith . outlist - list of already open libraries that may contain symbol (can be PETSC_NULL and only the executable is searched for the function) 21030a1dd1fSBarry Smith . path - optional complete library name (if provided checks here before checking outlist) 211e5c89e4eSSatish Balay - insymbol - name of symbol 212e5c89e4eSSatish Balay 213e5c89e4eSSatish Balay Output Parameter: 21430a1dd1fSBarry Smith . value - if symbol not found then this value is set to PETSC_NULL 215e5c89e4eSSatish Balay 216e5c89e4eSSatish Balay Level: developer 217e5c89e4eSSatish Balay 218e5c89e4eSSatish Balay Notes: Symbol can be of the form 219e5c89e4eSSatish Balay [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional 220e5c89e4eSSatish Balay 221e5c89e4eSSatish Balay Will attempt to (retrieve and) open the library if it is not yet been opened. 222e5c89e4eSSatish Balay 223e5c89e4eSSatish Balay @*/ 2247087cfbeSBarry Smith PetscErrorCode PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *outlist,const char path[],const char insymbol[],void **value) 225e5c89e4eSSatish Balay { 226b3bb0f5eSLisandro Dalcin char libname[PETSC_MAX_PATH_LEN],suffix[16],*symbol,*s; 227e5c89e4eSSatish Balay size_t len; 228*340b11eeSBarry Smith PetscDLLibrary nlist,prev,list = PETSC_NULL; 229b3bb0f5eSLisandro Dalcin PetscErrorCode ierr; 230e5c89e4eSSatish Balay 231e5c89e4eSSatish Balay PetscFunctionBegin; 232*340b11eeSBarry Smith if (outlist) PetscValidPointer(outlist,2); 2335673baf8SLisandro Dalcin if (path) PetscValidCharPointer(path,3); 2345673baf8SLisandro Dalcin PetscValidCharPointer(insymbol,4); 2355673baf8SLisandro Dalcin PetscValidPointer(value,5); 2365673baf8SLisandro Dalcin 237*340b11eeSBarry Smith if (outlist) list = *outlist; 238e5c89e4eSSatish Balay *value = 0; 239e5c89e4eSSatish Balay 240e5c89e4eSSatish Balay /* make copy of symbol so we can edit it in place */ 241e5c89e4eSSatish Balay ierr = PetscStrlen(insymbol,&len);CHKERRQ(ierr); 242e5c89e4eSSatish Balay ierr = PetscMalloc((len+1)*sizeof(char),&symbol);CHKERRQ(ierr); 243e5c89e4eSSatish Balay ierr = PetscStrcpy(symbol,insymbol);CHKERRQ(ierr); 244b3bb0f5eSLisandro Dalcin /* If symbol contains () then replace with a NULL, to support functionname() */ 245b3bb0f5eSLisandro Dalcin ierr = PetscStrchr(symbol,'(',&s);CHKERRQ(ierr); 246b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 247e5c89e4eSSatish Balay 248e5c89e4eSSatish Balay /* 249e5c89e4eSSatish Balay Function name does include library 250e5c89e4eSSatish Balay ------------------------------------- 251e5c89e4eSSatish Balay */ 252e5c89e4eSSatish Balay if (path && path[0] != '\0') { 253b3bb0f5eSLisandro Dalcin /* copy path and remove suffix from libname */ 254b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 255b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 256b3bb0f5eSLisandro Dalcin ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 257b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 258b3bb0f5eSLisandro Dalcin if (s) s[0] = 0; 2595673baf8SLisandro Dalcin /* Look if library is already opened and in path */ 260e5c89e4eSSatish Balay prev = 0; 261b3bb0f5eSLisandro Dalcin nlist = list; 262e5c89e4eSSatish Balay while (nlist) { 263ace3abfcSBarry Smith PetscBool match; 264b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(nlist->libname,libname,&match);CHKERRQ(ierr); 2655673baf8SLisandro Dalcin if (match) goto done; 266e5c89e4eSSatish Balay prev = nlist; 267e5c89e4eSSatish Balay nlist = nlist->next; 268e5c89e4eSSatish Balay } 269b3bb0f5eSLisandro Dalcin /* open the library and append it to path */ 2705673baf8SLisandro Dalcin ierr = PetscDLLibraryOpen(comm,path,&nlist);CHKERRQ(ierr); 271ae15b995SBarry Smith ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr); 2725673baf8SLisandro Dalcin if (prev) { prev->next = nlist; } 273b3bb0f5eSLisandro Dalcin else { *outlist = nlist; } 274e5c89e4eSSatish Balay 275e5c89e4eSSatish Balay done:; 2765673baf8SLisandro Dalcin ierr = PetscDLSym(nlist->handle,symbol,value);CHKERRQ(ierr); 27730a1dd1fSBarry Smith if (*value) { 278ae15b995SBarry Smith ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr); 27930a1dd1fSBarry Smith } 280e5c89e4eSSatish Balay 281e5c89e4eSSatish Balay /* 282e5c89e4eSSatish Balay Function name does not include library so search path 283e5c89e4eSSatish Balay ----------------------------------------------------- 284e5c89e4eSSatish Balay */ 285e5c89e4eSSatish Balay } else { 286e5c89e4eSSatish Balay while (list) { 287ebd79076SLisandro Dalcin ierr = PetscDLSym(list->handle,symbol,value);CHKERRQ(ierr); 288e5c89e4eSSatish Balay if (*value) { 289b3bb0f5eSLisandro Dalcin ierr = PetscInfo2(0,"Loading symbol %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr); 290e5c89e4eSSatish Balay break; 291e5c89e4eSSatish Balay } 292e5c89e4eSSatish Balay list = list->next; 293e5c89e4eSSatish Balay } 294e5c89e4eSSatish Balay if (!*value) { 295ebd79076SLisandro Dalcin ierr = PetscDLSym(PETSC_NULL,symbol,value);CHKERRQ(ierr); 296e5c89e4eSSatish Balay if (*value) { 297b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Loading symbol %s from object code\n",symbol);CHKERRQ(ierr); 298e5c89e4eSSatish Balay } 299e5c89e4eSSatish Balay } 300e5c89e4eSSatish Balay } 301e5c89e4eSSatish Balay 302e5c89e4eSSatish Balay ierr = PetscFree(symbol);CHKERRQ(ierr); 303e5c89e4eSSatish Balay PetscFunctionReturn(0); 304e5c89e4eSSatish Balay } 305e5c89e4eSSatish Balay 306e5c89e4eSSatish Balay #undef __FUNCT__ 307e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryAppend" 308e5c89e4eSSatish Balay /*@C 309e5c89e4eSSatish Balay PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end 310e5c89e4eSSatish Balay of the search path. 311e5c89e4eSSatish Balay 312e5c89e4eSSatish Balay Collective on MPI_Comm 313e5c89e4eSSatish Balay 314e5c89e4eSSatish Balay Input Parameters: 315e5c89e4eSSatish Balay + comm - MPI communicator 3160f31fb7fSLisandro Dalcin - path - name of the library 317e5c89e4eSSatish Balay 318e5c89e4eSSatish Balay Output Parameter: 319e5c89e4eSSatish Balay . outlist - list of libraries 320e5c89e4eSSatish Balay 321e5c89e4eSSatish Balay Level: developer 322e5c89e4eSSatish Balay 323e5c89e4eSSatish Balay Notes: if library is already in path will not add it. 324bb84e0fdSBarry Smith 325bb84e0fdSBarry Smith If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run 326bb84e0fdSBarry Smith when the library is opened. 327bb84e0fdSBarry Smith 328bb84e0fdSBarry Smith .seealso: PetscDLLibraryOpen() 329e5c89e4eSSatish Balay @*/ 3307087cfbeSBarry Smith PetscErrorCode PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 331e5c89e4eSSatish Balay { 332e5bd5246SBarry Smith PetscDLLibrary list,prev; 333e5c89e4eSSatish Balay PetscErrorCode ierr; 334e5c89e4eSSatish Balay size_t len; 335ace3abfcSBarry Smith PetscBool match,dir; 336b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 337b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 3389c9d3cfdSBarry Smith PetscToken token; 339e5c89e4eSSatish Balay 340e5c89e4eSSatish Balay PetscFunctionBegin; 341b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 342e5c89e4eSSatish Balay 343b3bb0f5eSLisandro Dalcin /* is path a directory? */ 344b3bb0f5eSLisandro Dalcin ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr); 345e5c89e4eSSatish Balay if (dir) { 346b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr); 347b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(program,path);CHKERRQ(ierr); 348e5c89e4eSSatish Balay ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 349e5c89e4eSSatish Balay if (program[len-1] == '/') { 350e5c89e4eSSatish Balay ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 351e5c89e4eSSatish Balay } else { 352e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 353e5c89e4eSSatish Balay } 354e5c89e4eSSatish Balay ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 355e5c89e4eSSatish Balay 356b3bb0f5eSLisandro Dalcin ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 357e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 358e5c89e4eSSatish Balay } else { 359b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 360e5c89e4eSSatish Balay } 361e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 362e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 363e5c89e4eSSatish Balay 364e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 365b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 366b3bb0f5eSLisandro Dalcin while (libname) { 367b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 368b3bb0f5eSLisandro Dalcin ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr); 369e5c89e4eSSatish Balay if (s) s[0] = 0; 370e5c89e4eSSatish Balay /* see if library was already open then we are done */ 371e5c89e4eSSatish Balay list = prev = *outlist; 372e5c89e4eSSatish Balay match = PETSC_FALSE; 373e5c89e4eSSatish Balay while (list) { 374b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr); 375e5c89e4eSSatish Balay if (match) break; 376e5c89e4eSSatish Balay prev = list; 377e5c89e4eSSatish Balay list = list->next; 378e5c89e4eSSatish Balay } 379b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 380b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 381e5c89e4eSSatish Balay if (!match) { 3825673baf8SLisandro Dalcin /* open the library and add to end of list */ 383b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr); 384b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname);CHKERRQ(ierr); 385e5c89e4eSSatish Balay if (!*outlist) { 386e5c89e4eSSatish Balay *outlist = list; 387e5c89e4eSSatish Balay } else { 388e5c89e4eSSatish Balay prev->next = list; 389e5c89e4eSSatish Balay } 390e5c89e4eSSatish Balay } 391b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 392e5c89e4eSSatish Balay } 393e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 394e5c89e4eSSatish Balay PetscFunctionReturn(0); 395e5c89e4eSSatish Balay } 396e5c89e4eSSatish Balay 397e5c89e4eSSatish Balay #undef __FUNCT__ 398e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrepend" 399e5c89e4eSSatish Balay /*@C 400e5c89e4eSSatish Balay PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of 401e5c89e4eSSatish Balay the search path. 402e5c89e4eSSatish Balay 403e5c89e4eSSatish Balay Collective on MPI_Comm 404e5c89e4eSSatish Balay 405e5c89e4eSSatish Balay Input Parameters: 406e5c89e4eSSatish Balay + comm - MPI communicator 4070f31fb7fSLisandro Dalcin - path - name of the library 408e5c89e4eSSatish Balay 409e5c89e4eSSatish Balay Output Parameter: 410e5c89e4eSSatish Balay . outlist - list of libraries 411e5c89e4eSSatish Balay 412e5c89e4eSSatish Balay Level: developer 413e5c89e4eSSatish Balay 414e5c89e4eSSatish Balay Notes: If library is already in path will remove old reference. 415e5c89e4eSSatish Balay 416e5c89e4eSSatish Balay @*/ 4177087cfbeSBarry Smith PetscErrorCode PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[]) 418e5c89e4eSSatish Balay { 419e5bd5246SBarry Smith PetscDLLibrary list,prev; 420e5c89e4eSSatish Balay PetscErrorCode ierr; 421e5c89e4eSSatish Balay size_t len; 422ace3abfcSBarry Smith PetscBool match,dir; 423b3bb0f5eSLisandro Dalcin char program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN]; 424b3bb0f5eSLisandro Dalcin char *libname,suffix[16],*s; 4255b096c79SMatthew Knepley PetscToken token; 426e5c89e4eSSatish Balay 427e5c89e4eSSatish Balay PetscFunctionBegin; 428b3bb0f5eSLisandro Dalcin PetscValidPointer(outlist,2); 429e5c89e4eSSatish Balay 430b3bb0f5eSLisandro Dalcin /* is path a directory? */ 431b3bb0f5eSLisandro Dalcin ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr); 432e5c89e4eSSatish Balay if (dir) { 433b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr); 434b3bb0f5eSLisandro Dalcin ierr = PetscStrcpy(program,path);CHKERRQ(ierr); 435e5c89e4eSSatish Balay ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 436e5c89e4eSSatish Balay if (program[len-1] == '/') { 437e5c89e4eSSatish Balay ierr = PetscStrcat(program,"*.");CHKERRQ(ierr); 438e5c89e4eSSatish Balay } else { 439e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr); 440e5c89e4eSSatish Balay } 441e5c89e4eSSatish Balay ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr); 442e5c89e4eSSatish Balay 443b3bb0f5eSLisandro Dalcin ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 444e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 445e5c89e4eSSatish Balay } else { 446b3bb0f5eSLisandro Dalcin ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 447e5c89e4eSSatish Balay } 448e5c89e4eSSatish Balay 449e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 450e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 451e5c89e4eSSatish Balay 452e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr); 453b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 454b3bb0f5eSLisandro Dalcin while (libname) { 455b3bb0f5eSLisandro Dalcin /* remove suffix from libname */ 456b3bb0f5eSLisandro Dalcin ierr = PetscStrstr(libname,suffix,&s);CHKERRQ(ierr); 457e5c89e4eSSatish Balay if (s) s[0] = 0; 458e5c89e4eSSatish Balay /* see if library was already open and move it to the front */ 459e5c89e4eSSatish Balay prev = 0; 460b3bb0f5eSLisandro Dalcin list = *outlist; 461e5c89e4eSSatish Balay match = PETSC_FALSE; 462e5c89e4eSSatish Balay while (list) { 463b3bb0f5eSLisandro Dalcin ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr); 464e5c89e4eSSatish Balay if (match) { 465b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Moving %s to begin of dynamic library search path\n",libname);CHKERRQ(ierr); 466e5c89e4eSSatish Balay if (prev) prev->next = list->next; 467b3bb0f5eSLisandro Dalcin if (prev) list->next = *outlist; 468e5c89e4eSSatish Balay *outlist = list; 469e5c89e4eSSatish Balay break; 470e5c89e4eSSatish Balay } 471e5c89e4eSSatish Balay prev = list; 472e5c89e4eSSatish Balay list = list->next; 473e5c89e4eSSatish Balay } 474b3bb0f5eSLisandro Dalcin /* restore suffix from libname */ 475b3bb0f5eSLisandro Dalcin if (s) s[0] = '.'; 476e5c89e4eSSatish Balay if (!match) { 4775673baf8SLisandro Dalcin /* open the library and add to front of list */ 478b3bb0f5eSLisandro Dalcin ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr); 479b3bb0f5eSLisandro Dalcin ierr = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname);CHKERRQ(ierr); 480ebd79076SLisandro Dalcin list->next = *outlist; 481e5c89e4eSSatish Balay *outlist = list; 482e5c89e4eSSatish Balay } 483b3bb0f5eSLisandro Dalcin ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr); 484e5c89e4eSSatish Balay } 485e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token);CHKERRQ(ierr); 486e5c89e4eSSatish Balay PetscFunctionReturn(0); 487e5c89e4eSSatish Balay } 488e5c89e4eSSatish Balay 489e5c89e4eSSatish Balay #undef __FUNCT__ 490e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryClose" 491e5c89e4eSSatish Balay /*@C 492e5c89e4eSSatish Balay PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries. 493e5c89e4eSSatish Balay 494e5c89e4eSSatish Balay Collective on PetscDLLibrary 495e5c89e4eSSatish Balay 496e5c89e4eSSatish Balay Input Parameter: 4973fa76a5bSLisandro Dalcin . head - library list 498e5c89e4eSSatish Balay 499e5c89e4eSSatish Balay Level: developer 500e5c89e4eSSatish Balay 501e5c89e4eSSatish Balay @*/ 5027087cfbeSBarry Smith PetscErrorCode PetscDLLibraryClose(PetscDLLibrary list) 503e5c89e4eSSatish Balay { 504ace3abfcSBarry Smith PetscBool done = PETSC_FALSE; 5050f31fb7fSLisandro Dalcin PetscDLLibrary prev,tail; 506e5c89e4eSSatish Balay PetscErrorCode ierr; 507e5c89e4eSSatish Balay 508e5c89e4eSSatish Balay PetscFunctionBegin; 5090f31fb7fSLisandro Dalcin if (!list) PetscFunctionReturn(0); 5103fa76a5bSLisandro Dalcin /* traverse the list in reverse order */ 5113fa76a5bSLisandro Dalcin while (!done) { 5120f31fb7fSLisandro Dalcin if (!list->next) done = PETSC_TRUE; 5130f31fb7fSLisandro Dalcin prev = tail = list; 5143fa76a5bSLisandro Dalcin while (tail->next) { 5153fa76a5bSLisandro Dalcin prev = tail; 5163fa76a5bSLisandro Dalcin tail = tail->next; 517e5c89e4eSSatish Balay } 5183fa76a5bSLisandro Dalcin prev->next = 0; 5193fa76a5bSLisandro Dalcin /* close the dynamic library and free the space in entry data-structure*/ 5203fa76a5bSLisandro Dalcin ierr = PetscInfo1(0,"Closing dynamic library %s\n",tail->libname);CHKERRQ(ierr); 5213fa76a5bSLisandro Dalcin ierr = PetscDLClose(&tail->handle);CHKERRQ(ierr); 5223fa76a5bSLisandro Dalcin ierr = PetscFree(tail);CHKERRQ(ierr); 5233fa76a5bSLisandro Dalcin }; 524e5c89e4eSSatish Balay PetscFunctionReturn(0); 525e5c89e4eSSatish Balay } 526e5c89e4eSSatish Balay 5273fa76a5bSLisandro Dalcin /* ------------------------------------------------------------------------------*/ 5283fa76a5bSLisandro Dalcin 5293fa76a5bSLisandro Dalcin /* 5303fa76a5bSLisandro Dalcin Contains the list of registered CCA components 5313fa76a5bSLisandro Dalcin */ 5323fa76a5bSLisandro Dalcin PetscFList CCAList = 0; 5333fa76a5bSLisandro Dalcin 534e5c89e4eSSatish Balay #undef __FUNCT__ 535e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryCCAAppend" 536e5c89e4eSSatish Balay /*@C 537e5c89e4eSSatish Balay PetscDLLibraryCCAAppend - Appends another CCA dynamic link library to the seach list, to the end 538e5c89e4eSSatish Balay of the search path. 539e5c89e4eSSatish Balay 540e5c89e4eSSatish Balay Collective on MPI_Comm 541e5c89e4eSSatish Balay 542e5c89e4eSSatish Balay Input Parameters: 543e5c89e4eSSatish Balay + comm - MPI communicator 5440f31fb7fSLisandro Dalcin - dirname - name of directory to check 545e5c89e4eSSatish Balay 546e5c89e4eSSatish Balay Output Parameter: 547e5c89e4eSSatish Balay . outlist - list of libraries 548e5c89e4eSSatish Balay 549e5c89e4eSSatish Balay Level: developer 550e5c89e4eSSatish Balay 551e5c89e4eSSatish Balay Notes: if library is already in path will not add it. 552e5c89e4eSSatish Balay @*/ 5537087cfbeSBarry Smith PetscErrorCode PetscDLLibraryCCAAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char dirname[]) 554e5c89e4eSSatish Balay { 555e5c89e4eSSatish Balay PetscErrorCode ierr; 556e5c89e4eSSatish Balay size_t l; 557ace3abfcSBarry Smith PetscBool dir; 558e5c89e4eSSatish Balay char program[PETSC_MAX_PATH_LEN],buf[8*PETSC_MAX_PATH_LEN],*libname1,fbuf[PETSC_MAX_PATH_LEN],*found,suffix[16],*f2; 559e5c89e4eSSatish Balay char *func,*funcname,libname[PETSC_MAX_PATH_LEN],*lib; 560e5c89e4eSSatish Balay FILE *fp; 5615b096c79SMatthew Knepley PetscToken token1, token2; 562ed9cf6e9SBarry Smith int err; 563e5c89e4eSSatish Balay 564e5c89e4eSSatish Balay PetscFunctionBegin; 565e5c89e4eSSatish Balay /* is dirname a directory? */ 566e5c89e4eSSatish Balay ierr = PetscTestDirectory(dirname,'r',&dir);CHKERRQ(ierr); 567e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 568e5c89e4eSSatish Balay 569ae15b995SBarry Smith ierr = PetscInfo1(0,"Checking directory %s for CCA components\n",dirname);CHKERRQ(ierr); 570e5c89e4eSSatish Balay ierr = PetscStrcpy(program,dirname);CHKERRQ(ierr); 571e5c89e4eSSatish Balay ierr = PetscStrcat(program,"/*.cca");CHKERRQ(ierr); 572e5c89e4eSSatish Balay 573e5c89e4eSSatish Balay ierr = PetscLs(comm,program,buf,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr); 574e5c89e4eSSatish Balay if (!dir) PetscFunctionReturn(0); 575e5c89e4eSSatish Balay 576e5c89e4eSSatish Balay ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr); 577e5c89e4eSSatish Balay ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr); 578e5c89e4eSSatish Balay ierr = PetscTokenCreate(buf,'\n',&token1);CHKERRQ(ierr); 579e5c89e4eSSatish Balay ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 580e5c89e4eSSatish Balay while (libname1) { 581e5c89e4eSSatish Balay fp = fopen(libname1,"r"); if (!fp) continue; 582e5c89e4eSSatish Balay while ((found = fgets(fbuf,PETSC_MAX_PATH_LEN,fp))) { 583e5c89e4eSSatish Balay if (found[0] == '!') continue; 584e5c89e4eSSatish Balay ierr = PetscStrstr(found,suffix,&f2);CHKERRQ(ierr); 585e5c89e4eSSatish Balay if (f2) { /* found library name */ 586e5c89e4eSSatish Balay if (found[0] == '/') { 587e5c89e4eSSatish Balay lib = found; 588e5c89e4eSSatish Balay } else { 589e5c89e4eSSatish Balay ierr = PetscStrcpy(libname,dirname);CHKERRQ(ierr); 590e5c89e4eSSatish Balay ierr = PetscStrlen(libname,&l);CHKERRQ(ierr); 591e5c89e4eSSatish Balay if (libname[l-1] != '/') {ierr = PetscStrcat(libname,"/");CHKERRQ(ierr);} 592e5c89e4eSSatish Balay ierr = PetscStrcat(libname,found);CHKERRQ(ierr); 593e5c89e4eSSatish Balay lib = libname; 594e5c89e4eSSatish Balay } 595e5c89e4eSSatish Balay ierr = PetscDLLibraryAppend(comm,outlist,lib);CHKERRQ(ierr); 596e5c89e4eSSatish Balay } else { 597ae15b995SBarry Smith ierr = PetscInfo2(0,"CCA Component function and name: %s from %s\n",found,libname1);CHKERRQ(ierr); 598e5c89e4eSSatish Balay ierr = PetscTokenCreate(found,' ',&token2);CHKERRQ(ierr); 599e5c89e4eSSatish Balay ierr = PetscTokenFind(token2,&func);CHKERRQ(ierr); 600e5c89e4eSSatish Balay ierr = PetscTokenFind(token2,&funcname);CHKERRQ(ierr); 601e5c89e4eSSatish Balay ierr = PetscFListAdd(&CCAList,funcname,func,PETSC_NULL);CHKERRQ(ierr); 602e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token2);CHKERRQ(ierr); 603e5c89e4eSSatish Balay } 604e5c89e4eSSatish Balay } 605ed9cf6e9SBarry Smith err = fclose(fp); 606e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 607e5c89e4eSSatish Balay ierr = PetscTokenFind(token1,&libname1);CHKERRQ(ierr); 608e5c89e4eSSatish Balay } 609e5c89e4eSSatish Balay ierr = PetscTokenDestroy(token1);CHKERRQ(ierr); 610e5c89e4eSSatish Balay PetscFunctionReturn(0); 611e5c89e4eSSatish Balay } 612