clsql_uffi loading patch

"Nathan Bird" <[email protected]> Fri, 7 Apr 2006 18:55:56 -0400
Newsgroups gmane.lisp.clsql.devel
Message-ID <[email protected]>
I was trying to get this running on windows and ran into a small bug. The
relative pathname calculation wasn't taking into account the :device, and
the *default-pathname-defaults* is a different device since the files are on
D: and the Lisp is on C: (grr)


Here is a patch to fix that, as well as trying to clean up the loading code
a little bit. Where to search was being calculated in several different ways
and I think this is a bit more straightforward (and possibly even more
efficient).

The biggest change along those lines is to the find-and-load-foreign-library
function. It is searching in every location given by the cross-join of type,
name, and search path. Before it was partially computing this result and
then looping over the rest of the cross join. I have now collapsed this into
one loop structure that I think is cleaner, in doing so I changed the search
order slightly:

  ;;the (effective) search order before i started was
  ;;foreach type ->
  ;;  foreach search-path
  ;;	  foreach filename (ie "/path/filename.type")
  ;;  foreach filename (ie "filename.type")
  ;;i'm not sure if this order matters, but I tried to preserve it.

  ;; it is a bit nicer if we were to instead change to
  ;;foreach type ->
  ;;  foreach filename 
  ;;    foreach search-path (ie "/path/filename.type")
  ;;	  test filname by itself (ie "filename.type")

I don't think that searching for each filename in a given directory before
checking for that filename without any directory is a big deal but I only
have a small subset of the systems that this runs on to test.

I have tested this with 
* WinXP + ACL7-trial + ODBC
* Debian + SBCL 0.9.10 + ODBC

That at least tests two major operating system and ODBC has different
foreign libraries to load so...

The version of find-and-load-foreign-library in the patch has some extra
comments for alternate methods that you might want to remove if you approve
of this change.

Nathan Bird

_______________________________________________
CLSQL-Devel mailing list
[email protected]
http://lists.b9.com/mailman/listinfo/clsql-devel
uffi-loader.diff (application/octet-stream, 6.5 KB)
Fri Apr  7 17:10:41 Eastern Standard Time 2006  Nathan Bird <[email protected]>
  * CLSQL-uffi-loader improvements
diff -rN -u old-clsql-accel/clsql-uffi.asd new-clsql-accel/clsql-uffi.asd
--- old-clsql-accel/clsql-uffi.asd	2006-04-07 18:22:58.584803500 -0400
+++ new-clsql-accel/clsql-uffi.asd	2006-04-07 18:22:58.600428200 -0400
@@ -21,8 +21,9 @@
 (defpackage clsql-uffi-system (:use #:asdf #:cl))
 (in-package clsql-uffi-system)
 
-(defvar *library-file-dir* (append (pathname-directory *load-truename*)
-				   (list "uffi")))
+(defvar *clsql-uffi-library-dir*
+  (merge-pathnames "uffi/"
+		   (make-pathname :name nil :type nil :defaults *load-truename*)))
 
 (defclass clsql-uffi-source-file (c-source-file)
   ())
@@ -43,7 +44,7 @@
 	      found
 	      (make-pathname :name (component-name c)
 			     :type library-file-type
-			     :directory *library-file-dir*)))))
+			     :defaults *clsql-uffi-library-dir*)))))
 
 (defmethod perform ((o load-op) (c clsql-uffi-source-file))
   nil) ;;; library will be loaded by a loader file
@@ -59,9 +60,7 @@
     (unless (zerop (run-shell-command
 		    #-freebsd "cd ~A; make"
 		    #+freebsd "cd ~A; gmake"
-		    (namestring (make-pathname :name nil
-					       :type nil
-					       :directory *library-file-dir*))))
+		    (namestring *clsql-uffi-library-dir*)))
       (error 'operation-error :component c :operation o))))
 
 (defmethod operation-done-p ((o compile-op) (c clsql-uffi-source-file))
diff -rN -u old-clsql-accel/sql/db-interface.lisp new-clsql-accel/sql/db-interface.lisp
--- old-clsql-accel/sql/db-interface.lisp	2006-04-07 18:22:58.584803500 -0400
+++ new-clsql-accel/sql/db-interface.lisp	2006-04-07 18:22:58.709801100 -0400
@@ -476,4 +476,4 @@
 (defun push-library-path (path)
   "Adds the pathspec PATH \(which should denote a directory) to
 the list *FOREIGN-LIBRARY-SEARCH-PATHS*."
-  (push path *foreign-library-search-paths*))
\ No newline at end of file
+  (pushnew path *foreign-library-search-paths* :test #'equal))
diff -rN -u old-clsql-accel/uffi/clsql-uffi-loader.lisp new-clsql-accel/uffi/clsql-uffi-loader.lisp
--- old-clsql-accel/uffi/clsql-uffi-loader.lisp	2006-04-07 18:22:58.584803500 -0400
+++ new-clsql-accel/uffi/clsql-uffi-loader.lisp	2006-04-07 18:22:58.741050500 -0400
@@ -19,35 +19,60 @@
 (in-package #:clsql-uffi)
 
 (defun find-and-load-foreign-library (filenames &key module supporting-libraries (errorp t))
-  (setq filenames (if (listp filenames) filenames (list filenames))
-        filenames
-          (append
-           (loop for search-path in clsql:*foreign-library-search-paths*
-                 nconc (loop for filename in filenames
-                             collect (merge-pathnames filename search-path)))
-           filenames))
-  (or (loop for type in (uffi:foreign-library-types)
-            for suffix = (make-pathname :type type)
-            thereis (loop for filename in filenames
-                          thereis (handler-case
-                                    (uffi:load-foreign-library (merge-pathnames filename suffix)
-                                                               :module module
-                                                               :supporting-libraries supporting-libraries)
-                                    (error (c)
-                                      (warn "~A" c)
-                                      nil))))
-      (when errorp
-	(error "Couldn't load foreign librar~@P ~{~S~^, ~}. (searched ~S)"
-               (length filenames) filenames
-	       'clsql:*foreign-library-search-paths*))))
+  "Attempt to load a foreign library. This will search for any of the filenames, as
+well as any of the filenames in any of the clsql:*foreign-library-search-paths*"
+  (setq filenames (if (listp filenames) filenames (list filenames)))
+  
+  ;;the search order before i started was
+  ;;foreach type ->
+  ;;  foreach search-path
+  ;;	foreach filename (ie "/path/filename.type")
+  ;;  foreach filename (ie "filename.type")
+  ;;i'm not sure if this order matters, but I tried to preserve it.
+
+  ;; it is a bit nicer if we were to instead change to
+  ;;foreach type ->
+  ;;  foreach filename 
+  ;;    foreach search-path (ie "/path/filename.type")
+  ;;	test filname by itself (ie "filename.type")
+
+  ;;the other thought i had was to move all of this to a seperate function
+  (flet ((try-load (testpath)
+	   (handler-case
+	       (uffi:load-foreign-library testpath
+					  :module module
+					  :supporting-libraries supporting-libraries)
+	     (error (c) (warn "~A" c) nil))))
+    (or
+     #| this is the same search order as the original.
+     (loop for type in (uffi:foreign-library-types)
+	      thereis (or
+		       (loop for search-path in clsql:*foreign-library-search-paths*
+			     thereis (loop for name in filenames
+					   thereis (try-load
+						    (make-pathname :name name
+								   :type type
+								   :defaults search-path))))
+		       (loop for name in filenames
+			     thereis (try-load
+				      (make-pathname :name name
+						     :type type)))))|# 
+     (loop for type in (uffi:foreign-library-types)
+	   thereis 
+	   (loop for name in filenames
+		 for pn = (make-pathname :name name :type type)
+		 thereis (or
+			  (loop for search-path in clsql:*foreign-library-search-paths*
+				thereis (try-load (merge-pathnames pn search-path))) 
+			  (try-load pn))))
+     (when errorp
+       (error "Couldn't load foreign librar~@P ~{~S~^, ~}. (searched ~S)"
+	      (length filenames) filenames
+	      'clsql:*foreign-library-search-paths*)))))
 
 (defvar *clsql-uffi-library-filenames*
-    (list #+(or 64bit x86-64) "clsql_uffi64"
-          #+(or 64bit x86-64) (make-pathname :name "clsql_uffi64"
-                                             :directory clsql-uffi-system::*library-file-dir*)
-          "clsql_uffi"
-          (make-pathname :name "clsql_uffi"
-                         :directory clsql-uffi-system::*library-file-dir*)))
+  (list #+(or 64bit x86-64) "clsql_uffi64"
+	"clsql_uffi"))
 
 (defvar *clsql-uffi-supporting-libraries* '("c")
   "Used only by CMU. List of library flags needed to be passed to ld to
@@ -58,6 +83,7 @@
   "T if foreign library was able to be loaded successfully")
 
 (defun load-uffi-foreign-library ()
+  (clsql:push-library-path clsql-uffi-system::*clsql-uffi-library-dir*)
   (find-and-load-foreign-library *clsql-uffi-library-filenames*
                                  :module "clsql-uffi"
                                  :supporting-libraries
@@ -65,4 +91,3 @@
   (setq *uffi-library-loaded* t))
 
 (load-uffi-foreign-library)
-