Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Makefile equivalent of shell 'TRAP' command for concise identification of build failure on exit

Criteria: Makefile is a GNU Make Makefile - I'm not interested in makepp, qmake, cmake, etc. They're all nice (especially cmake), but this is for work and at work we use GNU Make. The optimal solution is a pure Makefile solution rather than a shell script that parses make for you.

I also don't want to do a 'continue on failure' solution - if it's broken, it's broken and needs to be fixed.

The situation is this, I've got a makefile that builds several directories in parallel - if one of them fails, of course the whole build fails, but not until all the running makes run to completion (or failure). This means that the reason why make actually failed is buried somewhere arbitrarily far from the end of make's output.

Here's an example of what I've got:

all: $(SUBDIRS)

SUBDIRS = \
  apple \
  orange \
  banana \
  pineapple \
  lemon \
  watermelon \
  grapefruit

$(SUBDIRS):
  cd $@ && $(MAKE) $(MFLAGS) 2>&1 | sed -e "s/^/$(notdir $(@)): /g"

If I run 'make -j 5' and 'orange' happens to fail - I'd like to see a table like this at the end of the make process

  apple     - passed
  orange    - FAILED
  banana    - passed
  pineapple - passed
  lemon     - passed

I've considered having an && echo "passed" >.result || echo "FAILED" >.result, but make still needs some sort of TRAP or __onexit() cleanup command to print at them on exit.

Any Makefile ninjas out there have a pure-makefile solution for this?

un-edit - my solution wasn't actually working the way I had hoped.. STYMIED!

like image 843
synthesizerpatel Avatar asked Jun 20 '11 19:06

synthesizerpatel


1 Answers

When you want make to abort at the first failure, end immediately and kill all in-flight jobs instead of waiting for them to finish, you need to patch GNU Make like this http://lists.gnu.org/archive/html/bug-make/2009-01/msg00035.html

Then you need to set a trap for every shell that make invokes (as well as set -o pipefail if you use a pipe), as described in this post http://lists.gnu.org/archive/html/help-make/2009-02/msg00011.html

In a nutshell:

target1:
    trap 'kill $$(jobs -p)'; command && something || something-else
target2:
    trap 'kill $$(jobs -p)'; set -o pipefail; command | sed '...'
like image 198
user1241663 Avatar answered Oct 18 '22 10:10

user1241663