module is not recompiled if _intra_-system dependency changes

Bug #502946 reported by Tobias C. Rittweiler on 2010-01-04
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
ASDF
High
Unassigned

Bug Description

Test script:

#!/bin/bash

set -x

SBCL=sbcl-git

cd /tmp
touch foo.asd
touch bar.lisp
mkdir -p quux
touch quux/zurp.lisp

cat > foo.asd <<EOF
(asdf:defsystem :foo
  :components ((:file "bar")
               (:module "quux"
                        :depends-on ("bar")
                        :components ((:file "zurp")))))
EOF

$SBCL <<EOF
(load "/tmp/foo.asd")
(asdf:load-system :foo)
EOF

touch bar.lisp

$SBCL <<EOF
(load "/tmp/foo.asd")
(asdf:load-system :foo)
EOF

Output:

tcr@thaleron:/tmp$ ./asdf-test.sh
+ SBCL=sbcl-git
+ cd /tmp
+ touch foo.asd
+ touch bar.lisp
+ mkdir -p quux
+ touch quux/zurp.lisp
+ cat
+ sbcl-git
This is SBCL 1.0.33.4, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
*
T
*
; compiling file "/tmp/bar.lisp" (written 04 JAN 2010 02:35:53 PM):

; /tmp/bar.fasl written
; compilation finished in 0:00:00.001
; compiling file "/tmp/quux/zurp.lisp" (written 04 JAN 2010 02:35:53 PM):

; /tmp/quux/zurp.fasl written
; compilation finished in 0:00:00.001
NIL
* + touch bar.lisp
+ sbcl-git
This is SBCL 1.0.33.4, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
*
T
*
; compiling file "/tmp/bar.lisp" (written 04 JAN 2010 02:35:59 PM):

; /tmp/bar.fasl written
; compilation finished in 0:00:00.002
NIL
* tcr@thaleron:/tmp$

As you can see, the second time, only /tmp/bar.lisp is recompiled but not the contents
of the /tmp/quux/ module.

Ironclad uses this kind of dependency setup.

It's not clear that you need to recompile if the inter-system dependency
changes, unless the API has changed, and in particular in ways that
affect the behavior of downstream systems (e.g., macro definitions change).

ISTR that some Lisp defsystems made it possible for the programmer to
annotate them as providing things like macro definitions that should
trigger recompilation downstream. I think it would be good to add
something like that to ASDF. I believe that this is the semantics of
the :definitions spec in Franz's version of defsystem, but I can't say
for sure, never having used that defsystem.

Tobias C. Rittweiler (tcr) wrote :

"Robert P. Goldman" <email address hidden> writes:

> It's not clear that you need to recompile if the inter-system dependency
> changes, unless the API has changed, and in particular in ways that
> affect the behavior of downstream systems (e.g., macro definitions change).

The subject line was slightly incorrect. It's not about inter-system
dependency which Bug #479522 is about.

This is about _intra_-system dependencies.

(:file)s depending on other (:file)s are recompiled, too. Why should
(:module)s not be recompiled if they depend on (:file)s and those
change?

  -T.

--
Diese Nachricht wurde auf Viren und andere gefaerliche Inhalte untersucht
und ist - aktuelle Virenscanner vorausgesetzt - sauber.
Freebits E-Mail Virus Scanner

summary: - module is not recompiled if inter-system dependency changes
+ module is not recompiled if _intra_-system dependency changes
Robert P. Goldman (rpgoldman) wrote :

I looked at the source to TRAVERSE and I don't claim to understand it fully in the time available, but I suspect that this may, in fact, be the same issue as the inter-system issue. It looks like the logic there is all conditioned on whether a component is a module. In the ASDF class hierarchy, a system isa module isa component, and a cl-source-file isa component (and is NOT a subclass of module).

I suspect that solving this for the module case will involve refactoring the class hierarchy so that there is some "internal" class that holds components and that would be the common parent of both module and system.

Robert P. Goldman (rpgoldman) wrote :

Interim notes on progress:

I have written (but not yet committed, since it fails) a test case based on tcr's example above.

I believe I understand the problem more clearly. The problem occurs in TRAVERSE and it happens because a module's components do NOT inherit their parent's dependencies, which seems clearly wrong. I.e., if I say module "quux" depends on "bar" and "quux" contains file "zurp," zurp does NOT depend on bar and is not recompiled if bar is recompiled.

If you do a test case like tcr's and you touch bar, then call traverse, you will see in the plan that ASDF tries to compile and load "quux", but operation-done-p compile-op zurp returns T, and ASDF does not recompile zurp.

Side note: looking at TRAVERSE to fix this, I see that the conditions for applying an operator to a module are a four element disjunction. The first three are simple to understand, but the fourth is a complex let that is --- alas --- uncommented. Anyone have any idea what that is trying to do?

Robert P. Goldman (rpgoldman) wrote :

Fix committed to asdf git repo on module-depends branch (NOT master!).

Changed in asdf:
status: New → Fix Committed
Changed in asdf:
milestone: none → version2
Changed in asdf:
importance: Undecided → High
Faré (fahree) wrote :

Robert P. Goldman fixed this in 1.608.

Changed in asdf:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers