63

After years of not using make, I find myself needing it again, the gnu version now. I'm pretty sure I should be able to do what I want, but haven't figured out how, or found an answer with Google, etc.

I'm trying to create a test target which will execute my program a number of times, saving the results in a log file. Some tests should cause my program to abort. Unfortunately, my makefile aborts on the first test which leads to an error. I have something like:

# Makefile
# 
test:
        myProg -h > test.log              # Display help
        myProg good_input >> test.log     # should run fine
        myProg bad_input1 >> test.log      # Error 1
        myProg bad_input2 >> test.log      # Error 2

With the above, make quits after the bad_input1 run, never getting to the bad_input2 run.

JBRWilkinson
  • 4,821
  • 1
  • 24
  • 36
GreenMatt
  • 18,244
  • 7
  • 53
  • 79
  • Make is not well suited to this. You can run into a number of issues including: `in | a | piped | sequence`, the last one determines the exit code; `a; more; involved; recipe; line;` suffers from the same problem; without jumping through a lot of hurdles, running the same thing repeatedly with different parameters can be annoying to script. I've typically opted for scripting my tests, then if necessary use it from a makefile. – Brian Vandenberg Oct 02 '15 at 20:28
  • As an alternative [`set -e`](http://stackoverflow.com/questions/3474526/stop-on-first-error) in bash can make it possible to error out when a command fails similar to make recipe lines. – Brian Vandenberg Oct 02 '15 at 20:32

3 Answers3

119

Put a - before the command, e.g.:

-myProg bad_input >> test.log

GNU make will then ignore the process exit code.

  • 1
    Yeah but that defies the use of `make test` being run in a script that, if it fails, means that the tests do not pass!!! – Alexis Wilke Aug 24 '13 at 21:02
  • 6
    Even though this doesn't answer the actual question, it answers what the question appears to be just by reading the title, which is why it has so many upvotes. – LukeGT Oct 23 '14 at 08:49
  • 1
    @LukeGT: Part of the reason this has so many more votes than tripleee's answer is that it was the selected answer for 4 years before tripleee provided a better answer. – GreenMatt Feb 03 '15 at 14:02
32

Try running it as

make -i

or

make --ignore-errors

which ignores all errors in all rules.

I'd also suggest running it as

make -i 2>&1 | tee results

so that you got all the errors and output to see what happened.

Just blindly continuing on after an error is probably not what you're really wanting to do. The make utility, by its very nature, is usually relying on successful completion of previous commands so that it can use the artefacts of those commands as pre-requisites for commands to be executed later on.

BTW I'd highly recommend getting a copy of the O'Reilly book on make. The first edition has an excellent overview of the basic nature of make, specifically its backward chaining behaviour. Later editions are still good but the first ed. still has the clearest explanation of what's actually happening. In fact, my own copy is the first thing I pass to people who come to me to ask "WTF? questions" about make! (-:

Rob Wells
  • 36,220
  • 13
  • 81
  • 146
17

The proper solution if you want to require the target to fail is to negate its exit code.

# Makefile
# 
test:
    myProg -h > test.log              # Display help
    myProg good_input >> test.log     # should run fine
    ! myProg bad_input1 >> test.log      # Error 1
    ! myProg bad_input2 >> test.log      # Error 2

Now, it is an error to succeed in those two cases.

tripleee
  • 175,061
  • 34
  • 275
  • 318