Compiling OS code with CMake
I was thinking for some time to switch from GNU Make to CMake for an OS project of mine. Sadly the project is just a barebones of an OS but it proved a good playground for testing things related to compiling and linking projects: the tutorial about GNU Make that I wrote a while ago came out as a consequence of this project.
Anyway, for some time, I just thought that it wouldn’t be possible to do this so I didn’t bothered but in the past month I did a build system at work using CMake and I learned a lot of things. CMake is truly an incredible tool! So today I gave it a shot. It was easy but I learned a couple of things in the process.
cmake_minimum_required (VERSION 2.8)
PROJECT (kernel)
INCLUDE_DIRECTORIES (include)
SET (CMAKE_CXX_FLAGS "-m32 -ffreestanding -fno-rtti -fno-exceptions -nostdlib -nostdinc -fno-stack-protector")
SET (CMAKE_C_FLAGS "-m32 -ffreestanding -fno-exceptions -nostdlib -nostdinc -fno-stack-protector")
SET (CMAKE_EXE_LINKER_FLAGS "-m elf_i386 -T${CMAKE_CURRENT_LIST_DIR}/link.ld")
SET (CMAKE_ASM_NASM_OBJECT_FORMAT "elf")
ENABLE_LANGUAGE (ASM_NASM)
FILE (GLOB_RECURSE kernel_C_SOURCES "kernel/*.c")
FILE (GLOB_RECURSE kernel_CPP_SOURCES "kernel/*.cpp")
FILE (GLOB_RECURSE kernel_ASM_SOURCES "arch/x86/asm/*.nasm")
FILE (GLOB_RECURSE kernel_ARCH_C_SOURCES "arch/x86/*.c")
FILE (GLOB_RECURSE kernel_ARCH_CPP_SOURCES "arch/x86/*cpp")
ADD_LIBRARY (kernel.img STATIC
${kernel_C_SOURCES}
${kernel_CPP_SOURCES}
${kernel_ARCH_C_SOURCES}
${kernel_ARCH_CPP_SOURCES}
${kernel_ASM_SOURCES})
ADD_CUSTOM_COMMAND (TARGET kernel.img
POST_BUILD
COMMAND "/usr/bin/ld -m elf_i386 -T${CMAKE_CURRENT_LIST_DIR}/link.ld -o phOS.img ${CMAKE_BINARY_DIR}/libkernel.img.a")
As you can see the file came out pretty small. The first thing that I’ve learned was about compiling asm files. CMake has now support for that. All you have to do is ENABLE_LANGUAGE (ASM_NASM) and when you feed it *.nasm and *.asm files it will do the job. The thing that I was stuck with was the format of the outputed binary. By default CMake gave nasm a -f elf64 option (considering that I’m on a x86_64 platform). It took me a while to discover that you can change that by setting CMAKE_ASM_NASM_OBJECT_FORMAT variable.
The second major problem was with linking. I want to issue the link command myself and I tried to influence CMake but it came out wrong. As far as I understand CMake generates a link script and on linux it uses the compiler to link object files instead of LD (in the end LD is used probably but trough the compiler). In the end I solved this by making a static library and then adding a POST_BUILD command that relinked that library in something that I wanted. After the build finishes the custom command is executed and I obtain the binary that I want.
Now I get all the good things that come with CMake, IDE support being the most wanted feature on my list.
No trackbacks yet.