Skip to content
Snippets Groups Projects
Commit 45a36620 authored by Francois-Rene Rideau's avatar Francois-Rene Rideau
Browse files

2.26.21: move children dependencies from traverse to component-depends-on,

where it ought to always have been, based on a properly cleaned up prepare-op
(previously introduced in 2.26.14 as parent-load-op).

This is a checkpoint of a mostly working system after major changes;
it requires further cleanup and fixes:
strangely, fails some tests on CCL but not SBCL.

Introduce find-operation as a companion to find-component,
subsuming make-sub-operation.
The results of component-depends-on are processed with find-operation and resolve-component-spec.
component-self-dependencies is fixed to play well with prepare-op.

Also, some internal renamings and signature changes:
parent-operation becomes upward-operation
parent-load-op becomes prepare-op
parent-source-load op becomes prepare-source-op
parent-component is distinguished from module
module-components becomes component-children
module-components-by-name becomes component-children-by-name
compute-module-components-by-name becomes compute-children-by-name
circular-dependency-components becomes circular-dependency-actions
component-load-dependencies becomes component-sibling-dependencies (with a stub)
introducing child-component, downward-operation.
refactoring visit-dependencies to include the loop in which it's always used.
refactoring force and force-not processing to use a function action-override-p;
force is achieved with a trivial method on operation-done-p for prepare-op,
and force-not as a trivial check in visit-action.

Tweak tests along the way. Tweak the documentation.

Failed to either rename operation-error or introduce action-error in its superclasses:
that breaks sb-grovel.
parent 56bbe776
No related branches found
No related tags found
No related merge requests found
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
:licence "MIT" :licence "MIT"
:description "Another System Definition Facility" :description "Another System Definition Facility"
:long-description "ASDF builds Common Lisp software organized into defined systems." :long-description "ASDF builds Common Lisp software organized into defined systems."
:version "2.26.20" ;; to be automatically updated by bin/bump-revision :version "2.26.21" ;; to be automatically updated by bin/bump-revision
:depends-on () :depends-on ()
:components :components
((:file "asdf"))) ((:file "asdf")))
......
This diff is collapsed.
...@@ -1264,10 +1264,9 @@ from within an editor without clobbering its source location) ...@@ -1264,10 +1264,9 @@ from within an editor without clobbering its source location)
@subsection if-component-dep-fails option @subsection if-component-dep-fails option
This option is only appropriate for module components (including This option was removed in ASDF 2.27,
systems), not individual source files. because its semantics was limited in purpose and dubious to explain,
and its implementation was breaking a hole into ASDF abstractions.
For more information about this option, @pxref{Pre-defined subclasses of component}.
@node Other code in .asd files, , The defsystem grammar, Defining systems with defsystem @node Other code in .asd files, , The defsystem grammar, Defining systems with defsystem
@section Other code in .asd files @section Other code in .asd files
...@@ -1306,34 +1305,33 @@ to interface with C libraries and of wrapper files to embed C code in Lisp; ...@@ -1306,34 +1305,33 @@ to interface with C libraries and of wrapper files to embed C code in Lisp;
@code{abcl-jar} supports creating Java JAR archives in ABCL; @code{abcl-jar} supports creating Java JAR archives in ABCL;
and @code{poiu} supports for compiling code in parallel using background processes. and @code{poiu} supports for compiling code in parallel using background processes.
This chapter deals with @emph{components} and @emph{operations}. This chapter deals with @code{component}s and @code{operation}s.
An @emph{component} represents an individual source file or a group of source files, A @code{component} represents an individual source file or a group of source files,
and the things that get transformed into. and the things that get transformed into.
A @emph{source-file} is a component representing a single source-file A @code{system} is a component at the top level of the component hierarchy.
A @code{source-file} is a component representing a single source-file
and the successive output files into which it is transformed. and the successive output files into which it is transformed.
A @emph{module} is a component itself grouping several other components, A @code{module} is an intermediate component itself grouping several other components,
themselves source-files or further modules. themselves source-files or further modules.
A @emph{system} is a module at the top level of the component and module hierarchy.
An @emph{Operation} represents a transformation that can be performed on a component, An @code{Operation} represents a transformation that can be performed on a component,
turning them from source files to intermediate results to final outputs. turning them from source files to intermediate results to final outputs.
A pair of an @emph{operation} and a @emph{component} A pair of an @code{operation} and a @code{component} is called an @code{action}.
is sometimes called an @emph{action}. An @code{action} represents a particular build step to be @code{perform}ed,
An @emph{action} represents a particular build step to be @emph{performed},
after all its dependencies have been fulfilled. after all its dependencies have been fulfilled.
In the ASDF model, @emph{actions} depend on other actions. In the ASDF model, actions depend on other actions.
The term @emph{action} itself originated in ASDF 2, The term @emph{action} itself was used by Kent Pitman in his old article,
and is now found in its internals, but was only used by ASDF hackers starting with the ASDF 2;
but the concept is ubiquitous since the beginning of ASDF 1, but the concept is ubiquitous since the very beginning of ASDF 1,
though previously implicit. though previously implicit.
Then, there are many @emph{functions} available Then, there are many @emph{functions} available
to users, extenders and implementers of ASDF to users, extenders and implementers of ASDF
to use, define or implement the activities to use, define or implement the activities
that are part of building your software. that are part of building your software.
Though they manipulate @emph{actions}, Though they manipulate @code{action}s,
most of these functions do not take as an argument most of these functions do not take as an argument
a reified pair (a CONS cell) of an operation and a component; a reified pair (a CONS cell) of an operation and a component;
instead, they usually take two separate arguments, instead, they usually take two separate arguments,
...@@ -1351,15 +1349,17 @@ with some @emph{operation} on some toplevel @emph{system}; ...@@ -1351,15 +1349,17 @@ with some @emph{operation} on some toplevel @emph{system};
it will then @emph{traverse} the graph and build a @emph{plan} it will then @emph{traverse} the graph and build a @emph{plan}
that follows its structure. that follows its structure.
To be successfully buildable, this graph of actions but be acyclic. To be successfully buildable, this graph of actions but be acyclic.
If as a user, extender or implementer of ASDF, you fail If, as a user, extender or implementer of ASDF, you fail
to keep the dependency graph without cycles, to keep the dependency graph without cycles,
and ASDF will fail loudly as it eventually finds one. ASDF will fail loudly as it eventually finds one.
To clearly distinguish the direction of dependencies, To clearly distinguish the direction of dependencies,
ASDF 2.27 (after POIU 1.29) introduces the words @emph{parent} and @emph{child} ASDF 2.27 introduces the words @emph{parent} and @emph{child}
as applied to an action depending on the other: as applied to an action depending on the other:
the parent action @emph{depends-on} the completion of all children actions the parent action @code{depends-on} the completion of all children actions
before it may itself be @emph{performed}. before it may itself be @code{perform}ed.
ASDF has long had parent operations and children operations,
whereby the ancestor holds some options valid for all the children (notably regarding forcing).
Using the defsystem syntax, users may easily express Using the defsystem syntax, users may easily express
direct dependencies along the graph of the object hierarchy: direct dependencies along the graph of the object hierarchy:
...@@ -2030,15 +2030,7 @@ are inferred to be of this type. ...@@ -2030,15 +2030,7 @@ are inferred to be of this type.
@item @item
@code{:if-component-dep-fails} @code{:if-component-dep-fails}
This attribute takes one of the values This attribute was removed in ASDF 2.27. Do not use it.
@code{:fail}, @code{:try-next}, @code{:ignore},
its default value is @code{:fail}.
The other values can be used for implementing conditional compilation
based on implementation @code{*features*},
for the case where it is not necessary for all files in a module to be
compiled.
@emph{FIXME: such conditional compilation has been reported
to be broken in 2009.}
@item @item
@code{:serial} When this attribute is set, @code{:serial} When this attribute is set,
......
...@@ -108,6 +108,10 @@ ...@@ -108,6 +108,10 @@
(finish-output *standard-output*) (finish-output *standard-output*)
(exit-lisp return)) (exit-lisp return))
(defmacro assert-equal (x y)
`(assert (equal ,x ,y) () "These two expressions are not equal:~% ~S evaluates to ~S~% ~S evaluates to ~S~%"
',x ,x ',y ,y))
(defmacro quit-on-error (&body body) (defmacro quit-on-error (&body body)
`(call-quitting-on-error (lambda () ,@body))) `(call-quitting-on-error (lambda () ,@body)))
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
(let ((*read-base* 2)) (let ((*read-base* 2))
(funcall thunk))) (funcall thunk)))
;;(trace call-in-base-2 compile-file load trace around-compile-hook)
(defsystem test-around-compile (defsystem test-around-compile
:around-compile call-in-base-2 :around-compile call-in-base-2
:depends-on ((:version :asdf "2.017.18")) ; no :around-compile before that. :depends-on ((:version :asdf "2.017.18")) ; no :around-compile before that.
......
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
(quit-on-error (quit-on-error
(setf *central-registry* '(*default-pathname-defaults*)) (setf *central-registry* '(*default-pathname-defaults*))
(load-system 'test-around-compile :force t) (load-system 'test-around-compile :force t)
(assert (= 3 (add10 1)))) ;; add10 must have been compiled in base 2 (assert (= 3 (funcall 'add10 1)))) ;; add10 must have been compiled in base 2
...@@ -2,23 +2,26 @@ ...@@ -2,23 +2,26 @@
(load "script-support.lisp") (load "script-support.lisp")
(load-asdf) (load-asdf)
;;(trace source-file-type)
(quit-on-error (quit-on-error
(format t "~D~%" (asdf:asdf-version))
(setf asdf:*central-registry* '(*default-pathname-defaults*)) (setf asdf:*central-registry* '(*default-pathname-defaults*))
(asdf:load-system 'test-builtin-source-file-type-1 :verbose t) (asdf:load-system 'test-builtin-source-file-type-1 :verbose t)
(assert (symbol-value (read-from-string "test-package::*test-tmp-cl*"))) (assert (symbol-value (read-from-string "test-package::*test-tmp-cl*")))
(assert (assert-equal
(equal (mapcar #'pathname-type (mapcar #'pathname-type
(mapcar #'asdf:component-pathname (asdf:module-components (asdf:find-system :test-source-file-type-1)))) (mapcar #'asdf:component-pathname (asdf:module-components (asdf:find-system :test-source-file-type-1))))
'("lisp" "cl"))) '("lisp" "cl"))
(delete-package :test-package) (delete-package :test-package)
(asdf:load-system 'test-builtin-source-file-type-2 :verbose t) (asdf:load-system 'test-builtin-source-file-type-2 :verbose t)
(assert (symbol-value (read-from-string "test-package::*test-tmp-cl*"))) (assert (symbol-value (read-from-string "test-package::*test-tmp-cl*")))
(asdf:load-system 'test-builtin-source-file-type-3 :verbose t) (asdf:load-system 'test-builtin-source-file-type-3 :verbose t)
(assert (symbol-value (read-from-string "test-package::*test-tmp-cl*"))) (assert (symbol-value (read-from-string "test-package::*test-tmp-cl*")))
(assert (assert-equal
(equal (mapcar #'pathname-type (mapcar #'pathname-type
(mapcar #'asdf:component-pathname (asdf:module-components (asdf:find-system :test-source-file-type-1)))) (mapcar #'asdf:component-pathname (asdf:module-components (asdf:find-system :test-source-file-type-1))))
'("lisp" "cl"))) '("lisp" "cl"))
(delete-package :test-package) (delete-package :test-package)
(asdf:load-system 'test-builtin-source-file-type-4 :verbose t) (asdf:load-system 'test-builtin-source-file-type-4 :verbose t)
(assert (symbol-value (read-from-string "test-package::*test-tmp-cl*"))) (assert (symbol-value (read-from-string "test-package::*test-tmp-cl*")))
......
...@@ -95,7 +95,6 @@ ...@@ -95,7 +95,6 @@
(format t "~&subdirectories of dir5/: ~S~%" (subdirectories (under-test-directory "dir5/"))) (format t "~&subdirectories of dir5/: ~S~%" (subdirectories (under-test-directory "dir5/")))
(assert (= 2 (length (subdirectories (under-test-directory "dir5/"))))) (assert (= 2 (length (subdirectories (under-test-directory "dir5/")))))
;; (trace asdf::process-source-registry)
(initialize-source-registry (initialize-source-registry
`(:source-registry (:include ,(under-test-directory "conf.d/")) `(:source-registry (:include ,(under-test-directory "conf.d/"))
(:include ,(under-test-directory "dir5/")) (:include ,(under-test-directory "dir5/"))
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
(defclass cl-source-file-1 (cl-source-file) (defclass cl-source-file-1 (cl-source-file)
()) ())
(defmethod source-file-type ((f cl-source-file-1) (m module)) (defmethod asdf::source-file-type ((f cl-source-file-1) (s system))
(declare (ignorable f m)) (declare (ignorable f s))
(format t "Hello, world!~%")
"cl") "cl")
(defsystem test-source-file-type-1 (defsystem test-source-file-type-1
:default-component-class cl-source-file-1 :default-component-class cl-source-file-1
:serial t :serial t
:components ((:cl-source-file "file1") ; for the package :components ((:cl-source-file "file1") ; for the package
(:file "test-tmp"))) (:file "test-tmp")))
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
(load "script-support.lisp") (load "script-support.lisp")
(load-asdf) (load-asdf)
;;(trace asdf::source-file-type asdf::source-file-explicit-type)
(quit-on-error (quit-on-error
(setf asdf:*central-registry* '(*default-pathname-defaults*)) (setf asdf:*central-registry* '(*default-pathname-defaults*))
(asdf:load-system 'test-source-file-type-1 :verbose t) (asdf:load-system 'test-source-file-type-1 :verbose t)
......
;;;; Example lisp code. ;;;; Example lisp code.
(in-package :asdf-test) (in-package :asdf-test)
(eval-when (:compile-toplevel)
(format t "This is compile-time and the *read-base* is ~D~%" *read-base*))
(eval-when (:load-toplevel)
(format t "This is load-time and the *read-base* is ~D~%" *read-base*))
(eval-when (:execute)
(format t "This is execute-time and *read-base* is ~D~%" *read-base*))
(defun tst (x) (defun tst (x)
(1+ x)) (1+ x))
(defun add10 (x) (defun add10 (x)
(+ x 10)) (+ x 10))
(format t "(add10 0) is (in decimal) ~D~%" (add10 0))
...@@ -8,27 +8,27 @@ ...@@ -8,27 +8,27 @@
;; test that it compiled ;; test that it compiled
(let* ((file1 (asdf:compile-file-pathname* "file1")) (let* ((file1 (asdf:compile-file-pathname* "file1"))
(file2 (asdf:compile-file-pathname* "file2")) (file2 (asdf:compile-file-pathname* "file2"))
(file1-date (file-write-date file1))) (file1-date (file-write-date file1))
(file2-date (file-write-date file2)))
(format t "~&test1 1: ~S ~S~%" file1 file1-date) (format t "~&test1 1: ~S ~S~%" file1 file1-date)
(assert file1-date) (assert file1-date)
(assert (file-write-date file2)) (assert file2-date)
;; and loaded (DBG "and loaded")
(assert (symbol-value (find-symbol (symbol-name :*file1*) :test-package))) (assert (symbol-value (find-symbol (symbol-name :*file1*) :test-package)))
;; now remove one output file and check that the other is _not_ recompiled (DBG "now remove file2 that depends-on file1 check that file1 is _not_ recompiled, but file2 is")
(asdf::run-shell-command "rm -f ~A" (namestring file2)) (asdf::run-shell-command "rm -f ~A" (namestring file2))
;; filesystem mtime has 1 second granularity. Make sure even fast machines see a difference.
(sleep 1)
(asdf:operate 'asdf:load-op 'test1) (asdf:operate 'asdf:load-op 'test1)
(assert (= file1-date (file-write-date file1))) (assert (= file1-date (file-write-date file1)))
(assert (file-write-date file2)) (assert (< file2-date (file-write-date file2)))
;; now touch file1 and check that file2 _is_ also recompiled
(DBG "now touch file1 and check that file2 _is_ also recompiled")
;; XXX run-shell-command loses if *default-pathname-defaults* is not the ;; XXX run-shell-command loses if *default-pathname-defaults* is not the
;; unix cwd. this is not a problem for run-tests.sh, but can be in general ;; unix cwd. this is not a problem for run-tests.sh, but can be in general
(let ((before (file-write-date file2))) (let ((before (file-write-date file2)))
;; filesystem mtime has 1 second granularity. Make sure even fast machines see a difference. ;; filesystem mtime has 1 second granularity. Make sure even fast machines see a difference.
(sleep 1) (sleep 1)
......
...@@ -4,9 +4,6 @@ ...@@ -4,9 +4,6 @@
(quit-on-error (quit-on-error
(format t "test2 1~%") (format t "test2 1~%")
(setf asdf:*central-registry* '(*default-pathname-defaults*)) (setf asdf:*central-registry* '(*default-pathname-defaults*))
;(trace asdf::perform)
;(trace asdf::find-component)
;(trace asdf::traverse)
(asdf:oos 'asdf:load-op 'test2b1) (asdf:oos 'asdf:load-op 'test2b1)
(format t "test2 2~%") (format t "test2 2~%")
(assert (and (probe-file (asdf:compile-file-pathname* (truename "file3.lisp"))) (assert (and (probe-file (asdf:compile-file-pathname* (truename "file3.lisp")))
......
;;; -*- Lisp -*- ;;; -*- Lisp -*-
#+(or f1 f2) (error "This test cannot run if :f1 or :f2 are on *features*") #+(or f1 f2) (error "This test cannot run if :f1 or :f2 are on *features*")
(load "script-support.lisp") (load "script-support.lisp")
(load-asdf)
;;; This test relies on the removed features :if-component-dep-fails and :feature.
;;; It is disabled.
(asdf-test:leave-lisp "This test was removed, because is stressed a feature that was removed." 0)
(load-asdf)
(quit-on-error (quit-on-error
(let* ((fasl1 (asdf:compile-file-pathname* (truename "file1.lisp"))) (let* ((fasl1 (asdf:compile-file-pathname* (truename "file1.lisp")))
(fasl2 (asdf:compile-file-pathname* (truename "file2.lisp"))) (fasl2 (asdf:compile-file-pathname* (truename "file2.lisp")))
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
(component-options :accessor wild-module-component-options (component-options :accessor wild-module-component-options
:initform nil :initarg :component-options))) :initform nil :initarg :component-options)))
(defmethod (setf module-components) (new-value (module wild-module)) (defmethod (setf components-children) (new-value (module wild-module))
(when new-value (when new-value
(sysdef-error "Cannot explicitly set wild-module ~A's components. Please ~ (sysdef-error "Cannot explicitly set wild-module ~A's children components. Please ~
use a wild pathname instead." module))) use a wild pathname instead." module)))
(defmethod reinitialize-instance :after ((self wild-module) &key) (defmethod reinitialize-instance :after ((self wild-module) &key)
...@@ -27,7 +27,7 @@ use a wild pathname instead." module))) ...@@ -27,7 +27,7 @@ use a wild pathname instead." module)))
:parent self :parent self
options)) options))
files))) files)))
(compute-module-components-by-name self) (compute-children-by-name self)
(values))) (values)))
(export 'wild-module) (export 'wild-module)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment