xref: /petsc/src/sys/dll/dl.c (revision b00a91154f763f12aa55f3d53a3f2776f15f49e3)
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 
6afcb2eb5SJed Brown #include <petsc-private/petscimpl.h>
7e5c89e4eSSatish Balay 
8e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
9e5c89e4eSSatish Balay /*
10e5c89e4eSSatish Balay       Code to maintain a list of opened dynamic libraries and load symbols
11e5c89e4eSSatish Balay */
12e5bd5246SBarry Smith struct _n_PetscDLLibrary {
13e5bd5246SBarry Smith   PetscDLLibrary next;
14ebd79076SLisandro Dalcin   PetscDLHandle  handle;
15e5c89e4eSSatish Balay   char           libname[PETSC_MAX_PATH_LEN];
16e5c89e4eSSatish Balay };
17e5c89e4eSSatish Balay 
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);
68785e854fSJed Brown   ierr = PetscMalloc1(len,&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);
848ce0dc28SMatthew 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;
138607a6623SBarry Smith   PetscErrorCode (*func)(void) = NULL;
139e5c89e4eSSatish Balay   size_t         len;
140e5c89e4eSSatish Balay 
141e5c89e4eSSatish Balay   PetscFunctionBegin;
14282a51d08SSatish Balay   PetscValidCharPointer(path,2);
1435673baf8SLisandro Dalcin   PetscValidPointer(entry,3);
144ebd79076SLisandro Dalcin 
1450298fd71SBarry Smith   *entry = 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);
179a297a907SKarl Rupp   if (match) basename = basename + 3;
180a297a907SKarl Rupp   else {
181bb84e0fdSBarry Smith     ierr = PetscInfo1(0,"Dynamic library %s does not have lib prefix\n",libname);CHKERRQ(ierr);
182e5c89e4eSSatish Balay   }
183cf4b33a9SJed Brown   for (s=basename; *s; s++) if (*s == '-') *s = '_';
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);
190607a6623SBarry Smith     ierr = (*func)();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 
195*b00a9115SJed Brown   ierr = PetscNew(entry);CHKERRQ(ierr);
1965673baf8SLisandro Dalcin   (*entry)->next   = 0;
197b3bb0f5eSLisandro Dalcin   (*entry)->handle = handle;
198b3bb0f5eSLisandro Dalcin   ierr = PetscStrcpy((*entry)->libname,libname);CHKERRQ(ierr);
199e5c89e4eSSatish Balay   PetscFunctionReturn(0);
200e5c89e4eSSatish Balay }
201e5c89e4eSSatish Balay 
202e5c89e4eSSatish Balay #undef __FUNCT__
203e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibrarySym"
204e5c89e4eSSatish Balay /*@C
205e5c89e4eSSatish Balay    PetscDLLibrarySym - Load a symbol from the dynamic link libraries.
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay    Collective on MPI_Comm
208e5c89e4eSSatish Balay 
209e5c89e4eSSatish Balay    Input Parameter:
210e5bd5246SBarry Smith +  comm - communicator that will open the library
2110298fd71SBarry Smith .  outlist - list of already open libraries that may contain symbol (can be NULL and only the executable is searched for the function)
21230a1dd1fSBarry Smith .  path     - optional complete library name (if provided checks here before checking outlist)
213e5c89e4eSSatish Balay -  insymbol - name of symbol
214e5c89e4eSSatish Balay 
215e5c89e4eSSatish Balay    Output Parameter:
2160298fd71SBarry Smith .  value - if symbol not found then this value is set to NULL
217e5c89e4eSSatish Balay 
218e5c89e4eSSatish Balay    Level: developer
219e5c89e4eSSatish Balay 
220e5c89e4eSSatish Balay    Notes: Symbol can be of the form
221e5c89e4eSSatish Balay         [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional
222e5c89e4eSSatish Balay 
223e5c89e4eSSatish Balay         Will attempt to (retrieve and) open the library if it is not yet been opened.
224e5c89e4eSSatish Balay 
225e5c89e4eSSatish Balay @*/
2267087cfbeSBarry Smith PetscErrorCode  PetscDLLibrarySym(MPI_Comm comm,PetscDLLibrary *outlist,const char path[],const char insymbol[],void **value)
227e5c89e4eSSatish Balay {
228b3bb0f5eSLisandro Dalcin   char           libname[PETSC_MAX_PATH_LEN],suffix[16],*symbol,*s;
2290298fd71SBarry Smith   PetscDLLibrary nlist,prev,list = NULL;
230b3bb0f5eSLisandro Dalcin   PetscErrorCode ierr;
231e5c89e4eSSatish Balay 
232e5c89e4eSSatish Balay   PetscFunctionBegin;
233340b11eeSBarry Smith   if (outlist) PetscValidPointer(outlist,2);
2345673baf8SLisandro Dalcin   if (path) PetscValidCharPointer(path,3);
2355673baf8SLisandro Dalcin   PetscValidCharPointer(insymbol,4);
2365673baf8SLisandro Dalcin   PetscValidPointer(value,5);
2375673baf8SLisandro Dalcin 
238340b11eeSBarry Smith   if (outlist) list = *outlist;
239e5c89e4eSSatish Balay   *value = 0;
240e5c89e4eSSatish Balay 
2412d53ad75SBarry Smith 
2422d53ad75SBarry Smith   ierr = PetscStrchr(insymbol,'(',&s);CHKERRQ(ierr);
2432d53ad75SBarry Smith   if (s) {
244e5c89e4eSSatish Balay     /* make copy of symbol so we can edit it in place */
2452d53ad75SBarry Smith     ierr = PetscStrallocpy(insymbol,&symbol);CHKERRQ(ierr);
246b3bb0f5eSLisandro Dalcin     /* If symbol contains () then replace with a NULL, to support functionname() */
247b3bb0f5eSLisandro Dalcin     ierr = PetscStrchr(symbol,'(',&s);CHKERRQ(ierr);
2482d53ad75SBarry Smith     s[0] = 0;
249a297a907SKarl Rupp   } else symbol = (char*)insymbol;
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay   /*
252e5c89e4eSSatish Balay        Function name does include library
253e5c89e4eSSatish Balay        -------------------------------------
254e5c89e4eSSatish Balay   */
255e5c89e4eSSatish Balay   if (path && path[0] != '\0') {
256b3bb0f5eSLisandro Dalcin     /* copy path and remove suffix from libname */
257b3bb0f5eSLisandro Dalcin     ierr = PetscStrncpy(libname,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
258b3bb0f5eSLisandro Dalcin     ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
259b3bb0f5eSLisandro Dalcin     ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
260b3bb0f5eSLisandro Dalcin     ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr);
261b3bb0f5eSLisandro Dalcin     if (s) s[0] = 0;
2625673baf8SLisandro Dalcin     /* Look if library is already opened and in path */
263e5c89e4eSSatish Balay     prev  = 0;
264b3bb0f5eSLisandro Dalcin     nlist = list;
265e5c89e4eSSatish Balay     while (nlist) {
266ace3abfcSBarry Smith       PetscBool match;
267b3bb0f5eSLisandro Dalcin       ierr = PetscStrcmp(nlist->libname,libname,&match);CHKERRQ(ierr);
2685673baf8SLisandro Dalcin       if (match) goto done;
269e5c89e4eSSatish Balay       prev  = nlist;
270e5c89e4eSSatish Balay       nlist = nlist->next;
271e5c89e4eSSatish Balay     }
272b3bb0f5eSLisandro Dalcin     /* open the library and append it to path */
2735673baf8SLisandro Dalcin     ierr = PetscDLLibraryOpen(comm,path,&nlist);CHKERRQ(ierr);
274ae15b995SBarry Smith     ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",path);CHKERRQ(ierr);
275a297a907SKarl Rupp     if (prev) prev->next = nlist;
276a297a907SKarl Rupp     else      *outlist   = nlist;
277e5c89e4eSSatish Balay 
278e5c89e4eSSatish Balay done:;
2795673baf8SLisandro Dalcin     ierr = PetscDLSym(nlist->handle,symbol,value);CHKERRQ(ierr);
28030a1dd1fSBarry Smith     if (*value) {
281ae15b995SBarry Smith       ierr = PetscInfo2(0,"Loading function %s from dynamic library %s\n",insymbol,path);CHKERRQ(ierr);
28230a1dd1fSBarry Smith     }
283e5c89e4eSSatish Balay 
284e5c89e4eSSatish Balay     /*
285e5c89e4eSSatish Balay          Function name does not include library so search path
286e5c89e4eSSatish Balay          -----------------------------------------------------
287e5c89e4eSSatish Balay     */
288e5c89e4eSSatish Balay   } else {
289e5c89e4eSSatish Balay     while (list) {
290ebd79076SLisandro Dalcin       ierr = PetscDLSym(list->handle,symbol,value);CHKERRQ(ierr);
291e5c89e4eSSatish Balay       if (*value) {
292b3bb0f5eSLisandro Dalcin         ierr = PetscInfo2(0,"Loading symbol %s from dynamic library %s\n",symbol,list->libname);CHKERRQ(ierr);
293e5c89e4eSSatish Balay         break;
294e5c89e4eSSatish Balay       }
295e5c89e4eSSatish Balay       list = list->next;
296e5c89e4eSSatish Balay     }
297e5c89e4eSSatish Balay     if (!*value) {
2980298fd71SBarry Smith       ierr = PetscDLSym(NULL,symbol,value);CHKERRQ(ierr);
299e5c89e4eSSatish Balay       if (*value) {
300b3bb0f5eSLisandro Dalcin         ierr = PetscInfo1(0,"Loading symbol %s from object code\n",symbol);CHKERRQ(ierr);
301e5c89e4eSSatish Balay       }
302e5c89e4eSSatish Balay     }
303e5c89e4eSSatish Balay   }
304e5c89e4eSSatish Balay 
3052d53ad75SBarry Smith   if (symbol != insymbol) {
306e5c89e4eSSatish Balay     ierr = PetscFree(symbol);CHKERRQ(ierr);
3072d53ad75SBarry Smith   }
308e5c89e4eSSatish Balay   PetscFunctionReturn(0);
309e5c89e4eSSatish Balay }
310e5c89e4eSSatish Balay 
311e5c89e4eSSatish Balay #undef __FUNCT__
312e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryAppend"
313e5c89e4eSSatish Balay /*@C
314e5c89e4eSSatish Balay      PetscDLLibraryAppend - Appends another dynamic link library to the seach list, to the end
315e5c89e4eSSatish Balay                 of the search path.
316e5c89e4eSSatish Balay 
317e5c89e4eSSatish Balay      Collective on MPI_Comm
318e5c89e4eSSatish Balay 
319e5c89e4eSSatish Balay      Input Parameters:
320e5c89e4eSSatish Balay +     comm - MPI communicator
3210f31fb7fSLisandro Dalcin -     path - name of the library
322e5c89e4eSSatish Balay 
323e5c89e4eSSatish Balay      Output Parameter:
324e5c89e4eSSatish Balay .     outlist - list of libraries
325e5c89e4eSSatish Balay 
326e5c89e4eSSatish Balay      Level: developer
327e5c89e4eSSatish Balay 
328e5c89e4eSSatish Balay      Notes: if library is already in path will not add it.
329bb84e0fdSBarry Smith 
330bb84e0fdSBarry Smith   If the library has the symbol PetscDLLibraryRegister_basename() in it then that function is automatically run
331bb84e0fdSBarry Smith       when the library is opened.
332bb84e0fdSBarry Smith 
333bb84e0fdSBarry Smith .seealso: PetscDLLibraryOpen()
334e5c89e4eSSatish Balay @*/
3357087cfbeSBarry Smith PetscErrorCode  PetscDLLibraryAppend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[])
336e5c89e4eSSatish Balay {
337e5bd5246SBarry Smith   PetscDLLibrary list,prev;
338e5c89e4eSSatish Balay   PetscErrorCode ierr;
339e5c89e4eSSatish Balay   size_t         len;
340ace3abfcSBarry Smith   PetscBool      match,dir;
341b3bb0f5eSLisandro Dalcin   char           program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN];
342b3bb0f5eSLisandro Dalcin   char           *libname,suffix[16],*s;
3439c9d3cfdSBarry Smith   PetscToken     token;
344e5c89e4eSSatish Balay 
345e5c89e4eSSatish Balay   PetscFunctionBegin;
346b3bb0f5eSLisandro Dalcin   PetscValidPointer(outlist,2);
347e5c89e4eSSatish Balay 
348b3bb0f5eSLisandro Dalcin   /* is path a directory? */
349b3bb0f5eSLisandro Dalcin   ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr);
350e5c89e4eSSatish Balay   if (dir) {
351b3bb0f5eSLisandro Dalcin     ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr);
352b3bb0f5eSLisandro Dalcin     ierr = PetscStrcpy(program,path);CHKERRQ(ierr);
353e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
354e5c89e4eSSatish Balay     if (program[len-1] == '/') {
355e5c89e4eSSatish Balay       ierr = PetscStrcat(program,"*.");CHKERRQ(ierr);
356e5c89e4eSSatish Balay     } else {
357e5c89e4eSSatish Balay       ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr);
358e5c89e4eSSatish Balay     }
359e5c89e4eSSatish Balay     ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr);
360e5c89e4eSSatish Balay 
361b3bb0f5eSLisandro Dalcin     ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
362e5c89e4eSSatish Balay     if (!dir) PetscFunctionReturn(0);
363e5c89e4eSSatish Balay   } else {
364b3bb0f5eSLisandro Dalcin     ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
365e5c89e4eSSatish Balay   }
366e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
367e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
368e5c89e4eSSatish Balay 
369e5c89e4eSSatish Balay   ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr);
370b3bb0f5eSLisandro Dalcin   ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
371b3bb0f5eSLisandro Dalcin   while (libname) {
372b3bb0f5eSLisandro Dalcin     /* remove suffix from libname */
373b3bb0f5eSLisandro Dalcin     ierr = PetscStrrstr(libname,suffix,&s);CHKERRQ(ierr);
374e5c89e4eSSatish Balay     if (s) s[0] = 0;
375e5c89e4eSSatish Balay     /* see if library was already open then we are done */
376e5c89e4eSSatish Balay     list  = prev = *outlist;
377e5c89e4eSSatish Balay     match = PETSC_FALSE;
378e5c89e4eSSatish Balay     while (list) {
379b3bb0f5eSLisandro Dalcin       ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr);
380e5c89e4eSSatish Balay       if (match) break;
381e5c89e4eSSatish Balay       prev = list;
382e5c89e4eSSatish Balay       list = list->next;
383e5c89e4eSSatish Balay     }
384b3bb0f5eSLisandro Dalcin     /* restore suffix from libname */
385b3bb0f5eSLisandro Dalcin     if (s) s[0] = '.';
386e5c89e4eSSatish Balay     if (!match) {
3875673baf8SLisandro Dalcin       /* open the library and add to end of list */
388b3bb0f5eSLisandro Dalcin       ierr = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr);
389b3bb0f5eSLisandro Dalcin       ierr = PetscInfo1(0,"Appending %s to dynamic library search path\n",libname);CHKERRQ(ierr);
390a297a907SKarl Rupp       if (!*outlist) *outlist   = list;
391a297a907SKarl Rupp       else           prev->next = list;
392e5c89e4eSSatish Balay     }
393b3bb0f5eSLisandro Dalcin     ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
394e5c89e4eSSatish Balay   }
3958c74ee41SBarry Smith   ierr = PetscTokenDestroy(&token);CHKERRQ(ierr);
396e5c89e4eSSatish Balay   PetscFunctionReturn(0);
397e5c89e4eSSatish Balay }
398e5c89e4eSSatish Balay 
399e5c89e4eSSatish Balay #undef __FUNCT__
400e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryPrepend"
401e5c89e4eSSatish Balay /*@C
402e5c89e4eSSatish Balay      PetscDLLibraryPrepend - Add another dynamic library to search for symbols to the beginning of
403e5c89e4eSSatish Balay                  the search path.
404e5c89e4eSSatish Balay 
405e5c89e4eSSatish Balay      Collective on MPI_Comm
406e5c89e4eSSatish Balay 
407e5c89e4eSSatish Balay      Input Parameters:
408e5c89e4eSSatish Balay +     comm - MPI communicator
4090f31fb7fSLisandro Dalcin -     path - name of the library
410e5c89e4eSSatish Balay 
411e5c89e4eSSatish Balay      Output Parameter:
412e5c89e4eSSatish Balay .     outlist - list of libraries
413e5c89e4eSSatish Balay 
414e5c89e4eSSatish Balay      Level: developer
415e5c89e4eSSatish Balay 
416e5c89e4eSSatish Balay      Notes: If library is already in path will remove old reference.
417e5c89e4eSSatish Balay 
418e5c89e4eSSatish Balay @*/
4197087cfbeSBarry Smith PetscErrorCode  PetscDLLibraryPrepend(MPI_Comm comm,PetscDLLibrary *outlist,const char path[])
420e5c89e4eSSatish Balay {
421e5bd5246SBarry Smith   PetscDLLibrary list,prev;
422e5c89e4eSSatish Balay   PetscErrorCode ierr;
423e5c89e4eSSatish Balay   size_t         len;
424ace3abfcSBarry Smith   PetscBool      match,dir;
425b3bb0f5eSLisandro Dalcin   char           program[PETSC_MAX_PATH_LEN],found[8*PETSC_MAX_PATH_LEN];
426b3bb0f5eSLisandro Dalcin   char           *libname,suffix[16],*s;
4275b096c79SMatthew Knepley   PetscToken     token;
428e5c89e4eSSatish Balay 
429e5c89e4eSSatish Balay   PetscFunctionBegin;
430b3bb0f5eSLisandro Dalcin   PetscValidPointer(outlist,2);
431e5c89e4eSSatish Balay 
432b3bb0f5eSLisandro Dalcin   /* is path a directory? */
433b3bb0f5eSLisandro Dalcin   ierr = PetscTestDirectory(path,'r',&dir);CHKERRQ(ierr);
434e5c89e4eSSatish Balay   if (dir) {
435b3bb0f5eSLisandro Dalcin     ierr = PetscInfo1(0,"Checking directory %s for dynamic libraries\n",path);CHKERRQ(ierr);
436b3bb0f5eSLisandro Dalcin     ierr = PetscStrcpy(program,path);CHKERRQ(ierr);
437e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
438e5c89e4eSSatish Balay     if (program[len-1] == '/') {
439e5c89e4eSSatish Balay       ierr = PetscStrcat(program,"*.");CHKERRQ(ierr);
440e5c89e4eSSatish Balay     } else {
441e5c89e4eSSatish Balay       ierr = PetscStrcat(program,"/*.");CHKERRQ(ierr);
442e5c89e4eSSatish Balay     }
443e5c89e4eSSatish Balay     ierr = PetscStrcat(program,PETSC_SLSUFFIX);CHKERRQ(ierr);
444e5c89e4eSSatish Balay 
445b3bb0f5eSLisandro Dalcin     ierr = PetscLs(comm,program,found,8*PETSC_MAX_PATH_LEN,&dir);CHKERRQ(ierr);
446e5c89e4eSSatish Balay     if (!dir) PetscFunctionReturn(0);
447e5c89e4eSSatish Balay   } else {
448b3bb0f5eSLisandro Dalcin     ierr = PetscStrncpy(found,path,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
449e5c89e4eSSatish Balay   }
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay   ierr = PetscStrcpy(suffix,".");CHKERRQ(ierr);
452e5c89e4eSSatish Balay   ierr = PetscStrcat(suffix,PETSC_SLSUFFIX);CHKERRQ(ierr);
453e5c89e4eSSatish Balay 
454e5c89e4eSSatish Balay   ierr = PetscTokenCreate(found,'\n',&token);CHKERRQ(ierr);
455b3bb0f5eSLisandro Dalcin   ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
456b3bb0f5eSLisandro Dalcin   while (libname) {
457b3bb0f5eSLisandro Dalcin     /* remove suffix from libname */
458b3bb0f5eSLisandro Dalcin     ierr = PetscStrstr(libname,suffix,&s);CHKERRQ(ierr);
459e5c89e4eSSatish Balay     if (s) s[0] = 0;
460e5c89e4eSSatish Balay     /* see if library was already open and move it to the front */
461e5c89e4eSSatish Balay     prev  = 0;
462b3bb0f5eSLisandro Dalcin     list  = *outlist;
463e5c89e4eSSatish Balay     match = PETSC_FALSE;
464e5c89e4eSSatish Balay     while (list) {
465b3bb0f5eSLisandro Dalcin       ierr = PetscStrcmp(list->libname,libname,&match);CHKERRQ(ierr);
466e5c89e4eSSatish Balay       if (match) {
467b3bb0f5eSLisandro Dalcin         ierr = PetscInfo1(0,"Moving %s to begin of dynamic library search path\n",libname);CHKERRQ(ierr);
468e5c89e4eSSatish Balay         if (prev) prev->next = list->next;
469b3bb0f5eSLisandro Dalcin         if (prev) list->next = *outlist;
470e5c89e4eSSatish Balay         *outlist = list;
471e5c89e4eSSatish Balay         break;
472e5c89e4eSSatish Balay       }
473e5c89e4eSSatish Balay       prev = list;
474e5c89e4eSSatish Balay       list = list->next;
475e5c89e4eSSatish Balay     }
476b3bb0f5eSLisandro Dalcin     /* restore suffix from libname */
477b3bb0f5eSLisandro Dalcin     if (s) s[0] = '.';
478e5c89e4eSSatish Balay     if (!match) {
4795673baf8SLisandro Dalcin       /* open the library and add to front of list */
480b3bb0f5eSLisandro Dalcin       ierr       = PetscDLLibraryOpen(comm,libname,&list);CHKERRQ(ierr);
481b3bb0f5eSLisandro Dalcin       ierr       = PetscInfo1(0,"Prepending %s to dynamic library search path\n",libname);CHKERRQ(ierr);
482ebd79076SLisandro Dalcin       list->next = *outlist;
483e5c89e4eSSatish Balay       *outlist   = list;
484e5c89e4eSSatish Balay     }
485b3bb0f5eSLisandro Dalcin     ierr = PetscTokenFind(token,&libname);CHKERRQ(ierr);
486e5c89e4eSSatish Balay   }
4878c74ee41SBarry Smith   ierr = PetscTokenDestroy(&token);CHKERRQ(ierr);
488e5c89e4eSSatish Balay   PetscFunctionReturn(0);
489e5c89e4eSSatish Balay }
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay #undef __FUNCT__
492e5c89e4eSSatish Balay #define __FUNCT__ "PetscDLLibraryClose"
493e5c89e4eSSatish Balay /*@C
494e5c89e4eSSatish Balay      PetscDLLibraryClose - Destroys the search path of dynamic libraries and closes the libraries.
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay     Collective on PetscDLLibrary
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay     Input Parameter:
4993fa76a5bSLisandro Dalcin .     head - library list
500e5c89e4eSSatish Balay 
501e5c89e4eSSatish Balay      Level: developer
502e5c89e4eSSatish Balay 
503e5c89e4eSSatish Balay @*/
5047087cfbeSBarry Smith PetscErrorCode  PetscDLLibraryClose(PetscDLLibrary list)
505e5c89e4eSSatish Balay {
506ace3abfcSBarry Smith   PetscBool      done = PETSC_FALSE;
5070f31fb7fSLisandro Dalcin   PetscDLLibrary prev,tail;
508e5c89e4eSSatish Balay   PetscErrorCode ierr;
509e5c89e4eSSatish Balay 
510e5c89e4eSSatish Balay   PetscFunctionBegin;
5110f31fb7fSLisandro Dalcin   if (!list) PetscFunctionReturn(0);
5123fa76a5bSLisandro Dalcin   /* traverse the list in reverse order */
5133fa76a5bSLisandro Dalcin   while (!done) {
5140f31fb7fSLisandro Dalcin     if (!list->next) done = PETSC_TRUE;
5150f31fb7fSLisandro Dalcin     prev = tail = list;
5163fa76a5bSLisandro Dalcin     while (tail->next) {
5173fa76a5bSLisandro Dalcin       prev = tail;
5183fa76a5bSLisandro Dalcin       tail = tail->next;
519e5c89e4eSSatish Balay     }
5203fa76a5bSLisandro Dalcin     prev->next = 0;
5213fa76a5bSLisandro Dalcin     /* close the dynamic library and free the space in entry data-structure*/
5223fa76a5bSLisandro Dalcin     ierr = PetscInfo1(0,"Closing dynamic library %s\n",tail->libname);CHKERRQ(ierr);
5233fa76a5bSLisandro Dalcin     ierr = PetscDLClose(&tail->handle);CHKERRQ(ierr);
5243fa76a5bSLisandro Dalcin     ierr = PetscFree(tail);CHKERRQ(ierr);
525a297a907SKarl Rupp   }
526e5c89e4eSSatish Balay   PetscFunctionReturn(0);
527e5c89e4eSSatish Balay }
528e5c89e4eSSatish Balay 
529