Kernel developent inside Qt Creator
I’ve always found myself missing a friendly environment for exploring the Linux kernel. One where I could quickly go to macro and find function usages without grepping through the entire code. I got motivated by this talk so I decided to try and out and polish it a bit.
Assumptions
I’m assuming that you have QtCreator installed. The simplest way I’ve found is to just install the whole Qt installer for the Open source version.
Steps
The setup bases itself on the script I’ve wrote for the purpose of reducing the number of files that need to be included in the project.
The steps apply for building on Lubuntu 16.10 in Virtualbox.
1. Building the kernel
~$ sudo apt-get install libncurses5-dev gcc make git exuberant-ctags bc libssl-dev
~$ git clone https://github.com/torvalds/linux.git
~$ cd linux
~/linux$ git checkout v4.8
~/linux$ make clean
~/linux$ cp /boot/config-`uname -r`* .config
Make a file mkfile.patch with the following content:
Signed-off-by: Steve Beattie <steve.beattie at canonical.com>
[apw at canonical.com: shifted up so works in arch/<arch/Makefile.]
BugLink: http://bugs.launchpad.net/bugs/1574982
Signed-off-by: Andy Whitcroft <apw at canonical.com>
---
Makefile | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Makefile b/Makefile
index dda982c..f96b174 100644
--- a/Makefile
+++ b/Makefile
@@ -608,6 +608,12 @@ endif # $(dot-config)
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux
+# force no-pie for distro compilers that enable pie by default
+KBUILD_CFLAGS += $(call cc-option, -fno-pie)
+KBUILD_CFLAGS += $(call cc-option, -no-pie)
+KBUILD_AFLAGS += $(call cc-option, -fno-pie)
+KBUILD_CPPFLAGS += $(call cc-option, -fno-pie)
+
# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
# values of the respective KBUILD_* variables
ARCH_CPPFLAGS :=
--
2.8.1
Continue with the steps
~/linux$ patch < mkfile.patch
~/linux$ sed -i 's/CONFIG_CC_STACKPROTECTOR=y/# CONFIG_CC_STACKPROTECTOR is not set/' .config
~/linux$ sed -i 's/# CONFIG_CC_STACKPROTECTOR_NONE is not set/CONFIG_CC_STACKPROTECTOR_NONE=y/' .config
~/linux$ sed -i 's/CONFIG_CC_STACKPROTECTOR_STRONG=y/# CONFIG_CC_STACKPROTECTOR_STRONG is not set/' .config
~/linux$ sed -i 's/CONFIG_LOCALVERSION=""/CONFIG_LOCALVERSION="my-dev"/' .config
~/linux$ make KBUILD_VERBOSE=1 | tee build.log
~/linux$ sudo make modules_install install
~/linux$ sudo sed -i 's/GRUB_HIDDEN_TIMEOUT_QUIET=true/#GRUB_HIDDEN_TIMEOUT_QUIET=true/' /etc/default/grub
~/linux$ sudo sed -i 's/GRUB_HIDDEN_TIMEOUT=0/#GRUB_HIDDEN_TIMEOUT=0/' /etc/default/grub
~/linux$ sudo update-grub2
Reboot and select Ubuntu, with Linux 4.8.0my-dev+
in the Advanced options for Ubuntu
of grub menu.
There are some issues with building the kernel in virtualbox with the gcc flag -fstack-protector-strong
. The patches and edits of the config files are a workaround for that.
We’re keeping the log of the build which will be a basis for knowing what files to include in the Qt creator project.
2. Creating the QtCreator project
~/linux$ git clone https://github.com/TheMeaningfulEngineer/linux-in-qtcreator.git
~/linux$ cp linux-in-qtcreator/prepare_kernel_project.py .
~/linux$ chmod 755 prepare_kernel_project.py
~/linux$ ./prepare_kernel_project.py build.log linux
This runs the script responsible for parsing the build log and creating the OtCreator project config files. Argument build.log
is the path to the build log and linux
is the project name in QtCreator.
~/Qt/Tools/QtCreator/bin/$ ./qtcreator -noload Welcome -noload QmlDesigner -noload QmlProfiler
File -> Open File or Project -> ~/workspace/linux/linux.creator
This will open the project that contains all the files used for building the kernel in step one. This allows you to use QtCreators search functions to explore the code.
qtcreator
is run from the default installation location with flags that prevent issues in Virtualbox.
Be aware that it takes some time for Qt Creator to index all the files once you open the project.
3. Setting the new kernel module
~/linux$ mkdir out-of-tree-modules
~/linux$ echo "out-of-tree-modules/our-module.c" >> linux-rpi.files
Two files need to be created in ~/linux/out-of-tree-modules
-
Makefile
obj-m+=our-module.o all: make -C ../ M=$(PWD) modules clean: make -C . M=$(PWD) clean
-
our-module.c
#include <linux/module.h> // included for all kernel modules #include <linux/kernel.h> // included for KERN_INFO #include <linux/init.h> // included for __init and __exit macros MODULE_LICENSE("GPL"); static int __init hello_init(void) { printk(KERN_INFO "It's me, Mr. Kernel Module and I'm just being initialized\n"); return 0; // Non-zero return means that the module couldn't be loaded. } static void __exit hello_cleanup(void) { printk(KERN_INFO "Cleaning up module.\n"); } module_init(hello_init); module_exit(hello_cleanup);
Continue with building and loading the module.
~/linux/out-of-tree-modules$ make
~/linux/out-of-tree-modules$ sudo insmod our-module.ko
If all went well, you should see a line printed when running dmesg
.
[ 37.737250] It's me, Mr. Kernel Module and I'm just being initialized
Conclusion
This is the most practical driver development environment I found so far. Am open to hear your comments, critics or different approaches. If you find issues in the script, please support it by submitting them in the github repo.
Be Well :)