I'm trying to build a static -helper- library of pure C code (no standards c headers) and then link it with a kernel module in compile time in the Makefile, but I can't seem to get it working.
Let's say I have a library which is just this header file utils.h
:
#ifndef __UTILS__
#define __UTILS__
int initialize(int value);
void increment(void);
int get(void);
#endif // __UTILS__
and it's implementation utils.c
:
#include "utils.h"
int g_value;
int initialize(int value) {
g_value = value;
return 0;
}
void increment(void) {
g_value++;
}
int get(void) {
return g_value;
}
and I'm using this Makefile
to build the library out of it:
BIN_DIR := .
# Specify extensions of files to delete when cleaning
CLEANEXTS = o a
# Specify the target file and the install directory
OUTPUTFILE = libutils.a
INSTALLDIR = ../
# Default target
.PHONY: all
all: $(OUTPUTFILE)
# Build libutils.a from uilts.o
$(OUTPUTFILE): utils.o
ar cr $@ $^
ranlib $@
# No rule to build utils.o from .c
# files is required; this is handled by make's database of
# implicit rules
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Indicate dependencies of .c files on .h files
utils.o: utils.h
I run make all
to build the library and I get libutils.a
and utils.o
files.
Then I have a simple kernel module which uses the utils library mymodule_main.c
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
#include "utils/utils.h"
int init_module(void) {
int i;
initialize(1);
for(i = 0; i < 10; ++i) {
increment();
}
return 0;
}
void cleanup_module(void)
{
pr_info("value=%d\n", get());
}
and the Makefile
for it:
NAME := mymodule
target := $(shell uname -r)
KERNEL_DIR ?= /lib/modules/$(target)/build
obj-m := $(NAME).o
$(NAME)-y := mymodule_main.o libutils.a
all:
make -C $(KERNEL_DIR) M=$(shell pwd)
clean:
make -C $(KERNEL_DIR) M=$(shell pwd) clean
Now when I try to build this kernel module make all
I get these errors:
ERROR: "initialize" [/home/mosa/dev/mymodule.ko] undefined!
ERROR: "get" [/home/mosa/dev/mymodule.ko] undefined!
ERROR: "increment" [/home/mosa/dev/mymodule.ko] undefined!
I then tried using the utils.o
file instead of the libutils.a
and updated the Makefile
for the kernel module accordingly, I got these warnings:
WARNING: "g_value" [/home/mosa/dev/mymodule] is COMMON symbol
WARNING: could not find /home/mosa/dev/.utils.o.cmd for /home/mosa/dev/utils.o
and if I tried to insmod
the resulting kernel module I get this error in the logs:
mymodule: please compile with -fno-common
I tried adding ccflags-y += -fno-common
to the Makefile
and still same error.
I've read that it's possible to do this but I can't get it to work.
What I'm trying to do here is to not distribute the utils source code, just the kernel module code along with the headers of the utils and the library object file. How can I go with this?