This section demonstrates through examples how modifications to different layers of the source code must be accounted for when building a ChorusOS system.
A fundamental strength of the ChorusOS operating system is its portability across a range of target family hardware architectures. The trade-off made to achieve broad portability manifests itself as build management complexity. ChorusOS system builds require powerful tools to generate the necessary Makefiles to render the process more straightforward. These tools, imake and mkmk:
Provide the rules for compiling
Manage dependencies
Allow you to add components
Enable you to configure source files with configurator or the ews graphical tool
ChorusOS operating system builds involve make for end-result build tasks, and involve imake and mkmk for generating and managing Makefiles inside components. The following tables indicate which standard system components are managed using which Makefile generation tool.
Table 4-1 Components Managed with imake
Component |
Description |
---|---|
BSP |
Bootstrap code |
DRV |
Drivers |
EXAMPLES |
Example applications |
Table 4-2 Components Managed with mkmk
Component |
Description |
---|---|
NUCLEUS |
Microkernel and related code |
OS |
POSIX, file system and networking layers of the operating system |
The rule of thumb for choosing between imake and mkmk is simple: use imake if you can; use mkmk if you must. User-level application components can be handled using imake. Hardware driver components can be handled using imake. Subsystem components -- such as microkernel components and components that modify the POSIX, file system and networking layers of the operating system itself -- might require you to use mkmk.
An Imakefile is a machine-independent description of the make targets you want to build. In the first step of the build process, the imake tool generates a Makefile from each Imakefile, by selecting the configuration files with dependencies appropriate to your target system. This has the advantage that the Imakefile is a machine-independent description of the targets you want to build and is thus portable.
If files are altered they must be rebuilt. For the imake tool within the ChorusOS operating system, only dependencies between source and binary files are taken into account when altered files are rebuilt.
ChorusOS--specific imake rules are provided in the imake subdirectory of the install-dir/tools directory, as shown below.
host% cd install_dir/chorus-family/tools/imake host% ls Imake.rules Imake.tmpl Imake32.rules Package.rules Project.tmpl host% |
Table 4-3 presents each imake file.
Table 4-3 The imake files provided with the ChorusOS System
File |
Description |
---|---|
imake/Imake.rules |
imake rules |
imake/Imake32.rules |
Provides compatibility with r3.2 imake rules |
imake/Imake.tmpl |
Template Makefile, for imake |
imake/Package.rules |
Packaging rules, for imake |
imake/Project.tmpl |
Empty Project.tmpl |
Components managed with imake export their public information through packaging rules based on those found in these files. Examples demonstrating the use of ChorusOS--specific imake rules can be found in the ChorusOS 5.0 Application Developer's Guide. Commercially available books offer extensive explanations of how to use imake to manage portable software.
The imake command uses Project.tmpl and Imakefiles you include in each directory of your component source to generate Makefiles. During builds managed with imake, only dependencies between source and binary files are taken into account.
Table 4-4 ChorusOS imake Targets
iMake Target |
Description |
---|---|
all (default target) |
Builds everything |
clean |
Removes generated files recursively |
depend |
Generates dependencies recursively |
Makefile |
Regenerates the Makefile in the current directory. |
Makefiles |
Regenerates Makefiles recursively |
Each file in the tgt-make directory deals with make rules for compiling target binary files. Certain files are specific to the gcc compiler, others to the ghs compiler. Only common and gcc/powerpc specific files are described here. All files listed in Table 4-5 are located in the bin_dir/tools/tgt-make directory:
Table 4-5 Target Rules for ChorusOS
File |
Description |
---|---|
gcc-devsys.mk | make rules used by the imake environment |
gcc-ld.ld | Linker script used to reduce the section number |
gcc-variables.rf | make variables, for the mkmk and imake environments |
gcc-tgtdevsys.rf | make rules, for mkmk |
variables.rf | Includes the compiler specific file about variables |
tgtdevsys.rf | Includes the compiler specific file about rules |
shared.rf | Calls mkmake |
Makefile.mkimage | Makefile used during image creation |
Makefile.conf | Makefile used during configurable actor links |
genLink | Generic linker, calls genLink.conf and genLink.noconf |
genLink.conf | Links configurable actors |
genLink.noconf | Links non-configurable actors |
mkdbginfo | Generates offsets and symbol information |
powerpc/genOff | Create offset files |
powerpc/genOff.awk | awk file used by genOff |
powerpc/act.ld | Linker script used for actors using dynamic libraries |
powerpc/lib.ld | Linker script used to create dynamic libraries |
The mkmk tool is used to generate Makefiles that let you build a particular target system image from source code that supports multiple target hardware architectures. The mkmk rules allow you to manage system configuration entities such as features, parameters and tunables.
The mkmk build process consists of the following steps:
Merging -- creating links to source files from the build directory; the links enable mkmk to locate source code during builds.
Generating Makefiles in the build subdirectory for the component using mkmk.
Building the object component.
Creating the dependency files for subsequent builds.
Building the system image.
The role of mkmerge is to link the source files and the component's build directory. For further information, see the mkmerge(1CC) man page.
The code for ChorusOS components containing family-specific code is organized in projected trees. Within the projected trees, there are sub-trees for:
common code
code that is related to specific families or CPU
Before generation begins, subtrees are merged into a merged tree. There is only one merged tree in each merged component. Initially, it contains symbolic, or hard, links that point to files in the projected trees. The build takes place in the merged tree, so the projected trees remain free of generated files, such as object files and Makefiles. You can delete a merged tree at any time. This will not affect the source code, as it remains clean in the projected trees.
Different merged trees can be built from a given set of subtrees of the projected trees. This allows you to produce several system configurations concurrently.
Building the merged tree is called the merge operation. When performing this operation, you provide a number of first-level options, called generation options. These options correspond to fundamental production choices, such as the choice of a development system or the target family and are typically found in the build profile.
On systems running the Solaris operating environment, mkmerge populates the merge directory with symbolic links. These links point to the source directories required for your build.
Source directories within the projected tree can be populated with special files, named merge.rf (for merge rule files), which provide a number of directives for mkmerge, for example:
Preventing merging source files depending upon flags specified in the profile file
Exporting source.h files to other directories
Pruning the merge of the source tree, depending on the flags.
During a merge, directories are examined recursively and merge.rf files are analyzed. If no problems are encountered, the real merge begins: directories, links and files are created as specified in the various merge.rf files found.
A merge.rf file is composed of lines that are evaluated one at a time. A status is associated with this file. This status evolves as the file is analyzed. Depending on its value at the end of the merge.rf file, the current directory will be merged or cut.
A merge.rf file can contain commands to describe how the current directory should be merged, where it will go, and when it will be merged. The MKMERGE_IGNORE environment variable can be used to specify a list of file suffixes that should be ignored during the merge process.
For more information about merge.rf, see the mkmerge(1CC) man page.
The build profile used by the configure command is an argument of the mkmerge command. There is one default profile for each board, as shown in"Families, Targets and Profiles" . For non-standard system generation, customize the build profile using the information on the file entries described here.
The build profile contains entries of the following type:
var = value
The range of value values depends on the variable. Note that:
on and yes are equivalent values (both mean included)
off and no are equivalent values (both mean not included)
Build profile files provide configuration flags used during the merge. The following listing shows an example microkernel build profile file for UltraSPARCTM family targets.
[profile] FLAG=host=solaris FLAG=target=upSparc FLAG=devsys=gcc FLAG=flm=on FLAG=locks=rt FLAG=optim=on FLAG=tree=upSparc [profile] devsys=gcc binfmt=elf # directories to merge tree=./../common tree=./../sparc tree=./../sparc_v9 tree=./../usparc # kernel locks configuration : # 2 choices : locks=rt, locks=gp locks=rt # available memory management implementations flm=on prm=on vm=off # # shared_lib support # choices : sharedlib=on, sharedlib=off sharedlib=on # stack fault support : # 2 choices : stack_fault_support=on, stack_fault_support=off stack_fault_support=on # FPU support : # 2 choices : fpu_support=on, fpu_support=off fpu_support=on # optimisation type # choices : optim=on, optim=no optim=on # debug on or off (default) debug=off # profiling on or off (default) profile=off
The predefined flags include:
Table 4-6 Configuration Flags
Name |
Possible values |
Description |
---|---|---|
debug |
(off|on) |
Indicates whether to compile with debugging information; default is off |
devsys |
(gcc) |
Indicates which host development tool chain is used for compilation; default is gcc |
flm |
(off|on) |
Indicates whether flat memory is in use. |
prm |
(off|on) |
Indicates whether protected memory is in use |
vm |
(off|on) |
Indicates whether virtual memory is in use |
locks |
(gp|rt) |
Specifies which type of locking to use in the core executive; default is gp |
merge_dir |
(dir) |
Specifies the path to the root of the merge tree |
optim |
(off|on|size|speed) |
Indicates how to optimize compilation; setting this flag to speed might make symbolic debugging impossible; default is on, a compromise between size and speed optimizations |
profile |
(off|on) |
Indicates whether to compile with performance profiling capabilities; default is off |
shared_lib |
(off|on) |
Shared library support. Default is on. |
softload |
(off|on) |
Library fp emulation. Default is on. |
tree |
(dir1,dir2,...) |
Specifies projected tree directories to merge |
The mkmk tool uses portable description files, independently of both the host and target systems. High-level mkmk rules are included in .bf, .df and .mf portable description files for a component, and are then processed to create Makefiles and .dp dependency files for the builds.
The mkmk command uses three types of build description files, suffixed by .df, .bf, and .mf, to produce Makefiles and generate all .dp dependencies. With mkmk, you create a .mf file for each host. In this way the mkmk tool ensures portability during cross compilation and so ensures the portability of hosts and targets.
The .bf suffix denotes build file.
The .bf files are a subset of Imakefiles. They contain link directives , and you can have several .bf files per directory. The mkmk tool concatenates the .bf files inside the Makefile product. The .bf file is preprocessed by the macro processor m4(1).
Table 4-7 lists the macros used in a .bf file. The Actor
, ConfigurableActor
, Library
and BigObject
macros use getExport, either directly or
indirectly, to get the list of object files. The getExport
command computes the list of object files to use when creating a link.
Macro |
Description |
---|---|
|
Build actor using libs |
|
Build actor using libs |
|
Build lib |
|
Build a relocatable object file |
|
Copy file into dir |
|
Copy file into dir |
|
Build actor using libs |
|
Build actor using libs |
|
Build lib |
|
Build a relocatable object file |
|
Copy file into dir |
|
Copy file into dir |
|
Build a pre-built actor and its finalized makefile using libs and local_libs. |
The .df suffix denotes definitions file.
The .df files are used as shell scripts that are launched when the Makefile is created to adjust variables before they are written into the Makefile. The .df files define the following variables:
The cpp symbols
The header file directories
The list of subdirectories
The .df files have similar properties to the Project.tmpl files of the imake tool. They affect the building of the Makefiles for all the subdirectories. With mkmk, you can have several .df files in each directory of the source tree. This contrasts with the imake tool, which has only one Project.tmpl file per component.
The inheritance mechanism of the mkmk tool is different from that of the imake tool. With mkmk, every Makefile is dependent on the Makefile present in the parent directory. However, with imake, every Makefile is dependent on the Project.tmpl file present in the top-level directory of the component and on the few variables inherited from the parent directory. The variables and macros are defined in the production tools. Table 4-8 lists those you must not modify and Table 4-9 lists those you can modify.
Table 4-8 Variables for the .df Files that must not Change
Variable |
Description |
---|---|
DTL | (DEVTOOLS_DIR)/host/bin/ |
GROOT | ../../ (the relative path to the root component) |
BDIR | build_dir |
BNAME | Name of current directory |
HOST | Type of host |
FAMILY | Type of target |
COMPILER | Type of compiler |
MPATH |
Pathname of current directory relative to the component root |
BFILES | List of .bf files found in your work directory |
MFILES | List of .lf and .mf files found in your work directory |
DFILES | List of .df files in your work directory |
Table 4-9 Variables in the .df Files hat can Change
Variable |
Description |
---|---|
DEFINES | List of macro definitions to use in every compilation rule |
INCLUDES | List of directories to search for header files |
VARIABLES | The list of user defined variables to export in Makefiles produced in subdirectories |
SUB_DIRS | The list of directories to use when compiling; these are usually the subdirectories of your build directory |
EXTRA_DIRS | A list of directories to use, in addition to SUB_DIRS, when creating libraries or linking actors (usually empty) |
MODULES | The name of the module to which the object in your build directory (and subdirectories) belong; this is only useful in configurable actors |
FARROP |
Application profiling |
FEXCEPTION | (ON/OFF): Compile with exception support |
FPU | (ON/OFF): Compile with FPU support |
FOPTIM | (ON/OFF): Compile with optimization |
FPROF | (ON/OFF): Support for profiling |
FREMOTEDEB | (ON/OFF): Compile with debug options, to enable source level debugging |
FVERBOSE | (ON/OFF): Verbose compilations |
FWARN | (STRICT/ON/OFF): Enable production of warnings during compilation; with STRICT, warnings are treated as errors. The NUCLEUS component uses STRICT |
FASSERT |
(ON/OFF): Enable or disable assertions |
FGCOV |
(ON/OFF): Enable or disable code coverage testing with gcov |
FPIC |
(ON/OFF): Enable or disable compilation for inclusion in shared libraries |
FVEC |
(ON/OFF): Enable or disable generation/build options to use or not use a unit vector |
The .mf suffix denotes make file.
The .mf files contain lists of source files. The .mf files are used during make sources when the binary file to be built uses many subdirectories, each subdirectory containing a variable number of files to be compiled.
Another form of .mf files are .lf files. The variables and macros used in the .mf and .lf files are listed in Table 4-10.
Table 4-10 Variables and Macros used in .mf and .lf Files
Variable |
Description |
---|---|
C++SRCS | C++ source files |
C_SRCS | C source files |
AS_SRCS | Assembly code source files |
M4_SRCS | M4 source files (assembly code source files preprocessed with m4). |
OF_SRCS | C++ source files used to produce offset files |
During generation, mkmk goes down the build tree and creates a Makefile for each build directory. The Makefiles are used to build the binary files and each of these Makefiles is autonomous. This means that you can set make running from any directory and all files located in the subdirectories attached to that directory are built automatically. The Makefile content depends on the mkmk production files.
In each directory, where mkmk produces a Makefile, mkmk:
Calculates the initial value of the variables, in relation to the Makefile of the parent directory.
Activates the .df script files, located in the current directory, in a parallel shell.
Asks the shell to recover the values of the variables defined by the .df files.
The list of files to be compiled varies depending on the merge operation. Writing a Makefile that will work on several configurations can be complicated. The solution offered by mkmk is to:
Place the .mf files found in projected trees at the same directory level as the sources files to be compiled.
Concatenate the .mf files inside the Makefile that it produces.
The .mf files do not have an equivalent within the imake tool.
The mkmk tool will regenerate the Makefile produced if the .df, .bf or .mf files used to build it change.
Once a file has been modified, for example with an editor, or by a previous compilation, the files that depend on the altered file must be rebuilt. Most development tools only deal with the dependencies between source and binary files. The mkmk system goes further, taking into account any changes which occur in the source files during the build process.
The relationship between the different components is managed through the components' Makefile.bin and Makefile.src files and through the build paths found in the Paths file in your ChorusOS build directory. For example, applications can access both the microkernel API and the OS API through the variables set in the Paths file:
NUCLEUS_DIR provides the applications with access to the microkernel
BSP_DIR and DRV_DIR give access to the board support package information
OS_DIR enables access to the operating system API
This section presents the complete list of make targets you can use with the mkmk tool.
Table 4-11 Description of Make Targets used with mkmk
Make Target |
Description |
---|---|
all | Default make target, builds everything |
Makefile | Rebuild the Makefile in current directory |
makemk | Rebuild the Makefiles (recursively) |
merge | Remerge the current component |
makesrc | Build offset files (recursively) |
sources | Build offset files in the current directory |
makeprod | Build object files and libraries (recursively) |
prod | Build object files and libraries in the current directory |
makelink | Link libraries and actors (recursively) |
link | Link libraries and actors in the current directory |
depend | Generate dependencies (recursively) |
clean | Remove files produced (recursively), with the exception of Makefiles and dependency files |
clobber | Remove files produced (recursively) |
There also exists an alternative to imake, cdstool, which you can use to compile simple binaries. The cdstool utility is a wrapper for the C compiler delivered with the ChorusOS operating system.
#include <stdio.h> main() { printf("Hello world\n"); }
host% build_dir/bin/cdstool cc example.c -o example
$ |