how to run make for a local subdirectory - linux-kernel

I am trying to port an existing code into a larger project. The larger project has a main Makefile with Makefiles in each sub-directory. I am sure the path below tells you all about how it is setup. I want to port my code to
/WORKING_DIRECTORY/Drivers/Char/example
And here is the content:
sansari#ubuntu:~/WORKING_DIRECTORY/drivers/char/examples$ ls
hello1.c Makefile
My question is 1- Should modify this local Makefile or the main one? I am setting up to modify this one, but I am not sure.
2- My other question is if I modify this local file, can I just run make from here and validate my configuration instead of running make for the entire project? I know that make only updates the files that are changed; however I feel better when I clean the build environment before each make. I have run into situations, which this alone fixed my issue.
Just as background, I did try to include the make file of my target project, the one I am trying to import here with -f command. What I did was: make -f Makefile -f ../mytarget/core/Makefile
But I ran into some issues with make not doing some of the normal things it does in the primary project. For instance, there was an include statement with a relative path to a header file, which make gave me an error about not seeing it. So now I am abandoning that strategy for the time being.
#Ahmad Masoud - Hey man, thanks. Here is the Makefile. Hey man, the link is exactly what I needed. I think it will address my other questions also. You see, I cross compiled this code, and when I flashed my phone, I get the following for
uname -r: 1|root#hltespr:/lib/modules # uname -r
uname -r
3.4.0-g7e6fbf7-dirty
And I have been wondering what "dirty" means and where it comes from. If you know please tell me. The link you sent, states that perhaps make would insert the Linux kernel version there? I ask this since, modprobe does not work when I try to load my module. Instead insmod works, and I can validate that my module is in. My main issue now is that I don't know how to execute the file to make sure it runs. I only know how to run the file using modprobe, and I can not use it. It gives me the following error:
1|root#hltespr:/ # modprobe /lib/modules/hello1.ko
modprobe /lib/modules/hello1.ko
modprobe: can't change directory to '3.4.0-g7e6fbf7-dirty': No such file or directory
Update as of 06/20/15 -I put in include /home/sansari/mytree2/tbt/makefile in my module's make file. I get the following error: makefile:3: *** missing separator. Stop.
#Ahmad - This is an update as of 062415. Thanks for the info. My goal is to get make to look into this external directory, collect all the source files and build them for me. What would you suggest? I am stuck because as it stands, I know make looks into my examples directory, but no other changes I make to that local make file in the examples directory shows up in make. For instance I tried adding ($warning ....) and #echo messages, but even they do not show up.
Update on 070215- Thanks for the previous comments and support. I feel I really should reopen this thread since I did not explain the goal in detail, and now I feel I can describe it better, and hopefully the resolution will help other. I issue the command:
TARGET=msm8974 PLATFORM=msm8974 make drivers/char/examples
But I get a message stating: Nothing to be done, while I have added a number of tasks to do. Below is my make file, and I'll elaborate on what I have added right after:
lib_tbt := ../../../m/shahin/tbt
lib_daemon := ../../../m/shahin/daemon
lib_lib := ../../../m/shahin/lib
lib_tasks := ../../../m/shahin/tasks
lib_tbt_driver := ../../../m/shahin/tbt_driver
lib_tbt_make := ../../../m/shahin/tbt/make
lib_tbt_msm_common := ../../../m/shahin/tbt/platform/msm8974/common
lib_tbt_msm8974 := ../../../m/shahin/tbt/platform/msm8974
lib_asm_generic = ../../../m/shahin/tbt/platform/msm8974/include/asm-generic
$(warning This is what is in lib_asm_generic $(lib_asm_generic))
#include $(lib_tbt_make)/macros.mk
.PHONY: all $(lib_tbt)
$(lib_tbt) $(lib_daemon) $(lib_lib) $(lib_tasks) $(lib_tbt_driver) $(lib_tbt_make) $(lib_tbt_msm_common) $(lib_tbt_msm8974) $(lib_asmgeneric) :
$(MAKE) --directory=$#
$(lib_*): $(MAKE) --directory=$#
obj-$(CONFIG_EXAMPLES) += hello1.o
_
Initially I only had the obj-$(CONFIG_EXAMPLES) += hello1.ostatement in my make file. I then proceeded to add the directory variables at the top of my makefile and added the $(lib_*): $(MAKE) --directory=$# directing make to compile what is in the directory. I believe that is what it does. Please let me know if I am mistaken. And although this same make file proceeds to create object files when I put it a different directory within my project, it won't do so when it is in a device driver directory. And I do not understand why. The other directory is the /external directory and it is at the top of the tree. But that should not matter right. What I have done was to first make sure I can compile a hello program in my device driver directory called /examples. I now want to add more source code to this section. I believe the correct term is module? I also want to know if I should copy of the source files to the /examples directory or referencing them via the path is ok. That is should I move the source code directory under /examples directory or not?

It is a LOT simpler than that if you are using a kernel that uses Kbuild.
Highly recommend reading
http://www.tldp.org/LDP/lkmpg/2.6/html/x181.html
Situation A - Your source is a sub-tree of the kernel source
You would NOT modify the top-level Makefile, just ensure that ~/WORKING_DIRECTORY/drivers/char/examples/Makefile and ~/WORKING_DIRECTORY/drivers/char/examples/KBuild are set up correctly/normally. THEN at the top-level of the kernel build directory (assuming you have a separate build directory) you would type:
foo#bar:~/build-dir$ make drivers/char/examples
The kernel top-level makefile then builds just that sub-tree. You can try it out on any part of the kernel, for example:
foo#bar:~/build-dir$ make fs
NOTE: build-dir can be the same as the kernel source directory
Situation B - You are building an external module
Then use the normal module KBuild / Makefile process.
P.S.
If you post your makefile / Kbuild then I may be able to help with the actual build processing.

Related

Is there a way to make a makefile autodownload another makefile?

i know it is possible to execute standard rules on a makefile by simply including them like
hi:; echo hello
include hi
but there is some way, by doing this, to fetch an external input like a ftp server or, lets say, the aws s3 to fetch a "newborn" makefile and then include it to the project? in runtime?
like
include https://s3.bucket.domain.com/newmk.mk
As mentioned there's no way to include a URL. However, you can do something almost as good with GNU make's auto-re-make feature.
To do this, include a local file you download and create a rule that knows how to download it:
include newmk.mk
newmk.mk:
wget https://s3.bucket.domain.com/newmk.mk -O $#
In this situation, if (and only if) newmk.mk doesn't exist, then the recipe will be invoked, the file will be downloaded, then make will re-exec itself to read that file.
The make utility has no built-in download support (not even GNU's make which sometimes seems to have the kitchen sink thrown in), but because it can run arbitrary commands, you can fake it up
The simplest case is a fragment like
your_primary_target: newmk.mk
#...
WGET=wget
WGET_FLAGS=-q
newmk.mk:
$(WGET) $(WGET_FLAGS) https://s3.bucket.domain.com/newmk.mk
#...
which will attempt to download the file only if no such file exists.
The main difficulty here is that your users may need to edit the makefile to specify the command-line downloader they have (perhaps curl instead of wget), or it set any flags their network environment requires.
To make the download unconditional use a unbuildable, non-existent target
WGET=wget
WGET_FLAGS=-1
newmk.mk: ALWAYS
$(WGET) $(WGET_FLAGS) https://s3.bucket.domain.com/newmk.mk
# Here "ALWAYS" is *not* the name of a file existing in the file-system
ALWAYS:
(or there are games you can play with .PHONY in GNU-make).

How to get make to fail if generation of a required include passes but the file is not actually created

I have a makefile that is erroneously generating a required makefile include file. The included file does not initially exist, but there is a rule to make it. The rule runs successfully, but because of a bug, the required include file is not created where expected (and thus make is unable to include it). However, instead of make failing (due to the fact that the file still can't be included), make completes successfully.
The following is my makefile1.mak file.
include myfile.mak
default:
#echo hi
myfile.mak:
#echo hello
When I execute 'make -f makefile1.mak', I get:
makefile1.mak:1: myfile.mak: No such file or directory
hello
hi
Of course, I finally figured out that my code to generate myfile.mak was not generating it correctly, but the actual makefiles that I'm using are 100s of lines long, so we didn't notice that the include wasn't happening for quite a while (it was a very subtle build issue that was introduced).
So, my question is - is there any way to get make to fail on the above example?
Add a line to the rule:
myfile.mak:
do various things to build myfile.mak
test -f $#

Writing an LLVM Pass - failing

I'm working though http://llvm.org/docs/WritingAnLLVMPass.html, trying to write a very simple pass. (Assume I'm using 'Joe' rather than 'hello', because there is already a 'hello' in the relevant directory)
I create the directory 'joe' where I should , I create the suggested cpp file in 'joe' (although I note that none of the nearby directory's have any cpp files in them) and I name it 'joe.cpp' because I don't believe I've been told differently...
I reach the part of the documentation where it says 'compile the file with a simple "gmake" command in the local directory' but I get the error
make: *** No rule to make target
/Users/joXXXXX/llvm/llvm/lib/Transforms/joe/Makefile',
needed byMakefile'. Stop.
which is utterly confusing. I note the similarity to this case, but in that case running ../config and then a make in the root directory solved in the problem. In my task this takes 20 minutes and then nothing has changed... could anyone tell me what is meant to have happened or give me a trace of what success looks like?
Edit - Local Makefile looks like this:
# Makefile for hello pass
#
# # Path to top level of LLVM hierarchy
LEVEL = ../../..
#
# # Name of the library to build
LIBRARYNAME = joe
#
# # Make the shared library become a loadable module so the tools can
# # dlopen/dlsym on the resulting library.
# LOADABLE_MODULE = 1
BUILD_ARCHIVE = 1
# # Include the makefile implementation stuff
include $(LEVEL)/Makefile.common
I faced the same problem and resolved this by re-reading the tutorial:
First, configure and build LLVM. This needs to be done directly inside the LLVM source tree rather than in a separate objects directory.
It means that you should not create a "build" folder as recommended in LLVM get started. Assume you downloaded the llvm source in $LLVM, here is list that I made it works:
create a new folder, let says MyHello, in $LLVM/lib/Transforms/ and necessary files for a pass as in the tutorial.
$cd $LLVM
$./configure
$make
$cd lib/Transforms/MyHello
$make
So it turns out that when the helpfile says 'lib/Transforms/Hello' it means 'somestuff/llvm/lib/Transforms/Hello' not '/somestuff/build/lib/Transforms/Hello'. In hindsight this is not as opaque as it could be, but I'd like to leave this answer to help other people who might have missed this in the doc...

No rule to make target `/Makefile', needed by `Makefile'

I'm trying to 'make' using a pretty simple makefile. My makefile is named 'Makefile' so I'm simply using the command 'make'.
I get this strange error:
make: *** No rule to make target `/Makefile', needed by `Makefile'. Stop.
If, however, I use
make -f "full-path-to-makefile" it actually does run (with odd consequences...). I should say that I'm running all this from the directory where the Makefile lies, of course.
I'm working on Mac OSX, using tcsh.
Edit:
I'm working in the LLVM framework, trying to compile a pass function and this is the associated makefile:
LEVEL = ../../../
LIBRARYNAME = FunctionName
LOADABLE_MODULE = 1
include $(LEVEL)/Makefile.common
Any ideas will be appreciated :)
I had the same problem trying to write a new pass for LLVM i followed these instructions trying to make a HelloB (as Hello already exsited) http://llvm.org/docs/WritingAnLLVMPass.html#quickstart
What i has to do was do a ./configure again then make from the base directory.
I'll go out on a limb: you have an extra slash. Try omitting the final slash in $(LEVEL).
I found the answer, sort of:
The problem was with the installation process of LLVM. It seems that if you do the installation in one order instead of another it can lead to this error. It doesn't make any sense to me, but after I installed it properly everything compiles great (same code, same Makefile, same make program).
I don't really know why this happened, but I know how to fix it :)
What you want to do is ./configure again then make from the base directory (contrary to what is stated in the instructions on the web-site). That worked for me.
BTW - I got the same results running on Ubuntu (with the same fix).
Just to add some information here (since this is the first hit that comes up on Google when looking for the error) - I had the same problem which suddenly popped up on a (previously working) LLVM setup on OSX, and traced it back to the behavior of the realpath command in make.
Specifically, what was happening was that I had a directory called "LLVM/llvm-2.9-build", but for some reason the attempt to resolve PROJECT_OBJ_ROOT at the top of Makefile.config would decide that this directory was in fact called "llvm/llvm-2.9-build". Since OSX is case-insensitive by default, this doesn't cause an immediate problem, except that subsequently LLVM_SRC_ROOT would be set to "LLVM/llvm-2.9-build". This then meant that the creation of PROJ_SRC_DIR using patsubst to replace the object directory would result in a non-existent path (as the unmatched case means that no pattern replace occurs), which in turn would get resolved to / by realpath.
With PROJ_SRC_DIR set to /, this results in the makefile copy rule in Makefile.rules deciding that the source makefile is at $(PROJ_SRC_DIR)/Makefile (ie /Makefile), and the error message described.
It seems that it is only the built-in implementation of realpath in Make (GNU Make 3.81 in my case) that has this behaviour, as forcibly using the macro version of realpath from the top of Makefile.config fixes the problem. However, this isn't a good long-term fix, as you'd have to manually patch every one of the LLVM makefiles.
In the end, I couldn't see where realpath would be getting the lower-case "llvm" from, but figured it was probably an artifact somehow of some caching of the name from a point in time when I'd referenced the directory using its lower-case name. Hence I tried going to that directory and mv-ing it to a completely different name, and then back to "LLVM" before going in and building again, and that seems to have solved the problem.
I hope that's of some use to anyone else who comes across this particular weirdness!
It's not a complete answer, but what you are seeing is gmake not finding the Makefile it is told to include, and thus it is trying to remake it and failing because it can't find a recipe for it either.
However, the Makefile snippet you posted does not produce the error message you are seeing, so I think the problem is inside the Makefile.common file. Look for include statements which reference a $(some variable expansion)/Makefile and work backwards from there. You can also try to run gmake with the -d option and follow the processing based on the output.
Since your include line reads:
include $(LEVEL)/Makefile.common
it is puzzling that you are not getting an error about /Makefile.common. If you were, then I'd suggest that maybe you have a trailing blank after the definition of LEVEL.
Could there be a line in Makefile.common that itself includes $(SOMEMACRO)/Makefile and you have not set the value of SOMEMACRO?
here's my fixes for this issue: (https://github.com/rust-lang/rust/issues/24887#issuecomment-99391849)
update src/llvm/Makefile.config.in before running ./configure
or update x86_64-apple-darwin/llvm/Makefile.config before make
line 59:
PROJ_SRC_DIR := $(LLVM_SRC_ROOT)$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))
update to
PROJ_SRC_DIR := $(patsubst $(PROJ_OBJ_ROOT)%,$(LLVM_SRC_ROOT)%,$(PROJ_OBJ_DIR))
line 86:
PROJ_SRC_DIR := $(call realpath, $(PROJ_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)))
update to
PROJ_SRC_DIR := $(call realpath, $(patsubst $(PROJ_OBJ_ROOT)%,$(PROJ_SRC_ROOT)%,$(PROJ_OBJ_DIR)))

Makefile: need to do a target before including another makefile

Part of my Makefile:
CPUDEPS=./mydeps.cpu
(...)
deps: $(CPUDEPS)
$(CPUDEPS): $(CCFILES)
#echo [DEPS] CPU
$(CMDECHO)makedepend -Y -s'# CPU sources dependencies generated with "make deps"' \
-w4096 -f- -- $(CFLAGS) -- $^ 2> /dev/null > $(CPUDEPS)
(...)
sinclude $(CPUDEPS)
Problem 1: includes are done during the first phase of processing, targets during the second phase; so, if ./mydeps.cpu doesn't exist and I "make deps", I get first the error
Makefile:335: ./mydeps.cpu: No such file or directory
I hide the error using sinclude instead of include, but the problem is still there: the old file is included, not the just-generated-one. Have to run it twice to include the updated file. This is because make does a two-phase processing; is there any way to tell make to complete the target deps before parsing the includes?
Problem 2: even if the file ./mydeps.cpu doesn't exist and make deps actually creates it, I always get a "make: Nothing to do for deps". This doesn't happen with other targets. I don't understand why and how to avoid it.
Problem 1 is non-existant: before building a target, make automatically rebuilds makefiles (with implicit rules if no explicit rule is provided). So having a rule for the makefile ensures that will always be up to date, there is no need to run deps twice. Additionally, since CPUDEPS is a makefile, it will be updated automatically before any other rule is run, so dependencies will always be updated if necessary and make deps is not needed. You can probably notice this by yourself by observing the [DEPS] line being echoed if any of the CCFILES becomes more recent that the dependency file.
For Problem 2, adding anything to the recipe ensures that make doesn't complain about having nothing to do. If there is nothing else, you can use something like #echo OK to give feedback to the user, or a simple #true if you prefer totally silent makes.
What you are trying to achieve is useless: you can use the dependencies file that was created during the previous build. That's enough.
The main reasoning behind that rule is:
if you haven't changed any of your files, then the dependencies file is up-to-date, and there's nothing to build.
if you have changed anything, even very deep into your #include chain, on an existing file that were used by previous build, then the dependencies file have already caught it. You'll rebuild what is needed.
if you change something in a new file (you add that file!) then it was not used by previous build, and not listed in dependencies. But if you really want to use it, then you have to modify at least one of your other files that was used before, and you're back on the previous case.
The solution is to create the dependencies file during the normal process of the compilation, and to optionally include it (with sinclude) if it is present.

Resources