Compilation - northern-bites/nbites GitHub Wiki

The name of this page should have been compilation and linking, since they are different parts of the binary generation process, but since they are both so tightly related, we shall treat them both in this page. Also we don't interact with the compiler directly, but we do specify options that end up being passed onto the compiler.

A few words about compilers and linkers

A compiler is a program that takes code written in a language that the compiler can parse and then generates target binary code in the form of an object. Binary code means that the code is made so that it is directly executable by the CPU, whereas the CPU can't understand the words or the syntax of the original language the code was written in. This means that the compiler produces a file that has all the instructions that describe the functions that the user specified in his code, but they are not human readable.

A linker is a program that takes object files produced by a compiler and then links them together to produce the final binary (be it an executable or a dynamic or static library). This is because the compiler doesn't check that the code it compiles is self-sufficient, or, in other words, the linker make sure that all symbols USED were actually DEFINED. So if I use a function that was implemented in some other library but only compile my code, I will have to specify to the linker that it has to link against that external library so that the function is defined somewhere (imagine if you were using a function that didn't exist!).

GCC

Here's a pretty good short intro to gcc: http://www.cs.cf.ac.uk/Dave/C/node3.html

The short story is that our build system uses the system's gcc for compiling and either the Aldebaran provided geode cross-compiler or a cross-compiler that we use ourselves (which is just a variant of i586-linux-gcc), but we've ran code on the robot that's just been compiled natively on i686-linux before.

GCC flags

CMake will generate most of the flags it passes to GCC automatically (like -I and -l flags), but allows the user to specify some flags manually as well.

The compilation and optimization flags we pass to gcc are defined at the top of base_definitions.cmake.

The -On flag specifies optimization level, where 3 is the highest. The short story is that the compiler makes really safe optimization up to -O2, but -O3 really cracks the whip and hella-optimizes the code. Of course the downside is that if bugs are introduced at -O3 level they're hard to trace because the code becomes mangled. Also, of note is the fact that any optimization level lower than -O3 makes our code run noticeably slower.

The -w... flags specified are used to suppress compiler warnings. Compiler warnings occur when the compiler detects something iffy about the code (unused variables, etc.) but if the problem is not severe enough, then it won't abort the compilation process. Some warnings are important though, for example if you inadvertently convert a variable from float to int, then you will lose all of the decimal part in the conversion.