How do I add an include path for kernel module makefile - c

How do I add an include path for kernel module makefile? I want to include "test_kernel.h" in test_module.c. the "test_kernel.h" resides in other directory "inc"
I tried in the following solution in my Makefile but it does not work:
obj-m += test_module.o
test_module:
$(MAKE) -C "$(LINUX_DIR)" -Iinc $(MAKE_OPTS) modules

You should make use of EXTRA_CFLAGS in your Makefile. Try something on these lines:
obj-m += test_module.o
EXTRA_CFLAGS=-I$(PWD)/inc
test_module:
$(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) modules
See section 3.7 Compilation Flags section here.
Hope this helps!

are you sure you correctly specified the include in your file?
e.g.:
#include "inc/something.h"
instead of
#include <inc/something.h>

-I is a GCC flag, not a Make flag.1 You need to pass a variable down to your "sub" Make process; perhaps something like this:
$(MAKE) -C "$(LINUX_DIR)" CPPFLAGS="-Iinc" $(MAKE_OPTS) modules
where CPPFLAGS is a standard Make variable that's used in the implicit rules. Feel free to use your own variable instead, and ensure it's used appropriately in the sub-make.
The Make manual gives more details on communicating variables between Make instances: http://www.gnu.org/software/make/manual/make.html#Variables_002fRecursion.
1. Actually, it is also a Make flag, but for something completely unrelated.

For me, many trials have failed, until one of them has succeeded.
Using $(src) in the path will do it with ccflags-y, for instance:
# Include Paths
ccflags-y += -I$(src)/../../lib/include
For a directory "/lib/include" that is two levels up from the source folder.
This is driven from the statement in Kernel.org
Always use $(src) when referring to files located in the src tree
Specially, if your source code is in directory that is outside the Linux Kernel Tree.

Related

Source and Include for MakeFile in C

I am taking a Coursera course and I am totally stuck in one of the project. Project demands us to create a makefile but I could not.
Here is my files and folders:
project
|---include
|---CMSIS
|---cmsis_gcc.h
|---core_cm4.h
|---core_cmFunc.h
|---core_cmInstr.h
|---ore_cmSimd.h
|------common
|---memory.h
|---platform.h
|------msp432
|---cmsis_gcc.h
|---msp_compatibility.h
|---syste_msp432.h
|---src
|---interr.c
|---main.c
|---memory.c
|---str.h
|---system_msp.h
|---makefile
|---msp432p401r.lds
|---sources.mk
Here is my sources.mk and makefile.
For now, I just want to check whether makefile succesfully find related source and include files but it does not.
I have checked several example makefiles and could not find where is the fault of mine? What I have got here is:
What I understand from error is it can not find related memory.h file. What can I do?
Any help will be appreciated.
Thanks.
Make searches for prerequisites in the working directory. It doesn't know that you have memory.h somewhere else, and will not go looking for without instructions.
One way to solve this is with the vpath directive:
vpath %.h common
You can use the same trick when you run into problems finding other prerequisites:
vpath %h common CMSIS
vpath %.c src
That will get echo "HI" to work, but you will have more trouble with a real rule that actually uses the prerequisites. To take a contrived example:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) memory.c -o memory.o
This will fail because although Make can find the prerequisites, the compiler still doesn't know where they are.
We tell the compiler where memory.c is by referring it to the list of prerequisites:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) $< -o memory.o
($< means the first prerequisite; Make will provide the path.) We could use the same trick (with some effort) to tell the compiler where to search for the header file, but it's usually simpler to put that in by hand:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) -Icommon $< -o memory.o
It's important to understand that make and the compiler are two completely different programs, that do different things and work different ways. Make can run a compiler, but it can also do all sorts of other things: it could build documentation, or an entire website, or copy files, etc. Basically make is a general-purpose tool that can investigate when files are out of date and run any command you give it to make that file "up to date", whatever that may mean.
So, when you create a variable like INCLUDES = -I... that is setting a make variable to a flag that can tell the compiler where your header files are.
That means nothing to make.
Make sees this rule:
ysk: memory.h memory.c
and says "ok to build the file ysk I need to have memory.h and memory.c". It looks in the current directory and those files don't exist (because they are in src/memory.h and src/memory.c) so it fails.
You need to put the paths into your makefile, so make can find them.

Makefile with multiple submodules

I have following program structure:
main.c
Makefile
Submodule
--{somefiles}
--Makefile
Submodule is creating library submodule.a. It has many source files and it need some libraries.
All I want to know that
Makefile in submodule knows how to make submodule.a
Makefile in submodule sets variable SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS
How can I write Makefile in root project directory that:
it would create submodule.a using Makefile in submodule
it would add SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS to its own variable?
AT the end I want the following command in main Makefile works correctly:
TARGET = MyProgram
OBJS = $(TARGET).o submodule/submodule.a
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
Now it creates MyProgram.o and cannot create MyProgram, because Makefile doesn't know how to make submodule/submodule.a.
I can add lines:
submodule/submodule.a:
make -C submodule
but it won't help me with missing libraries.
There is no direct way for the sub-Make to pass variables to the parent process. There are (at least) two indirect ways.
You could have the sub-Make write a file containing the variable values, which the parent Make could then read.
You could copy the part of submodule/Makefile that constructs those variables, and put it into Makefile. Better still, you could isolate that code in a separate file that both makefiles would then include.
EDIT:
One disadvantage of recursive Make is that it interrupts much of Make's dependency handling. In this case, there's no clean way to have the sub-make run when and only when one of the library's sources is changed.
You can put the list of submodule sources -- or the code that constructs the list -- in a separate file which both makefiles will include. Then those files can be among the prerequisites of $(TARGET).
Or, you could make submodule/submodule.a a PHONY target. In that case, Make will rebuild the binary every time, but otherwise it'll work perfectly.

Linux makefile example

Hi I am a newbie to linux and am working my way through an example
http://www.linuxforu.com/2010/12/writing-your-first-linux-driver/
I am using Ubuntu 12.04 and have created the c code file called ofd.c (see below) and is is saved in a directory I created at ~/Development/MyProgs/myHelloWorldLinuxModule/v2. I have also created a Makefile (see below) which is in the same directory.
I was hoping to see a .ko file generated in the same directory when I type make, but all I get is a message saying "Nothing to be done for default"
I don't really understand the makefile
should I define KERNELRELEASE somewhere,
what is the line at default actually doing,does this mean carry out make on the kernel directory and the working directory or am I supposed to put my code somewhere in particular.
there is no usr/src/linux but a /usr/src/linux-headers-3.8.0-29, so I changed this, is that correct. (Didn't seem to make any difference though).
Any help would be greatly appreciated.
Code:
/* ofd.c – Our First Driver code */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
static int __init ofd_init(void) /* Constructor */
{
printk(KERN_INFO "Namaskar: ofd registered");
return 0;
}
static void __exit ofd_exit(void) /* Destructor */
{
printk(KERN_INFO "Alvida: ofd unregistered");
}
module_init(ofd_init);
module_exit(ofd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Driver");`
Makefile......
# Makefile – makefile of our first driver
# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
obj-m := ofd.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
KERNEL_SOURCE := /usr/src/linux
PWD := $(shell pwd)
default:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules
clean:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif
The error is due to naming convention your makefile is not able to find source code
First check which kernel is running by typing uname -a
Then go to cd /usr/src/
then check your linux source-code name
for e.g
uname -a
Linux vinay-VirtualBox 3.2.0-50-generic-pae #76-Ubuntu SMP Tue Jul 9 19:24:55 UTC 2013 i686 i686 i386 GNU/Linux
here its source-code name is linux-headers-3.2.0-50-generic-pae
So in your Makefile u need to give correct name like this
KERNEL_SOURCE := /usr/src/linux-headers-3.2.0-50-generic-pae
To avoid above problem try this Makefile
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := ofd.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
here uname -a resolves the problem
You have an error in your Makefile.
You must use a tab character on the lines defining the actions to take against the target, e.g. the lines:
default:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules
The line must have a tab from the start of the line to the ${MAKE}. You need to force a tab character there, otherwise the error you've witnessed will occur.
The Make syntax is very particular about this requirement, and it's an easy error to make. If you used an editor like vim, it would typically display the space characters to the user highlighted in red so that they can understand that an error is present there.
You didn't show the make command you ran to get this error. However, an error like that usually means that you have a file or subdirectory named default in your directory. Make wants to build targets and the first target in the makefile is default. It has no defined prerequisites which means that if it exists, make assumes it's up-to-date and nothing needs to be done to build it (it exists, and it doesn't depend on anything else).
You should probably use this:
.PHONY: default clean
to declare the default and clean targets to be "phony"; this tells make that even if those targets exist already it should still always run the recipe associated with them.
The error is coming due to the reason, the path specified in Makefile for headers or kernel source code, for the label KERNEL_SOURCE is not able to find the headers, which you already mentioned you suspected. Instead of changing the path, /usr/src/linux-headers-3.8.0-29 to /usr/src/linux.
Change the path given in the Makefile as the actual version of kernel whose source code you have or if the same kernel you are running you can get the version by uname command.
The better approach could be :
default:
$(MAKE) -C /usr/src/$(shell uname -r)/ M=$(shell pwd) modules

Critical section in parallel make file

I am trying to parallelize an old Makefile.
In fact I need to make sure that some generator scripts are called not parallel before the compiling procedure starts.
The generators are always called before the compile. Is there any way to establish a somewhat critical section in a makefile?
The Makefile is messy, I'd prefer not to post it here.
You could put the rules for the generated files in a separate Makefile, and do something like this:
generated-sources :
$(MAKE) -f Makefile.Generators
However, with GNU Make, this will be parallel by default. You'll need to suppress it, and the manual isn't exactly clear how you would do that. Maybe some combination of the following would work, depending on which implementations of make you wish to support:
Pass the -j1 flag:
generated-sources :
$(MAKE) -j1 -f Makefile.Generators
Suppress MAKEFLAGS options:
generated-sources :
$(MAKE) -f Makefile.Generators MAKEFLAGS=
Suppress parallel execution with the following line in Makefile.Generators:
.NOTPARALLEL :
You can make a rule that runs all of the scripts, and then make sure all of your other rules depend on that rule.
all: ${SOURCES} scripts
scripts: last_script
first_script:
./script1.sh
second_script: first_script
./script2.sh
last_script: second_script
./script3.sh
source1.o: source1.c scripts
gcc source1.c -c -o source1.o

Header Files in Multiple Directories: Best Practices

I'm a C Newb
I write lots of code in dynamic languages (javascript, python, haskell, etc.), but I'm now learning C for graduate school and I have no idea what I'm doing.
The Problem
Originally I was building all my source in one directory using a makefile, which has worked rather well. However, my project is growing and I would like to split the source into multiple directories (unit tests, utils, core, etc.). For example, my directory tree might look like the following:
.
|-- src
| |-- foo.c
| |-- foo.h
| `-- main.c
`-- test
`-- test_foo.c
test/test_foo.c uses both src/foo.c and src/foo.h. Using makefiles, what is the best/standard way to build this? Preferably, there would be one rule for building the project and one for building the tests.
Note
I know that there are other ways of doing this, including autoconf and other automatic solutions. However, I would like to understand what is happening and be able to write the makefiles from scratch despite its possible impracticality.
Any guidance or tips would be appreciated. Thanks!
[Edit]
So the three solutions given so far are as follows:
Place globally used header files in a parallel include directory
use the path in the #include satement as in #include "../src/foo.h"
use the -I switch to inform the compiler of include locations
So far I like the -I switch solution because it doesn't involve changing source code when directory structure changes.
For test_foo.c you simply need to tell the compiler where the header files can be found. E.g.
gcc -I../src -c test_foo.c
Then the compiler will also look into this directory to find the header files. In test_foo.c you write then:
#include "foo.h"
EDIT:
To link against foo.c, actually against foo.o, you need to mention it in the object file list. I assume you have already the object files, then do after that:
gcc test_foo.o ../src/foo.o -o test
I also rarely use the GNU autotools. Instead, I'll put a single hand-crafted makefile in the root directory.
To get all headers in the source directory, use something like this:
get_headers = $(wildcard $(1)/*.h)
headers := $(call get_headers,src)
Then, you can use the following to make the object-files in the test directory depend on these headers:
test/%.o : test/%.c $(headers)
gcc -std=c99 -pedantic -Wall -Wextra -Werror $(flags) -Isrc -g -c -o $# $<
As you can see, I'm no fan of built-in directives. Also note the -I switch.
Getting a list of object-files for a directory is slightly more complicated:
get_objects = $(patsubst %.c,%.o,$(wildcard $(1)/*.c))
test_objects = $(call get_objects,test)
The following rule would make the objects for your tests:
test : $(test_objects)
The test rule shouldn't just make the object files, but the executables. How to write the rule depends on the structure of your tests: Eg you could create an executable for each .c file or just a single one which tests all.
A common way of doing this is for header files used by a single C file to be named the same as that C file and in the same directory, and for header files used by many C files (especially those used by the whole project) to be in a directory include that is parallel to the C source directory.
Your test file should just include the header files directly using relative paths, like this:
#include "../src/foo.h"

Resources