Commit 58dfd53f authored by Robert P. Goldman's avatar Robert P. Goldman
Browse files
parents a661e90f 1aa0ea0f
?
?? ??
build build
asdf.lisp asdf.lisp
......
...@@ -10,13 +10,12 @@ sourceDirectory := $(shell pwd) ...@@ -10,13 +10,12 @@ sourceDirectory := $(shell pwd)
ifdef ASDF_TEST_LISPS ifdef ASDF_TEST_LISPS
lisps ?= ${ASDF_TEST_LISPS} lisps ?= ${ASDF_TEST_LISPS}
else else
lisps ?= ccl clisp sbcl ecl ecl_bytecodes cmucl abcl scl allegro lispworks allegromodern xcl gcl lisps ?= ccl clisp sbcl ecl ecl_bytecodes cmucl abcl scl allegro lispworks allegromodern gcl xcl
endif endif
## grep for #+/#- features in the test/ directory to see plenty of disabled tests on some platforms
## NOT SUPPORTED BY OUR AUTOMATED TESTS: ## NOT SUPPORTED BY OUR AUTOMATED TESTS:
## cormancl genera lispworks-personal-edition mkcl rmcl ## cormancl genera lispworks-personal-edition mkcl rmcl
## Some are manually tested once in a while. ## Some are manually tested once in a while.
## MAJOR FAIL: gclcvs -- Compiler bug fixed upstream, but gcl fails to compile on modern Linuxen.
## grep for #+/#- features in the test/ directory to see plenty of disabled tests.
ifdef ASDF_TEST_SYSTEMS ifdef ASDF_TEST_SYSTEMS
s ?= ${ASDF_TEST_SYSTEMS} s ?= ${ASDF_TEST_SYSTEMS}
endif endif
...@@ -41,11 +40,9 @@ SBCL ?= sbcl ...@@ -41,11 +40,9 @@ SBCL ?= sbcl
SCL ?= scl SCL ?= scl
XCL ?= xcl XCL ?= xcl
# website, tag, install
header_lisp := header.lisp header_lisp := header.lisp
driver_lisp := uiop/package.lisp uiop/common-lisp.lisp uiop/utility.lisp uiop/os.lisp uiop/pathname.lisp uiop/filesystem.lisp uiop/stream.lisp uiop/image.lisp uiop/run-program.lisp uiop/lisp-build.lisp uiop/configuration.lisp uiop/backward-driver.lisp uiop/driver.lisp driver_lisp := uiop/package.lisp uiop/common-lisp.lisp uiop/utility.lisp uiop/os.lisp uiop/pathname.lisp uiop/filesystem.lisp uiop/stream.lisp uiop/image.lisp uiop/run-program.lisp uiop/lisp-build.lisp uiop/configuration.lisp uiop/backward-driver.lisp uiop/driver.lisp
defsystem_lisp := upgrade.lisp component.lisp system.lisp cache.lisp find-system.lisp find-component.lisp operation.lisp action.lisp lisp-action.lisp plan.lisp operate.lisp backward-internals.lisp defsystem.lisp bundle.lisp concatenate-source.lisp output-translations.lisp backward-interface.lisp source-registry.lisp interface.lisp user.lisp footer.lisp defsystem_lisp := upgrade.lisp component.lisp system.lisp cache.lisp find-system.lisp find-component.lisp operation.lisp action.lisp lisp-action.lisp plan.lisp operate.lisp output-translations.lisp source-registry.lisp backward-internals.lisp parse-defsystem.lisp bundle.lisp concatenate-source.lisp backward-interface.lisp package-system.lisp interface.lisp user.lisp footer.lisp
all_lisp := $(header_lisp) $(driver_lisp) $(defsystem_lisp) all_lisp := $(header_lisp) $(driver_lisp) $(defsystem_lisp)
# Making ASDF itself should be our first, default, target: # Making ASDF itself should be our first, default, target:
...@@ -60,6 +57,8 @@ load: build/asdf.lisp ...@@ -60,6 +57,8 @@ load: build/asdf.lisp
install: archive install: archive
bump: bump-version bump: bump-version
git commit -a -m "Bump version to $$(eval a=$$(cat version.lisp-expr) ; echo $$a)"
bump-version: build/asdf.lisp bump-version: build/asdf.lisp
./bin/asdf-builder bump-version ${v} ./bin/asdf-builder bump-version ${v}
...@@ -131,27 +130,53 @@ test: test-lisp test-clean-load test-load-systems doc ...@@ -131,27 +130,53 @@ test: test-lisp test-clean-load test-load-systems doc
test-load-systems: build/asdf.lisp test-load-systems: build/asdf.lisp
./test/run-tests.sh -l ${l} ${s} ./test/run-tests.sh -l ${l} ${s}
test-all-lisps: test-all-lisps: test-load-systems test-all-clean-load test-all-lisp test-all-upgrade
${MAKE} test-load-systems
@for lisp in ${lisps} ; do \
${MAKE} test-lisp test-upgrade test-clean-load l=$$lisp || exit 1 ; \
done
# test upgrade is a very long run... This does just the regression tests test-all-clean-load:
test-all-no-upgrade: @for lisp in ${lisps} ; do ${MAKE} test-clean-load l=$$lisp || exit 1 ; done
@for lisp in ${lisps} ; do \
${MAKE} test-lisp test-clean-load l=$$lisp || exit 1 ; \ test-all-lisp:
done @for lisp in ${lisps} ; do ${MAKE} test-lisp l=$$lisp || exit 1 ; done
test-all-upgrade: test-all-upgrade:
@for lisp in ${lisps} ; do \ @for lisp in ${lisps} ; do ${MAKE} test-upgrade l=$$lisp || exit 1 ; done
${MAKE} test-upgrade l=$$lisp || exit 1 ; \
done test-all-no-upgrade: doc test-load-systems test-all-clean-load test-all-lisp
test-all: test-all-no-upgrade test-all-upgrade
test-all-lisp-no-stop:
@for lisp in ${lisps} ; do ${MAKE} test-lisp l=$$lisp ; done ; :
test-all-upgrade-no-stop:
@for lisp in ${lisps} ; do ${MAKE} test-upgrade l=$$lisp ; done ; :
test-all-no-upgrade-no-stop: doc test-load-systems test-all-clean-load test-all-lisp-no-stop
make --quiet check-all-test-results
test-all-no-stop: doc test-load-systems test-all-clean-load test-all-lisp-no-stop test-all-upgrade-no-stop
make --quiet check-all-results
check-all-test-results:
@A="`grep -L '[5-9][0-9] passing and 0 failing' build/results/*-test.text`" ; \
if [ -n "$$A" ] ; then \
echo "Unexpected test failures on these implementations:" ; \
echo "$$A" ; \
exit 1 ; \
fi
test-all: doc test-all-lisps check-all-upgrade-results:
@A="$$(for i in build/results/*-upgrade.text ; do \
case "$$(tail -1 < $$i)" in "Upgrade test succeeded for "*) ;; \
*) echo $$i ; esac ; done)" ; \
if [ -n "$$A" ] ; then \
echo "Unexpected upgrade failures on these implementations:" ; \
echo "$$A" ; \
exit 1 ; \
fi
test-all-no-stop: check-all-results:
-make doc ; for l in ${lisps} ; do make t l=$$l ; make u l=$$l ; done ; true @r=0 ; make check-all-test-results || r=1 ; make check-all-upgrade-results || r=1 ; exit $r
extract: extract-all-tagged-asdf extract: extract-all-tagged-asdf
extract-all-tagged-asdf: build/asdf.lisp extract-all-tagged-asdf: build/asdf.lisp
......
ASDF: another system definition facility ASDF: Another System Definition Facility
======================================== ========================================
If you cloned our git repository, bootstrap a copy of build/asdf.lisp with: Quick Summary
make -------------
1- Build it with::
make
2- Make sure you put it under a path registered by the source-registry,
if that isn't the case yet (see the manual). One place would be::
~/.local/share/common-lisp/source/asdf/
To use ASDF, read our manual: What is ASDF?
-------------
ASDF is the de facto standard build facility for Common Lisp.
If you come from the C/C++ world, the function ASDF covers a bit of what
each of Make, autoconf, Make, dlopen and libc do for C programs:
it orchestrates the compilation and dependency management,
handles some of the portability issues, dynamically finds and loads code,
and offers some portable system access.
Except everything is different in Common Lisp, and ultimately much simpler,
though it requires acquiring some basic concepts;
notably, ASDF tries to make it all happen in the current Lisp image.
To use ASDF, read our manual::
http://common-lisp.net/project/asdf/asdf.html http://common-lisp.net/project/asdf/asdf.html
The first few sections, Loading ASDF, Configuring ASDF and Using ASDF, The first few sections, Loading ASDF, Configuring ASDF and Using ASDF,
will get you started as a simple user. will get you started as a simple user.
If you want to define your own systems, further read the section If you want to define your own systems, further read the section
Defining systems with defsystem. Defining systems with defsystem.
ASDF 3 now includes an extensive runtime support library: ASDF 3 now includes an extensive runtime support library:
UIOP, the Utilities for Implementation- and OS- Portability. UIOP, the Utilities for Implementation- and OS- Portability.
Its documentation unhappily lies mainly in the source code and docstrings. Its documentation unhappily lies mainly in the source code and docstrings.
See uiop/README for an introduction.
More information and additional links can be found on ASDF's home page at::
More information and additional links can be found on ASDF's home page at:
http://common-lisp.net/project/asdf/ http://common-lisp.net/project/asdf/
Last updated Thursday, April 10th, 2013. Building and testing it
-----------------------
If you cloned our git repository, bootstrap a copy of build/asdf.lisp with::
make
To run all the tests on your favorite Lisp implementation $L,
choose your most elaborate installed system $S, and try::
make t u l=$L s=$S
Debugging tip
-------------
To load ASDF in such a way that M-. will work, install the source code, and run::
(asdf:load-system :uiop) ;; for uiop
(map () 'load ;; for asdf/defsystem
(mapcar 'asdf:component-pathname
(asdf::required-components :asdf/defsystem :keep-component 'asdf:cl-source-file)))
Last updated Wednesday, January 31st, 2014.
* Find out why ABCL fails the timestamp propagation test. * Decree that versions older than 2 years are not supported;
yet, keep supporting an upgrade from whatever vendors provide
— so push them to provide recent stuff.
Already, swank-asdf doesn't support anything older than 2.014.6
(as provided by the first 2011 iteration of Quicklisp), and
I (fare) am pushing for swank-asdf to not support anything older
than 2.019 (still used by LispWorks 6.1).
Hopefully, sometime in 2014, everyone will have adopted ASDF 3.
Maybe remove old versions from upgrade tests; or maybe not:
if we support old versions in any way,
it should be for upgrade only, and "punt" is acceptable.
Upgrade tests might be split in two test sets: short and long.
* Moving toward cross-compilation (ASDF 3.2? 4?)
This would allow to get most of the benefits of XCVB
(reproducibility, scalability, applicability to mobile platforms, etc.),
except without the backward incompatibility of XCVB.
NB: the MOCL author would benefit a lot, and might chip in.
** Need to further split asdf:perform in two parts:
A part that runs on the host and specifies (as SEXP or string to read)
forms that must be evaluated on the target machine, not the host:
(asdf:perform-forms target operation component)
The default implementation can fallback to running the
(asdf:perform operation component) on the target,
which if it is on specially crafted operation and component objects
that do not require recreating the component hierarchy and plan,
but still require loading the defsystem-depends-on dependencies:
on the target:
;; null means the target is the current host.
;; Or should the base class be plan-traversal or such?
(defmethod perform-form ((target null) operation component)
;; :host means execute on the host. () is empty options.
`(:host () (asdf:perform ',op ',comp)))
;; external-target means a cross compiler that we spawn.
(defmethod perform-form ((target external-target) operation component)
`(:target ;; who is to execute that? the target Lisp.
;; options for the performing system:
(:depends-on ,(defsystem-dependencies
(component-system component)))
;; The actual forms to evaluate
(asdf:perform ,(fake-operation-form operation)
,(fake-component-form component))))
By specifying :host-common-lisp you can have forms run on the host.
By specifying :run-program, you can spawn a subprocess without
having to first spawn a Lisp that will call run-program. etc.
The other way around the default perform method could be:
(defmethod perform ((o t) (c t))
(let ((forms (perform-forms nil o c)))
(if (equal forms
`((asdf:perform ',o ',c)))
(error "Missing perform method on ..." ...)
(map () 'eval-thunk forms))))
Note that in the general case, there are multiple forms,
that must be provided on the command line somehow
(see the lisp-invocation system and also how cl-launch does it),
with packages necessary to read latter forms being
created by former forms, so you cannot read everything in one go.
ASDF or at least UIOP should probably be provided in the target
image by default, anyway, without needing to be explicitly specified.
A more declarative interface to needing the defsystem-deps
is probably useful.
** A real cross-compiling backend that works the way of XCVB
would need to compute a complete graph for the plan,
which could be achieved by inheriting from the code in POIU.
Thinking about it, the cross-compiling target object
could actually be the same as the plan object.
The basic case of in-image execution would need to be in ASDF,
while the actual cross-compilation case would be in an extension.
** Audit all the current specializers of perform, and offer them a new way;
they can keep the perform method to run on older versions of ASDF.
** Modify SBCL and other implementations so they provide UIOP
independently from ASDF?
** The default perform-plan method could iterate over pre-computed forms,
in a way that does not involve the ASDF object model anymore,
making ASDF friendlier to self-upgrades.
Then, ASDF wouldn't need to be concatenated during upgrade
— but should still concatenate for bootstrap purposes,
when require'ing it as an implementation-provided module,
compiling from ASDF 2, or otherwise distributing as a single file.
* Implementation bugs
** CMUCL has bugs:
*** In ASDF 2.32.13, sibling-dependencies is renamed to sideway-dependencies
in defclass component, a superclass of system, and upgrade from
2.32 or earlier thus fails with
Error in function KERNEL:CLASS-TYPEP: Class is currently invalid:
#<KERNEL::STANDARD-CLASS ASDF/SYSTEM:SYSTEM {58398145}>
in a direct call from ASDF/FIND-SYSTEM:LOCATE-SYSTEM,
which suggests CMUCL's PCL fails to finalize classes properly.
*** Non-default optimize settings may or may not subtly break PCL.
For the longest time (from 2.26.136 to 3.1.0.42), ASDF had:
(declaim (optimize (speed 1) (safety 3) (debug 3)))
This form may or may not work around that breakage in some cases:
(setf c::top-level-lambda-max 0)
*** At some point there was massive breakage due to uninitialized slots
as revealed in 3.1.0.37 with
make t l=cmucl t=test-encodings.script
which was a different PCL bug from the above (without same workaround)
but possibly also triggered by the non-standard declaim.
** XCL has bad bugs:
make-pathname doesn't handle :type nil properly and
has massive lossage in logical-pathname support.
If using block () and return in search-for-system-definition
instead of return-from, XCL mistakenly has the return jump
to the end of the try function or something.
It also takes a long time for errors to propagate into a debugging REPL —
Maybe O(n^3) behavior or worse in walking the C++ stack?
The backtrace frames may contains unprintable objects.
make-pathname fails to copy the version from the defaults.
(make-pathname :host "ASDFTEST" :directory '(:absolute "system2" "module4")
:name nil :type nil) fails to handle the logical-pathname-ness of ASDFTEST.
** GCL is almost working again; but implementation bugs remain.
See November 2013 discussion on gcl-devel.
* Another GCL compiler bug:
when I changed the definition of getcwd from
(let ((*default-pathname-defaults* #p"")) (truename #p"")) to
(let ((*default-pathname-defaults* *nil-pathname*)) (truename *nil-pathname*))
to guard against e.g. a logical-pathname context while loading asdf
and parsing #p"", calls to getcwd result in a segfault.
* An another bug: gcl refuses dynamic-extent declaration on functions.
uiop/stream.lisp: #-gcl (declare (dynamic-extent ,@(when
before `(#',beforef)) ,@(when after `(#',afterf))))
* (typep p 'logical-pathname) should be T if p has a logical-pathname host.
* apropos is case-sensitive and returns a same symbol many times
* compile-file fails to return proper secondary values in case of non-style WARNING.
* (pathname-directory #p"foo/") is incorrectly ("foo") instead of (:RELATIVE "foo")
* Missing: chdir, combine-fasls, and plenty more UIOP functions.
* Do whatever it takes to pass the asdf tests, add the above?
* Have (require "asdf") and (require "ASDF") both work.
* Trying to uiop:slurp-stream-forms from a stream with #+(or) :foo
(or read-file-forms from an file with same) results in an error,
rather than nil. This is probably a bug in #+ processing.
Unhappily, debian creates such a file in
/etc/common-lisp/asdf-output-translations.conf.d/01-common-lisp-controller.conf
* Tests that try to catch an error fail (but catching a warning succeeds),
which suggests brokenness in handler-bind and/or error.
** Find out why ABCL fails the timestamp propagation test.
** ECL has issues with its bundles.
On MacOS X, test-bundle.script fails.
On Linux, test-program.script fails with recent ECL 237af2e,
but used to work quite fine earlier in 2013.
* Find an easier way to bind variables around compilation and loading of files
* Design & Implement some out-of-line configuration mechanism for various options?
i.e. let configuration files override some variables around some actions.
* Could be used to override new backward-incompatible defaults
(e.g. for operation propagation, deferred warnings, etc.)
* Use the above variable binding mechanism.
* Fix bugs on http://bugs.launchpad.net/asdf/+bugs * Fix bugs on http://bugs.launchpad.net/asdf/+bugs
* fix directory-files to not return directories on CCL, etc. Add tests. ** fix directory-files to not return directories on CCL, etc. Add tests.
* use cl-test-grid to see if asdf-user can :use most (all?) of UIOP.
Unhappily, on SBCL, sb-grovel uses asdf and sb-ext, * Learn to use cl-grid-test
which causes a clash with run-program. ** So we can easily make sure ASDF changes don't break stuff,
Or has this been changed long enough ago? Can it be special-cased? and that breakage gets fixed quickly.
** So we see if ASDF-USER can :use most (all?) of UIOP.
SB-GROVEL used (until 25c1769 from 2013-02-23) to :use both ASDF and
SB-EXT, which prevents ASDF from exporting RUN-PROGRAM, but
should not be a problem with ASDF-USER :use'ing UIOP.
A run of quicklisp is necessary, with an eye also for warnings
from .asd's that might be overriding definitions in UIOP(!)
* have a mode to explain WHY a component needs to be recompiled. * have a mode to explain WHY a component needs to be recompiled.
* have a better defsystem form verifier - see lp#1007335
* have a function verify-strict-asd that can verify a asd is pure lp#541562 * Improve robustness
** have a better defsystem form verifier - see lp#1007335
** have a function verify-strict-asd that can verify a asd is pure lp#541562
Then if it passes, use load-strict-asd. Then if it passes, use load-strict-asd.
If not, optionally issue a warning. Start migrating people toward that. If not, optionally issue a warning. Start migrating people toward that.
* have with-input-file use the encodings mechanism? * have with-input-file use the encodings mechanism?
** Import asdf-encodings into UIOP? Sounds a lot of code for no users.
* have a single test .asd that tests as many features as possible, use it for upgrade test. * have a single test .asd that tests as many features as possible, use it for upgrade test.
* implement deferred warnings support on lispworks
* work with cl-test-grid to eliminate deferred warnings from quicklisp libraries
* fix upgrade on clisp, cmucl, abcl (if still broken)
** Extract minimal test case, build a battery of automated tests
* Bug found by fe[nl]ix: infinite loop if the definitions in an asd file * Bug found by fe[nl]ix: infinite loop if the definitions in an asd file
are not in strict defsystem-depends-on dependency order. are not in strict defsystem-depends-on dependency order.
** At least document the issue. ** At least document the issue.
** Real solution: defer parsing and evaluation of defsystem forms. ** Real solution: defer parsing and evaluation of defsystem forms.
* Learn to use cl-grid-test, to make sure ASDF changes don't break stuff,
and that breakage gets fixed quickly. * Include some ABL test for stassats's (now obsolete?) thing:
* Include some ABL test for stassats's thing:
(asdf:enable-asdf-binary-locations-compatibility (asdf:enable-asdf-binary-locations-compatibility
:centralize-lisp-binaries t :default-toplevel-directory *fasl-dir*) :centralize-lisp-binaries t :default-toplevel-directory
*fasl-dir*)
** Or deprecate and remove ABL compatibility altogether?
No one has been using ASDF1 for years.
There is no ABL to be compatible with —
is anyone still using the compatibility mode?
Maybe issue a warning, then a cerror, before to remove the code?
* Make load-op a generic operation that selects the proper strategy * Make load-op a generic operation that selects the proper strategy
for each system, module or file, according to component properties and user-configuration: for each system, module or file, according to component properties and user-configuration:
compile the lisp file then load the fasl (load-fasl-op on a cl-source-file), compile the lisp file then load the fasl (load-fasl-op on a cl-source-file),
...@@ -35,9 +209,38 @@ ...@@ -35,9 +209,38 @@
concatenate all files for the system, then load the result (load-concatenated-source-op), concatenate all files for the system, then load the result (load-concatenated-source-op),
concatenate all files for the system, then link them and load the result (load-compiled-concatenated-op), concatenate all files for the system, then link them and load the result (load-compiled-concatenated-op),
concatenate all files for the system *and* its dependencies, link and load (monolithic-load-compiled-concatenated-op). concatenate all files for the system *and* its dependencies, link and load (monolithic-load-compiled-concatenated-op).
* operation cleanup? * operation cleanup?
** Kill backward-compat functions after all clients have moved on. ** Kill backward-compat functions after all clients have moved on.
** Kill original-initargs -- BEWARE, it currently has clients! ** Kill original-initargs -- BEWARE, it currently has clients!
** To allow semantically distinct operations of the same class:
You'd need to have a protocol to canonicalize them
in the *OPERATIONS* memoization table, not by class name,
but by CONS of the class name and some CANONICAL-OPERATION-INITARGS.
The latter would be a generic function called on the initargs,
where any parasite initargs such as FORCE and FORCE-NOT have been removed,
since they below to the PLAN, not the OPERATION:
the OPERATE protocol would be refined to explicit split
arguments to be passed to MAKE-PLAN or to MAKE-OPERATION.
The default method for CANONICAL-OPERATION-INITARGS
would SORT (a plist->alist of) the initargs,
and that would replace the current ORIGINAL-INITARGS slot.
For this scheme to work even in presence of undisciplined users
using MAKE-INSTANCE on an operation class,
the OPERATION class would have an extra slot EFFECTIVE-OPERATION,
uninitialized by default (nil or unbound), whose accessor initializes it
if it's uninitialized, by looking up a canonical instance in *OPERATIONS*,
and if unfound registering the current operation as canonical.
Then, each component's COMPONENT-OPERATION-TIME hash-table
would be indexed by canonicalized operation object
rather than by operation class,
and POIU would have to be changed accordingly.
Of course, this entire cleanup is incompatible
with how SWANK and GBBopen currently abuse slots of operation,
so these would have to be fixed first.
And that's why I didn't do it.
It looks like SWANK can be fixed soon, though, so we'll see.
* Get rid of component-properties * Get rid of component-properties
** directly use component-properties: ** directly use component-properties:
*** yaclml.asd => misguided :features for version comparison *** yaclml.asd => misguided :features for version comparison
...@@ -109,6 +312,19 @@ ...@@ -109,6 +312,19 @@
*** com.clearly-useful.generic-collection-interface => :com.clearly-useful *** com.clearly-useful.generic-collection-interface => :com.clearly-useful
*** metatilities *** metatilities
=> :ait-timeout :system-applicable-p => :ait-timeout :system-applicable-p
*** ucw ucw-core *** ucw ucw-core
=> =>
version version
* ASDF4: search for this tag, rename things (incompatibly, thus) and cleanup code.
* See message from 2014-01-27 05:26:44 GMT for stuff to document.
http://thread.gmane.org/gmane.lisp.asdf.devel/3675/focus=3695
* deferred-warnings support probably needs to be redone better.
* implement deferred warnings support on lispworks
* turn undefined function style-warnings into full warnings(?)
* work with cl-test-grid to eliminate deferred warnings from quicklisp libraries
* https://www.mail-archive.com/asdf-devel@common-lisp.net/msg03608.html
* czak@google.com rewrote part of deferred warnings support.
Ask him for the code he implemented at Google.
;;;; ------------------------------------------------------------------------- ;;;; -------------------------------------------------------------------------
;;;; Actions ;;;; Actions
(asdf/package:define-package :asdf/action (uiop/package:define-package :asdf/action
(:nicknames :asdf-action) (:nicknames :asdf-action)
(:recycle :asdf/action :asdf) (:recycle :asdf/action :asdf)
(:use :uiop/common-lisp :uiop :asdf/upgrade (:use :uiop/common-lisp :uiop :asdf/upgrade
...@@ -9,18 +9,27 @@ ...@@ -9,18 +9,27 @@
(:export (:export
#:action #:define-convenience-action-methods #:action #:define-convenience-action-methods
#:explain #:action-description #:explain #:action-description
#:downward-operation #:upward-operation #:sideway-operation #:selfward-operation #:downward-operation #:upward-operation #:sideway-operation #:selfward-operation #:non-propagating-operation
#:component-depends-on #:component-depends-on
#:input-files #:output-files #:output-file #:operation-done-p #:input-files #:output-files #:output-file #:operation-done-p
#:action-status #:action-stamp #:action-done-p #:action-status #:action-stamp #:action-done-p
#:component-operation-time #:mark-operation-done #:compute-action-stamp #:component-operation-time #:mark-operation-done #:compute-action-stamp
#:perform #:perform-with-restarts #:retry #:accept #:perform #:perform-with-restarts #:retry #:accept
#:traverse-actions #:traverse-sub-actions #:required-components ;; in plan #:traverse-actions #:traverse-sub-actions #:required-components ;; in plan
#:action-path #:find-action #:stamp #:done-p)) #:action-path #:find-action #:stamp #:done-p
#:operation-definition-warning #:operation-definition-error ;; condition
#:build-op ;; THE generic operation
))
(in-package :asdf/action) (in-package :asdf/action)
(eval-when (#-lispworks :compile-toplevel :load-toplevel :execute) (eval-when (#-lispworks :compile-toplevel :load-toplevel :execute) ;; LispWorks issues spurious warning
(deftype action () '(cons operation component))) ;; a step to be performed while building (deftype action () '(cons operation component)) ;; a step to be performed while building
(deftype operation-designator ()
;; an operation designates itself,
;; nil designates a context-dependent current operation, and
;; class-name or class designates an instance of the designated class.
'(or operation null symbol class)))
(with-upgradability () (with-upgradability ()
(defgeneric traverse-actions (actions &key &allow-other-keys)) (defgeneric traverse-actions (actions &key &allow-other-keys))
...@@ -106,7 +115,14 @@ You can put together sentences using this phrase.")) ...@@ -106,7 +115,14 @@ You can put together sentences using this phrase."))
and each <component> is a component designator with respect to and each <component> is a component designator with respect to
FIND-COMPONENT in the context of the COMPONENT argument, FIND-COMPONENT in the context of the COMPONENT argument,
and means that the component depends on and means that the component depends on
<operation> having been performed on each <component>; or <operation> having been performed on each <component>;
[Note: an <operation> is an operation designator -- it can be either an
operation name or an operation object. Similarly, a <component> may be
a component name or a component object. Also note that, the degenerate
case of (<operation>) is a no-op.]
or
(FEATURE <feature>), which means that the component depends (FEATURE <feature>), which means that the component depends
on the <feature> expression satisfying FEATUREP. on the <feature> expression satisfying FEATUREP.
...@@ -118,54 +134,135 @@ You can put together sentences using this phrase.")) ...@@ -118,54 +134,135 @@ You can put together sentences using this phrase."))
(defmethod component-depends-on :around ((o operation) (c component)) (defmethod component-depends-on :around ((o operation) (c component))
(do-asdf-cache `(component-depends-on ,o ,c) (do-asdf-cache `(component-depends-on ,o ,c)
(call-next-method))) (call-next-method))))
(defmethod component-depends-on ((o operation) (c component))
(cdr (assoc (type-of o) (component-in-order-to c))))) ; User-specified in-order dependencies
;;;; upward-operation, downward-operation ;;;; upward-operation, downward-operation, sideway-operation, selfward-operation
;; These together handle actions that propagate along the component hierarchy. ;; These together handle actions that propagate along the component hierarchy or operation universe.
;; Downward operations like load-op or compile-op propagate down the hierarchy:
;; operation on a parent depends-on operation on its children.
;; By default, an operation propagates itself, but it may propagate another one instead.
(with-upgradability () (with-upgradability ()
(defclass downward-operation (operation) (defclass downward-operation (operation)
((downward-operation ((downward-operation
:initform nil :initarg :downward-operation :reader downward-operation :allocation :class))) :initform nil :reader downward-operation
:type operation-designator :allocation :class))
(:documentation "A DOWNWARD-OPERATION's dependencies propagate down the component hierarchy.
I.e., if O is a DOWNWARD-OPERATION and its DOWNWARD-OPERATION slot designates operation D, then
the action (O . M) of O on module M will depends on each of (D . C) for each child C of module M.
The default value for slot DOWNWARD-OPERATION is NIL, which designates the operation O itself.
E.g. in order for a MODULE to be loaded with LOAD-OP (resp. compiled with COMPILE-OP), all the
children of the MODULE must have been loaded with LOAD-OP (resp. compiled with COMPILE-OP."))
(defun downward-operation-depends-on (o c)
`((,(or (downward-operation o) o) ,@(component-children c))))
(defmethod component-depends-on ((o downward-operation) (c parent-component)) (defmethod component-depends-on ((o downward-operation) (c parent-component))
`((,(or (downward-operation o) o) ,@(component-children c)) ,@(call-next-method)))