I'm writing a beaglebone driver and for this I need two modules: gpio_module and BBG_module which are related to EXPORT_SYMBOL.
In gpio_module.c I wrote
uint8_t GPIO_device(void)
{}
EXPORT_SYMBOL(GPIO_device);
and in BBG_module.c
extern uint8_t GPIO_device(void);
GPIO_device();
added to makefile
obj-m := gpio-module.o BBG_module.o
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabi-
KERNELDIR=/usr/src/kernels/linux-4.9.82-ti-r102
arm_modules:
$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(shell pwd) modules KBUILD_EXTRA_SYMBOLS=`pwd`/dep/Module.symvers
echo "bulding module for arm architecture:"
by running the make command, I got two .ko files and a Module.symvers dependency file with all EXPORT_SYMBOLs.
Do I need to send the Module.symvers to the beaglebone too?
Or add something to the makefile and is KBUILD_EXTRA_SYMBOLS=pwd/dep/Module.symvers needed
I'm a beginner and would appreciate any help.
Thanks in advance.
Related
I was re-implementing a simple linux file system and got this error when I ran make:
No rule to make target 'arch/x86/entry/syscalls/syscall_32.tbl', needed by 'arch/x86/include/generated/uapi/asm/unistd_32.h'. Stop.
More specifically, the error was like this:
This is my Makefile:
ifneq (${KERNELRELEASE},)
obj-m += evanfs.o
else
KERNEL_SOURCE := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C ${KERNEL_SOURCE} SUBDIRS=$(shell pwd) modules
clean:
rm *.o *.ko
endif
I've seen many similar posts but the solutions provided did not work for me.
Plus, I was actually following instructions from link and it was using kernel 2.6, however, my kernel is 5.15.0-53-generic, so maybe it's a matter of version?
Please help me fix this, thanks in advance!
I've scoured on the Internet and found no solutions that work for me...
I am trying to compile uleds.c driver and this driver includes multiple files existing under this path :
/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/src/kernel/include/linux
I want now to modify my Makefile and add this path so I can compile correctly uleds.c
This is my Makefile :
#CC=arm-poky-linux-gnueabi-gcc -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a5 --sysroot=/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi
#CC="gcc"
obj-m += uleds.o
KERNEL_SOURCE := /opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/lib/modules/4.14.73-linux4sam-6.0-dirty
default:
${CC} ${KERNEL_SOURCE} uleds.c
clean:
${CC} $(INC) ${KERNEL_SOURCE} clean
Any suggestions for that ? Thank you
This appears to be an attempt at a kbuild file,.
You should not be manually compiling the file yourself using your default rule. Instead, you should be running the kernel's makefile, and have it compile the driver based on obj-m and friends.
Your makefile would look like so:
ifneq ($(KERNELRELEASE),)
ccflags-y += -I some/other/dir
obj-m += uleds.o
else
# default to build against running kernel if KDIR not
# specified:
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
endif
If you call make from the driver's directory, it will in turn call make from your kernel directory, which will know everything about the kernel and will be able to properly build your module.
Notice that by default, the built-in kernel's clean target will remove all generated *.[oas] files, so no need for a special clean target. Also, by default, the kernel's makefile will include its own include directories, so you likely don't need to do anything special for that. In case you do need to include from somewhere else, you can add a -I directive to the ccflags-y as shown in the example.
See Linux Kernel Makefiles and Building External Modules for details.
Simplest is:
${CC} -I/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/src/kernel/include/linux uleds.c
Try reading the following to get familiar with other GCC (compiler) options: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options
I have a project directory structure of:
Root
Source
Common
MyFolder
++ My 3 source files and header
When I am building my project it generates 3 to 4 shared libraries. Lib1 compiled using c++98 and others using c++11. Flags are added in CmakeList.txt which is at root.
I need my 3 source files to be compiled for Lib1 and for other Libs as as well. but here what happens is compiler is first compiling my source file for lib using c++11 and then it is trying to use same .o file for Lib1 as well. So for .o file which is generated using c++11 is throwing exception when same is used for c++98 compiled library.
So how do write this in CmakeList.txt such that compiler rather than trying to use same .o file will compile source file again for Lib1(c++98 compiled library)
Is there any flag I can specify so that it won't take precompiled .o file and will compile it again ?
Here flags are not being overridden for different shared libraries but actually same object file by make file is being used for different flags
This is sort of counter to how makefiles and cmake usually work.
Most users consider it really important that make performs an incremental build.
The usual way with makefiles is to do make clean which is supposed to remove any binaries and object files that were created.
However, sometimes I write cmake scripts that use globbing over the source directory to assemble the project. (That means, it says "just grab all *.cpp files in the /src folder and make an executable from them".) A makefile cannot check what files in a directory, so the make build will be broken after I add a new file, and make clean won't fix it -- the whole makefile will need to be regenerated by cmake.
Usually what I do is, I write a simple bash script, named rebuild.sh or something,
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make -j3
./tests
And I put that in the root of my repository, and add /build to my .gitignore. I call that when I want to do a full rebuild -- it nukes the build directory, so its foolproof. When I want an incremental rebuild, I just type make again in the /build directory.
The rebuild.sh script can also serve a double purpose if you use travis-ci for continuous integration.
Most build system assume the compiled objects remain the same within the same pass. To avoid shooting your foot I would suggest telling the build system they were actually different objects, while still compiled from same source files.
I'm not familiar with cmake but this is how you do with make:
For example you have a a.cpp which you want to compile 2 times for different compiler options:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf ("Hello %d\n", TOKEN);
return 0;
}
And the Makefile would looks like:
SRC := $(wildcard *.cpp)
OBJ_1 := $(patsubst %.cpp,%_1.o,$(SRC))
OBJ_2 := $(patsubst %.cpp,%_2.o,$(SRC))
all: pass1 pass2
pass1: $(OBJ_1)
gcc -o $# $(OBJ_1) -lstdc++
pass2: $(OBJ_2)
gcc -o $# $(OBJ_2) -lstdc++
%_1.o: %.cpp
gcc -DTOKEN=1 -c $< -o $#
%_2.o: %.cpp
gcc -DTOKEN=2 -c $< -o $#
clean:
rm -f $(OBJ_1) $(OBJ_2)
What I do here is generate two different list of object from the same source files, which you can even do the same for dependency(-MMD -MP flags).
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.
$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.