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? Commented Nov 11, 2013 at 17:03
  • @umlaute it's 1 Commented Nov 11, 2013 at 17:13
  • @umlaute ok so replacing 'diff' with '-diff' fixes it - it was a Makefile thing Commented 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. Commented Nov 11, 2013 at 18:27
  • @derobert your assumption is correct. I note as much at the beginning of my post ("Narrow-down ..") Commented 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... Commented 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 Commented 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, … Commented 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. Commented Nov 12, 2013 at 0:31
  • @derobert diff and cmp ask “are these files identical?” Commented Nov 12, 2013 at 0:38

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.