make with -R looks for fileName..asm not fileName.asm - makefile

Make looking for file(dot dot).asm
I used the -R switch to avoid being overwhelmed with -d lines. I have file findKey.s. No problem using cpp extension with equivalent makefile statements.
What I assume to be the pertinent makefile lines:
CC = "f:\IAR Systems\Embedded Workbench 6.5\arm\bin\iccarm"
ASM = "f:\IAR Systems\Embedded Workbench 6.5\arm\bin\iasmarm"
all : findKey.o intVec.o invBea.o
%.o: %.cpp
$(CC) "$<" -lC "$(listDir)" -o "$(objDir)" $(dlib) $(C_allOptions) --eec++
%.o: %.c
$(CC) "$<" -lC "$(listDir)" -o "$(objDir)" $(dlib) $(C_allOptions)
%o: %.asm
$(ASM) "$<" -O"$(objDir)" -L"$(listDir)" -r -cM t8 --cpu Cortex-M4 --fpu None
%o: %.s
$(ASM) "$<" -O"$(objDir)" -L"$(listDir)" -r -cM t8 --cpu Cortex-M4 --fpu None
[BEGIN Debug output]
GNU Make 3.82
Built for x86_64-w64-mingw32
This program is built by Equation Solution <http://www.Equation.com>
for Windows.
Copyright (C) 2010 Free Software Foundation, Inc.
[snip]
Updating goal targets....
Considering target file `all'.
File `all' does not exist.
Considering target file `findKey.o'.
File `findKey.o' does not exist.
Looking for an implicit rule for `findKey.o'.
Trying pattern rule with stem `findKey'.
Trying implicit prerequisite `findKey.cpp'.
Trying pattern rule with stem `findKey'.
Trying implicit prerequisite `findKey.c'.
Trying pattern rule with stem `findKey.'.
Trying implicit prerequisite `findKey..asm'. <== WHY THIS??
Trying pattern rule with stem `findKey.'.
Trying implicit prerequisite `findKey..s'. <== AND THIS??
Trying pattern rule with stem `findKey'.
Trying implicit prerequisite `findKey.cpp'.
Looking for a rule with intermediate file `findKey.cpp'.
Avoiding implicit rule recursion.
Trying pattern rule with stem `findKey'.
Trying implicit prerequisite `findKey.c'.
Looking for a rule with intermediate file `findKey.c'.
Avoiding implicit rule recursion.
Trying pattern rule with stem `findKey.'.
Trying implicit prerequisite `findKey..asm'.
Looking for a rule with intermediate file `findKey..asm'.
Avoiding implicit rule recursion.
Trying pattern rule with stem `findKey.'.
Trying implicit prerequisite `findKey..s'.
Looking for a rule with intermediate file `findKey..s'.
Avoiding implicit rule recursion.
No implicit rule found for `findKey.o'.
Finished prerequisites of target file `findKey.o'.
Must remake target `findKey.o'.
[END Debug output]
And then it complained “no rule to make target findKey.o” and stopped.
Possible clue: I removed -R from the command line and make tried to assemble findKey.s with as which is some kind of gnu thing.
Ideas?

Look closely at your two assembler rules:
%o: %.asm
$(ASM) "$<" -O"$(objDir)" -L"$(listDir)" -r -cM t8 --cpu Cortex-M4 --fpu None
%o: %.s
$(ASM) "$<" -O"$(objDir)" -L"$(listDir)" -r -cM t8 --cpu Cortex-M4 --fpu None
Those should be %.o, not %o. That would be the source of the stray double dots in your debug output and the lack of a proper "compile .s to .o" rule.

Related

GNU Make: Force use of my own version of a rule

I have this rule in my Makefile:
%: ${OBJ}/%.o ${OBJ}/AgentProgram.o ${LIB}
$(CXX) $^ ${LDFLAGS} ${LIB_DIRS} ${LIBS} $(OUTPUT_OPTION)
If obj/Foo.o exists, make will use this rule. However, if the object doesn't already exist, it will use the built-in rule and attempt to directly compile from my .cpp.
Is there some way to define this rule as the default, or turn off the built-in rule?
My workaround is to modify my make bins target to produce all .o files first. It wasn't that hard in this case, I altered:
bins: ${BINS}
and turned it into this: (I already had ${OBJECTS} available)
bins: ${OBJECTS} ${BINS}
You can cancel pattern rules, including built-in pattern rules, by defining them without a recipe:
%: %.c
%: %.cpp
will remove the pattern rule for creating binaries from a .c and a .cpp.
Or, with a sufficiently new version of GNU make, you can disable ALL builtin rules by adding this to your makefile:
MAKEFLAGS += -r
(see the manual for the meaning of the -r option).

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

Right way to use VPATH/vpath?

I am trying to use my Makefile (Make for Windows) by adding source paths to vpath/VPATH. This seems trivial but for some reason I am unable to get it to work
My directory structure is like this:
├── Makefile
├── out\
└── src\
└── hello.cpp
My Makefile is:
TGT=out
OBJ=hello.o
VPATH=src
# vpath %.cpp src
all: $(TGT)\app.exe
$(TGT)\app : $(TGT)\$(OBJ)
g++ $^ -o $#
$(TGT)\%.o : %.cpp
g++ -Wall -Wextra -Werror -c $<
changing to vpath didn't help me. I seem to have something fundamentally wrong here. The error I see is:
make: *** No rule to make target `out\hello.o', needed by `out\app'. Stop.
EDIT: debug output from make -d
Considering target file `all'.
File `all' does not exist.
No implicit rule found for `all'.
Considering target file `out\app'.
File `out\app' does not exist.
Considering target file `out\hello.o'.
File `out\hello.o' does not exist.
Looking for an implicit rule for `out\hello.o'.
Trying pattern rule with stem `hello'.
Looking for a rule with intermediate file `out\hello.cpp'.
Avoiding implicit rule recursion.
Trying pattern rule with stem `hello.cpp'.
No implicit rule found for `out\hello.o'.
Finished prerequisites of target file `out\hello.o'.
Must remake target `out\hello.o'.
As MadScientist points out you should avoid backslashes as they have odd results like this, had you used forward slashes throughout your Makefile you wouldn't have had this issue, that said it is possible to work around them.
There are a few things wrong here:
You haven't posted the same Makefile you're using again, the first rule after all should have $(TGT)\app.exe as a target.
A backslash before % in a pattern rule will turn it into a literal %, escape the backslash
You forgot to tell gcc where to output the object file
Once you've fixed all of this you should find vpath works as expected, the complete fixed Makefile is
TGT=out
OBJ=hello.o
vpath %.cpp src
all: $(TGT)\app.exe
$(TGT)\app.exe : $(TGT)\$(OBJ)
g++ $^ -o $#
$(TGT)\\%.o : %.cpp
g++ -Wall -Wextra -Werror -c $< -o $#

Force make not to re-order pre-requisites in automatic variable expansion

Here a is my makefile (GNU make) to compile a small OCaml program:
SUFFIXES:=
OCAML=ocamlopt
LD=ocamlopt
OFLAGS=
.PHONY: all clean
all: playground
playground.cmx: playground.ml lstream.cmi
playground: lstream.cmx playground.cmx
%.cmi: %.ml
$(OCAML) $(OFLAGS) -c $<
%.cmx: %.ml
$(OCAML) $(OFLAGS) -c $<
%: %.cmx
$(LD) -o $# $^
playground uses functions from the Lstream module. In this case, the ocaml linker requires the files to link to be specified in order of dependency (eg: ocamlopt -o playground lstream.cmx playground.cmx).
Despite the fact that I defined the playground rule's dependencies in the right order,
make consistently re-orders them and executes ocamlopt -o playground playground.cmx lstream.cmx which causes a linker error.
Is there a way to enforce the correct behaviour ? I would like to avoid specifying the link command explicitely and let make infer it from the dependencies.
Implicit rules always force the pattern matching prerequisite to be first, regardless of the order in which they're defined elsewhere. This is almost always what you want, because in most rules the pattern matching prerequisite is special.
For example when compiling an object file the prerequisites consist of one source file and a bunch of header files; the source file is special and needs to be listed on the command line. Make ensures that for a pattern rule %.o : %.c (for example) the prerequisite matching %.c is first in the list, and so is assigned to the $< automatic variable, and it can be treated differently.
In any event the short answer is no, you cannot modify this behavior. An implicit rule % : %.cmx matching a target playground will always force the prerequisite playground.cmx to be listed first in the prerequisite list. The other prerequisites will maintain their order.
If you really need the prerequisites to maintain their order then I recommend using a static pattern rule:
TARGETS = playground
$(TARGETS) : % :
$(LD) -o $# $^
(you can also use a "match anything" pattern rule but this can be a real performance degrader). Here since you have no pattern in the prerequisite list, nothing will be reordered.

Pattern rule depending on another pattern rule

consider the following fragment of my makefile:
gui_backend: $(BUILDDIR)/gui_backend
$(BUILDDIR)/gui_backend: $(BUILDDIR)/gui_backend.o $(BUILDDIR)/config.pb.o
$(CXX) $(LDFLAGS) -o $# $^
$(BUILDDIR)/%.o: $(SRCDIR)/%.cc $(SRCDIR)/%.h | $(BUILDDIR)
$(CXX) $(CXXFLAGS) -c -o $# $<
$(SRCDIR)/%.pb.cc: $(PROTODIR)/%.proto
$(PROTOC) $(PROTOOPTIONS) --cpp_out=$(SRCDIR) $<
now if I call to make gui_backend, I get
make: *** No rule to make target `build/config.pb.o', needed by `build/gui_backend'.
Why doesn't make pick up on the $(BUILDDIR)/%.o pattern here? If I state things explicitly by adding the rule
$(BUILDDIR)/config.pb.o: $(SRCDIR)/config.pb.cc $(SRCDIR)/config.pb.h | $(BUILDDIR)
$(CXX) $(CXXFLAGS) -c -o $# $<
it seems to work. However, I would like to keep the makefile as concise as possible.
Running make with -d gives me the following (complete output here):
Considering target file `build/config.pb.o'.
File `build/config.pb.o' does not exist.
Looking for an implicit rule for `build/config.pb.o'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `src/config.pb.cc'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `build/config.pb.c'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `build/config.pb.cc'.
Trying pattern rule with stem `config.pb'.
[...]
Trying implicit prerequisite `build/SCCS/s.config.pb.o'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `src/config.pb.cc'.
Looking for a rule with intermediate file `src/config.pb.cc'.
Avoiding implicit rule recursion.
Trying pattern rule with stem `config'.
Trying implicit prerequisite `src/proto/config.proto'.
[...]
I'm running GNU Make 3.81, btw.
Also, I just noticed that if I run make src/config.pb.cc and then make build/config.pb.o manually, it works.
Why doesn't this work?
Your example looks correct to me. The only difference between the pattern rule and the explicit rule I see is that the explicit rule doesn't have the order-only prerequisite. What version of GNU make are you running? Are you sure it supports order-only prerequisites? If it doesn't then the pattern rule will not match as it's trying to find a way to build a target like | and can't.
Whenever you hit issues like this the simplest thing to do is run make -d. The output is voluminous but it is also very enlightening: find the section where it's trying to build config.pb.o and see what patterns it's trying and why it decides to give up on that one.
I am also building proto files, I am using these Makefile targets:
%.pb.cpp: %.proto
protoc --cpp_out=. $<
mv $(#:cpp=cc) $#
%.pb.h: %.pb.cpp ;
build/%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) $(NON_PROFILE_CXXFLAGS) -MD -MF $(#:%.o=%.d) -MT $# -c $< -o $#
I can execute
rm -rf build/lsm.pb.o lsm.pb.h lsm.pb.cpp
make build/lsm.pb.o
And it correctly finds the dependencies. For me, I was unable to get this to work until I added the semicolon to the end of the first rule. For some reason, Make does not like empty recipes for pattern rules.
Six year old question at this point, but hopefully this answer can help others like me who end up here.

Resources