diff --git a/doc/Changelog b/doc/Changelog index 942b513c86fadbcb7b1b0b1fbb8e3c66979f686c..6a2c48eaec8c63f623af38a17a5f0b437c5b9f5b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,6 @@ cl-asdf (2:3.3.5-1) unstable; urgency=low IN PROGRESS +* Fix bug in handling combination of :serial and :if-feature dependencies. * Add support for package local nicknames to UIOP:DEFINE-PACKAGE and ASDF's package-inferred systems. Extend support for package local nicknames to more lisp implementations. diff --git a/parse-defsystem.lisp b/parse-defsystem.lisp index 083f9082cd9d725c3d81d306df6e7614c7f0a68c..fa6170bed8b0b73c910d629b9f953a70cee00d2e 100644 --- a/parse-defsystem.lisp +++ b/parse-defsystem.lisp @@ -268,7 +268,43 @@ Please only define ~S and secondary systems with a name starting with ~S (e.g. ~ system names contained using COERCE-NAME. Return the result." (mapcar 'parse-dependency-def dd-list)) - (defun* (parse-component-form) (parent options &key previous-serial-component) + ;;; Helper function for parse-component-form. Sets the CHILDREN slot of + ;;; COMPONENT, using COMPONENTS list, and adds dependency links if + ;;; the COMPONENT is a serial component. Should ONLY be called on a + ;;; PARENT-COMPONENT. + ;;; Returns the list of child components -- it's not entirely clear to me + ;;; what is the set of possible values for elements of this list. + (declaim (ftype (function (parent-component list (or t nil)) t) + compute-component-children) + (ftype (function ((or parent-component null) list &key (:previous-serial-components list))) + parse-component-form)) + + (defun* compute-component-children (component components serial-p) + (prog1 + (setf (component-children component) + (loop + :with previous-components = nil ; list of strings + :for c-form :in components + :for c = (parse-component-form component c-form + :previous-serial-components previous-components) + :for name :of-type string = (component-name c) + :collect c + :when serial-p + ;; if this is an if-feature component, we need to make a serial link + ;; from previous components to following components -- otherwise should + ;; the IF-FEATURE component drop out, the chain of serial dependencies will be + ;; broken. + :unless (component-if-feature c) + :do (setf previous-components nil) + :end + :and :do (push name previous-components))) + (compute-children-by-name component))) + + (defun* stable-union (s1 s2 &key (test #'eql) (key 'identity)) + (append s1 + (remove-if #'(lambda (e2) (member (funcall key e2) (funcall key s1) :test test)) s2))) + + (defun* (parse-component-form) (parent options &key previous-serial-components) (destructuring-bind (type name &rest rest &key (builtin-system-p () bspp) @@ -320,18 +356,9 @@ system names contained using COERCE-NAME. Return the result." ;; A better fix is required. (setf (slot-value component 'version) version) (when (typep component 'parent-component) - (setf (component-children component) - (loop - :with previous-component = nil - :for c-form :in components - :for c = (parse-component-form component c-form - :previous-serial-component previous-component) - :for name = (component-name c) - :collect c - :when serial :do (setf previous-component name))) - (compute-children-by-name component)) - (when previous-serial-component - (push previous-serial-component depends-on)) + (compute-component-children component components serial)) + (when previous-serial-components + (setf depends-on (stable-union depends-on previous-serial-components :test #'equal))) (when weakly-depends-on ;; ASDF4: deprecate this feature and remove it. (appendf depends-on @@ -343,7 +370,7 @@ system names contained using COERCE-NAME. Return the result." (error "The system definition for ~S uses deprecated ~ ASDF option :IF-COMPONENT-DEP-FAILS. ~ Starting with ASDF 3, please use :IF-FEATURE instead" - (coerce-name (component-system component)))) + (coerce-name (component-system component)))) component))) ;; the following are all systems that Stas Boukarev maintains and refuses to fix, diff --git a/test/test-serial-dependencies.asd b/test/test-serial-dependencies.asd new file mode 100644 index 0000000000000000000000000000000000000000..33b4c32836e63fface1f7d97e7b02d64103b9e13 --- /dev/null +++ b/test/test-serial-dependencies.asd @@ -0,0 +1,10 @@ +;;; This test example shows a failure in propagating serial dependencies across :if-feature +;;; conditionalization. + +(asdf:defsystem test-serial-dependencies + :serial t + :components ((:file "file1") + (:file "file4" :if-feature :undef) + (:file "file3" :if-feature :undef) + ;; we expect an error loading here, because file1 won't be loaded + (:file "file2"))) diff --git a/test/test-serial-dependencies.script b/test/test-serial-dependencies.script new file mode 100644 index 0000000000000000000000000000000000000000..d47036843683d8663b000f21598a50ed346dedfc --- /dev/null +++ b/test/test-serial-dependencies.script @@ -0,0 +1,14 @@ +;;; -*- mode: common-lisp; -*- + +(in-package :asdf-test) + +(configure-asdf) + +;;; According to Gitlab issue 39, this should cause an error. We can't use +;;; LOAD-SYSTEM because LOAD-OP is a downward operation. Therefore the plan +;;; will always have a LOAD-OP on every source file of the system (in serial +;;; order). +;;; +(asdf:operate 'asdf:load-op + (asdf:find-component (asdf:find-system "test-serial-dependencies") + (list "file2")))