Make mistaking a path, failing with "No rule to make target" - linux

I'm trying to build trace-cmd.git from source; the worst is, I had already built this once on this same machine, succesfully; however didn't keep any notes, and cannot tell what could have happened in the meantime.
So now I'm trying to rebuild, and I get the dreaded:
trace-cmd$ make
make: *** No rule to make target `/media/disk/trace-cmd/event-parse.c', needed by `event-parse.o'. Stop.
Ok, let's see what the debug says:
trace-cmd$ make -d
...
Successfully remade target file `trace_python_dir'.
Pruning file `tc_version.h'.
Considering target file `libparsevent.a'.
Considering target file `event-parse.o'.
Pruning file `/media/disk/src/trace-cmd/event-parse.c'. ## THIS EXISTS!
Pruning file `.event-parse.d'.
Considering target file `/media/disk/trace-cmd/event-parse.c'. ## THIS DOESN'T???
File `/media/disk/trace-cmd/event-parse.c' does not exist.
...
Trying pattern rule with stem `event-parse.w'.
Trying implicit prerequisite `/media/disk/trace-cmd/SCCS/s.event-parse.w'.
Trying pattern rule with stem `event-parse'.
Rejecting impossible implicit prerequisite `/media/disk/trace-cmd/event-parse.w'.
No implicit rule found for `/media/disk/trace-cmd/event-parse.c'.
Finished prerequisites of target file `/media/disk/trace-cmd/event-parse.c'.
Must remake target `/media/disk/trace-cmd/event-parse.c'.
make: *** No rule to make target `/media/disk/trace-cmd/event-parse.c', needed by `event-parse.o'. Stop.
OK, what is going on? Of course the actual file exists:
trace-cmd$ ls -la /media/disk/src/trace-cmd/event-parse.c
-rw-r--r-- 1 user user 121563 2013-03-20 19:03 /media/disk/src/trace-cmd/event-parse.c
... but this is /media/disk/src/trace-cmd/event-parse.c!! And:
make already found it once;
yet make decided to, for some reason, drop the /src/ from the path,
... and that file obviously doesn't exist:
trace-cmd$ ls /media/disk/trace-cmd/event-parse.c
ls: cannot access /media/disk/trace-cmd/event-parse.c: No such file or directory
Can someone explain me, for what possible reason could make decide to drop a part of the path, such that it cannot find a file, that it originally had a correct reference to?

Got it - thought I'd focus on that .event-parse.d file:
trace-cmd$ head -n 4 .event-parse.d
event-parse.o: /media/disk/trace-cmd/event-parse.c \
/usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
... and indeed, that is the wrong path there... What happens if I delete this .d file?
trace-cmd$ rm .event-parse.d
trace-cmd$ make
COMPILE FPIC event-parse.o
make: *** No rule to make target `/media/disk/trace-cmd/trace-seq.c', needed by `trace-seq.o'. Stop.
Oh, my. There must be more of them:
trace-cmd$ ls .*.d
.event-parse.d .plugin_kmem.d .trace-filter.d .trace-options.d .trace-seq.d
.kbuffer-parse.d .plugin_kvm.d .trace-ftrace.d .trace-output.d .trace-split.d
.kernel-shark.d .plugin_mac80211.d .trace-graph.d .trace-plot-cpu.d .trace-stack.d
...
... and indeed, there are; apparently cached files from previous compilation, where indeed I compiled in another directory. And if I delete them all:
trace-cmd$ rm .*.d
trace-cmd$ make
...
gcc --shared event-parse.o trace-seq.o parse-filter.o parse-utils.o trace-util.o trace-input.o trace-ftrace.o trace-output.o trace-recorder.o trace-restore.o trace-usage.o trace-blk-hack.o kbuffer-parse.o ctracecmd_wrap.o -o ctracecmd.so
Note: to build the gui, type "make gui"
to build man pages, type "make doc"
Well, that seemingly worked; I'm back to being happy again :)
Cheers!

Related

Why does GNU Make try to compile an object file that doesn't exist, for a rule without a recipe?

If you run make test on the following Makefile (with an otherwise empty directory):
test.%:
#echo $*
test: test.dummyextension
you get the following output:
dummyextension
o
cc test.o test.dummyextension -o test
clang: error: no such file or directory: 'test.o'
clang: error: no such file or directory: 'test.dummyextension'
clang: error: no input files
make: *** [test] Error 1
Why?
I suspect it has something todo with implicit rules, but I searched make -p on my machine, and can't find any implicit rules that match %: %. I would expect the output to simply be dummyextension, but it's almost like there's a phantom test.o file in my directory (despite my checking ten times that there is not).
If you put a ; after the test.dummyextension prerequisite, or add any content to the test rule, everything works as expected. This is the minimal failing example I can come up with, and I haven't a clue why you'd see this behaviour. Any ideas?
Make can chain multiple rules to create a target. In this case it has the following built-in rule:
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
This tells make that it can make test if it can find a way to make intermediate file test.o. So now it looks for a way to make test.o and it sees your pattern rule test.%:, which matches with stem o. So it has found a way!
You have also told make that test needs test.dummyextension, so it looks for a way to make that and again the pattern test.%: matches, this time with stem dummyextension.
So make first runs the test.% recipe twice to make the two prereqs. Then it runs the %: %.o recipe to make the final target. The $^ in the recipe is all prerequisites, so both test.o, gained from the built-in pattern rule, and test.dummyextension, gained by the explicit dependency in your Makefile, appear in the command.
You can test this by using the -r flag to disable built-in rules and then add the above pattern rule manually to your Makefile.
The key points to understand here are:
A line of the form:
test: test.dummyextension
Only adds a dependency to a target. It is not a rule to make the target. That can come from elsewhere. Make does not see this and decide test should be created with a blank recipe.
A stanza of the form:
test: test.dummyextension
;
This is a rule to make the target. Being an explicit rule it has a higher priority than a pattern rule that might also match. This does tell make it has found the rule to make test using the recipe ; and it stops looking for another rule.
Make will search for an implicit rule to make any target if it does not find an explicit one. If you don't want it to do this, you can either give it an explicit rule, like above, or declare the target as phony, with .PHONY: target. Implicit rules are not searched for phony targets.

Linux Kbuild: what is the difference between $(src) and $(obj)

In Documentation/kbuild/makefiles.txt chapter 3.10 it is mentioned that $(src) refers to the location of the source code while $(obj) refers to the location of the generated output files. I am confused about this when using a different output directory.
In Makefile.build the very first thing that is done is src := $(obj). How does that make any sense? If I print $(src) and $(obj) they always have the same value.
However, what is even more confusing to me, is that if this was the case, make should issue an error.
If the working directory is outside the kernel source (O=path/to/out/dir) when the rule $(obj)/%.o: $(src)/%.c is evaluated it should search for the source file relative to the output directory. And since the source file is not there it should fail saying it cannot find a rule for $(src)/%.c target.
Can someone please explain what I'm getting wrong here?
Answering my own question in case others wondered about this...
The main Makefile uses vpath to add the src location, so when kbuild does not find the source file in the output tree it will find it in the source tree.

My rule is invisible when declared in a sub makefile

These are simplified examples of my question.
I have:
Makefile in top/sub/sub/dir:
THINGSTODO := dothis
dothis:
#echo Do cool stuff
Main makefile in top dir:
all: $(THINGSTODO)
#echo do important stuff
Makefile in the sub dirs get included automatically.
If I run this (make all) I get:
No rule to make target 'dothis', needed by 'all'.
My conclusion is that the variable THINGSTODO gets a value but for some reason the rule "dothis" is not visible.
If I place the "dothis" rule in the main makefile it works like a charm.
But I don't want to change the main makefile, I just want to add a rule, in the sub/sub/dir makefile, that is executed before the "all" rule is executed.
I must be missing a vital bit of knowledge to solve this. Any suggestions?
Thanks.
system: Linux 4.18.13-100.fc27.x86_64
make: GNU Make 4.2.1 (Built for x86_64-redhat-linux-gnu)

Makefile rule with percent symbol is not evaluated

I'm trying to port linux kernel's kconfig util to my product
while compiling I got next error:
make[6]: *** No rule to make target `zconf.tab.c', needed by `zconf.tab.o'. Stop.
I found next rule in Makefile.lib for this file
$(obj)/%: $(src)/%_shipped
$(call cmd,shipped)
It looks ok for me and it just works in kernel but not in my product.
Then I added another rule right after previous one.
$(obj)/%c: $(src)/%c_shipped
$(call cmd,shipped)
And now it works just fine.
Can someone explain me what's wrong with original rule?
In my case obj=. and src=. (both = dot). Current dir contains appropriate *_shipped file.
My guess is that $(obj)/%: $(src)/%_shipped qualifies as a match-anything pattern rule. (The manual doesn't mention how targets and prerequisites with with directory components are handled, but it would make sense.)
Note the following in the manual:
A non-terminal match-anything rule cannot apply to a file name that indicates a specific type of data. A file name indicates a specific type of data if some non-match-anything implicit rule target matches it.
Since there are already built-in implicit rules for creating .c files (using parser generators for example), the match-anything rule is never considered.
The reason the error doesn't happen for the kernel makefiles is that they run make with -r, which eliminates built-in implicit rules. It's done in the top-level makefile by setting the MAKEFLAGS variable:
# Do not use make's built-in rules and variables
# (this increases performance and avoids hard-to-debug behaviour);
MAKEFLAGS += -rR
As a simple experiment, I created a file test.c_foo and the following makefile:
MAKEFLAGS += -r
%: %_foo
#echo building
make test.c without the first line gives
make: *** No rule to make target 'test.c'. Stop.
With the first line, it prints "building" instead.

Latest linux kernel installation issue(rm: invalid option -- '0')

I have clone the latest linux source from git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
And compile this kernel using (make O=/usr/local/kernel).
But when i install the kernel the following error getting,
# make O=/usr/local/kernel modules_install install
make[1]: Entering directory `/usr/local/kernel'
rm: invalid option -- '0'
Try 'rm --help' for more information.
make[1]: *** [_modinst_] Error 1
make: *** [sub-make] Error 2
I faced the same issue today (24/1/20) and after a bit of searching, I decided to remove the # in front of each line in modinst target in Makefile. The problem was immediately visible to me. If you add space in extra version, the space will appear in your folder name. So, if you write extra version as
EXTRAVERSION= -test[un-noticed-space-here]
Your module folder name will also have that space. To avoid it, I tried the following
Made sure that there are no spaces at the end of version lines in Makefile
Did "make kernelversion" and made sure that it is devoid of any space character
Did a
echo -n `make kernelversion`| wc
and reconfirmed above point by comparing wc output and the count of characters from previous step

Resources