xref: /petsc/src/sys/dll/dl.c (revision b3bb0f5ecefb682ae1a0272025cbe5bfbdb38d92)
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