-
Notifications
You must be signed in to change notification settings - Fork 6
MoMo Build System
The MoMo build system is based on SCons, which is a python based build dependency tracking tool. None of the details of Scons are important for MoMo users since we have automated the use of the build system. This document will detail how the build systems is designed and how to use it.
The build system is organized around modules. A module is a set of source files that produce a .hex file containing object code that runs on an embedded processor (8-bit or 16-bit). These files all live in one directory tree organized in the following fashion:
> ls <generic_module>
build src test SConstruct
- SConstruct is the SCons version of a Makefile. It contains all of the instructions needed to build the module.
- src contains all of the source code.
- test contains all of unit tests for the module
- build will contain all of the intermediate and final build files.
A module can target one or more architectures. All of the code is recompiled for each architecture and stored in a separate directory under the build directory. The final hex files and associated symbol information for all built targets is stored in build/output with the architecture name appended. As an example, lets take the pic12_executive module:
> cd momo_modules/pic12_executive
> ls build
12lf1822_exec 16lf1823_exec 16lf1847_exec output test
This module supports 3 chips (the PIC 12LF1822, 16LF1823 and 16LF1847). The test directory contains the results of all of the units tests.
> ls build/output
mib12_executive_12lf1822_exec.hex mib12_executive_symbols_16lf1823_exec.h
mib12_executive_16lf1823_exec.hex mib12_executive_symbols_16lf1823_exec.stb
mib12_executive_16lf1847_exec.hex mib12_executive_symbols_16lf1847_exec.h
mib12_executive_symbols_12lf1822_exec.h mib12_executive_symbols_16lf1847_exec.stb
mib12_executive_symbols_12lf1822_exec.stb
We see the hex file and 2 symbol files for each target architecture, with the architecture's name appended to the file. This is the standard naming convention for all momo build products: module-name_optional-identifier_target-architecture.extension
##Architectures There are a lot of details about the target platform that the build system needs to know in order to produce a correct hex file that will work and interoperate with the rest of the MoMo ecosystem. It's also often desirable to have the same source code target multiple platforms. To do this in a scalable way, the MoMo build system has a concept of stackable 'archictures'. Each architecture contains a (possibly nested) dictionary of name/value pairs. Multiple architectures may be specified in a list and later architectures can overwrite the values for keys that are defined in previous architectures. The build system just operates on the final dictionary of keys/values that is produced by concatenating all of the separate dictionaries for each architecture listed.
For example, look at the pic12_executive in the previous section. One of the architectures it targets is '12lf1822/exec'. The 12lf1822 contains all of the definitions needed to build code for the PIC12LF1822 chip and the exec architecture adds the definitions of usable RAM and ROM spaces so that the executive does not conflict with any application code. All of the architectures are defined in:
config/build_settings.json
The build_settings.json file stores per-module and per-architecture definitions for both 8-bit (mib12) and 16-bit (mib24) modules. The file is divided into mib12 and mib24 sections, each of which applies only to their respective family. In order to build a module for a specific architecture, the build system reads build_settings.json and pulls information from 3 places:
- Default family settings - stored in a dictionary under family/default_settings
- Default architecture settings - stored in a dictionary under family/architectures/<architecture_name>
- Per-module overrides - stored in a dictionary under family/modules/<module_name>
The three dictionaries found in these locations (any of which may be empty but they all must exist) are merged in the above order with subsequent dictionaries overriding earlier ones wherever they define the same key. The merge is done recursively.
Many of the settings defined in build_settings.json are opaque in the sense that they refer to internal MoMo operational details and should not be modified. Others are documented here.
- defines a dictionary of key:value pairs that are passed to the C/ASM preprocessor for macro expansion
- includes a list of include directories for header files. Include paths are relative to momo_modules/ for consistency.
- extra_includes another list of include directories that is concatenated with includes. Modules should use this key to maintain the system-wide includes defined in default_settings/includes
- linker (mib24 only) a path relative to the module SConstruct file for a linker script used to link the module together
Sometimes a module may need to have special settings depending on the architecture that it's targeting. For example, normally the mainboard code uses an external flash chip but when it targets an architecture without that chip it must disable that functionaly. For this purpose each module can define a dictionary of module specific overlays by including a dictionary under the 'overlays' key. Each key in overlays should be a dictionary and have the same name as the architecture that requires modification for this module. When the module is built for an overlaid architecture, the original architecture dictionary is merged the overlay and that dictionary is then merged with the rest of the architectures listed for the module.
Building a module requires invoking mibtool build in the module's base directory:
> mibtool build
Once the command finishes, all of the output files for debugging and programming will be placed in build/output. If you have a multicore machine, you can speed up the build process by using N compilation steps in parallel:
> mibtool build -jN
To clean up all of the build artifacts use:
> mibtool build -c
Any arguments passed after mibtool build are forwarded on to Scons so you can use whatever Scons specific flags you wish to troubleshoot build issues.
Creating a new module involves creating an SConstruct file for it based on the templates in a similar existing module and adding an entry for it into build_settings.json to specify the architecture(s) that it targets. By default each module targets all architectures in its family.