Reduce recipe echoing in make - makefile

I know the silent flag (-s) for make will hide the recipe echoing completely, however this makes it hard to see progress.
For example currently I have hundreds of lines such as (I've broken up the line to fit SO):
g++ -I. -std=c++11 -Wall -Wno-unused-local-typedefs -Wno-literal-suffix
-Wno-unused-but-set-variable `wx-config --cxxflags --unicode=no`
-MT dialog_export.o -MD -MP -MF .deps/dialog_export.Tpo
-c -o dialog_export.o dialog_export.cpp
It would be great if it could just print part of the line, say without the flags, something like:
g++ dialog_export.o dialog_export.cpp
Or just some way of seeing progress, but without spamming the console with a tonne of messages.

A number of build systems from the autotools to the kernel build system to CMake, etc. do this sort of thing.
The trick is to dynamically control whether the silencing # is present on the recipe lines or not and if it is to replace it with a manual echo of some friendlier message.
To get a message like what you want you would use something like this:
E_g++ := #echo 'g++ $(filter %.o,$^) $#'
%.o: %.cpp
$(E_g++)g++ ... -o $# $^
To make this sort of thing easier for myself in projects that don't use the autotools or anything like that I wrote Silent Make Rules.
Which you would use like this:
include silent_rules.mk
$(eval $(call vrule,G++,g++ $$(filter %.o,$$^) $$#))
%.o: %.cpp:
$(SR_V_G++)g++ ... -o $# $^
This would also (like the autotools and kernel make versions) allow you to specify V=1 on the make command line to go back to the normal make output and use V=-1 to silence the output entirely.

I like rules like this:
dialog_export.o: dialog_export.cpp
#echo $#...
#g++ -I. -std=c++11 -Wall -Wno-unused-local-typedefs -Wno-literal-suffix -Wno-unused-but-set-variable `wx-config --cxxflags --unicode=no` -MT dialog_export.o -MD -MP -MF .deps/dialog_export.Tpo -c -o $# $<
The leading '#' symbols suppress command echoing, and the first command echoes the name of the target:
dialog_export.o...
If you have a makefile with hundreds of rules, you can convert them all to that form in minutes with a good editor. Or faster with a macro or sed, if you're bold.
(If you have hundreds of lines like that, your makefile can probably be simplified quite a lot, but that's for another day.)

I always use $(Q):
ifeq ("$(V)","1")
Q :=
vecho = #echo
else
Q := #
vecho = #true
endif
somerule:
$(vecho) building $# verbosely
$(Q)do command
You can then modify your pattern rules to only output the text you care about. If you need more verbose, then you just build with make V=1. I don't think there's any shortcut in make to doing this automatically save piping your output through sed (which I wouldn't recommend).

Related

Order of libraries and source files from makefile

I should start by saying I'm a bit of a newbie when it comes to gcc and makefiles.
On an Ubuntu machine that I've recently started using, I find that when running gcc, the order in which I put the source files and the libraries/headers makes a difference. On another machine I could do:
gcc -I../include -L../lib myProgram.c -o myProgram
But on the new machine, this will not link the libraries, and I must do:
gcc myProgram.c -o myProgram -I../include -L../lib
Now, I have the following makefile:
SHELL = /bin/sh
CC = gcc -O3
CFLAGS = -I../include
LDFLAGS = -L../lib
PROGS = myProgram
all: $(PROGS)
$(all): $(PROGS).o
$(CC) -o $# $#.o $(LIBS) $(CFLAGS) $(LDFLAGS)
rm -f $#.o
clean:
rm -f *.o $(PROGS)
But when I do "make", the actual gcc command that it runs has the libraries and source files in the wrong order. My question is: what do I need to do in the makefile to force the "-L../libs" option to come after the source files, so that the libraries will link properly?
I've also tried including the "-Wl,--no-as-needed" option, as I thought that an --as-needed flag might be the reason that the order matters in the first place, but this didn't appear to change anything (i.e. it still fails to link the libraries unless "-L../libs" comes after the source files).
The problem was that you thought you were using that rule, but you weren't. You never defined a variable named all, so the target of the second rule actually expanded to nothing. When you commanded Make to build myProgram, Make found no suitable rule in this makefile. Make has a toolbox of implicit rules it can fall back on in such cases; it wanted to build myProgram, it saw a file named myProgram.c, and one of its rules looks something like this:
%: %.c
$(CC) $(LDFLAGS) $^ -o $#
There you have it, linker flags before sources.
You can write your own pattern rule which Make will use instead:
%: %.o
$(CC) -o $# $^ $(LIBS) $(CFLAGS) $(LDFLAGS)
(Note that this builds myProgram from myProgram.o, and lets Make figure out how to build myProgram.o.)
If your executable is to be built from several object files, add a rule like this:
myProgram: other.o yetAnother.o
If you like you can have one more rule (the first) to tell Make what you want built:
all: myProgram myOtherProgram friendsProgram
(A final note: we've all had tight work deadlines. Asking for help once can be faster than learning the tools, but learning the tools is faster than asking for help N times. Determining the value of N is up to you.)

How to restore g++/gcc compiling messages

I'm using CentOS 6.5. When I do a make, I typically see the full gcc/g++ commands that the Makefile is executing, like
...
gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I/opt/emacs/emacs-24.3/lib -I../src -I/opt/emacs/emacs-24.3/src -g3 -O2 -MT pthread_sigmask.o -MD -MP -MF .deps/pthread_sigmask.Tpo -c -o pthread_sigmask.o pthread_sigmask.c
...
But in some systems, I only see:
$ make
Building test1.o...
Building test2.o...
...
Is it possible to change the "Building ..." messages back to the full gcc/g++ command output?
The output that you see when you run make with a given makefile
depends on how the makefile is written. You will see the
output that the author of the makefile wants you to see.
If a command in a recipe in the makefile is prefixed with #,
then make will not echo the command. So if my makefile is, e.g.
foobar: foobar.o
gcc -o $# $<
foobar.o: foobar.c
gcc -c -o $# $<
then the output of make will be:
gcc -c -o foobar.o foobar.c
gcc -o foobar foobar.o
But if I change the makefile to:
foobar: foobar.o
#echo "Linking foobar"
#gcc -o $# $<
foobar.o: foobar.c
#echo "Compiling foobar"
#gcc -c -o $# $<
then the output becomes:
Compiling foobar
Linking foobar
So to see the output that you would prefer to see you will have to edit the
makefile, removing the #-prefixes from the commands you expect to see
and deleting entirely the commands that print the "Building..." messages.
At least, this is what you would need to do if the makefiles that bother
you in this way build the target using recipes that directly invoke gcc/g++. It
is possible that they build their targets using recipes that invoke some intermediate
tool that doesn't echo the compiler commands and instead emits the "Building..."
messages. Without seeing the makefile(s) I can't say.

How to hide print information of Makefile?

when Makefile execute some tasks, il will print many information in console, can we choose to hide them? when I have many .o to generate, these information will be too many to see and they are just meaningless if we don't read them.
The following code
$(obj)environment.o: $(src)environment.c
$(CC) $(AFLAGS) -Wa, --no-warn \
-DENV_CRC=$(shell $(obj)../tools/envcrc) \
-c -o $# $(src)environment.c
will print heavy information like
arm-linux-gcc -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float
-D__KERNEL__ -DTEXT_BASE=0x01000000
-I/home/mingzhao/Documents/bootloader/u-boot-1.2.0/include
-fno-builtin -ffreestanding -nostdinc -isystem
/home/mingzhao/Documents/bootloader/arm/4.3.2/bin/../lib/
gcc/arm-none-linux-gnueabi/4.3.2/include -pipe -DCONFIG_ARM
-D__ARM__ -march=armv4 -mabi=apcs-gnu -Wall -Wstrict-prototypes
-c -o environment.o environment.c
The "right" way to handle this (IMO) is to add this to your makefile:
$(VERBOSE).SILENT:
Then in your rules where you don't ever want the command printed (for example, an echo statement as in Beta's answer below) you prefix it with #. For all other commands, you don't prefix it with #.
What this does is enable "silent" mode by default (because the variable VERBOSE is not set and so this resolves to the .SILENT pseudo-target).
Then if you want to see everything, you add a VERBOSE=1 (actually you can set it to any non-empty value, so VERBOSE=true if you prefer). When you do that it turns off "silent" mode because the above line expands to 1.SILENT: (or true.SILENT: or whatever) which is meaningless to make.
You can use the option make --silent which will suppress output for all targets. If you want to suppress output for some commands, you can prefix them by #
I like something like this:
$(obj)environment.o: $(src)environment.c
#echo building $#
#$(CC) $(AFLAGS) -Wa, --no-warn \
-DENV_CRC=$(shell $(obj)../tools/envcrc) \
-c -o $# $(src)environment.c
The #echo ... gives a minimal status message, the '#' in front of the $(CC) suppresses standard output (but still allows error messages).
You can use this syntax : #$(CC) $(AFLAGS) -Wa, --no-warn \...

How to enable quiet build using automake?

Imagine the following target and command generated by autoconf:
.c.lo:
$(LTCOMPILE) -MT $# -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $# $<
$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
I'm looking for a way in Makefile.am to manipulate that command, knowing that the command is generated by autoconf and I don't know what it is. In theory, something like this:
if BUILD_QUIETLY
Q=#
endif
.c.lo:
$(Q)$(autoconf-command-for-c-lo)
Or something like this (this is similar to Linux kernel's build output):
quiet_cmd_cc = CC $#
cmd_cc = $(autoconf-command-for-c-o)
.c.o:
$(call cmd,cc)
Where cmd is a function that executes cmd_$1 and either prints quiet_cmd_$1 or cmd_$1 based on a variable.
I looked for this on the internet, but most of the websites talk about the basics of autoconf. There doesn't seem to be any questions related to this here either.
Is this even possible?
Per chirlu's comment, automake has an option to generate quiet output builds.
This page has the necessary instructions. In short, put the following in configure.ac:
AM_SILENT_RULES([yes])
To then disable it, either do:
make V=0
after configuration, or:
./configure --enable-silent-rules
on configuration.
You can always pipe the output to /dev/null:
./configure 2>&1 >/dev/null
make 2>&1 >/dev/null

Strange make implicit rule

I have written a small makefile for a few simple C programs that compiles them and then tests their execution time:
CC = gcc
CFLAGS = -Wall
PTEST = /usr/bin/time -f "%Us"
ARCH=-march=native
OPTIMIZATION=
NOPTIMIZATION=
%comp : %.c
$(CC) $(CFLAGS) $(NOPTIMIZATION) -o $* $<
$(CC) $(CFLAGS) $(OPTIMIZATION) -o $*_opt $<
$(CC) $(CFLAGS) $(NOPTIMIZATION) $(ARCH) -o $*_arch $<
$(CC) $(CFLAGS) $(OPTIMIZATION) $(ARCH) -o $*_opt_arch $<
%test:
#echo ---$<---
#echo Bez optymalizacji, bez podowania architektury
#$(PTEST) ./$*
#echo Bez optymalizacji, uwzgledniana architektura
#$(PTEST) ./$*_arch
#echo Opcja $(OPTIMIZATION), bez podawania architektury
#$(PTEST) ./$*_opt
#echo Opcja $(OPTIMIZATION), uwzgledniania architektura
#$(PTEST) ./$*_opt_arch
loop%:OPTIMIZATION=-O2
logic%:OPTIMIZATION=-O1
math%:OPTIMIZATION=-O1 -ffast-math
recursive%:OPTIMIZATION=-O2 -foptimize-sibling-calls
recursive%:NOPTIMIZATION=-O2 -fno-optimize-sibling-calls
#all: loopcomp logiccomp mathcomp recursivecomp looptest logictest mathtest recursivetest
loop:loopcomp looptest
clean:
rm -rf loop loop_opt loop_arch loop_opt_arch \
logic logic_opt logic_arch logic_opt_arch \
math math_opt math_arch math_opt_arch \
recursive recursive_opt recursive_arch recursive_opt_arch
When I type make loop it compiles and tests them but then it invokes strange implicit rule that does this:
gcc -Wall loop.c loopcomp looptest -o loop
gcc: error: loopcomp: No such file or directory
gcc: error: looptest: No such file or directory
I know that this is make implicit rule because when I invoke make -r loop everything goes OK. I can't figure it out: which built-in implicit rule is make trying to invoke and how can I override it, preferably without adding -r option when invoking make? If it is possible, I would like to override it or somehow diasable make implicit rules inside makefile.
If you don't want to create a file called "loop" and you just want to be able to say "make loop" as a way to bundle up other targets (like "make all") then you should declare "loop" to be phony and make won't search for implicit rules:
.PHONY: loop
loop: loopcomp looptest
If you don't want to do that but want to ensure that a given target doesn't undergo implicit rule search, then you should declare an explicit rule for it. A simple way to do that is add a do-nothing recipe, like this:
loop: loopcomp looptest
#:
(the ":" command is the shell's "do-nothing" command).
Your default target in the makefile is:
loop: loopcomp looptest
This tells make that to build loop, it must first ensure that loopcomp and looptest are up to date, and then it must find a way to build loop. Since there is a file loop.c, it invokes its default %.c: rule to build loop:
gcc -Wall loop.c loopcomp looptest -o loop
This includes the two files (programs) you told it that loop depends on.
While you have a loop.c, I think you're likely to run into this problem.
There does not seem to be a way to say in the makefile "do not use any built-in rules". If there was, you'd expect it to be a 'Special Built-in Target Name' (ยง4.8 of the GNU Make manual for version 3.82), such as .DEFAULT.
Your only remaining hope is that declaring .PHONY: loop might suppress this. Otherwise, rewrite the default target rule as:
check-loop: loopcomp looptest
This is a mind-boggling makefile. Porting that to anything other than GNU make will not be trivial.

Resources