26

I am writing a short shell script which calls 'make all'. It's not critical, but is there a way I can suppress the message saying 'nothing to be done for all' if that is the case? I am hoping to find a flag for make which suppresses this (not sure there is one), but an additional line or 2 of code would work too.

FYI I'm using bash.

Edit: to be more clear, I only want to suppess messages that therer is nothing to be done. Otherwise, I want to display the output.

sas4740
  • 4,510
  • 8
  • 26
  • 23

4 Answers4

22

You can make "all" a PHONY target (if it isn't already) which has the real target as a prerequisite, and does something inconspicuous:

.PHONY: all

all: realTarget
    @echo > /dev/null
Beta
  • 96,650
  • 16
  • 149
  • 150
  • 12
    Rather than echo, you can probably just do @: for a no-op – William Pursell Aug 07 '10 at 15:58
  • @William Pursell: by golly, you're right. I never knew `:` was a shell no-op... or that I'd ever have a use for such a thing. – Beta Aug 07 '10 at 17:14
  • 1
    I like this sneaky approach. The warning goes away because `all` now has something to do, but what it does is nothing. Another option to `echo` is to make the action be `@true` which should print nothing and silently succeed. – RBerteig Aug 13 '10 at 09:25
  • This breaks "make -q" because make always thinks there's work to be done – Aron Griffis Feb 05 '14 at 19:16
  • this solution adds ~1 sec delay at least in MinGW – Sergey May 20 '18 at 12:30
13

I would like to improve on the previous solution, just to make it a little bit more efficient...:)

.PHONY: all
all: realTarget
        @:

@true would also work but is a little slower than @: (I've done some performance tests). In any case both are quite faster than "echo > /dev/null"...

Mark Veltzer
  • 1,394
  • 15
  • 20
1

The flag -s silences make: make -s all

EDIT: I originally answered that the flag -q silenced make. It works for me, although the manpage specifies -s, --silent, --quiet as the valid flags.

Ryan Tenney
  • 1,812
  • 3
  • 16
  • 29
  • W Tenney, for me this is `-s`, `--silent` or `--quiet` – Anders Aug 05 '10 at 17:38
  • 2
    I should have been more clear. I only want to suppress the case where the files are up to date. Otherwise I want to show the output. – sas4740 Aug 05 '10 at 17:39
  • I saw someone else answered and suggested `make all | grep -v "Nothing to be done for"` but it seems they deleted that answer. – Ryan Tenney Aug 05 '10 at 19:00
1

The grep solution:

{ make all 2>&1 1>&3 | grep -v 'No rule to make target `all' >&2; } 3>&1 

The construct 2>&1 1>&3 sends make's stdout to fd 3 and make's stderr to stdout. grep then reads from the previous command's stdout, removes the offending line and sends its stdout to stderr. Finally, fd 3 is returned to stdout.


2022-11-17, A response to @Pryftan's comment:

Ignoring the minor error that I used the wrong text.

Lets create a function that outputs some stuff

make() {
    echo "this is stdout"
    echo "this is stderr" >&2
    printf 'oops, No rule to make target `%s`, not at all' "$1" >&2
}

Testing my solution:

$ { make foobar 2>&1 1>&3 | grep -v 'No rule to make target `all' >&2; } 3>&1
this is stdout
this is stderr
oops, No rule to make target `foobar`, not at all

$ { make all 2>&1 1>&3 | grep -v 'No rule to make target `all' >&2; } 3>&1
this is stdout
this is stderr

Looks good so far.

What about without the braces?

$ make all 2>&1 1>&3 | grep -v 'No rule to make target `all' >&2 3>&1
bash: 3: Bad file descriptor

In this case, we'd need to explicitly create fd 3

$ exec 3>&1; make all 2>&1 1>&3 | grep -v 'No rule to make target `all' >&2 3>&1
this is stdout
this is stderr

What is it about the braces? I think it's delaying evaluation of the contents, and that allows the trailing 3>&1 to be processed first. And that makes the inner 1>&3 valid.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Is all that really necessary? What different from just doing the grep -v? – sas4740 Aug 05 '10 at 23:31
  • 2
    First of all, on my make anyway, that message goes to stderr, so at least you have to redirect stderr for grep to have any effect. Next, you wanted the rest of make's output untouched, so I didn't want to mix stderr with stdout. Lastly, it's a learning exercise for me too. – glenn jackman Aug 06 '10 at 15:38
  • @glennjackman There are a number of things wrong here. First you're filtering out the wrong text. This isn't a matter of there not being a rule 'all'. Second is the FDs start from 0 - the `{}` masks the problem that fd 3 is invalid. Try removing them and you'll see what I mean. Even if you change the filter to use the correct text it won't work right for those reasons (or maybe other reasons). And you're right - that message does go to stderr but stderr is 2 and 3 is not defined (well maybe some shells have it? Not sure). – Pryftan Nov 17 '22 at 22:34
  • ...even so I'm voted you up for the effort and for wanting to learn as well. But @sas4740 is correct and the `grep -v` would be the right way to go about it if you're going to use grep for this task. – Pryftan Nov 17 '22 at 22:35
  • I have to say, I was taken aback by your comments. I spent a lot of time pondering the "fd 3 is invalid" comment and working out a justification for my (correct) answer. IMO the fact that the grep pattern isn't exactly right is trivial. I do object to "maybe other reasons" -- if you can't enumerate errors, please don't suggest they exist. This site requires more precision. – glenn jackman Nov 18 '22 at 00:54