Groveler ASDF integration: import new build system from CFFI
authorStelian Ionescu <sionescu@cddr.org>
Sat, 19 Jan 2013 23:47:02 +0000 (20 00:47 +0100)
committerStelian Ionescu <sionescu@cddr.org>
Sat, 19 Jan 2013 23:47:02 +0000 (20 00:47 +0100)
src/grovel/asdf.lisp

index aba6cdb..bfe1066 100644 (file)
   ((cc-flags :initform nil :accessor cc-flags-of :initarg :cc-flags)))
 
 (defmethod asdf:perform :around ((op asdf:compile-op) (file cc-flags-mixin))
+  (declare (ignore op))
   (let ((*cc-flags* (append (ensure-list (cc-flags-of file))
                             *cc-flags*)))
     (call-next-method)))
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defclass process-op (asdf:operation)
+    ()
+    (:documentation "This ASDF operation performs the steps necessary
+  to generate a compilable and loadable lisp file from a
+  PROCESS-OP-INPUT component."))
+
+  (defclass process-op-input (asdf:cl-source-file)
+    ((generated-lisp-file-type
+      :initarg :generated-lisp-file-type
+      :accessor generated-lisp-file-type
+      :documentation "The :TYPE argument to use for the generated lisp file."))
+    (:default-initargs
+     :generated-lisp-file-type "generated-lisp-file")
+    (:documentation "This ASDF component represents a file that is
+    used as input to a function that generates lisp source file. This
+    component acts as if it is a CL-SOURCE-FILE by applying the
+    COMPILE-OP and LOAD-SOURCE-OP operations to the file generated by
+    PROCESS-OP.")))
+
+(defmethod asdf:output-files ((op process-op) (c process-op-input))
+  (declare (ignore op))
+  (list (make-pathname :type (generated-lisp-file-type c)
+                       :defaults (asdf:component-pathname c))))
+
+(defmethod asdf:component-depends-on ((op process-op) (c process-op-input))
+  (append (call-next-method)
+          (list (cons 'asdf:load-op (asdf::component-load-dependencies c)))))
+
+(defmethod asdf:component-depends-on ((op asdf:compile-op) (c process-op-input))
+  (declare (ignore op))
+  (append (call-next-method)
+          (list (list 'process-op (asdf:component-name c)))))
+
+(defmethod asdf:component-depends-on ((op asdf:load-source-op) (c process-op-input))
+  (declare (ignore op))
+  (append (call-next-method)
+          (list (list 'process-op (asdf:component-name c)))))
+
+(defmethod asdf:perform ((op asdf:compile-op) (c process-op-input))
+  (let ((generated-lisp-file (asdf:output-file (make-instance 'process-op) c)))
+    (asdf:perform op (make-instance 'asdf:cl-source-file
+                                    :name (asdf:component-name c)
+                                    :parent (asdf:component-parent c)
+                                    :pathname generated-lisp-file))))
+
+(defmethod asdf:perform ((op asdf:load-source-op) (c process-op-input))
+  (let ((generated-lisp-file (asdf:output-file (make-instance 'process-op) c)))
+    (asdf:perform op (make-instance 'asdf:cl-source-file
+                                    :name (asdf:component-name c)
+                                    :parent (asdf:component-parent c)
+                                    :pathname generated-lisp-file))))
+
 ;;;# ASDF component: GROVEL-FILE
 
-(defclass asdf::iolib-grovel-file (:iolib-muffled-source-file cc-flags-mixin)
-  ()
-  (:documentation
-   "This ASDF component defines COMPILE-OP and LOAD-SOURCE-OP
-operations that take care of calling PROCESS-GROVEL-FILE in order
-to generate a Lisp file that is subsequently compiled and/or
-loaded."))
-
-(defmethod asdf:perform ((op asdf:compile-op)
-                         (c asdf::iolib-grovel-file))
-  (let ((output-file (ensure-pathname (car (asdf:output-files op c)))))
-    (compile-file (process-grovel-file (asdf:component-pathname c) output-file)
-                  :output-file output-file
-                  #+ecl :system-p #+ecl t)))
-
-(defmethod asdf:perform ((op asdf:load-source-op)
-                         (c asdf::iolib-grovel-file))
-  (load (process-grovel-file
-         (asdf:component-pathname c)
-         (ensure-pathname (car (asdf:output-files op c))))))
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defclass asdf::iolib-grovel-file (process-op-input cc-flags-mixin)
+    ()
+    (:default-initargs
+     :generated-lisp-file-type "processed-iolib-grovel-file")
+    (:documentation
+     "This ASDF component represents an input file that is processed
+     by PROCESS-GROVEL-FILE.")))
+
+(defmethod asdf:perform ((op process-op) (c asdf::iolib-grovel-file))
+  (let ((output-file (asdf:output-file op c))
+         (input-file (asdf:component-pathname c)))
+    (ensure-directories-exist (directory-namestring output-file))
+    (let ((tmp-file    (process-grovel-file input-file (ensure-pathname output-file))))
+      (unwind-protect
+           (alexandria:copy-file tmp-file output-file :if-to-exists :supersede)
+        (delete-file tmp-file)))))
 
 ;;;# ASDF component: WRAPPER-FILE
 
-(defclass asdf::iolib-wrapper-file (:iolib-muffled-source-file cc-flags-mixin)
-  ((soname :initform nil :initarg :soname :accessor soname-of))
-  (:documentation
-   "This ASDF component defines COMPILE-OP and LOAD-SOURCE-OP
-operations that take care of calling PROCESS-WRAPPER-FILE in
-order to generate a foreign library and matching CFFI bindings
-that are subsequently compiled and/or loaded."))
-
-(defun %perform-process-wrapper-file (op c)
-  (let ((fasl-file (ensure-pathname (car (asdf:output-files op c)))))
-    (values (process-wrapper-file (asdf:component-pathname c)
-                                  fasl-file
-                                  (or (soname-of c)
-                                      (asdf:component-name c)))
-            fasl-file)))
-
-(defmethod asdf:perform ((op asdf:compile-op)
-                         (c asdf::iolib-wrapper-file))
-  (multiple-value-bind (generated-source-file fasl-file)
-      (%perform-process-wrapper-file op c)
-    (compile-file generated-source-file
-                  :output-file fasl-file
-                  #+ecl :system-p #+ecl t)))
-
-(defmethod asdf:perform ((op asdf:load-source-op)
-                         (c asdf::iolib-wrapper-file))
-  (load (%perform-process-wrapper-file op c)))
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defclass asdf::iolib-wrapper-file (process-op-input cc-flags-mixin)
+    ((soname :initform nil :initarg :soname :accessor soname-of))
+    (:default-initargs
+     :generated-lisp-file-type "processed-iolib-wrapper-file")
+    (:documentation
+      "This ASDF component represents an input file that is processed
+      by PROCESS-WRAPPER-FILE. This generates a foreign library and
+      matching CFFI bindings that are subsequently compiled and
+      loaded.")))
+
+(defmethod asdf:perform ((op process-op) (c asdf::iolib-wrapper-file))
+  (let ((output-file (asdf:output-file op c))
+        (input-file  (asdf:component-pathname c)))
+    (ensure-directories-exist (directory-namestring output-file))
+    (let ((tmp-file    (process-wrapper-file input-file output-file (or (soname-of c)
+                                                                        (asdf:component-name c)))))
+      (unwind-protect
+           (alexandria:copy-file tmp-file output-file :if-to-exists :supersede)
+        (delete-file tmp-file)))))