Nbites cmake setup - northern-bites/nbites GitHub Wiki

For some background, make sure to look at Compilation and Makefiles first!

CMake

We use CMake to generate a Makefile that is then used to build our code. CMake parses files written in special CMake syntax for directions in which to generate targets and all of such. We run the cmake command in the target build folder of choice (e.g. for qtool the source is in src/qtool but all of the generated buold files are in build/qtool) and give it the target source directory. CMake will then look for a file called CMakeLists.txt to parse. Then this file will include any other files that need to be parsed and so forth.

You may wonder where the cmake command is called! We wrap it in a Makefile under a virtual target! A quick look at the QTool Makefile reveals that the build target depends on the target $(GEN_MAKEFILE) = build/qtool/Makefile to be present. If it's not present then the commands under the $(GEN_MAKEFILE) target are executed. The last one is the actual cmake command!

CCMake

ccmake is short for curses-gui cmake cache editor. The curses-gui part means it uses the curses library to build its gui, which is a command line gui library. That explains the looks!

What it does is it allows you to quickly edit the cmake configuration cache file for a particular build. When CMake first gets run, it can be configured by passing -DVAR_NAME=value, for example -DUSE_MOTION=OFF or -DROBOT_NAME=marvin. Then it stores all of these variables used in configuring in a cache file in the build directory, so the user doesn't have to input his configuration options each file. By running ccmake and giving it the path to the cache file (usually it's in the build directory), then you can quickly edit some of the options, then re-build the project with the new options.

Again, the command is wrapped in our Makefile so that it is automatically called when we call some targets (like make cross or make straight)!.

CCMake could, in theory, be swapped in for any other cmake cache editor (like cmake-gui) or you could even manually edit the cache file if you're hardcore enough :) .

CMakeLists.txt

You should first check out this handy tutorial and also this official one.

The way CMake is set up with our code is that the topmost CMakeLists.txt will include each subdirectory with a CMakeLists.txt file using the command add_subdirectory(). Each CMakeLists.txt usually defines one (or more) target libraries, each comprised of source files residing in the same folder as the CMakeLists.txt file. Also, each of these CMakeLists.txt files will declare the include directories they depend on, the other targets their target library depends on and all of the external dependencies (usually found with find_package()). Sometimes it will also configure some files, add some custom targets or run some tests (more on this later). All of these lesser libraries get linked in the end in the target overarching binary (be in the man library or the qtool executable). You can check out any of our CMakeLists.txt for handy examples of how this all comes together.

Find_package

Once in a while we want to import some external libraries and includes for use in our code. The problem is the installation point of these files changes from system to system! Well, CMake addresses this issue with the inclusion of so-called CMake find modules that one can call easily with the command find_package(). More on this in this handy tutorial.

Configuring files

In our codebase you will sometimes see files called Something.in. These files are templates that get 'configured' by CMake, which means CMake goes through them and then replaces CMake variables (the ones that look like ${VARIABLE}) with their actual value, and then places the generated file in the folder specified by the user. Our upload script is one such template.

Options

Options are cmake variables that the user defines as being build options. This means that when you edit the cache using CCMake, then these options are always visible as variables that one can change. In our code, these options are specified in separate files, for example the man buildconfig.cmake and then included in the CMakeLists.txt file associated with it.

Custom target commands

Sometimes you want to compile some files using a different compiler (not gcc). You can achieve this by using add_custom_command(). For an example of how this is done check out this random blog post on it. The sample code can be seen here.

Toolchain files

Toolchain files are special cmake files that define build-crucial information such as choosing a compiler. We have our own generic.cmake file that is used for our native compiling (it doesn't do any special compiler selection, it just adds some additional include and library directories to the cmake search path) and also our own geode.cmake toolchain for cross-compiling on the geode, but it also includes the Aldebaran geode toolchain. Our geode.cmake does one important thing: it defines the FIND_ROOT_PATH to be the staging folder for the nao OS. This makes CMake treat that one folder as the root path of the system it would be normally searching for in (e.g. instead of looking in /usr/include it looks in ${FIND_ROOT_PATH}/usr/include, which is sometimes crucial in ensuring the right include files and libraries are linked against (or else you might have that on the robot the same library is missing some symbols, making the system segfault horribly).