Skip to content

Commit

Permalink
Merge pull request #128 from djolertrk/feature/build-system
Browse files Browse the repository at this point in the history
Add CMake Build System with Testing Infra
  • Loading branch information
carloslack authored Oct 30, 2024
2 parents d01bd4b + e0cd127 commit 91f653d
Show file tree
Hide file tree
Showing 21 changed files with 845 additions and 2 deletions.
Empty file added .gitattributes
Empty file.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf

build/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "volundr"]
path = volundr
url = https://github.com/carloslack/volundr.git
[submodule "test/test-artefacts"]
path = test/test-artefacts
url = https://github.com/djolertrk/KoviD-test-artefacts.git
125 changes: 125 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
cmake_minimum_required(VERSION 3.10)
project(kovid)

# Step 1: Define Kernel Version Variable
execute_process(
COMMAND uname -r
OUTPUT_VARIABLE CURRENT_KERNEL_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(KOVID_LINUX_VERSION "${CURRENT_KERNEL_VERSION}" CACHE STRING "Linux kernel version to build against")
message("-- Linux Target: ${KOVID_LINUX_VERSION}")

# Step 2: Allow user to specify the kernel directory
set(KERNEL_DIR "/lib/modules/${KOVID_LINUX_VERSION}/build" CACHE PATH "Path to the kernel source or headers for version ${KOVID_LINUX_VERSION}")

# Step 3: Check for Kernel Headers
if(NOT EXISTS "${KERNEL_DIR}")
message(FATAL_ERROR "Kernel headers for version ${KOVID_LINUX_VERSION} not found in ${KERNEL_DIR}")
endif()
message("-- Linux Headers: ${KERNEL_DIR}")

# Step 4: Find Necessary Programs
find_program(LD ld)
find_program(AS as)
find_program(CTAGS ctags)
find_program(JOURNALCTL journalctl)
find_program(UUIDGEN uuidgen)

set(CMAKE_C_COMPILER "gcc")

set(KOVID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})

# Step 5: Get UUID
execute_process(
COMMAND ${UUIDGEN}
OUTPUT_VARIABLE UUIDGEN_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Step 6: Define Build Options
option(DEPLOY "Turn off ring buffer debug" OFF)

if(NOT DEPLOY)
set(DEBUG_PR -DDEBUG_RING_BUFFER)
endif()

# Define COMPILER_OPTIONS as a list
set(COMPILER_OPTIONS
-Wno-error
"-DPROCNAME=\"${PROCNAME}\""
"-DMODNAME=\"${MODNAME}\""
-DKSOCKET_EMBEDDED
${DEBUG_PR}
-DCPUHACK
-DPRCTIMEOUT=1200
"-DUUIDGEN=\"${UUIDGEN_OUTPUT}\""
"-DJOURNALCTL=\"${JOURNALCTL}\""
)

# Combine the list into a space-separated string
string(JOIN " " COMPILER_OPTIONS_STR ${COMPILER_OPTIONS})

# Define EXTRA_CFLAGS as a list and join it into a string
set(EXTRA_CFLAGS_LIST
"-I${KERNEL_DIR}/include"
"-I${CMAKE_CURRENT_SOURCE_DIR}/src"
"-I${CMAKE_CURRENT_SOURCE_DIR}/fs"
"-I$(KERNEL_DIR)/include/generated"
${COMPILER_OPTIONS}
)

string(JOIN " " EXTRA_CFLAGS_STR ${EXTRA_CFLAGS_LIST})

message("-- Extra CFLAGS: ${EXTRA_CFLAGS_STR}")

# Step 7: Define Source Files and Extra Flags
set(SRC
src/${MODNAME}.c
src/pid.c
src/fs.c
src/sys.c
src/sock.c
src/util.c
src/vm.c
)

# Step 8: Create the 'persist' Target using configure_file
set(UUIDGEN_SH "${UUIDGEN_OUTPUT}.sh")
set(UUIDGEN_KO "${UUIDGEN_OUTPUT}.ko")

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/persist.S.in ${CMAKE_CURRENT_BINARY_DIR}/persist.S @ONLY)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/persist.o ${CMAKE_CURRENT_BINARY_DIR}/persist
COMMAND ${AS} --64 ${CMAKE_CURRENT_BINARY_DIR}/persist.S -statistics -fatal-warnings -size-check=error -o ${CMAKE_CURRENT_BINARY_DIR}/persist.o
COMMAND ${LD} -Ttext 200000 --oformat binary -o ${CMAKE_CURRENT_BINARY_DIR}/persist ${CMAKE_CURRENT_BINARY_DIR}/persist.o
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/persist.S
COMMENT "Building persist binary"
)

# Step 9: Rename the custom target to avoid name collision
add_custom_target(build_persist DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/persist)

# Step 10: Create the 'kovid' Target
add_custom_target(kovid ALL
DEPENDS build_persist
COMMAND make -C "${KERNEL_DIR}" M="${CMAKE_CURRENT_SOURCE_DIR}" modules KBUILD_EXTRA_CFLAGS="${EXTRA_CFLAGS_STR}" V=1
COMMENT "Building kovid kernel module"
)

# Step 11: Handle Cleaning
add_custom_target(clean-kovid
COMMAND make -C "${KERNEL_DIR}" M="${CMAKE_CURRENT_SOURCE_DIR}" clean
COMMAND ${CMAKE_COMMAND} -E rm -f ${CMAKE_CURRENT_BINARY_DIR}/persist ${CMAKE_CURRENT_BINARY_DIR}/persist.o ${CMAKE_CURRENT_BINARY_DIR}/persist.S
COMMENT "Cleaning kovid module"
)

# Step 12: Copy kovid.ko and qemu-runner.sh to the build directory
add_custom_command(TARGET kovid POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/kovid.ko ${CMAKE_CURRENT_BINARY_DIR}/kovid.ko
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/test/Artefacts/qemu-runner.sh ${CMAKE_CURRENT_BINARY_DIR}/qemu-runner.sh
COMMENT "Copying kovid.ko and qemu-runner.sh to build directory"
)

add_subdirectory(test)
16 changes: 14 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ CTAGS=$(shell which ctags))
JOURNALCTL := $(shell which journalctl)
UUIDGEN := $(shell uuidgen)

# PROCNAME, /proc/<name> interface. You must change it.
COMPILER_OPTIONS := -Wall -DPROCNAME='"changeme"' \
# TODO: Check if we can generate a random PROCNAME, something like:
# PROCNAME ?= $(shell uuidgen | cut -c1-8)

ifeq ($(origin PROCNAME), undefined)
$(error ERROR: PROCNAME is not defined. Please invoke make with PROCNAME="your_process_name")
else ifeq ($(strip $(PROCNAME)),)
$(error ERROR: PROCNAME is empty. Please set PROCNAME to a non-empty value)
endif

# Display the selected PROCNAME during the build
$(info -- Selected PROCNAME is $(PROCNAME))

# PROCNAME, /proc/<name> interface.
COMPILER_OPTIONS := -Wall -DPROCNAME='"$(PROCNAME)"' \
-DMODNAME='"kovid"' -DKSOCKET_EMBEDDED ${DEBUG_PR} -DCPUHACK -DPRCTIMEOUT=1200 \
-DUUIDGEN=\"$(UUIDGEN)\" -DJOURNALCTL=\"$(JOURNALCTL)\"

Expand Down
132 changes: 132 additions & 0 deletions docs/TestFeatures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Manual testing of KoviD features

This document describes the process of testing the features of Kovid LKM.
Please see `docs/QEMUSetupForTesting.md` that contains info for qemu setup.

## Fetch LFS and submodules

```
$ git fetch --recurse-submodules
```
or:

```
$ git submodule update --remote --recursive
```

LFS should be fetched:

```
$ git lfs fetch --all
```

## Build KoviD

Old way (using pre-existing GNU Makefile):
```
$ cd KoviD
$ make clean && make CC=gcc-12
```

New way by using CMake:

```
$ mkdir build && cd build
$ cmake ../ -DCMAKE_C_COMPILER=gcc-12 && make CC=gcc-12
```

or

```
$ cmake ../ && make
```

NOTE: You can customize it:

```
$ cmake -DPROCNAME=myproc -DMODNAME=mymodule ../
```

### Building for Linux version other than native

```
$ cmake ../ -DKOVID_LINUX_VERSION=5.10 -DCMAKE_C_COMPILER=gcc-12 && make CC=gcc-12
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/gcc-12 - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:14 (message):
Kernel headers for version 5.10 not found in /lib/modules/5.10/build
-- Configuring incomplete, errors occurred!
See also "build/CMakeFiles/CMakeOutput.log".
```

But lets say we built `linux` in `projects/private/kovid/linux`, we can set up manually the variables:

```
$ cmake ../ -DKOVID_LINUX_VERSION=5.10 -DKERNEL_DIR=projects/private/kovid/linux -DKOVID_LINUX_VERSION=5.10 -DCMAKE_C_COMPILER=gcc
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Linux Target: 5.10
-- Linux Headers: projects/private/kovid/linux
-- Extra CFLAGS: -Iprojects/private/kovid/linux/include -Iprojects/private/kovid/KoviD/src -Iprojects/private/kovid/KoviD/fs -I$(KERNEL_DIR)/include/generated -Wno-error -DPROCNAME="changeme" -DMODNAME="kovid" -DKSOCKET_EMBEDDED -DDEBUG_RING_BUFFER -DCPUHACK -DPRCTIMEOUT=1200 -DUUIDGEN="5a803031-366c-4070-8656-1f940a2467b8" -DJOURNALCTL="/usr/bin/journalctl"
-- Configuring done
-- Generating done
-- Build files have been written to: projects/private/kovid/build
$ make PROCNAME="mykovidproc"
-- Selected PROCNAME is mykovidproc
```

If you miss the `PROCNAME`, it will emit an error during build time:

```
$ make
...
*** ERROR: PROCNAME is not defined. Please invoke make with PROCNAME="your_process_name". Stop.
```

### Run tests

Please make sure to install llvm-tools, since we will be using some of the tools for testing infrastructure:

```
sudo apt-get install llvm-18-dev
sudo apt-get install llvm-18-tools
sudo apt-get install libslirp-dev
sudo apt-get install qemu-system-x86
```

Run tests:

```
$ cd KoviD && mkdir build && cd build
$ cmake ../ -DKOVID_LINUX_VERSION=5.10 -DKERNEL_DIR=projects/private/kovid/linux -DKOVID_LINUX_VERSION=5.10 -DCMAKE_C_COMPILER=gcc
$ make PROCNAME="myprocname"
$ make check-kovid
```

## Linux Kernel 5.10

1. Hide itself

TODO
Loading

0 comments on commit 91f653d

Please sign in to comment.