I have simple module program which will call to other function which are in other files. eg:
Arith.c <=== main module which calls sum(), diff(), mul() ...
|
|----sum.c
|----Sub.c
|----mul.c
|----div.c
|----remainder.c
|----quotient.c
I wrote the program for it. For make file I didn't understand how to write. I studied section 3.3 here and edited Makefile.
So now my make file is (I tested only for sum)
obj-m := arith.o
arith-y += sum.o
KDIR=/lib/modules/$(shell uname -r)/build
module:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
When I run make it compiled and generated arith.ko. When I inserted it not showing anything in dmesg. When I inserted other modules dmesg working properly.
arith.c:
extern void sum(void);
int init_module(void)
{
pr_info("module inserted..\n");
sum();
return 0;
}
void cleanup_module(void)
{
pr_info("module removed..\n");
}
sum.c:
void sum(void)
{
pr_info("sum of 1 and 2: %d\n", 1+2);
}
Additional Info:
If I comment arith-y += sum.o in Makefile and not calling sum function in arith.c, dmesg working correctly.
Questions:
1.Is that make file correct?
2.If it is correct, why arith module not showing anything in dmesg even other modules working fine?
3.If it is not correct, how to write Makefile and why?
You never refer to obj-m or arith-y after declaring them; so they are either:
some sort of magic that your make knows about (which I doubt),
normal variables which you need to reference somewhere else, or
dead code.
You might have more luck looking through the kernel tree for a simple makefile which you can read and understand in detail.
Related
I want to create a Makefile which will build a program which when run's output will be used as a value for a variable in the same Makefile.
Consider the program:
print_name.c:
#include <stdio.h>
int main() {
printf("foo\n");
return 0;
}
I'd like to use the standard output of this program to then determine a directory name to be stored in a variable used in the makefile and used for other rules, so far I've tried:
all: $(MY_DIRECTORY_NAME)/my_program
print_name: print_name.c | print_name
gcc $^ -o $#
MY_DIRECTORY_NAME:=$(shell ./print_name)
$(MY_DIRECTORY_NAME)/my_program: my_program.c
mkdir -p $(MY_DIRECTORY_NAME)
gcc $^ -o $#
However when I run:
make all
I get:
make: *** No rule to make target '/my_program', needed by 'all'. Stop
Whereas I'd like:
mkdir -p foo
gcc my_program.c -o foo/my_program
So basically, I want to compile print_name before the assignment to MY_DIRECTORY_NAME, and then that variable in then used in the following rules. Is this possible, and if not are there any workarounds for this?
The basic problem is that you need to build (and run) print_name before you can parse the rules that use it -- but all rules are read and parsed before anything is built. So you need to run make twice -- first to build print_name and second to build everything that depends on it. Something like
all: print_name
$(MAKE) `./print_name`/my_program
should do the trick
I am trying to learn the make command but I am having a little trouble with the way headers are being used
I got prg1.c
#include <stdio.h>
main()
{
printf("Hello World\n");
print();
}
and the prg2.c
#include <stdio.h>
print()
{
printf("Hello World from prg2\n");
}
and here is the make file
objects = prg1.o prg2.o
exe : $(objects)
cc -o exe $(objects)
prg1.o : prg1.c
cc -c prg1.c
prg2.o : prg2.c
cc -c prg2.c
This works perfectly. But if I don't include stdio.h in both file and then I have to compile it using the make, how am I supposed to write the makefile?
If you don't include <stdio.h>, then you can do one of two things:
supply a correct declaration for printf yourself:
int printf(const char *fmt, ...);
There is almost never any reason to do such a thing.
If your compiler is GCC, use the -include compiler option to force the inclusion of "stdio.h":
prg1.o: prg1.c
gcc -c -include stdio.h prg1.c
This is completely hokey; don't do it.
Note that the make utility has nothing to do with ensuring that the correct header material is included in C translation units. make is a utility which runs shell commands in response to some files not existing or having modification stamps older than other files.
I am a newbie in Kernel Development. I was trying to understand the following makefile for Hello World! program. But I am not able to figure it out completely.
obj-m += hello.o
all:
sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I am not able to understand what is meant by 'obj-m += hello.o' . I know m here means module and thats it.
Also why are we not defining the dependencies of hello.o
And lastly I am not able to figure out completely the compiling rules defined under all: and clean:
Any help would be highly appreciated.!!
obj-m is a Makefile variable. It actually consists of 2 parts: 'obj' means that the referred target is a kernel object, while 'm' part means that the object is to be build like a module.
The variable is considered by kernel build rules. As kernel modules follow a certain convention, running your Makefile will result in creation of module hello.ko from source file hello.c (if everything works properly).
The 'obj' variable may take different suffixes as well. For example 'obj-y' will try to link the referred object into the main kernel image, instead of creating a module. The suffix may also refer to a kernel .config file variable, like this:
obj-$(CONFIG_HOTPLUG) += hotplug.o
In this case, if CONFIG_HOTPLUG is set to 'y' the hoplug object will be compiled into the main kernel; if set to 'm' then a separate hotplug.ko loadable module will be created. If not set to anything (resulting in 'obj-'), hotplug will be omitted outright.
Hi I am trying to write a 'Hello World' kernel module.
I wrote the following C code:
Module514.c
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("BMC")
MODULE_DESCRIPTION(" My module]")
static int __init module514(void){
printk(KERN_INFO"Hello World");
return 0;
}
static void __exit module514_cleanup(void){
printk(KERN_INFO"unloaded")
}
module_init(module514);
module_exit(module514_cleanup);
Then created the following Makefile
obj-m += Module514.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
But when I give make I get the following message.
make: Nothing to be done for `all'.
What am I doing wrong.
The problem here seems to have been caused by my Vim configuration. When I used TAB to indent the makefile spaces were getting inserted instead of TAB. Once I corrected this using a different editor all is going file.
PS: Also makefile need to be named with capital M = Makefile
$insmod helloworld module generates the error message "Invalid module format".
$dmesg outputs:
overflow in relocation type 10 val ffffffff88640070
'hello' likely not compiled with -mcmodel=kernel
The Makefile is a mix of tradition format (using (CC)) and module build system format "make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules".
The system is 1.6.18-194.el5 x86_64. The same Makefile works fine when it is used in i386 machine.
Any idea of what to look into? Thanks.
#Makefile, mix of (CC) and kernel module build system
CFLAGS+=-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(hello)"
CFLAGS+=-D__KERNEL__ -DMODULE -I$(KERNEL_BUILD_DIR)/include
KERNEL_BUILD_DIR=/lib/modules/2.6.18-194.el5/build
TARGETNAME=hello
BUILD_ALT_DIR=linux
# The main target (note that both library and driver are .ko files
#
all: $(BUILD_ALT_DIR)/$(TARGETNAME).ko
$(BUILD_ALT_DIR)/_$(TARGETNAME).o: hello.o
#echo Linking objects to loadable module
#mkdir -p $(BUILD_ALT_DIR)
#echo $(CURDIR)/$#
#$(LD) -Map=$#.map -r -o $# $^
#echo " LD_D [$#]"
$(BUILD_ALT_DIR)/$(TARGETNAME).ko: $(BUILD_ALT_DIR)/_$(TARGETNAME).o
#rm -f $(BUILD_ALT_DIR)/$(TARGETNAME).o
#echo create Makefile
#$(SHELL) -c 'echo "obj-m := $(TARGETNAME).o" > $(BUILD_ALT_DIR)/Makefile'
#$(SHELL) -c 'echo "$(TARGETNAME)-objs := _$(TARGETNAME).o" >> $(BUILD_ALT_DIR)/Makefile'
#$(SHELL) -c 'echo ".PHONY: `pwd`/$(BUILD_ALT_DIR)/_$(TARGETNAME).o" >> $(BUILD_ALT_DIR)/Makefile'
#$(SHELL) -c 'cd $(BUILD_ALT_DIR); $(MAKE) -C $(KERNEL_BUILD_DIR) M=`pwd`'
#echo " KO_D [$#]"
$(BUILD_ALT_DIR)/%.o: %.c
#echo Compiling C source to object file:
#mkdir -p $(BUILD_ALT_DIR)
# #echo $(CURDIR)/$#
#$(CC) -c -Wall $(CFLAGS) $(CFLAGS) $< -o $#
#echo " CC_D [$#]"
clean:
rm -f $(BUILD_ALT_DIR)/*.o $(BUILD_ALT_DIR)/*.d $(BUILD_ALT_DIR)/core $(BUILD_ALT_DIR)/*.map
hello.c
#include <linux/autoconf.h> // this is needed
#include <linux/init.h>
#include <linux/module.h>
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
The dmesg output tells you what is wrong:
'hello' likely not compiled with -mcmodel=kernel
On the x86-64 architecture, all code running in the kernel (including modules) must be compiled with a special flag, which tells the compiler to generate code which will run in the top half of the virtual address space (user mode programs run on the bottom half of the address space).
If I am reading your Makefile correctly, you are compiling the C code outside the kernel build system, and calling into the kernel build system only for the final linking. Do not do this. It is not just the memory model, there are several other flags which must be added when compiling the C source code. These flags can change with the kernel version, or even with the kernel configuration — you do not know, and you are not supposed to have to know, since the kernel build system deals with it all for you.
It is not just -mcmodel=kernel. There are many others, and getting them wrong can and will cause problems.
The fact that you are missing the correct flags is quite visible in your code:
#include <linux/autoconf.h> // this is needed
No, this is not needed. If you need it, you are doing it wrong. Take a look at one of the flags the kernel build system passes to the C compiler:
-include include/linux/autoconf.h
This flags tells the C compiler to always implicitly include the linux/autoconf.h header. Since it is always implicitly included, you never have to include it manually. And since you never include it manually, its location is allowed to change — it moved to generated/autoconf.h and later to linux/kconfig.h, and who knows where else it will end up next.
The fact that it worked at all for you in 32-bit x86 is just luck. You should do it the correct way even on 32-bit.
Second iteration:
All right, you've confirmed that Make builds _helloworld.o and $(BUILD_ALT_DIR)/Makefile. Now could you post the makefile that's in $(KERNEL_BUILD_DIR) (on the x86_64)?
(I'll go out on a limb and suggest that maybe $(BUILD_ALT_DIR) and $(KERNEL_BUILD_DIR) are the same on the i386 but not on the x84_64.)
EDIT: (third iteration)
1400 lines? Most of that in one branch? Half a dozen include directives? Architecture-specific branches? Autoconf?
Are you allowed to modify this nightmare in place, or must you tinker with the higher-level tools like automake? (I ask only because in the latter case it won't do much good to figure out what the problem is, you'll probably have to start over from scratch.)
1) From $(KERNEL_BUILD_DIR), try make M=$(BUILD_ALT_DIR) (whatever $(BUILD_ALT_DIR) is). Verify that that gives you the same error message. If it doesn't then ignore what follows (in this iteration).
2) From $(BUILD_ALT_DIR), try make, and see if it gives the same error. If it does, try replacing the makefile (in $(BUILD_ALT_DIR)) with a trivial makefile like
all:
#echo trivial makefile working
and test it, then try step 1 again. If it just says "trivial makefile working" and doesn't give the error, then things look good.
EDIT: (fourth iteration)
All right, we can't change $(KERNEL_BUILD_DIR)/Makefile. That doesn't necessarily sink us.
"Your suggestion (1) would not work, since $(BUILD_ALT_DIR) is a output directory, no source is in it."
Make does not require the presence of source code, and whether or not this would work (whatever "work" means), it is what your makefile appears to be attempting:
#$(SHELL) -c 'cd $(BUILD_ALT_DIR); $(MAKE) -C $(KERNEL_BUILD_DIR) M=`pwd`'
Try it and see what happens.
"Is there a possibility that x86_64 doesn't support tradition format (CC) for the kernel module?"
I'm not entirely sure what you mean, but we can probably answer your question by experiment.