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

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.

Related

How is the -fprofile-prefix-path option supposed to work?

When compiling code for coverage instrumentation (to use with lcov later on), we're compiling from a base directory tree (let's call it A), and we want the .gcda files to be produced at a different place (because the target directory tree is different - let's call it B).
So, the compilation command looked like this:
gcc -O0 -g --coverage -fprofile-dir=B -c -fPIC -Wall -o A/otherpath/to/mySourceFile.o A/path/to/mySourceFile.c
When checking the contents of mySourceFile.o (with the strings command), I saw that the mySourceFile.gcda file was set to be generated in B/A/otherpath/to/mySourceFile.gcda
Which is the mangling of the path given through the -fprofile-dir option with the exact absolute path of the object file created - just as written in the documentation. So far, no problem - except that what I want would be the mySourceFile.gcda file to be generated from the B directory, WITHOUT the A part.
So, the documentation also mentions the -fprofile-prefix-path option, which is supposed to allow you to remove part of the path, so that the mangling doesn't add the old path to the new.
I tried using it in the following way:
gcc -O0 -g --coverage -fprofile-dir=B -fprofile-prefix-path=A -c -fPIC -Wall -o A/otherpath/to/mySourceFile.o A/path/to/mySourceFile.c
However, after checking through strings, once again, in the generated object file, the path was still B/A/otherpath/to/mySourceFile.gcda, whereas I expected it to be B/otherpath/to/mySourceFile.gcda (that is, I expected the A part to have been stripped by the -fprofile-prefix-path option.)
Obviously, it didn't work. Any insight why ?
( Compiler used is GCC 11.2.1, which is a version recent enough to know about the option. )
Ok, after some tinkering, I got results. Maybe not exactly what I was expecting, but close enough.
Let me start by saying that the A and B "directories" I mentioned in my question were absolute paths. And it didn't work well.
However, while keeping the absolute B (target) path, I tried not using the full A (source) path while compiling. More precisely, I didn't use it to specify the OUTPUT file name, for the object. Instead, I went to the base directory (the A path), and then, ran the command by specifying the output file path relative to the current (A) directory
Which would give the following command:
(From directory A)
gcc -O0 -g --coverage -fprofile-dir=B -fprofile-prefix-path=A -c -fPIC -Wall -o otherpath/to/mySourceFile.o path/to/mySourceFile.c
This time, the source command did show an interesting result, for the mySourceFile.gcda file:
B#otherpath#to#mySourceFile.gcda
As you can see, it's not exactly what I wanted (there are # instead of /), but mentions to A disappeared, and overall, I'm confident it should work as intended. Not utterly sure yet (I still have to test it on the target platform, which will need tinkering with the way the makefiles currently work), but confident nonetheless.
Also, if I didn't use the -fprofile-prefix-path in the command, then the string would mention the A path, like this (with the '/' inside the A path being replaced with '#' characters, obviously):
B#A#otherpath#to#mySourceFile.gcda
So, the option works, but only when using relative paths, not when using absolute ones, for the object file. Hope that helps people.
PS: I checked by changing the path to the source (.c) file. Whether specified using absolute, or relative, paths, it didn't change the outcome. What matters is specifying the path to the object file in a relative manner.

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.

Runtime determination of files used in a makefile

I am trying to generate a make file in Linux that is fairly dynamic and will take get all the files from the /src directory of a certain type. Essentially the output of ls *.type I seem to be having difficulties in doing this. Below is what I currently have but it does not seem to work. Hopefully someone can help me out. Thanks!
JIL_B_TMPL : sh = ls *.type
JIL_LIST = $(JIL_B_TMPL)
I will also add this is not for compiling a C program.
To capture the output of a shell command in a makefile, you can do:
JIL_B_TMPL := $(shell ls *.type)
JIL_LIST := $(JIL_B_TMPL)
This is of course the same as writing:
JIL_LIST := $(shell ls *.type)
This works with GNU make, but since you mention Linux, I suppose you're using that.
Pat got the core of something that works, but in your case, you'll probably want something more like
JIL_LIST := $(wildcard *.type)
This gets rid of a call to an external program, which will be important if you decide in the future that you want to support Windows. Also, if you're using makepp, the wildcard function will also catch any .type files that can be built, regardless of whether or not they already have been.

SCons: Get abspath of original file (as though I hadn't set variant_dir)

I can use File('foo.bar').abspath to get the location of a file, but if I've got variant_dir set then the returned path will be in variant_dir rather than it's original location. If I have duplicate=0 set, then the file returned won't actually exist.
Obviously SCons knows where the original file is, as it's passed as an argument when the file's actually built (eg gcc -c -o variant/foo.o orig/foo.c).
Is there some sort of File('foo.bar').origpath that I can use?
If it came to it I could use os.path.join(Dir('#').abspath, 'orig') but that requires the SConscript to know which directory it's in, which is messy.
You can use srcnode(). To quote the man page:
The srcnode() method returns another
File or Dir object representing the
source path of the given File or Dir.
This will give you the absolute path in the source directory:
File('foo.bar').srcnode().abspath

g++ searches /lib/../lib/, then /lib/

According to g++ -print-search-dirs my C++ compiler is searching for libraries in many directories, including ...
/lib/../lib/:
/usr/lib/../lib/:
/lib/:
/usr/lib/
Naively, /lib/../lib/ would appear to be the same directory as /lib/ — lib's parent will have a child named lib, "that man's father's son is my father's son's son" and all that. The same holds for /usr/lib/../lib/ and /usr/lib/
Is there some reason, perhaps having to do with symbolic links, that g++ ought to be configured to search both /lib/../lib/ and /lib/?
If this is unnecessary redundancy, how would one go about fixing it?
If it matters, this was observed on an unmodified install of Ubuntu 9.04.
Edit: More information.
The results are from executing g++ -print-search-dirs with no other switches, from a bash shell.
Neither LIBRARY_PATH nor LPATH are output from printenv, and both echo $LPATH and echo LIBRARY_PATH return blank lines.
An attempt at an answer (which I gathered from a few minutes of looking at the gcc.c driver source and the Makefile environment).
These paths are constructed in runtime from:
GCC exec prefix (see GCC documentation on GCC_EXEC_PREFIX)
The $LIBRARY_PATH environment variable
The $LPATH environment variable (which is treated like $LIBRARY_PATH)
Any values passed to -B command-line switch
Standard executable prefixes (as specified during compilation time)
Tooldir prefix
The last one (tooldir prefix) is usually defined to be a relative path:
From gcc's Makefile.in
# Directory in which the compiler finds libraries etc.
libsubdir = $(libdir)/gcc/$(target_noncanonical)/$(version)
# Directory in which the compiler finds executables
libexecsubdir = $(libexecdir)/gcc/$(target_noncanonical)/$(version)
# Used to produce a relative $(gcc_tooldir) in gcc.o
unlibsubdir = ../../..
....
# These go as compilation flags, so they define the tooldir base prefix
# as ../../../../, and the one of the library search prefixes as ../../../
# These get PREFIX appended, and then machine for which gcc is built
# i.e i484-linux-gnu, to get something like:
# /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../i486-linux-gnu/lib/../lib/
DRIVER_DEFINES = \
-DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
-DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\" \
However, these are for compiler-version specific paths. Your examples are likely affected by the environment variables that I've listed above (LIBRARY_PATH, LPATH)
Well, theoretically, if /lib was a symlink to /drive2/foo, then /lib/../lib would point to /drive2/lib if I'm not mistaken. Theoretically...
Edit: I just tested and it's not the case - it comes back to /lib. Hrm :(

Resources