Printing CFLAGS in GNU make exaclty once if source files have changed - gnu-make

Here is a snippet from my makefile:
all: $(TARGET)
$(C_OBJS): %.o: %.c
# echo -n "Compiling " $*.c;
# $(CC) -c $(CFLAGS) $*.c -o $*.o
# echo " ...... Done"
$(TARGET): $(C_OBJS)
# $(AR) rus $# $(C_OBJS);
print_cflags:
# echo "CFLAGS: " $(CFLAGS) "\n"
Moving forward, I want to
Print the CFLAGS once if compilation takes place.
Get make: Nothing to be done for "all" message if no modifications has been done from previous build. Printing CFLAGS is optional in this case.
I feel, it can be achieved by keeping a counter inside $(C_OBJS): %.o: %.cBut is there any better way to achieve this?
I understand that this is a very specific question but any help will be appreciated.

Etan gives a number of good options. Here's another one, assuming your version of GNU make is new enough to support eval:
print_CFLAGS := $(CFLAGS)
$(C_OBJS): %.o: %.c
# $(if $(print_CFLAGS),echo "CFLAGS: $(print_CFLAGS)" $(eval print_CFLAGS:=))
# echo -n "Compiling " $*.c;
# $(CC) -c $(CFLAGS) $*.c -o $*.o
# echo " ...... Done"

Related

Error in calling one make target from another

$make --- Will have normal build
$make CAdvisor
Above will do following steps:
1) Update variable CC, now it should become "cadvise -pdb mypdb +wlint +wall aCC"
2) Run all with updated CC option
CC = aCC
CFLAGS = -c #-Wall
LDFLAGS =
SOURCES = foo.cc
OBJECTS = $(SOURCES:.cc=.o)
EXECUTABLE = observer
RM=rm -rf
CADVISE_OPTS= -pdb mypdb +wlint
CADVISE= /opt/cadvise/bin/cadvise
.PHONY : CAdvisor update_cc clean all
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cc.o:
$(CC) $(CFLAGS) $< -o $#
clean:
$(RM) $(EXECUTABLE) $(OBJECTS)
update_cc: CC := ${$(CADVISE) $(CADVISE_OPTS) $(CC)}
CAdvisor: update_cc all;
#echo DEBD $(CC)
Now above code is giving me error:
**$ make CAdvisor
Make: Don't know how to make CC. Stop.
$**
How to fix this error
Any better option?
Linkes:link_how to call target from another
Thanks
Sorry, but that's not how target-specific variables work. Target-specific variables are scoped to their target and any prerequisite built as a result of building that target. It's not the case that the target-specific setting changes the value of the global variable for the rest of the recipes expanded by make.
In your example, all is not a prerequisite of update_cc, it's a sibling. So, target-specific variables that are set for update_cc have no impact on the all target.
Second, using ${$(CADVISE) $(CADVISE_OPTS) $(CC)} is definitely not right: the inside will be expanded first then because the entire thing is enclosed in ${...} it will be treated as a variable name, and that variable (which clearly doesn't exist) will be looked up, resulting in an empty string.
I don't know why you have added the extra target update_cc at all; why not just set the target-specific variable on the CAdvisor target?
CAdvisor: CC := $(CADVISE) $(CADVISE_OPTS) $(CC)
CAdvisor: all
#echo DEBD $(CC)

Autodependency generation in makefiles

I am trying to understand how autodependency is generated in makefiles in the given link, i cannot understand the following piece of code:
DEPDIR = .deps
df = $(DEPDIR)/$(*F)
SRCS = foo.c bar.c ...
%.o : %.c
#$(MAKEDEPEND); \
cp $(df).d $(df).P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P; \
rm -f $(df).d
$(COMPILE.c) -o $# $<
-include $(SRCS:%.c=$(DEPDIR)/%.P)
I got it from this link. I know it will generate dependency files but I am not able to understand what this line does:
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P; \
Can somebody please explain me this code, so many wildcards give me butterflies, i am new to makefiles.
That is a number of distinct commands so break it up.
-e 's/#.*//'
Delete everything that starts with a # (Comments? Pre-processor directives?)
-e 's/^[^:]*: *//'
Delete everything up to a : on any that has : it.
-e 's/ *\\$$//'
Delete line-continuation slashes (and spaces before them) from the end of lines.
-e '/^$$/ d'
Delete any blank lines.
-e 's/$$/ :/'
Add : to the end of every line.
This adds explicit targets for every listed dependency file so that make "knows" how to build them to avoid the "No rule to make target" errors. The reasoning here is explained in your link in an earlier section.
Briefly, this creates a .P file with the original prerequisites list, then adds targets to it by taking each line, removing any existing target information and any line continuation (\) characters, then adding a target separator (:) to the end. This works with the values for MAKEDEPEND I suggest below; it’s possible you will need to modify the translation for other dependency generators you might use.
This is not meant to be an answer to your actual question, but since you said you were new to GNU make, I think spreading the words that a simpler way to handle auto dependencies exists won't do any harm.
Nowadays compilers like GCC or Clang can do this for you while compiling your code !
Simply pass them a preprocessor flag:
# Preprocessor flags
CPPFLAGS += -MMD
And include the generated files into the Makefile:
-include $(wildcard *.d)
And you're done.
You can learn more about the preprocessor options here for GCC, Clang simply mirror these options.
A relatively good example lies here too.

Can GNU Make recognise multiple matches in a pattern?

I have a rule in a makefile like this:
%.120.png : %.svg
inkscape -z -e $# -w 120 -h 120 $<
which works as intended. I would like to rewrite this in a more generic fashion, something like this:
%.%2.png : %.svg
inkscape -z -e $# -w %2 -h %1 $<
where %2 is a second match (% being the first).
As far as I know, this isn't supported. However, if it is, how ?
You cannot use multiple patterns. In the example you give, though, it's not hard to automate the recipe, although you'll still have to write multiple patterns:
INKSCAPECMD = inkscape -z -e $# -w $(patsubst $*.%.png,%,$#) -h $* $<
%.120.png : %.svg
$(INKSCAPECMD)
%.100.png : %.svg
$(INKSCAPECMD)
Etc. Except, looking at it more I'm pretty sure your description is wrong and that this pattern won't do what you really want

No rule to make target in Maefile

I'm learning to write makefiles. I made my own simple one just to try and test, but every time I run make, i get:
make: *** No rule to make target `/%.cpp', needed by `obj'. Stop.
I googled. I'm pretty sure I typed everything correctly, and my folders are set up the way they should be. Here is the makefile:
CC = g++
LD = g++
NAME = app
OBJ_DIR = obj
SRC_DIR = src
CC_FLAGS = -std=c++0x
all: $(NAME)
$(NAME): $(OBJ_DIR)/%.o
$(LD) $(OBJ_DIR)/%.o -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $< -o $# $(CC_FLAGS)
clean:
rm $(NAME) $(OBJ_DIR) -rf
What is the problem?
The line:
$(NAME): $(OBJ_DIR)/%.o
is not correct. This is not a pattern rule (because the target doesn't contain a pattern character, %) and so it's interpreted as an explicit rule, saying that app depends on the actual file named obj/%.o which doesn't exist, and make doesn't know how to build it (because there's no file src/%.cpp).
You need to change this to:
$(NAME): $(OBJ_DIR)/foo.o ...
or whatever object files you have.

makefile rule to build multiple targets without intermediate file

I am stumped coming up with a makefile rule to have several executables where each depends on its respective source file. There is a library common to all and each program has a single source file: a.c compiled and linked with the library produces executable a, etc.
LIB_C_FILES = f1.c f2.c f3.c
LIB_H_FILES = f1.h f2.h f3.h
TARGETS = a b c
CFLAGS = -g -O0 -DDEBUG
.PHONY : all clean
.c.o:
g++ -c $(CFLAGS) -o $# $<
all: $(TARGETS)
${TARGETS} : lib.a ${#:%=%.c}
g++ $(CFLAGS) ${#:=.c} -o $# lib.a
lib.a: ${LIB_C_FILES:.c=.o} $(LIB_H_FILES)
ar r $# $?
The library portion works fine. And when an executable does not exist, it also works fine. But when one of the standalone source files is modified it says make: Nothing to be done for 'all'.
I don't understand the proper way to make target a depend on source a.c individually in a list. What am I missing?
Just for completeness: you can do what you want with plain old static pattern rules, so long as you can match all of ${TARGETS} with make's (noddy) pattern matching.
${TARGETS}: %: %.C lib.a
g++ ${CFLAGS} $< -o $# lib.a
lib.a: ...
ar ...
A tad more readable, and perhaps more compatible than .SECONDEXPANSION?
First, I assume fio.a was a typo (you probably meant lib.a).
Second, I think the tricky part is your ${#:%=%.c} prerequisite. AFAIK, $# can't be used this way.
I think you can get the behavior you're looking for using .SECONDEXPANSION though.
Try:
.SECONDEXPANSION:
${TARGETS} : lib.a $$(patsubst %,%.c,$$#)
There may be an old-style substitution way to do this, but I find the patsubst line to be more readable than ${#:%=%.c}.
(I should add that this applies to Gnu make 3.82. YMMV with older versions of Gnu make, or [heaven forbid] non-Gnu versions of make).

Resources