bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Erroneously not updating intermediate/secondary dependency


From: Martin Dorey
Subject: Re: Erroneously not updating intermediate/secondary dependency
Date: Fri, 22 Feb 2019 20:39:25 +0000

make kindaclean; make --debug=all says:

    Finished prerequisites of target file 'a-derived.src'.
    Prerequisite 'a.out' of target 'a-derived.src' does not exist.
   No need to remake target 'a-derived.src'.

https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html#Chained-Rules teaches:

The first difference is what happens if the intermediate file does not exist. If an ordinary file b does not exist, and make considers a target that depends on b, it invariably creates b and then updates the target from b. But if b is an intermediate file, then make can leave well enough alone. It won’t bother updating b, or the ultimate target, unless some prerequisite of b is newer than that target or there is some other reason to update that target.

By using .SECONDARY with no prerequisites, you've marked everything as intermediate.  Marking just a.out as .SECONDARY seems enough to cause the problem.


From: Bug-make <bug-make-bounces+address@hidden> on behalf of Luke Shumaker <address@hidden>
Sent: Friday, February 22, 2019 11:45
To: address@hidden
Subject: Erroneously not updating intermediate/secondary dependency
 
***** EXTERNAL EMAIL *****

I believe that I have found a bug present in both Make 4.2.1 (as shipped by Arch
Linux) and in the latest git commit (214865ed5c66d8e363b16ea74509f23d93456707).

Here is a simple Makefile demonstrating the bug:

        all: a-derived.out
        .PHONY: all

        kindaclean:
                rm -f -- *.out
        clean: kindaclean
                rm -f -- a-derived.src
        .PHONY: kindaclean clean

        %.out: %.src
                { echo 'build'; date; ls -l $^; } > $@

        a-derived.src: a.out
                { echo 'generate'; date; ls -l $^; } > $@
        a-derived.out: a.out # Make sure that "a.out" isn't skipped as intermediate

        .SECONDARY:

For clarity, here is the dependency graph; "==" indicates an explicit
rule, "--" indicates an implicit rule:

        all >===> a-derived.out >---> a-derived.src >===> a.out >---> a.src
                               `>=======================>'

The bug is that when running

        $ echo foo > a.src

        $ make
        { echo 'build'; date; ls -l a.src; } > a.out
        { echo 'generate'; date; ls -l a.out; } > a-derived.src
        { echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out

        $ make kindaclean
        rm -f -- *.out

        $ make
        { echo 'build'; date; ls -l a.src; } > a.out
        { echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out

The "a-derived.src" does not get updated, despite both of thes
conditions being met: (1) its dependency "a.out" getting updated, and
(2) it being used in a later recipe.

We can instrument the Makefile to more explicitly demonstrate the
failure:

        define sanitycheck
          if ! test -e $1; then \
            echo '=> dependency "$(strip $1): $(strip $2)" skipped because dependent "$(strip $1)" does not exist'; \
          elif ! test -e $2; then \
            echo '=> dependency "$(strip $1): $(strip $2)" skipped because dependency "$(strip $2)" does not exist'; \
          elif test $2 -nt $1; then \
            echo '=> dependency "$(strip $1): $(strip $2)" failed because dependency "$(strip $2)" is newer than dependant "$(strip $1)"'; \
            ls -l $1 $2; \
            exit 1; \
          else \
            echo '=> dependency "$(strip $1): $(strip $2)" passed'; \
          fi
        endef

        all: a-derived.out
                @$(call sanitycheck, a.out         , a.src         )
                @$(call sanitycheck, a-derived.src , a.out         )
                @$(call sanitycheck, a-derived.out , a-derived.src )
        .PHONY: all

        kindaclean:
                rm -f -- *.out
        clean: kindaclean
                rm -f -- a-derived.src
        .PHONY: kindaclean clean

        %.out: %.src
                { echo 'build'; date; ls -l $^; } > $@

        a-derived.src: a.out
                { echo 'generate'; date; ls -l $^; } > $@
        a-derived.out: a.out # Make sure that "a.out" isn't skipped as intermediate

        .SECONDARY:

Which yields:

        $ echo foo > a.src

        $ make
        { echo 'build'; date; ls -l a.src; } > a.out
        { echo 'generate'; date; ls -l a.out; } > a-derived.src
        { echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out
        => dependency "a.out: a.src" passed
        => dependency "a-derived.src: a.out" passed
        => dependency "a-derived.out: a-derived.src" passed

        $ make kindaclean
        rm -f -- *.out

    $ # wait a momenent, so the timestamps are visibly different

        $ make
        { echo 'build'; date; ls -l a.src; } > a.out
        { echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out
        => dependency "a.out: a.src" passed
        => dependency "a-derived.src: a.out" failed because dependency "a.out" is newer than dependant "a-derived.src"
        -rw-r--r-- 1 lukeshu lukeshu 89 Feb 22 13:45 a-derived.src
        -rw-r--r-- 1 lukeshu lukeshu 85 Feb 22 13:47 a.out
        make: *** [Makefile:17: all] Error 1

--
Happy hacking,
~ Luke Shumaker

_______________________________________________
Bug-make mailing list
address@hidden
https://nam04.safelinks.protection.outlook.com/?url="">

reply via email to

[Prev in Thread] Current Thread [Next in Thread]