Build System

From Embedded Xinu
Jump to navigation Jump to search

Building Embedded XINU is as simple as typing make in the compile directory. However, if you want to understand how the build system works you'll need to acquaint yourself with the Makefile. It should be noted that this is not a recursive build process (make only calls another make process when building the libraries and a few other special cases), but rather a single Makefile that sources rules to build logically separated components.

This is a description of the build process for building the trunk version of XINU and may not be applicable to all versions.

Makefile

Open compile/Makefile and you'll discover numerous variables and settings for building XINU. The first is the directive to include mipsVars. This simply adds the contents of the compile/mipsVars file to the Makefile. We chose to include this file so that moving from system to system is easier by storing dynamic variables in an external file. The less we change the Makefile the better.

mipsVars defines the location of the cross-compiler and various flags for compiling C and assembly source files.

After the local configuration is included we set a number of variables giving the final compiled image name, an archive file to create (if requested), where the main program is located, flags to pass to the loader, and file locations. Then there is the default make target which will be called when make with no arguments is typed at the shell prompt.

Now, the next two variables are very important. COMPS is a listing of the major system components we should include while building. Similarly LIBS is a listing of the libraries we will include when building the system. From the COMPS line we use another include directive, this time sourcing a Makerules file located in the directory to which each component points. Each Makerules file will append the source files to build that component into the kernel image. After all the source files are loaded, the Makefile converts the collection of C source files and assembly files to make one massive listing of object files.

Now, that all the important variables are set up there are a number of targets that can be executed. The most common target is ${BOOTIMAGE} (which is typically xinu.boot), this depends on all the object files, library files, and the loader script. Then it will link all the object files together to create the boot image. There is also a objects target that will only build the object files for the system (and not link them).

There are several ways of cleaning the source tree. make clean will remove all the object files and the bootimage. make libclean will call the clean target for all the libraries. make depclean removes all the header file dependencies from the Makefile. make docclean will remove the documentation generated by the make docs command. make realclean will do all of the above and remove the vn and version files as well.

Moving above and beyond those targets, there are also a few special targets that can be called. make [component] will create object files only for the specified subsystem (useful during development). make [libname] will build the library archive, and make [libname]-clean will clean the library.

Makerules

As mentioned above a Makerules file resides in each component directory. This file will append a listing of the source files for the component. There are two important factors about this file:

  1. At the top of the file, make sure that COMP is the name of the component and the name of the directory.
  2. Make sure you append all the files to the COMP_SRC variable and that they are prefixed with the proper directory (so gcc can find them.)

Within the file itself you can breakup files as you see fit. Typically, assembly files are stored in local S_FILES variables while C source is stored in C_FILES variables. This is not strictly needed, but makes it easier to read in some cases.

Library

XINU libraries are built using the recursive make paradigm. Since the libraries do not change commonly they are not removed between builds unless specially requested. In the master Makefile all relevant variables are exported (including the location of the cross-compiler, C and assembly flags), the library Makefile then uses those to build its files and create an archive of the object files.

This allows all important build variables to be in one location and not leave possible dependency issues if something were to change in the build system.