Build System
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 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 XINU from trunk 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:
- At the top of the file, make sure that
COMP
is the name of the component and the name of the directory. - 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.