build-system/asdf: Use asdf to determine dependencies.
This removes the need for conventions to determine which inputs are run-time dependencies, and also the need to specify "special" dependencies. * guix/build/lisp-utils.scm (patch-asd-file, lisp-dependencies) (wrap-perform-method): Remove them. (inputs->asd-file-map, system-dependencies, generate-system-definition) (generate-dependency-links, make-asd-file): New procedures. (lisp-eval-program): Add an error if no lisp matches. (compile-system): Don't use asdf's in-built asd-file generator.master
parent
290bf612bb
commit
35189728cd
|
@ -822,8 +822,6 @@ compatible with ANSI-compliant Common Lisp implementations.")
|
||||||
(substitute* "clx.asd"
|
(substitute* "clx.asd"
|
||||||
(("\\(:file \"trapezoid\"\\)") ""))))))
|
(("\\(:file \"trapezoid\"\\)") ""))))))
|
||||||
(build-system asdf-build-system/sbcl)
|
(build-system asdf-build-system/sbcl)
|
||||||
(arguments
|
|
||||||
'(#:special-dependencies '("sb-bsd-sockets")))
|
|
||||||
(home-page "http://www.cliki.net/portable-clx")
|
(home-page "http://www.cliki.net/portable-clx")
|
||||||
(synopsis "X11 client library for Common Lisp")
|
(synopsis "X11 client library for Common Lisp")
|
||||||
(description "CLX is an X11 client library for Common Lisp. The code was
|
(description "CLX is an X11 client library for Common Lisp. The code was
|
||||||
|
@ -855,8 +853,7 @@ from other CLXes around the net.")
|
||||||
("sbcl-clx" ,sbcl-clx)))
|
("sbcl-clx" ,sbcl-clx)))
|
||||||
(outputs '("out" "lib"))
|
(outputs '("out" "lib"))
|
||||||
(arguments
|
(arguments
|
||||||
'(#:special-dependencies '("sb-posix")
|
'(#:phases
|
||||||
#:phases
|
|
||||||
(modify-phases %standard-phases
|
(modify-phases %standard-phases
|
||||||
(add-after 'create-symlinks 'build-program
|
(add-after 'create-symlinks 'build-program
|
||||||
(lambda* (#:key lisp outputs inputs #:allow-other-keys)
|
(lambda* (#:key lisp outputs inputs #:allow-other-keys)
|
||||||
|
|
|
@ -194,8 +194,7 @@ set up using CL source package conventions."
|
||||||
(define base-arguments
|
(define base-arguments
|
||||||
(if target-is-source?
|
(if target-is-source?
|
||||||
(strip-keyword-arguments
|
(strip-keyword-arguments
|
||||||
'(#:tests? #:special-dependencies #:asd-file
|
'(#:tests? #:asd-file #:lisp)
|
||||||
#:test-only-systems #:lisp)
|
|
||||||
(package-arguments pkg))
|
(package-arguments pkg))
|
||||||
(package-arguments pkg)))
|
(package-arguments pkg)))
|
||||||
|
|
||||||
|
@ -262,9 +261,7 @@ set up using CL source package conventions."
|
||||||
(lambda* (store name inputs
|
(lambda* (store name inputs
|
||||||
#:key source outputs
|
#:key source outputs
|
||||||
(tests? #t)
|
(tests? #t)
|
||||||
(special-dependencies ''())
|
|
||||||
(asd-file #f)
|
(asd-file #f)
|
||||||
(test-only-systems ''())
|
|
||||||
(lisp lisp-implementation)
|
(lisp lisp-implementation)
|
||||||
(phases '(@ (guix build asdf-build-system)
|
(phases '(@ (guix build asdf-build-system)
|
||||||
%standard-phases))
|
%standard-phases))
|
||||||
|
@ -284,9 +281,7 @@ set up using CL source package conventions."
|
||||||
((source) source)
|
((source) source)
|
||||||
(source source))
|
(source source))
|
||||||
#:lisp ,lisp
|
#:lisp ,lisp
|
||||||
#:special-dependencies ,special-dependencies
|
|
||||||
#:asd-file ,asd-file
|
#:asd-file ,asd-file
|
||||||
#:test-only-systems ,test-only-systems
|
|
||||||
#:system ,system
|
#:system ,system
|
||||||
#:tests? ,tests?
|
#:tests? ,tests?
|
||||||
#:phases ,phases
|
#:phases ,phases
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#:use-module (guix build utils)
|
#:use-module (guix build utils)
|
||||||
#:use-module (guix build lisp-utils)
|
#:use-module (guix build lisp-utils)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:use-module (ice-9 rdelim)
|
#:use-module (ice-9 rdelim)
|
||||||
#:use-module (ice-9 receive)
|
#:use-module (ice-9 receive)
|
||||||
|
@ -161,31 +162,25 @@ valid."
|
||||||
(format #t "test suite not run~%")))
|
(format #t "test suite not run~%")))
|
||||||
#t)
|
#t)
|
||||||
|
|
||||||
(define* (patch-asd-files #:key outputs
|
(define* (create-asd-file #:key outputs
|
||||||
inputs
|
inputs
|
||||||
lisp
|
lisp
|
||||||
special-dependencies
|
asd-file
|
||||||
test-only-systems
|
|
||||||
#:allow-other-keys)
|
#:allow-other-keys)
|
||||||
"Patch any asd files created by the compilation process so that they can
|
"Create a system definition file for the built system."
|
||||||
find their dependencies. Exclude any TEST-ONLY-SYSTEMS which were only
|
(let*-values (((out) (library-output outputs))
|
||||||
included to run tests. Add any SPECIAL-DEPENDENCIES which the LISP
|
((full-name version) (package-name->name+version
|
||||||
implementation itself provides."
|
(strip-store-file-name out)))
|
||||||
(let* ((out (library-output outputs))
|
((name) (remove-lisp-from-name full-name lisp))
|
||||||
(name (remove-lisp-from-name (output-path->package-name out) lisp))
|
((new-asd-file) (string-append (library-directory out lisp)
|
||||||
(registry (lset-difference
|
"/" name ".asd")))
|
||||||
(lambda (input system)
|
|
||||||
(match input
|
|
||||||
((name . path) (string=? name system))))
|
|
||||||
(lisp-dependencies lisp inputs)
|
|
||||||
test-only-systems))
|
|
||||||
(lisp-systems (map first registry)))
|
|
||||||
|
|
||||||
(for-each
|
(make-asd-file new-asd-file
|
||||||
(lambda (asd-file)
|
#:lisp lisp
|
||||||
(patch-asd-file asd-file registry lisp
|
#:system name
|
||||||
(append lisp-systems special-dependencies)))
|
#:version version
|
||||||
(find-files out "\\.asd$")))
|
#:inputs inputs
|
||||||
|
#:system-asd-file asd-file))
|
||||||
#t)
|
#t)
|
||||||
|
|
||||||
(define* (symlink-asd-files #:key outputs lisp #:allow-other-keys)
|
(define* (symlink-asd-files #:key outputs lisp #:allow-other-keys)
|
||||||
|
@ -193,9 +188,6 @@ implementation itself provides."
|
||||||
(let* ((out (library-output outputs)))
|
(let* ((out (library-output outputs)))
|
||||||
(for-each
|
(for-each
|
||||||
(lambda (asd-file)
|
(lambda (asd-file)
|
||||||
(substitute* asd-file
|
|
||||||
((";;; Built for.*") "") ; remove potential non-determinism
|
|
||||||
(("^\\(DEFSYSTEM(.*)$" all end) (string-append "(asdf:defsystem" end)))
|
|
||||||
(receive (new-asd-file asd-file-directory)
|
(receive (new-asd-file asd-file-directory)
|
||||||
(bundle-asd-file out asd-file lisp)
|
(bundle-asd-file out asd-file lisp)
|
||||||
(mkdir-p asd-file-directory)
|
(mkdir-p asd-file-directory)
|
||||||
|
@ -205,12 +197,11 @@ implementation itself provides."
|
||||||
(prepend-to-source-registry
|
(prepend-to-source-registry
|
||||||
(string-append asd-file-directory "/"))))
|
(string-append asd-file-directory "/"))))
|
||||||
|
|
||||||
(find-files (string-append out %object-prefix) "\\.asd$"))
|
(find-files (string-append out %object-prefix) "\\.asd$")))
|
||||||
)
|
|
||||||
#t)
|
#t)
|
||||||
|
|
||||||
(define* (cleanup-files #:key outputs lisp
|
(define* (cleanup-files #:key outputs lisp
|
||||||
#:allow-other-keys)
|
#:allow-other-keys)
|
||||||
"Remove any compiled files which are not a part of the final bundle."
|
"Remove any compiled files which are not a part of the final bundle."
|
||||||
(let ((out (library-output outputs)))
|
(let ((out (library-output outputs)))
|
||||||
(match lisp
|
(match lisp
|
||||||
|
@ -261,8 +252,8 @@ implementation itself provides."
|
||||||
(add-before 'build 'copy-source copy-source)
|
(add-before 'build 'copy-source copy-source)
|
||||||
(replace 'check check)
|
(replace 'check check)
|
||||||
(replace 'strip strip)
|
(replace 'strip strip)
|
||||||
(add-after 'check 'link-dependencies patch-asd-files)
|
(add-after 'check 'create-asd-file create-asd-file)
|
||||||
(add-after 'link-dependencies 'cleanup cleanup-files)
|
(add-after 'create-asd-file 'cleanup cleanup-files)
|
||||||
(add-after 'cleanup 'create-symlinks symlink-asd-files)))
|
(add-after 'cleanup 'create-symlinks symlink-asd-files)))
|
||||||
|
|
||||||
(define* (asdf-build #:key inputs
|
(define* (asdf-build #:key inputs
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
(define-module (guix build lisp-utils)
|
(define-module (guix build lisp-utils)
|
||||||
#:use-module (ice-9 format)
|
#:use-module (ice-9 format)
|
||||||
|
#:use-module (ice-9 hash-table)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 regex)
|
#:use-module (ice-9 regex)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
@ -32,15 +33,14 @@
|
||||||
generate-executable-wrapper-system
|
generate-executable-wrapper-system
|
||||||
generate-executable-entry-point
|
generate-executable-entry-point
|
||||||
generate-executable-for-system
|
generate-executable-for-system
|
||||||
patch-asd-file
|
|
||||||
bundle-install-prefix
|
bundle-install-prefix
|
||||||
lisp-dependencies
|
|
||||||
bundle-asd-file
|
bundle-asd-file
|
||||||
remove-lisp-from-name
|
remove-lisp-from-name
|
||||||
wrap-output-translations
|
wrap-output-translations
|
||||||
prepend-to-source-registry
|
prepend-to-source-registry
|
||||||
build-program
|
build-program
|
||||||
build-image))
|
build-image
|
||||||
|
make-asd-file))
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -64,6 +64,23 @@
|
||||||
(define (remove-lisp-from-name name lisp)
|
(define (remove-lisp-from-name name lisp)
|
||||||
(string-drop name (1+ (string-length lisp))))
|
(string-drop name (1+ (string-length lisp))))
|
||||||
|
|
||||||
|
(define (inputs->asd-file-map inputs lisp)
|
||||||
|
"Produce a hash table of the form (system . asd-file), where system is the
|
||||||
|
name of an ASD system, and asd-file is the full path to its definition."
|
||||||
|
(alist->hash-table
|
||||||
|
(filter-map
|
||||||
|
(match-lambda
|
||||||
|
((_ . path)
|
||||||
|
(let ((prefix (string-append path (bundle-install-prefix lisp))))
|
||||||
|
(and (directory-exists? prefix)
|
||||||
|
(match (find-files prefix "\\.asd$")
|
||||||
|
((asd-file)
|
||||||
|
(cons
|
||||||
|
(string-drop-right (basename asd-file) 4) ; drop ".asd"
|
||||||
|
asd-file))
|
||||||
|
(_ #f))))))
|
||||||
|
inputs)))
|
||||||
|
|
||||||
(define (wrap-output-translations translations)
|
(define (wrap-output-translations translations)
|
||||||
`(:output-translations
|
`(:output-translations
|
||||||
,@translations
|
,@translations
|
||||||
|
@ -80,7 +97,8 @@
|
||||||
with PROGRAM."
|
with PROGRAM."
|
||||||
(match lisp
|
(match lisp
|
||||||
("sbcl" `(,(%lisp) "--non-interactive" "--eval" ,program))
|
("sbcl" `(,(%lisp) "--non-interactive" "--eval" ,program))
|
||||||
("ecl" `(,(%lisp) "-eval" ,program "-eval" "(quit)"))))
|
("ecl" `(,(%lisp) "-eval" ,program "-eval" "(quit)"))
|
||||||
|
(_ (error "The LISP provided is not supported at this time."))))
|
||||||
|
|
||||||
(define (asdf-load-all systems)
|
(define (asdf-load-all systems)
|
||||||
(map (lambda (system)
|
(map (lambda (system)
|
||||||
|
@ -108,15 +126,61 @@ first if SYSTEM is defined there."
|
||||||
(find-symbol
|
(find-symbol
|
||||||
(symbol-name :compile-bundle-op)
|
(symbol-name :compile-bundle-op)
|
||||||
(symbol-name :asdf))
|
(symbol-name :asdf))
|
||||||
,system)
|
|
||||||
(funcall (find-symbol
|
|
||||||
(symbol-name :operate)
|
|
||||||
(symbol-name :asdf))
|
|
||||||
(find-symbol
|
|
||||||
(symbol-name :deliver-asd-op)
|
|
||||||
(symbol-name :asdf))
|
|
||||||
,system))))
|
,system))))
|
||||||
|
|
||||||
|
(define (system-dependencies lisp system asd-file)
|
||||||
|
"Return the dependencies of SYSTEM, as reported by
|
||||||
|
asdf:system-depends-on. First load the system's ASD-FILE, if necessary."
|
||||||
|
(define deps-file ".deps.sexp")
|
||||||
|
(define program
|
||||||
|
`(progn
|
||||||
|
(require :asdf)
|
||||||
|
,@(if asd-file
|
||||||
|
`((let ((*package* (find-package :asdf)))
|
||||||
|
(load ,asd-file)))
|
||||||
|
'())
|
||||||
|
(with-open-file
|
||||||
|
(stream ,deps-file :direction :output)
|
||||||
|
(format stream
|
||||||
|
"~s~%"
|
||||||
|
(funcall
|
||||||
|
(find-symbol
|
||||||
|
(symbol-name :system-depends-on)
|
||||||
|
(symbol-name :asdf))
|
||||||
|
|
||||||
|
(funcall
|
||||||
|
(find-symbol
|
||||||
|
(symbol-name :find-system)
|
||||||
|
(symbol-name :asdf))
|
||||||
|
|
||||||
|
,system))))))
|
||||||
|
|
||||||
|
(dynamic-wind
|
||||||
|
(lambda _
|
||||||
|
(lisp-eval-program lisp program))
|
||||||
|
(lambda _
|
||||||
|
(call-with-input-file deps-file read))
|
||||||
|
(lambda _
|
||||||
|
(when (file-exists? deps-file)
|
||||||
|
(delete-file deps-file)))))
|
||||||
|
|
||||||
|
(define (compiled-system system lisp)
|
||||||
|
(match lisp
|
||||||
|
("sbcl" (string-append system "--system"))
|
||||||
|
(_ system)))
|
||||||
|
|
||||||
|
(define* (generate-system-definition lisp system
|
||||||
|
#:key version dependencies)
|
||||||
|
`(asdf:defsystem
|
||||||
|
,system
|
||||||
|
:class asdf/bundle:prebuilt-system
|
||||||
|
:version ,version
|
||||||
|
:depends-on ,dependencies
|
||||||
|
:components ((:compiled-file ,(compiled-system system lisp)))
|
||||||
|
,@(if (string=? "ecl" lisp)
|
||||||
|
`(:lib ,(string-append system ".a"))
|
||||||
|
'())))
|
||||||
|
|
||||||
(define (test-system system lisp asd-file)
|
(define (test-system system lisp asd-file)
|
||||||
"Use a lisp implementation to test SYSTEM using asdf. Load ASD-FILE first
|
"Use a lisp implementation to test SYSTEM using asdf. Load ASD-FILE first
|
||||||
if SYSTEM is defined there."
|
if SYSTEM is defined there."
|
||||||
|
@ -185,58 +249,53 @@ ENTRY-PROGRAM for SYSTEM within the current directory."
|
||||||
(declare (ignorable arguments))
|
(declare (ignorable arguments))
|
||||||
,@entry-program))))))))
|
,@entry-program))))))))
|
||||||
|
|
||||||
(define (wrap-perform-method lisp registry dependencies file-name)
|
(define (generate-dependency-links lisp registry system)
|
||||||
"Creates a wrapper method which allows the system to locate its dependent
|
"Creates a program which populates asdf's source registry from REGISTRY, an
|
||||||
systems from REGISTRY, an alist of the same form as %outputs, which contains
|
alist of dependency names to corresponding asd files. This allows the system
|
||||||
lisp systems which the systems is dependent on. All DEPENDENCIES which the
|
to locate its dependent systems."
|
||||||
system depends on will the be loaded before this system."
|
`(progn
|
||||||
(let* ((system (string-drop-right (basename file-name) 4))
|
(asdf/source-registry:ensure-source-registry)
|
||||||
(system-symbol (string->lisp-keyword system)))
|
,@(map (match-lambda
|
||||||
|
((name . asd-file)
|
||||||
|
`(setf
|
||||||
|
(gethash ,name
|
||||||
|
asdf/source-registry:*source-registry*)
|
||||||
|
,(string->symbol "#p")
|
||||||
|
,asd-file)))
|
||||||
|
registry)))
|
||||||
|
|
||||||
`(defmethod asdf:perform :before
|
(define* (make-asd-file asd-file
|
||||||
(op (c (eql (asdf:find-system ,system-symbol))))
|
#:key lisp system version inputs
|
||||||
(asdf/source-registry:ensure-source-registry)
|
(system-asd-file #f))
|
||||||
,@(map (match-lambda
|
"Create an ASD-FILE for SYSTEM@VERSION, appending a program to allow the
|
||||||
((name . path)
|
system to find its dependencies, as described by GENERATE-DEPENDENCY-LINKS."
|
||||||
(let ((asd-file (string-append path
|
(define dependencies
|
||||||
(bundle-install-prefix lisp)
|
(parameterize ((%lisp (string-append (assoc-ref inputs lisp) "/bin/" lisp)))
|
||||||
"/" name ".asd")))
|
(system-dependencies lisp system system-asd-file)))
|
||||||
`(setf
|
|
||||||
(gethash ,name
|
|
||||||
asdf/source-registry:*source-registry*)
|
|
||||||
,(string->symbol "#p")
|
|
||||||
,(bundle-asd-file path asd-file lisp)))))
|
|
||||||
registry)
|
|
||||||
,@(map (lambda (system)
|
|
||||||
`(asdf:load-system ,(string->lisp-keyword system)))
|
|
||||||
dependencies))))
|
|
||||||
|
|
||||||
(define (patch-asd-file asd-file registry lisp dependencies)
|
(define lisp-input-map
|
||||||
"Patches ASD-FILE with a perform method as described in WRAP-PERFORM-METHOD."
|
(inputs->asd-file-map inputs lisp))
|
||||||
(chmod asd-file #o644)
|
|
||||||
(let ((port (open-file asd-file "a")))
|
|
||||||
(dynamic-wind
|
|
||||||
(lambda _ #t)
|
|
||||||
(lambda _
|
|
||||||
(display
|
|
||||||
(replace-escaped-macros
|
|
||||||
(format #f "~%~y~%"
|
|
||||||
(wrap-perform-method lisp registry
|
|
||||||
dependencies asd-file)))
|
|
||||||
port))
|
|
||||||
(lambda _ (close-port port))))
|
|
||||||
(chmod asd-file #o444))
|
|
||||||
|
|
||||||
(define (lisp-dependencies lisp inputs)
|
(define registry
|
||||||
"Determine which inputs are lisp system dependencies, by using the convention
|
(filter-map hash-get-handle
|
||||||
that a lisp system dependency will resemble \"system-LISP\"."
|
(make-list (if (eq? 'NIL dependencies)
|
||||||
(filter-map (match-lambda
|
0
|
||||||
((name . value)
|
(length dependencies))
|
||||||
(and (string-prefix? lisp name)
|
lisp-input-map)
|
||||||
(string<> lisp name)
|
(if (eq? 'NIL dependencies)
|
||||||
`(,(remove-lisp-from-name name lisp)
|
'()
|
||||||
. ,value))))
|
dependencies)))
|
||||||
inputs))
|
|
||||||
|
(call-with-output-file asd-file
|
||||||
|
(lambda (port)
|
||||||
|
(display
|
||||||
|
(replace-escaped-macros
|
||||||
|
(format #f "~y~%~y~%"
|
||||||
|
(generate-system-definition lisp system
|
||||||
|
#:version version
|
||||||
|
#:dependencies dependencies)
|
||||||
|
(generate-dependency-links lisp registry system)))
|
||||||
|
port))))
|
||||||
|
|
||||||
(define (bundle-asd-file output-path original-asd-file lisp)
|
(define (bundle-asd-file output-path original-asd-file lisp)
|
||||||
"Find the symlinked bundle file for ORIGINAL-ASD-FILE by looking in
|
"Find the symlinked bundle file for ORIGINAL-ASD-FILE by looking in
|
||||||
|
|
Reference in New Issue