Makefile Static Pattern Rule - makefile

A part of my Makefile:
CFLAGS = -I ../headers -Wall
EXECUTABLES = testPattern testPatterns
$(EXECUTABLES): %Pattern: %.c pattern.o
g++ $(CFLAGS) $#.c pattern.o -o $#
I didn't include the object compilation because it's irrelevant.
The problem I have with this code is that the pattern matches only the first executable because it ends with 'Pattern', the second executable has an additional 's' at the end which kills the script. Is there any way I can make it work without changing the name of the second executable?
Thanks

There's no point in using a static pattern rule here, since the pattern doesn't appear in the prerequisites list. However, I assume you also wanted to include the .c file as a prerequisite here.
Why do you include the Pattern in the pattern match?
You can just write:
CFLAGS = -I ../headers -Wall
EXECUTABLES = testPattern testPatterns
$(EXECUTABLES): % : %.c pattern.o
g++ $(CFLAGS) $^ -o $#
ETA
It appears a better example that would show the real issues you face would be something like this:
EXECUTABLES = someThing somePattern morePatterns
where you want a static pattern rule that matches the two binaries containing Pattern but not the others.
As I said in my comment below, you cannot do this with a single pattern which means you can't do it in the target part of a static pattern rule.
However, you could do it like this:
$(foreach E,$(EXECUTABLES),$(if $(findstring Pattern,$E),$E)): % : %.c pattern.o
g++ $(CFLAGS) $^ -o $#
This basically loops through each entry in EXECUTABLES and tests to see if it contains the string Pattern, and if so expands to that string else expands to nothing.

Related

How to make makefile to use pattern rule?

Having this simple makefile:
VPATH = include
CC := gcc
CFLAGS := -I include -Wall -pedantic
%: %.o include.o
$(CC) -o $# $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
When I trigger it with the name of a program (the same name as is source with .c extension), I would expect to trigger the first rule (since I provided just a name without extension) and the the second one, because for the first rule, there is %.o prerequisite, which is exactly the second rule.
Having these file in pwd:
client.c include makefile server6.c server.c
Now If I make make server:
It does
gcc -I include -Wall -pedantic server.c -o server
In other words, The second rule is not triggered. there is no step with makeing object files, even though the object file is in the first rule as prerequisite. So how is that possible? The make is simply ignoring the prerequisite and trying to make just with the first rule. How to fix that?
That's because make has a built-in rule for %: %.c and make will always choose a pattern rule that can directly create the target over a pattern rule that requires another pattern rule:
Note however, that a rule whose prerequisites actually exist or are mentioned always takes priority over a rule with prerequisites that must be made by chaining other implicit rules.
You can run make -r to remove all the built-in rules, or else remove it yourself by adding:
% : %.c
to your makefile.
You can see all built-in rules by running make -p -f/dev/null

Makefile pattern matching not working as I expected

I'm trying to setup a simple Makefile for building a simple project that's not too hard to maintain.
I want to make use of pattern matching rules e.g. %.o : %.c ; g++ ... where I have all the object files I would want to compile deduced from wildcard matched source files.
The directory structure is
./src
./include
./build/bin
./build/objs
Right now my problem looks something like this.
INCL_DIR = ./include
SRC_DIR = ./src
BUILD_DIR = ./build
BIN_DIR = $(BUILD_DIR)/bin
OBJ_DIR = $(BUILD_DIR)/objs
SRCS = $(notdir $(wildcard $(SRC_DIR)/*.cc))
OBJS = $(addprefix $(OBJ_DIR)/, $(SRCS:%.cc=%.o))
$(BIN_DIR)/program : $(OBJS)
$(CXX) $(CXXFLAGS) -I $(INCL_DIR) $^ -o $#
$(OBJS):%.o : %.cc
$(CXX) $(CXXFLAGS) -I $(INCL_DIR) -c $< -o $#
In the line $(OBJS):%.o : %.cc an example expansion would be from target rule ./build/objs/a.o that depends on ./build/objs/a.cc but the source file is in ./src/a.cc.
So I figured I could strip away the dependency format to try and match ./src/a.cc but the utilies for text manipulations don't seem to work on the dependency side of a rule.
I tried something like
$(OBJS):%.o : $(SRC_DIR)/$(notdir %.cc)
or
$(OBJS):%.o : $(SRC_DIR)/$(*F).cc
where $(*F) would expand to a in the earlier example case but it doesn't expand to anything when listed as a dependency.
I'm not experienced with Makefiles and not sure why my attempts arent working and would very much like to hear a solution that might solve my issue.
Thanks.
The solution is already in #John's comment. I will try to explain it in bit more detail. I will use an example with hello.cc in folder src.
pattern rules hold the pattern in % symbol. If there is in the makefile a pattern rule: build/objs/%.o : src/%.cc and you request to build file build/objs/hello.o, % will carry value hello. But if your pattern rule would be $(OBJS):%.o : %.cc, the pattern % will be build/objs/hello and the dependency file build/objs/hello.cc is missing (because it is saved in src, not in build/objs).
So solution for you would be:
$(OBJS):$(OBJ_DIR)%.o : $(SRC_DIR)%.cc
$(CXX) $(CXXFLAGS) -I $(INCL_DIR) -c $< -o $#
If you want to make sure how patterns work, you can print pattern content by adding line #echo $* to recipe.

What is the semantics of '%' in Makefile?

Googling doesn't help much in understand how the % variable is being used in the Makefile snippet below.
_OBJ = a.o b.o c.o
OBJ = $(patsubst %,$(OBJDIR)/%,$(_OBJ))
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(INC)
$(CC) -c -o $# $< $(CFLAGS)
Can anybody please help me out? Does it mean that if there are five .c files present under $(SRCDIR), that many *.o rules are being populated behind the scene?
That is an "implicit rule". The % makes the word $(OBJDIR)/%.o a pattern. It tells make that if it's trying to build a target and the name of the target matches that pattern (where the % can substitute for one or more characters--any characters), AND that a file that matches the pattern $(SRCDIR)/%.c (where the % here has the same value as in the target) either already exists or can be built, then make can use this recipe to build that target.
So, if make wants to build a file foo/bar.o and the variable OBJDIR has the value foo, then this pattern foo/%.o will match that file with the % matching bar (this is called the stem in the GNU make documentation).
Then if SRCDIR has the value blah and make can find (or create) a file named blah/bar.c, then this implicit rule can be used to build the target foo/bar.o by running this recipe ($(CC) -c -o $# $< $(CFLAGS)).

getting the target name in a function in prerequisites list [makefile]

I'm trying to create a makefile where the target is used to search for dependencies in .d
Thanks to the answers here and here I have discovered that .SECONDEXPANSION: does the job. However I'm running into an issue nesting functions which is seemingly bizarre. The offending rule looks like this:
.SECONDEXPANSION:
$(APPS): %: $$(patsubst %.c,%.o,$$(wildcard $$#.d/*.c)) $$(INC_OBJS)
$(CC) $(CFLAGS) $^ -o $#
instead of:
gcc -Wall -std=c99 unittest.d/unittest.o common/cards.o -o unittest
which is what I want, I get:
gcc -Wall -std=c99 unittest.d/unittest.c common/cards.o -o unittest
which for some reason doesn't have the .o substituted for the .c. So it appears I'm almost there, I just need to get the substitution working. All help appreciated and if you think this is a poor way to organize a makefile, critizism on that front welcome.
The problem is that you're trying to use % as two different wildcards at once, the static pattern stem and the patsubst wildcard. So Make makes the stem replacement and gets this:
$(patsubst unittest.c,unittest.o,$(wildcard $#.d/*.c))
and then patsubst does nothing, because it finds no "unittest.c" to replace. (Note that the "unittest.c" in "unittest.d/unittest.c" doesn't match, because without a wildcard, patsubst looks for a perfect match.)
There's no need for this to be a static pattern rule (you never use that functionality), so you can just eliminate that part and the rest should work:
.SECONDEXPANSION:
$(APPS): $$(patsubst %.c,%.o,$$(wildcard $$#.d/*.c)) $$(INC_OBJS)
$(CC) $(CFLAGS) $^ -o $#

Understanding a makefile

I am talking about this question where the person has updated his final solution with a makefile for the task. I am having a hard time understanding how it's done.
There is a rule:
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
which I am unable to understand, but by intuition I know what it will be doing. Almost everything else is pretty much clear. Thanks!
This is a static pattern rule. The first field is a list of targets, the second is a target pattern which Make uses to isolate a target's "stem", the third is the prerequisite pattern which Make uses to construct the list of prerequisites.
Suppose you have
SRCDIR = src
OBJDIR = obj
OBJECTS = obj/foo.o obj/bar.o obj/baz.o
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
If you make obj/foo.o, Make first identifies this rule as the one to use (since obj/foo.o is in the target list $(OBJECTS)), matches it against the target pattern obj/%.o and finds that the stem (the part matched by the wildcard %) is foo, then plugs that into the prereq pattern src/%.c and finds that the prerequisite is src/foo.c.
If you've also defined the variables
CC = gcc
CFLAGS = -thisflag -thatflag=something
Then the command in the rule becomes
#gcc -thisflag -thatflag=something -c src/foo.c -o obj/foo.o
(Note that $< is the first prerequisite and $# is the target name.)
In answer to your other question: Yes, a makefile can handle a dependency on a header file (x.h) so that if the header has been modified, Make will rebuild the target. No, this makefile doesn't do that. You can modify the makefile by hand, adding rules like
a.o: x.h
assuming you know what the inclusions actually are, or you can have the makefile do it automatically, which is an advanced technique you probably shouldn't attempt yet.
This line is explaining how to obtain the object files (.o) from the source (.c), it avoids having to repeat the line for each .c file.
The objects will be in OBJDIR and the sources in SRCDIR
$(CC) will contain the compiler, CFLAGS will contain the options for the compiler and -c tells gcc to compile the source into objects.
For example:
CC = gcc
CFLAGS = -g -Wall
can be converted into
gcc -g -Wall -c test.c -o test.o

Resources