Behavior of Match-Anything Pattern Rules in makefile - makefile

Let's say my source is test.c:
#include <stdio.h>
int main()
{
printf("%s\n", "hi");
}
I want the executable called test to be created in a folder called bin. So my makefile is:
all:bin/test
When I execute make, I expect the following built-in rule to happen:
%: %.c
# recipe to execute (built-in):
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $#
because the target % should match bin/test and since test.c exists, it should execute the recipe. However, make says: No rule to make target 'bin/test', needed by 'all'. Stop.
Why does this happen?

If % matches bin/test, then the prerequisite is bin/test.c, which does not exist. So Make rejects that implicit rule in its search for a rule to build bin/test. It finds no other rule which fits the bill, and tells you so.
If you try to build test, or move test.c into bin/, then Make will use this rule.
If you want to build binaries in bin/ from sources in the working directory, you can write your own pattern rule, something that looks like:
bin/%: %.c
...

Related

Makefile: How to write a pattern rule with prerequisite without suffix

In embedded projects you typically convert an ELF output from gcc into a raw binary form with objcopy. I tried to write a pattern rule for that: %.bin: % (executable output from gcc doesn't have a suffix, at least on Linux). This fails with make: *** No rule to make target ...
Here is a complete test case:
test.c:
int main(int argc, char *argv[]) {
return 0;
}
Makefile:
%.bin: %
objcopy -O binary $< $#
This works by saying make test test.bin, that is, by explicitly asking it to build test executable first. It does not work by saying make test.bin. Somehow in that case make does not realize it can make prerequisite with a built in rule.
I know I can fix this by writing the rule as test.bin: test but I'd like to know, why this pattern rule does not work and can I make it work somehow.
Furthermore, I think the obvious and practical ways to make it work breaks the nice and elegant built in rule system. It could be rescued if I could put an option into e.g. LDFLAGS to make linker output the executable with some suffix e.g. .elf (do I still have to rewrite the built in rule for linking? Oh well...).
I admit, this is purely academic problem born in pedantic mind.
Your idea is correct, but you hit a caveat of make -- make will not chain pure % targets with other implicit rules --
https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html#Chained-Rules
... for performance reasons make will not consider non-terminal
match-anything rules (i.e., ‘%:’) when searching for a rule to build a
prerequisite of an implicit rule (see Match-Anything Rules).
You can generate an executable output with a suffix in gcc by passing the output -o option with the name and extension.
Example:
# Give your elf file name
ELF_FILE= test.elf
$(ELF_FILE): $(OBJ_FILES)
echo "Creating elf file"
gcc.exe -o $(ELF_FILE) $(OBJ_FILES)
%.bin: %.elf
objcopy -O binary $< $#
My example works when running make like this: make test test.bin because, IIUC, test is built first and then the prerequisite is already there for building test.bin. Exploiting that, I modified the Makefile like this:
all: $(subst .bin, , $(filter %.bin, $(MAKECMDGOALS))) $(MAKECMDGOALS)
%.bin: %
objcopy -O binary $< $#
Now I can run make test.bin and make builds first test and then test.bin. Or I can run make foo bar.bin and make tries to build foo, bar and bar.bin. This is the closest thing I can come up with. On the positive side is that the Makefile does not have to reference explicitly any file names and no built in rules are rewritten.

Is my understanding correct for the first rule of the makefile?

I'm learning make, and try to understand the following makefile from Prerequisite-Types
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
The first rule confuses me. It's to be firstly applied. Since $(OBJDIR) is not there, the last rule will be applied to mkdir objdir. Then, since there's nothing in the newly created directory, there's no stem.o, and correspondingly, no stem.c So the prerequisites and recipes seem to be meaningless.
The only thing that the first rule does is to make a directory, which seems to be unreal.
The first rule is a pattern rule, so it cannot be the default rule; it will not be the first applied unless you specify e.g. make thing.o.
The first rule might not do what you expect. The recipe is $(COMPILE.c) $(OUTPUT_OPTION) $<, but you don't assign a value to OUTPUT_OPTION in the makefile; unless you provide a value from outside (e.g. make thing.o OPTION_OUTPUT=...) this recipe has no special instructions about where to put the file it builds, it has never heard of objdir/, and will use the compiler's default which is probably the working directory.
The last rule will build objdir (if objdir does not already exist, and if Make invokes that rule). The command make objdir will work perfectly. If you try to build one of the object files listed in OBJS, Make will construct the directory (if the directory does not exit) -- not because it needs a place to put the file, but because $(OBJDIR) is a prerequisite of every member of $(OBJS), according to the third rule. It will not construct the directory if you try to build objdir/thing.o, because $(OBJDIR) is not a prerequisite of that target. You think Make should build it because it is obviously needed? Well, Make isn't that smart.
The first rule has a prerequisite pattern %.c, and the recipe looks for the source file in the working directory, not in any newly constructed subdirectory. If there is no such source file in the working directory, Make will not run that rule.
I don't really follow your logic.
The first rule in your makefile is this:
all: $(OBJS)
so the default goal for this makefile (if you don't specify one on the command line) is all.
all depends on all the .o files. All the .o files have an order-only dependency on the directory. So, first the directory is created, then the .o files are created, then all is done (there is no recipe here to create a program or library or anything out of those .o files).

calling sub makefiles in an easy way fails

I`m using a makefile and call some makefiles in subdirectories.
Can anyony explain me, why this works
$(MAKE) -C stub
$(MAKE) -C source
but this not
SUBDIRS = stub source
$(SUBDIRS):
$(MAKE) -C $#
First time I`m working with makefiles.
When you do not explicitly specify the target(s) to make, it will use the first target whose name doesn't start with a dot. Here, that target is stub.
Apparently, you expect all of the targets of the first rule to be used, but there can only be one default target.
The documentation isn't 100% clear on this.
You will get the desired behavior by prepending the rule:
all: $(SUBDIRS)

Simple Makefile reporting circular dependency -- possibly from suffix rules?

I'm using mingw32-make and attempting to create a simple rule to run windres to include an icon for a Windows executable.
The structure consists of a simple C program in a.c, an a.rs file containing only the line:
1 ICON "a.ico"
..the icon file itself, and the Makefile.
The Makefile:
CC = gcc
all: a
%.rc.o: %.rc
windres $< $#
a: a.o a.rc.o
The output I get:
>make
gcc -c -o a.o a.c
make: Circular a.rc <- a.rc.o dependency dropped.
windres a.rc a.rc.o
gcc a.o a.rc.o -o a
The output files are all created correctly, but I can't figure out how to write the .rc->.rc.o rule to get rid of the circular dependency message. From what I can tell it is interpreting it as a suffix rule where %.rc.o indicates the rule is intended to create %.rc from %.o, thus the dependency on a %.rc is circular...
I can use .rco instead of .rc.o and it doesn't generate this error, but I prefer keeping it to the compound extension if possible.
Is there any way to create a pattern rule giving outputs with an extension of the .ext1.ext2 sort, without having it be interpreted as a suffix rule?
The problem is that make has a built-in rule to build an executable file foo from an object file foo.o. In your situation make matches the rule %.rc.o for the target a.rc.o. Then it tries to find a rule that will update a.rc and when it looks it sees that a.rc.o will exist, and so it matches the rule % : %.o, but then realizes that it has a circular dependency for a.rc.o : a.rc and a.rc : a.rc.o.
The simplest thing to do is define an explicit rule for a.rc so that it won't look for a pattern rule:
a.rc : ;
Alternatively, if you don't need the built-in rule to create an executable from an object file, you can cancel it by adding:
%: %.o
with no recipe.

gnu make: match-anything: dependance on existence of prerequisites

Please consider the following Makefile:
CC = g++
CFLAGS = -c -O -Wall
EFLAGS = -O -Wall -lm -o
UTILITIES = error.o stream_manip.o mat_ops.o GaussElim.o
UTILITIES += abstractmatrix.o dvector.o dmatrix.o ConjGrad.o
# All objects
%.o: %.cpp %.hpp
$(CC) $(CFLAGS) $<
# Executables (doesn't have extension)
% : %.cpp $(UTILITIES)
$(CC) $(EFLAGS) % $< $(UTILITIES)
# Specific executable
#TS_CG : TS_CG.cpp $(UTILITIES)
#$(CC) $(EFLAGS) $# $#.cpp $(UTILITIES)
The match-anything rule (for executables) is supposed to enable me to type the following in a terminal:
make TS_CG
and have make compile the executable called TS_CG. However, make doesn't use my match-all target. Instead it uses its default compilation rule.
On the other hand, if all the objects listed in UTILITIES exist, it does use my match-all target. Hence it seems the matching depends on the existence of the prerequisites.
Apparently:
When a rule is terminal, it does not apply unless its prerequisites actually exist.
(according to
make manual ).
But my rule is not terminal; it is not marked by a double colon!
So why does this still seem to apply?
I might also ask if anyone has a better solution for differentiating between object targets and executable targets, as I have tried to do in my file.
I'm surprised that Make is able to build TS_CG when the UTILITIES don't already exist, since I wouldn't expect it to know that TS_CG needs them.
Anyway, when Make is trying to find a rule for TS_CG, all it finds are implicit rules (nothing specific to TS_CG). In particular, it has %: %.cpp $(UTILITIES), which you provided, and %: %.cpp, which is built in. If $(UTILITIES) all exist, then it will use the first rule, otherwise it will move down the list, looking for a rule whose prerequisites do exist, and find the second. Only if it fails to find any rule whose prerequisites exist will it resort to looking for rules to build the prerequisites.

Resources