how to stop Makefile from printing rule lines onto shell - makefile

I am using a makefile to build a set of C files. The rule of compiling the .c files to .o is as follows:
%.o : %.c
printf "\ncompiling $<\n"
$(CC) -c $(CFLAGS) $< -o $#
When this is executed, I"m observing following output on the shell:
printf "\ncompiling source/abcxyz.c\n"
compiling source/abcxyz.c
gcc.exe <other compiler inputs>
I want to prevent printf "\ncompiling source/abcxyz.c\n" from being printed to the the terminal.
How to do achieve that?

Prefix the rule command with a # sign:
#printf "\ncompiling $<\n"

Related

Error while executing makefile in c

I'm trying to create one makefile using c. For that I have main.c,add.c,minus.c,print.c and Functions.h header file.In this list other than main.c add files have simple add function, subtract function and print function. That Functions.h file have declarations for all functions.
my problem is I have written one makefile. In that I'm trying to redirect the object files into one directory. When I execute the makefile. It throws an error like
make: *** No rule to make target /%.c', needed byobj'. Stop
.
Make file has the lines
CFLAG :=-Wall -g
CC := gcc
INCLUDE:=-I include
OBJDIR:=obj
SRCDIR:=src
TARGET:=bin/Math
CFILES:=$(wildcard src/*.c)
OBJECTS:=$(patsubst src/%.c,obj/%.o,$(CFILES))
$(OBJDIR)/%.o:$(SRCDIR)/%.c
#$(CC) -c $(INCLUDE) -o $# $< $(CFLAG)
(TARGET):$(OBJECTS)
#$(CC) $(CFLAG) -o $# $(OBJECTS)
.PHONY : clean
clean :
-rm -f $(OBJDIR)/*.o
Please help me guys....

How to redirect output to a specific file into a sed command?

Some context : I'm trying to build a generic Makefile, with auto-dependency generation (using GCC as described here, non recursive, which could be used from any level of my projects.
For that purpose, the dependency files generated need to be of the following form :
$(DIR)file.o: $(DIR)file.c $(DIR)file.h
$(DIR)file.h
That way, whatever the level of the make invocation, make can properly locate the files.
In order to do so, I have the following implicit rule :
DEPFLAGS = -MT $# -MP -MMD -MF $(word 2,$^).tmp
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $# $<
POSTCOMPILE = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)\2|g' $(word 2,$^).tmp > $(word 2,$^)
%.o: %.c %.dep
$(COMPILE)
$(POSTCOMPILE)
$(RM) $(word 2,$^).tmp
touch $#
The sed invocation replace any directory part before the filename by $(DIR)
The problem is that since the dependency file is generated after the object file, it causes the Makefile to relink every time. And so i have to add a touch command to be sure that the object file will be considered up-to-date. Which is not very elegant.
So I have this question : instead of using a temporary file, is there a way to directly redirect the gcc output (which is directed into the .tmp file) into the sed command ?
In others words, is there a way to do the equivalent of the pipe redirection, but for an other stream/file descriptor than stdout ?
If you are in a full fledged linux environment, you can indeed skip the creation of the .tmp file and pipe the dependecies directly into sed.
# This is needed, because the default shell does not support
# process substitution
SHELL = /bin/bash
SED_COMMAND = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)\2|g' > $(word 2,$^)
DEPFLAGS = -MT $# -MP -MMD -MF >($(SED_COMMAND))
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $# $<
%.o: %.c %.dep
$(COMPILE)
touch $#
However, this still needs the touch command at the end, for the reason correctly mentioned in a comment by #MadScientist above:
there's no way to be 100% sure that the sed command would finish writing its file before the compiler finished writing the object file: they are running in parallel so you can't guarantee which one will finish first.

Create dependency files in Makefile

I am using a Makefile including a rule to create a dependency file. The compiler is GCC.
%.d: %.c
mkdir -p $(#D)
$(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
sed 's,\($(notdir $*)\.o\) *:,$(dir $#)\1 $#: ,' > $#.tmp
mv $#.tmp $#
I am quite new in Makefile technique and I find it a little bit difficult to understand this rule composed of a mixture of several options.
Can somebody give a simple explanation how this rule works?
Thanks in advance.
%.d: %.c
All files ending in .d can be made using this rule, as long as there is a .c file with the same directory and stem relative to the current directory or one of the vpaths.
mkdir -p $(#D)
Create the topmost and all intermediate directories for $(#D), which is an automatic make variable that expands to the directory part of the current target.
$(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
Invoke the C compiler on the first prerequisite (whatever.c) and tell it to output a list of make dependencies to the standard output. Pipe this output to
sed 's,\($(notdir $*)\.o\) *:,$(dir $#)\1 $#: ,' > $#.tmp
sed. The rules in the output will have the same path as the source files, but whoever wrote this rule wants the objects files in a different directory so we need sed to substitute the paths.
Sed captures any rules with targets ending with .o that match $(notdir $*). $* is another automatic variable that expands to the pattern that matches % in the current rule, and notdir will strip any directory parts so you're left with the filename stem with no extension.
Sed then prepends $(dir $#) to the object file target, which is the same thing as $(#D) we saw above, and adds the dependency file itself ($#) as a target of the same prerequisites. This output is redirected to a file with the name of the current target + .tmp.
mv $#.tmp $#
Moves the previous file to the real target of the rule.
Side note: if you don't mind the dependency files being generated in the same directory as the object files then these recipes are outdated, you can achieve the same thing with something like:
sources := src/somefile1.c src/somefile2.c
objects := $(sources:src/%.c=obj/%.o)
deps := $(objects:.o=.d)
CFLAGS := -MMD -MP
.PHONY: all
all $(objects)
$(objects): obj/%.o: src/%.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
-include $(deps)

Makefile target matching

I'm having troubles with my Makefile :-(
I have a mix of assembly and C sourcecode that I need to link together. I need different build-instructions for those two types. Since both the assembler and C compiler output *.o files, I cannot use the general %.o:%.c construction often found in example Makefiles
This what I'm trying now:
Get a list of all C files and their resulting output files:
C_SRCFILES := $(shell find $(SRCDIRS) -type -f -name "*.c")
C_OBJFILES := $(patsub %.c,%.o,$(C_SRCFILES))
Get a list of all asm files and their resulting output files:
A_SRCFILES := $(shell find $(SRCDIRS) -type -f -name "*.asm")
A_OBJFILES := $(patsub %.asm,%.o,$(A_SRCFILES))
When I echo those vars to the screen, they seem to be correct, but how I do define my targets now?
I tried something like this
$(A_OBJFILES): ($A_SRCFILES)
$(AS) $(AFLAGS) -o $# $*
$(C_OBJFILES): ($C_SRCFILES)
$(CC) $(CFLAGS) -c -o $# $*
all: $(A_OBJFILES) $(C_OBJFILES)
$(LD) $(LDFLAGS) $(A_OBJFILES) $(C_OBJFILES) -o $(TARGET_OUTPUT)
but ofcourse, this doesn't work...
Any suggestions?
First problem: a misplaced parenthesis or two.
$(A_OBJFILES): ($A_SRCFILES)
Notice that you have the $ inside the ( in ($A_SRCFILES). Make expands $A, which is nothing, and things go downhill. I think you meant $(A_SRCFILES), and the same thing in the other rule.
Second problem: I don't know the syntax of the assembler, but the syntax of the compiler command is wrong:
$(CC) $(CFLAGS) -c -o $# $*
The variable $* is nothing if we're not in a pattern rule, which we're not (yet). And anyway, if we were in a pattern rule and you were trying to build foo.o, this command would look for the source file foo, and there's no such file. Do it this way:
$(CC) $(CFLAGS) -c -o $# $<
Third problem: each object file depends on all source files (in each rule). Try this instead:
$(A_OBJFILES): %.o : %.asm
...
$(C_OBJFILES): %.o : %.c
...
(Now it's a pattern rule.)
Fourth problem: a lot of redundancy in the last rule. Change it to this:
all: $(A_OBJFILES) $(C_OBJFILES)
$(LD) $(LDFLAGS) $^ -o $(TARGET_OUTPUT)
or better still:
all: $(TARGET_OUTPUT)
$(TARGET_OUTPUT): $(A_OBJFILES) $(C_OBJFILES)
$(LD) $(LDFLAGS) $^ -o $#
Since both the assembler and C compiler output *.o files, I cannot use the general %.o:%.c construction often found in example Makefiles
Sure you can:
%.o : %.c
# commands to make .o from a corresponding .c
%.o : %.asm
# commands to make .o from a corresponding .asm

gcc -E -dM gives me preprocessor defines but I want it to compile

I have a large source directory with a complicated Makefile structure (lots of includes etc.)
I would like to grab the preprocessor defines that gcc will provide when you run
gcc -E -dM. However, I also want the source to be built. And when I check the make/build log, I'd like to see all the commands that were run by make, and ALSO the #defines from all the files in the source that were passed to the compiler and/or overriden.
I'm not sure how to go about this.
For e.g
If had a file foo.c with just this one line
#define PI 3.14
Running gcc -E -dM foo.c will print out all the preprocessory defines to stdout, as well as the define inside foo.c.
But it does not compile. How do I combine commands such that both things happen?
You need to do this in two passes, but you can probably set up a makefile rule to do it, e.g. for compiling C code:
%.o: %.c
$(CC) $(CFLAGS) -dM -E $< > $<.dump # dump all preprocessor symbols to .dump file
$(CC) $(CFLAGS) -c $< -o $# # compile to .o as normal
Alternatively if you want to separate the build and preprocessing you could have two rules, e.g.
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $# # compile to .o as normal
%.dump: %.c
$(CC) $(CFLAGS) -dM -E $< > $<.dump # dump all preprocessor symbols to .dump file
You would also need a fake target to ensure that all the .c files generate .dump files.

Resources