1

I have a make file that is always re-running a rule despite the prerequisite being up-to-date:

data.tar.bz2: data.tar
    bzip2 --keep data.tar

# The following rule always runs the rule for its prerequisite
# even if it is up-to-date. Note that it doesn't matter whether
# the bunzip2 directory exists or not. I suppose is has something
# to do with the dir/file naming of the rule but I haven't been
# able to decipher why.
bunzip2/data2.tar: data.tar.bz2
    mkdir bunzip2 && cd bunzip2 && bzip2 -ckd ../data.tar.bz2 > data2.tar && cd ..

.PHONY: clean
clean:
    rm -f data.tar.bz2
    rm -Rf bunzip2

Any ideas appreciated.

SO Stinks
  • 3,258
  • 4
  • 32
  • 37

3 Answers3

1

Something is missing from the example - but the process for analysis is the same, regardless: you can use the debug feature of make to see what rules it uses, e.g.,

make -d
Almo
  • 15,538
  • 13
  • 67
  • 95
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
1

I think I figured out what was going on here.

Using @Thomas Dickey advice to try make -d, it was saying that the file data.tar.bz2 was newer than data.tar itself. That seems silly because the former is created from the later. But using ls --full-time shows bzip2 archive seems use the timestamp of the source file but it also truncates it after the second place. In my case, the timestamp 2015-03-12 09:32:02.452091888 was getting truncated to 2015-03-12 09:32:02.000000000 which makes it appear to be newer than the source. (By truncate I mean that 2015-03-12 13:10:29.681793152 goes to 2015-03-12 13:10:29.000000000... it does not round up even in that case) Seems like bzip needs to bump the accuracy of their timestamps.

It appears that lunzip also truncates the timestamp and unxz preserves the original timestamp while gzip uses the current time. In other words, be careful with your makefiles when using compression utilities because they handle things differently.

SO Stinks
  • 3,258
  • 4
  • 32
  • 37
1

The standard POSIX system calls that set timestamps on files do not support sub-second accuracy. In order for these tools to set a specific time on a file (which they try to do so that the compressed file has the same timestamp as the original file) and preserve the original accuracy they need to use different system calls; apparently they don't do so.

What you can do to work around this is change your rule like this:

data.tar.bz2: data.tar
        bzip2 --keep data.tar && touch $@

so that the timestamp of the target is set to "now".

ETA The traditional system call for setting modification times on files is utime() which accepts timestamps only in increments of one second. Newer versions of the POSIX spec introduced utimensat() which allows nanosecond timestamp settings. There is also utimes() which allows microsecond accuracy but which has been considered "legacy" for a long time now.

If this behavior exists in the current latest release of bzip2, I would consider it a bug worthy of a bug report to them.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • Yep. Touch was my workaround after I discovered the issue. Thanks for mentioning POSIX. – SO Stinks Mar 12 '15 at 16:01
  • I'm running Debian Wheezy. For what it's worth, I have bzip2 v1.0.6, lzip v1.13 (with lunzip v1.1), and unxz 5.1.0alpha. Seems as if bzip2 v1.0.6 (from 2010!) *is* [the current release](http://www.bzip.org/downloads.html) while lzip (v1.16) and xz (v5.2.1) are not. – SO Stinks Mar 12 '15 at 17:01
  • I don't have the reputation to define a new tag but if you could add "lzip" as a tag to this question, that'd be beneficial. – SO Stinks Mar 12 '15 at 17:27