开发者

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

开发者 https://www.devze.com 2023-03-14 00:56 出处:网络
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 soluti

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 workin开发者_StackOverflow中文版g the way I had hoped.. STYMIED!


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 '...'


The only way I see is self-execution with a sub-make:

all : subdirs

subdirs : 
    $(MAKE) -f $(lastword $(MAKEFILE_LIST)) subdirs-recursive || cat log

subdirs-recursive: $(SUBDIRS)
0

精彩评论

暂无评论...
验证码 换一张
取 消