GCC and makefile: Only show errors and warnings - c

I have a makefile that compiles every .c file in my project. For each file, I get the whole compile command printed out to the shell, with all the options and flags. This is the example output for one file:
arm-none-eabi-gcc -c -mcpu=cortex-m3 -O0 -dM -g -gdwarf-2 -mthumb
-fomit-frame-pointer -fverbose-asm -Wa,-ahlms=src/sim/sim_configuration.lst -include ./lib/stm32core/stm32f2xx_conf.h -I . -I./lib/ARMStandardLibrary
-I./lib/LwIP -I./lib/LwIP/src/include -I./lib/LwIP/src/include -I./lib/LwIP/src/include/ipv4 -I./lib/LwIP/src/include/ipv6 -I./lib/FatFS -I./lib/stm32core -I./src -I./src/sim -I./src/sd -I./src/tftp src/sim/sim_configuration.c -o src/sim/sim_configuration.o
The problem is that various warnings get lost inside this whole mess of command outputs. Is there a way to only print the warnings and errors that appear (not the original command)?

Execute make with the -s option. From the man page.
-s, --silent, --quiet
Silent operation; do not print the commands as they are executed.

Just prepend the command with the # symbol.
If you rely on built-in implicit rules, you will have to make them explicit or, in your specific case, you could use:
.SILENT: *.o
for silencing all commands used for building to the %.o targets.

You could always filter all the output from stdout, which should leave you with all the errors on stderr:
make 1>/dev/null

Use # before a command to hide the it:
rule1:
#gcc someting

Related

Trying to pass preprocessor directive via command line in bash script

I'm trying to write a bash script that will take in an optional argument,
and based on the value of that argument, compile code using that argument
as a preprocessor directive. This is my file so far:
#!/bin/bash
OPTIMIZE="$1"
if[ $OPTIMIZE = "OPTIMIZE" ] then
echo "Compiling optimized algorithm..."
gcc -c -std=c99 -O2 code.c -D $OPTIMIZE
else
echo "Compiling naive algorithm..."
gcc -c -std=c99 -O2 code.c
fi
However, it doesn't seem to like the "-D" option, complaining that there is a macro name missing after -D. I was under the impression -D defines a new macro (as 1) with name of whatever is specified. I wanted "OPTIMIZE" to be the name of that macro. Any hints?
The -D should be glued to the name (ie -DFOO not -D FOO)
gcc -c -std=c99 -Wall "-D$OPTIMIZE" -O2 code.c
and you forgot to pass -Wall to gcc. It is almost always useful.
BTW, you might consider (even for a single file) using make with two phony targets: the default one (e.g. plain), and an optimized one.

Building a trivial program with dpkg-buildflags

I'm trying to build a very simple C program for inclusion into a .deb package. The bulk of the project is in Python. When this program is included into a .deb package, lintian gives me the hardening-no-fortify-functions warning.
On further reading, it appears that Debian expects you to include certain flags while building C programs, and that these flags can be retrieved using dpkg-buildflags --get CFLAGS.
My initial build flags looked like this:
gcc -Wall -pedantic -o somefile somefile.c
Now, I'm building with
CFLAGS=`dpkg-buildflags --get CFLAGS`
gcc $CFLAGS -o somefile somefile.c
However, I continue to get the hardening-no-fortify-functions warning. What am I doing wrong here? Is this now a false positive? Can I just add an override and forget about it?
There are several possibilities of which the third seems most likely, but I've mentioned 1 and 2 in case they are causing you problems too:
dpkg-buildflags --get CFLAGS is returning the wrong thing. On my system it returns:
-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security
If you just execute it from the command line, what do you get?
Your value of CFLAGS is not being passed to gcc. I assume you are using a Makefile here; are those two statements actually adjacent? Do you not want CFLAGS = (with a space) if so? Or are you setting CFLAGS at the command line in which case you should know the debian build tool stuff strips the environment of most things that don't start DEB_, so you will need to set CFLAGS inside whatever builds the package.
The CFLAGS aren't sufficient to eliminate the hardening error. Let's have a look at the lintian error: http://lintian.debian.org/tags/hardening-no-fortify-functions.html and note it says 'Certainty: wild guess'. That does not inspire confidence that it is correct. However, I suspect the actual problem is this: you are not bringing in LDFLAGS. Try:
$ dpkg-buildflags --get LDFLAGS
-Wl,-Bsymbolic-functions -Wl,-z,relro
You'll need those on your linker line.
This approach would seem to work (i.e. at least compile):
gcc `dpkg-buildflags --get CFLAGS` `dpkg-buildflags --get LDFLAGS` main.c -o main

Details on Makefiles

I am learning about Makefiles and when I first searched the web I did not get any response regarding my question(s).
What are the -o, -f, -c, -g, -Wall, -I, etc. actually called (like +, --, ||, && are called operators), so I can do a correct search on them in the future, and what do they do?
An example I found where this occurs in a Makefile is shown below:
helloworld : helloworld.c
gcc -o helloworld helloworld.c
hellomake: hellomake.c hellofunc.c
gcc -o hellomake hellomake.c hellofunc.c -I.
all: myprog.c
gcc -g -Wall -o myprog myprog.c
(Note: they are parts taken from other Makefiles examples just to show where the "-g", "-Wall", etc. were used
Those flags have nothing to do with make per se. Make is a program that exists to run other programs. Most commonly, but not solely, compilers.
Those flags are flags for your compiler (gcc in this case). So you should be looking at the documentation for your compiler to understand what they do.
Make just runs the commands you give it. You won't find compiler flags in the documentation for make any more than you would in the documentation for your shell, even though you can run the compiler from your shell.
You're conflating two different things. All a makefile does is define a set of commands you can use to shorten a command line call using the program Make. So, in your example, "make helloworld" will call "helloworld.c gcc -o helloworld helloworld.c" on the command line, where "make all" will call "myprog.c gcc -g -Wall -o myprog myprog.c". On the other hand, the program gcc has different command line arguments (such as -o) which tell the program to run a certain way. -Wall, for example, tells it to output all warnings, even trivial ones.
Those are command line flags. The flags you're referring to appear to be flags to gcc (your C compiler).
Much of a Makefile consists of what are essentially shell commands. The "gcc -g -Wall -o myprog myprog.c" is an example of this. You could type the same command in your shell (ie: in a terminal) to do the same thing. What make does is figure out the right time to execute these commands, and it also make it possible to come up with generalized rule (eg: "this is how I always compile .c files into .o files").
"-o", "-f", "-c", "-g", "-Wall", "-I",
Are all options of the Compiler, it's nothing to to with Make. Read the compiler man page.
man gcc

Pass an argument though makefile linux/unix command line in C

my makefile is:
CFLAGS=-g
all: mcast_client mcast_server
mcast_client: mcast_client.o $(ARG1)
mcast_server: mcast_server.o
clean:
rm -f mcast_client mcast_server mcast_client.o mcast_server.o
in the command window i type,
$ make ARG1=hello, world!
is this correct?
Use:
$ make ARG1="hello, world!"
Your invocation make ARG1="hello, world!" is almost correct (but the quotes are needed for the shell), but your Makefile is not.
A more realistic approach would be to pass the message as a preprocessor macro.
Assume hello.c contains (in the middle of some C function)
printf("%s\n", MESSAGE);
Then you could have a Makefile rule like
hello.o: hello.c
$(COMPILE.c) -DMESSAGE=\"$(MSG)\" $< -o $#
The quotes are backslashed because the preprocessor macro MESSAGE should have quotes.
And finally you could invoke
make "MSG=hello friend"
Beware that this won't work if MSG contains quotes " or backslashes \ .... In the command above the quotes are interpreted by the shell...
Notice that you are supposed to invoke make with the same command every time... (since hello.o won't be rebuilt if the MSG has changed).
BTW, take the habit of always compiling with -Wall so
CFLAGS= -Wall -g
and look at predefined rules of make given by make -p
Consider using remake (notably invoked with -x) to debug tricky or complex Makefile-s.

make is automatically attempting to link even when I pass -c in my makefile

I'm new to makefiles, so I apologize in advance if this is a silly question. Also I removed most variables from my makefile because they weren't working properly (gnu make tells me that $(myvar) should be completely replaces by the value of myvar, however the output of make was showing me that this was not happening), so I apologize for the ugliness and the more than 80 character lines.
acolibobj = acoLibInit acoGlobalDefs
acolibinterface: $(acolibobj).o
acoLibInit.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
acoGlobalDefs.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoGlobalDefs.o acoCommands/acoLibInterface/acoGlobalDefs.c
When I run this makefile I get:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
cc acoLibInit.o -o acoLibInit
gcc: acoLibInit.o: No such file or directory
gcc: no input files
make: *** [acoLibInit] Error 1
So far as I can tell, what's happening is that make is trying to compile AND link, even though I explicitly added the -c flag. When I run "gcc -fPIC -g -c..." myself (from bash), I do not get any problems at all. Why does make go on to try "cc acoLibInit.o -o acolibInit"?
make is trying to build acoLibInit. It probably has built-in rule that specifies "whatever" can be produced by linking "whatever.o", which is why you get that cc line.
This line:
acolibinterface: $(acolibobj).o
expands to:
acolibinterface: acoLibInit acoGlobalDefs.o
(note the absence of .o on the first dependency). This is why it's trying to link acoLibInit.
Try this:
acolibinterface: $(addsuffix .o,$(acolibobj))
if you want only the .o files as dependencies for that target.
$(acolibobj).o expands to acoLibInit acoGlobalDefs.o. Thus, you're really saying:
acolibinterface: acoLibInit acoGlobalDefs.o
Simply define acolibobj = acoLibInit.o acoGlobalDefs.o and use acolibinterface: $(acolibobj).

Resources