0

Trying to compile a kernel module with the Yocto SDK toolchain. Using CMakeLists inside CLion with ExternalProject_Add directive.

Makefile:

# Makefile for uio48

ifneq ($(KERNELRELEASE),) # called by kbuild
    obj-m := uio48.o
else # called from command line
    KERNEL_VERSION = `uname -r`
    KERNELDIR := /lib/modules/$(KERNEL_VERSION)/build
    PWD  := $(shell pwd)
    MODULE_INSTALLDIR = /lib/modules/$(KERNEL_VERSION)/kernel/drivers/gpio/

default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

uio48io.o: uio48io.c uio48.h Makefile
    #gcc -c $(EXTRA_CFLAGS) uio48io.c
    $(CC) -c $(EXTRA_CFLAGS) uio48io.c

libuio48io.a: uio48io.o
    ar rcs libuio48io.a uio48io.o

libs: libuio48io.a

all:    default libs

install:
    #mkdir -p ${PREFIX}/$(MODULE_INSTALLDIR)
    #rm -f $(MODULE_INSTALLDIR)uio48.ko
    #install -c -m 0644 ${PREFIX}/lib/modules/${KERNEL_VERSION}/extra/uio48.ko ${PREFIX}/$(MODULE_INSTALLDIR)
    #install -m 0755 ${PREFIX}flash ${D}${bindir}
    #/sbin/depmod -a

uninstall:
    rm -f $(MODULE_INSTALLDIR)uio48.ko
    /sbin/depmod -a

flash: flash.c uio48.h uio48io.o Makefile
    #gcc -static flash.c uio48io.o -o flash
    $(CC) flash.c uio48io.o -o flash
    chmod a+x flash

diotest: diosetpintest.c uio48.h uio48io.o Makefile
    #gcc -static flash.c uio48io.o -o flash
    ${CC} diosetpintest.c uio48io.o -o diotest
    chmod a+x diotest

poll:  poll.c uio48.h uio48io.o Makefile
    #gcc -D_REENTRANT -static poll.c uio48io.o -o poll -lpthread
    ${CC} -D_REENTRANT -static poll.c uio48io.o -o poll -lpthread
    chmod a+x poll

endif
 
clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions /dev/uio48?

spotless:
    rm -rf ioctl poll flash Module.* *.o *~ core .depend .*.cmd *.ko *.mod.c *.order .tmp_versions /dev/uio48?

As you can see I've already modified the make file provided by the vendor. I replaced some build lines with $(CC) to make sure it uses the toolchain compiler. Commented out the Install section because I couldn't figure out how to stop CMake ExternalProject from running the install command; just want to build it.

CMakeLists.txt:

project(driver)
cmake_minimum_required(VERSION 3.17)
enable_language(C ASM CXX)

set(CMAKE_CXX_STANDARD 11)
set(SHARED_LIBRARY_ROOT "$ENV{OECORE_TARGET_SYSROOT}/usr/lib")
set(SHARED_LIBRARY_INCLUDE "$ENV{OECORE_TARGET_SYSROOT}/usr/include")
set(CMAKE_FIND_ROOT_PATH $ENV{OECORE_TARGET_SYSROOT} $ENV{OECORE_NATIVE_SYSROOT} )
set(TARGET_PLATFORM_INCLUDE "$ENV{OECORE_TARGET_SYSROOT}/usr/src/kernel/include/linux")
set(TARGET_KERNEL_DIR "$ENV{OECORE_TARGET_SYSROOT}/usr/src/kernel")
set(TP_INCLUDE_CFLAG "-I${TARGET_PLATFORM_INCLUDE} -I${SHARED_LIBRARY_INCLUDE}")


MESSAGE(STATUS "CMAKE_FIND_ROOT_PATH            ${CMAKE_FIND_ROOT_PATH}")
MESSAGE(STATUS "TARGET_PLATFORM_INCLUDE      ${TARGET_PLATFORM_INCLUDE}")
MESSAGE(STATUS "CMake C compiler             ${CMAKE_C_COMPILER}")

include_directories(${CMAKE_CURRENT_LIST_DIR})
include_directories(${SHARED_LIBRARY_ROOT})
include_directories(${SHARED_LIBRARY_INCLUDE})

include(ExternalProject)

ExternalProject_Add(
        uio48
        UPDATE_COMMAND ""
        PATCH_COMMAND ""
        CONFIGURE_COMMAND ""
        BUILD_COMMAND make all CC=${CMAKE_C_COMPILER} KERNEL_DIR=${TARGET_KERNEL_DIR} EXTRA_CFLAGS=${TP_INCLUDE_CFLAG}
        SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}
        BUILD_IN_SOURCE 1
        BUILD_ALWAYS 1)

If I leave The Makefile the way it is, I can see from the output I am changing directory to my host kernel source. partial output:

make[5]: Entering directory `/usr/src/kernels/3.10.0-957.el7.x86_64'
  Building modules, stage 2.
  MODPOST 1 modules
make[5]: Leaving directory `/usr/src/kernels/3.10.0-957.el7.x86_64'

so I modified these lines in the make file:

#ifneq ($(KERNELRELEASE),) # called by kbuild
#   obj-m := uio48.o
#else # called from command line
KERNEL_VERSION = `uname -r`
KERNELDIR := /lib/modules/$(KERNEL_VERSION)/build
PWD  := $(shell pwd)
MODULE_INSTALLDIR = /lib/modules/$(KERNEL_VERSION)/kernel/drivers/gpio/

When I do this, I change directory into my kernel source in the toolchain as the output shows, however...:

ake[5]: Entering directory `/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/src/kernel'
  Building modules, stage 2.
  MODPOST 0 modules
make[5]: Leaving directory `/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/src/kernel'
#gcc -c -I/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/src/kernel/include/linux -I/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/include uio48io.c
/opt/poky-sdk/2.4.2/sysroots/x86_64-pokysdk-linux/usr/bin/x86_64-poky-linux/x86_64-poky-linux-gcc -c -I/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/src/kernel/include/linux -I/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/include uio48io.c
In file included from /opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/include/stdio.h:33:0,
                 from uio48io.c:35:
/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/src/kernel/include/linux/stddef.h:4:10: fatal error: uapi/linux/stddef.h: No such file or directory
 #include <uapi/linux/stddef.h>
          ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.

now i'm getting an error for a missing header file that is an include from another Linux kernel header file.

After searching for the 'uapi', it shows up under different architectures in the source; ./usr/src/kernel/tools/arch/powerpc/include/uapi for example. so, Im guessing i need to specify the arch in order for it to include the right header but I'm not having any luck.

I tried adding: -march=x86-64 here:

set(TP_INCLUDE_CFLAG "-I${TARGET_PLATFORM_INCLUDE} -I${SHARED_LIBRARY_INCLUDE} -march=x86-64")
.
.
.
BUILD_COMMAND make all CC=${CMAKE_C_COMPILER} KERNELDIR=${TARGET_KERNEL_DIR} EXTRA_CFLAGS=${TP_INCLUDE_CFLAG}

but that didn't seem to work. Any ideas?

UPDATE if I include the 'uapi' directory, it solves one problem and spawns another. Now I'm getting errors from the linux header files themselves...

example:

set(TARGET_KERNEL_DIR       "$ENV{OECORE_TARGET_SYSROOT}/usr/src/kernel")
set(TARGET_PLATFORM_INCLUDE "$ENV{OECORE_TARGET_SYSROOT}/usr/src/kernel/include/linux")
set(TARGET_ARCH_DIR_INCLUDE "$ENV{OECORE_TARGET_SYSROOT}/usr/src/kernel/include/uapi/linux/")
set(USER_INCLUDE            "$ENV{OECORE_TARGET_SYSROOT}/usr/include")

set(TP_INCLUDE_CFLAG "-I${TARGET_ARCH_DIR_INCLUDE} -I${TARGET_PLATFORM_INCLUDE}  -I${USER_INCLUDE}")
.
.
.
BUILD_COMMAND make all CC=${CMAKE_C_COMPILER} KERNELDIR=${TARGET_KERNEL_DIR} EXTRA_CFLAGS=${TP_INCLUDE_CFLAG}

one of these errors for example:

n file included from /opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/include/stdio.h:41:0,
                 from uio48io.c:35:
/opt/poky-sdk/2.4.2/sysroots/corei7-64-poky-linux/usr/include/libio.h:302:3: error: unknown type name ‘size_t’
   size_t __pad5;
   ^~~~~~
cogito
  • 80
  • 1
  • 11
  • 1
    "I couldn't figure out how to stop CMake ExternalProject from running the install command" - See [that question](https://stackoverflow.com/questions/37838786/how-to-not-make-install-step-when-building-external-project-with-cmake) about disabling `install` target. – Tsyvarev Jan 15 '21 at 23:28
  • You want to wrap building the kernel with CMake. Have you tried to build it **without** CMake, by directly issuing `make` with appropriate parameters? If you have done that, and building was successful, then compare commands, generated by CMake, with ones you run without it. If you haven't try to build without CMake then do that. – Tsyvarev Jan 15 '21 at 23:30
  • Did you solve this issue? Was it related to missing kernel headers via kernel-devsrc recipe? – Akilan Aug 04 '21 at 19:41

0 Answers0