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

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.

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.

Delete targets with recipes failed in Makefile

I tried to use .DELETE_ON_ERROR target in makefile in order to delete both $(OBJ)
and executable files if the recipe fails, but it doesn't work. If I put an error inside any object file than while compiling the pattern rule an error occurs and it stops. The old object file is still on its place but I expect .DELETE_ON_ERROR to remove it.
Can anyone test the code? Can -include $(DEP) or flag -DDBG influence? The goal is to delete both the .o file that failed and the executable.
OUTPUT = executable
CPP := $(shell find $(SRC) -type f -name "*.cpp")
OBJ := $(CPP:.cpp=.o)
DEP := $(OBJ:.o=.d)
CXX := g++
CXXFLAGS =-MMD -MP -DDBG
INCLUDES = -I.
.DELETE_ON_ERROR :
$(OUTPUT): $(OBJ)
$(CXX) $^ -o $#
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
-include $(DEP)
.PHONY : clean
clean:
rm -rf $(OBJ) $(DEP)
EDIT: According to the Ondrej K. solution to fix this problem you need to add #touch command before compilator in order to make the object files changed (the docs read "delete the target of a rule if it has changed".). So, the code should look like this:
%.o: %.cpp
#touch $#
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
Not sure what failure you're seeing, but I am afraid there really isn't a good way for you to do that. .o files and executable ($(OUTPUT)) are separate rules. If the latter fails, former is already out of consideration. See the documentation:
.DELETE_ON_ERROR:
If .DELETE_ON_ERROR is mentioned as a target anywhere in the makefile, then make will delete the target of a rule if it has changed and its recipe exits with a nonzero exit status, just as it does when it receives a signal. See Errors in Recipes.
In other words, if your the target producing a binary object failed after .o target itself got updated, make would prune the changed file. But if your executable did not link, it won't go back and delete object files.
Not sure it'd be nice, but if you really needed to, you could probably achieve this by refactoring your makefile to basically have direct exec + objs from source prerequisites rule with a single recipe. Obvious downside, such rule would mean single .c file change causing all files being recompiled (basically negating substantial benefit of using make).
EDIT: I'll expand on the comment a bit to clarify. What you seem to want is: in case there is a broken .c file and compilation fails, remove the old .o file. That is quite clearly not how .DELETE_ON_ERROR works though. If the .o file already got updated, and then the rule failed, it would remove it ("delete the target of a rule if it has changed"), but in case of a mentioned syntactical problem, the compiler would fail before it would produced an .o file.
So, if for instance you updated your (pattern) rule for compilation so that it first touches (effectively updates timestamp) on the .o file and then tries to compile. After the compiler call and rule failed make would consider the target of the failed root to have been updated and remove it. Alternatively you could also change to rule to first try to rm the expected '.o' file in which case you actually wouldn't need to use .DELETE_ON_ERROR (and if there is no change in the relevant sources, the rule does not get used, so it's actually not as terrible as it sounds). Either way is not exactly very clean, but leads towards the behavior I understand you're describing.
It is possible that the Compiler crashes while writing the Output file. In this case, there is a corrupt output file that is newer than its sources. Make will stop due to the error, but on next run, it won't recompile the output file as it is newer than ist sources - and the make will fail again and again in the build step.
With the .DELETE_ON_ERROR rule, make will delete the Output file if the compiler (or whatever build step failed) exits with an error after touching (and corrupting) the Output file, so it will be recompiled on next run. (if the Compiler failed without touching the old output file, it will always be recompiled on next run anyway)

makefile: dependency not build

The question was edited after MadScientist's answer. See history for the original makefile, but the problem stays the same.
I have a small makefile:
DEPFLAGS=-MD -Mo $(OUTDIR)/$*.Td
POSTCOMPILE=#mv -f $(OUTDIR)/$*.Td $(OUTDIR)/$*.d && touch $#
VPATH=../src
OUTDIR=../out
SOURCES:=$(notdir $(wildcard ../src/*.c))
OBJECTS:=$(SOURCES:%.c=$(OUTDIR)/%.o)
all: $(OBJECTS) $(OBJECTS:%.o=%.d)
$(OUTDIR)/%.o : %.c
$(OUTDIR)/%.o : %.c $(OUTDIR)/%.d
#$(CC) $(DEPFLAGS) -c $< -o $#
#$(POSTCOMPILE)
$(OUTDIR)/%.d : ;
.PRECIOUS: $(OUTDIR)/%.d
Directory structure looks like:
src
contains file.c
out
empty, after make: contains file.o and file.d
make
contains the makefile
When I call the makefile everything works fine and two files are generated: file.o and file.d
However, when I delete file.d nothing happens. I would expect that make finds a missing dependency for file.c and starts a rebuild. Why doesn't it happen?
Make version is 3.81 built for i386-pc-mingw32 under Windows 7.
Marking a file as .PRECIOUS does not remove all aspects of it's "intermediateness". All it does is prevent it from being deleted, but this feature of intermediate files is still in effect:
If an ordinary file b does not exist, and make considers a target that depends on b, it invariably creates b and then updates the target from b. But if b is an intermediate file, then make can leave well enough alone. It won’t bother updating b, or the ultimate target, unless some prerequisite of b is newer than that target or there is some other reason to update that target.
This is why your .d file is not recreated. In order for it to be recreated you need to ensure it's not an intermediate file. Fortunately this is trivial to do: you just need to mention the files explicitly somewhere as a target or prerequisite. You can do it like this:
all: $(OBJECTS) $(SOURCES:%.c=$(OUTDIR)/%.d)
Or if you prefer like this:
depends: $(SOURCES:%.c=$(OUTDIR)/%.d)
which would allow you to run make depends to update the dependency files, if you wanted to.
I'll just point out in passing that this method of managing dependencies is considered outdated. There's a better, more advanced way it can be done described here among other places.
(I'll be a horrific necromancer here, but I've ran into same problem, and found that actual issue isn't one mentioned in answer or comments here)
Dependency rule generated by compiler by default sports file name with ALL suffixes replaced by single suffix .o and path removed. Which doesn't match the pattern of rule in makefile.
For gcc 4.x and later correct options would be
$(OUTDIR)/%.o : %.c $(OUTDIR)/%.d
#$(CC) -MF $(OUTDIR)/$*.Td -MT $# -c $< -o $#
Mo flag no longer exist, you have to use only MF flag to specify dependency file name.MT flag allows to provide a literal line for target name.

Why does my GNU make skip making an object file (%.o) when building an %.s (assembler) program?

I am using implicit rules only - removing the makefile altogether for a minimal test case. I have an empty (no problem for GNU assembler) program.s file. Executing:
make program
Gives me following output from make:
cc program.s -o program
(and of course the expected errors, which here is of no importance for the question: since my assembler source file is empty, there is no "_start" and all kinds of linking fails.)
I wonder, why does make choose to attempt to build the program in one go? As opposed to first using as program.s ... and then ld program.o ...? Is this because it considers the object file unnecessary in my scenario here?
If I do make program.o, then as program.as ... is invoked, producing my program.o as expected.
Make will always choose one-step implicit rules in preference to multi-step implicit rules, to get the same result. In this case, make contains built-in rules that create an executable both from an object file, but also directly from various source files including assembly:
%: %.s
# recipe to execute (built-in):
$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $#
Since this is shorter than first building the .o then building the executable from the .o, and since your makefile doesn't say you want the .o, make uses the shortest set of steps.

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