8

Narrow-down of a patch problem I am trying to troubleshoot: Only two files, each with a size of 1 byte:

  • file a (containing 'a')
  • file b (containing 'b') and

Goal is to make and then apply a patch that will change the value of 'b' to 'a'. Contents of Makefile are:

patch:
        diff -u b a > b2a.patch
        patch -o b.corrected b < b2a.patch
        diff a b.corrected

clean:
        rm -f b2a.patch b.corrected

Given the above, make fails with the following output:

$ make
diff -u b a > b2a.patch
make: *** [patch] Error 1

If, however, I execute the commands in the Makefile one after the other on the bash shell, there is no problem at all.

5
  • 1
    what's the exit code of diff when you run it manually?
    – umläute
    Nov 11, 2013 at 17:03
  • @umlaute it's 1 Nov 11, 2013 at 17:13
  • @umlaute ok so replacing 'diff' with '-diff' fixes it - it was a Makefile thing Nov 11, 2013 at 17:16
  • I'm at a loss on why you want to make and then immediately apply the patch... e.g., why not just use cp? Since that doesn't really make much sense, I assume this is a simplified test case.
    – derobert
    Nov 11, 2013 at 18:27
  • @derobert your assumption is correct. I note as much at the beginning of my post ("Narrow-down ..") Nov 11, 2013 at 19:10

1 Answer 1

12

Make assumes that an exit code of 0 means success, anything else means failure. This is the standard convention used by almost all command-line tools.

Unfortunately, diff is not one of those. Checking the GNU diff info page, and also the Single Unix Specification "diff" entry, 0 means no differences found, 1 means differences found, and ≥2 means error.

You can tell Make to ignore the exit status entirely by prefixing the command with a hyphen, as you did in your comment, but this will ignore actual errors—probably not what you want. Instead, you can:

patch:
        diff -u b a > b2a.patch; [ $$? -eq 1 ]
        patch -o b.corrected b < b2a.patch
        diff a b.corrected; [ $$? -eq 1 ]

Note the ; [ $$? -eq 1 ] bit I've added to the end of the two diff lines. You can use ; test $$? -eq 1 as well, of course. The $? shell variable is $$? due to normal Makefile escaping conventions. Note this also rejects exit status 0 (no differences), which is probably what you want.

BTW: it appears this really ought to be:

patch: b.corrected
        diff …
b.corrected: b2a.patch
        patch …
b2a.patch: a b
        diff …

so that modifications of a and b get picked up, and the files regenerated correctly.

6
  • @Bananguin Thanks for the edit, that probably is true. I'm not entirely sure what OP is trying accomplish...
    – derobert
    Nov 11, 2013 at 18:26
  • actually i just felt bad because your version was not wrong, just one corner too much for me to handle before dinner. still, it's more spelled out now :D
    – Bananguin
    Nov 11, 2013 at 18:29
  • The Unix convention for return codes is a bit broader than “0 for success, >0 for failure”. For commands that return a boolean result, the convention is “0 for yes, 1 for no, >1 for failure”. diff is an example of this, as are grep, test, … Nov 12, 2013 at 0:09
  • @Gilles Well, diff would ask "are these files different?"... Arguably, diff is backwards. But I guess both it and cmp both return 0 for match, 1 for differ.
    – derobert
    Nov 12, 2013 at 0:31
  • @derobert diff and cmp ask “are these files identical?” Nov 12, 2013 at 0:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .