This Chapter shows you how to create your own component for your ChorusOS system. You can create this type of component with mkmk, imake or a tool of your choice.
A component must provide a set of Makefiles in order to be configured using the configure tool. These Makefiles are as follows:
Makefile.bin for binary components
Makefile.src and Makefile.bin for source components.
When you receive the ChorusOS product, the Makefile.src and Makefile.bin files are provided, for each component. This has the advantage that, prior to configuration, all the components have characteristics in common. This means that the components are compatible, even when they have been built using different tools.
You can choose a selection of components generated with the mkmk and imake tools from the lists given in Chapter 1, Introduction in order to create your system image.
You can also create your own component by creating the Makefile.bin and Makefile.src files yourself as shown in this Chapter.
This section describes how to build a ChorusOS component with mkmk and the basic operations needed to manage your component. The information is provided in the form of a tutorial, leading you through an example which shows you how to achieve each step.
To build a very simple ChorusOS component called MYCOMP, which contains an application that displays a short message, you must begin by creating a path in your /tmp directory which contains your new component.
host% cd /tmp/MYSRC host% mkdir MYCOMP
Create a Makefile.bin file, containing the following information, in your MYCOMP directory.
COMPONENT += MYCOMP ROOT += $(MYCOMP_DIR)/root
The first line in the output, which declares the component's name, is mandatory. As the COMPONENT variable is the list of all components to be configured, use '+=', and not '='. The ROOT variable contains a list of directories to be copied to the target root file system.
Create a Makefile.src, containing the following information, in your MYCOMP directory.
all:: MYCOMP.all MYCOMP.all:: NUCLEUS.all OS.all MYCOMP.all:: $(MYCOMP_DIR)/DONE $(MYCOMP_DIR)/DONE: rm -rf $(MYCOMP_DIR) $(DEVTOOLS_DIR)/host/bin/mkmerge -s $(MYCOMP) -t $(MYCOMP_DIR) cd $(MYCOMP_DIR); $(DEVTOOLS_DIR)/host/bin/mkmk -t $(NUCLEUS_DIR) cd $(MYCOMP_DIR); $(make) touch $(MYCOMP_DIR)/DONE
This file is more complex than the Makefile.bin file as it describes how to build the component. The first lines of output give the list of components that must be built before the MYCOMP component. As the application that you are building needs operating system services, you must build the NUCLEUS and OS components before building the MYCOMP component.
The other lines in the Makefile.src file explain the following phases of the build of an mkmk component:
Creation of the merged tree with mkmerge. The MYCOMP variable points to the source directory of the component, and MYCOMP_DIR points to the component's build directory. Both variables are provided by the Paths file. This file is located at the top of the working directory and is initialized by the configure command.
Creation of the Makefiles file with mkmk.
Running of the make command in the merged tree. It is important to use $(make) instead of $(MAKE), as the make -n option executes lines containing $(MAKE) instead of displaying the file.
Declaration that the component compilation is complete.
Even though the component, MYCOMP, is empty, it may be configured. Use the make reconfigure command in your work directory, that is to say the directory in which you have previously run configure to build your system image. To compile your component type make:
host% make reconfigure NEWCONF='-s /tmp/MYSRC/MYCOMP'
Type make to compile your component and you will see the following output.
... rm -rf /<work_dir>/build-MYCOMP /<work_dir>/build-DEVTOOLS/host/bin/mkmerge -s /tmp/MYSRC/MYCOMP \ -t /<work_dir>/build-MYCOMP merged tree installed in /<work_dir>/build-MYCOMP cd /<work_dir>/build-MYCOMP; /<work_dir>/build-DEVTOOLS/host/bin/mkmk \ -t /<work_dir>/build-NUCLEUS >> In build-MYCOMP makemk << In build-MYCOMP makemk done cd /<work_dir>/build-MYCOMP; make touch /<work_dir>/build-MYCOMP/DONE
Create a subdirectory, src, within your MYCOMP directory.
To create a simple hello application,
create the following three files in the MYCOMP/src directory:
hello.c, this source file will say hello and is written as follows:
#include <stdio.h> extern void bye(); main() { printf("Hello\n"); #ifdef BYE bye(); #endif exit(0); }
hello.bf, this file provides rules to build the application and contains the following information:
C__SRCS = hello.c LIBS = $(OS_DIR)/lib/classix/libcx.a $(NUCLEUS_DIR)/lib/classix/libsys.s.a Actor(hello, $(LIBS)) Export(hello, $(MYCOMP_DIR)/root/bin)
The source files to be compiled.
The libraries to be used.
The fact that you want to build the hello actor.
The fact that you want to copy the hello actor into the root/bin directory, once it is built.
hello.df, this file defines the variables and contains the following information:
../../Paths VARIABLES="OS_DIR NUCLEUS_DIR" BDIR=${BUILD_DIR} INCLUDES="-I${OS_DIR}/include -I${NUCLEUS_DIR}/include \ -I${OS_DIR}/include/chorus -I${NUCLEUS_DIR}/include/chorus"
The hello.df file contains two parts. The first three lines give the location of the various components that MYCOMP depends on. The INCLUDES variable shows where to look for header files.
Build your component in your work directory using the make command:
host% make
Add the hello binary file to the target file system, using the following command:
host% make root
Applications may have several source files in different directories. These files may be accessed using links. This example shows how to create a link between the files.
Define the BYE flag by creating a bye.df file in your MYCOMP/src, including the following information:
DEFINES="-DBYE"
The bye() function will be called once the BYE flag is defined in the compilation options.
Remove the MYCOMP build directory and run make again as follows:
host% rm -rf /<work_dir>/build-MYCOMP host% make
The link phase fails because the bye() function in not defined properly.
Create a new directory (bye) in your src directory and define the bye() function in the bye.c source file by including the following information in the file:
void bye() {}
The bye.c file is not in the same directory as the .df file. You must create a .mf file, bye.mf, in your bye directory containing the following information:
C__SRCS = bye.c
Run make again and the link phase will succeed.
host% make
Note, the bye.o object file has been automatically added to the list of files used to link hello. To display this list, use the getExport command:
host% <bin_dir>/host/bin/getExport build-MYCOMP/src build-MYCOMP/src/bye/bye.o build-MYCOMP/src/hello.o
If links produced by mkmerge are removed, make merge, run in the merged tree, will recreate them:
host% cd build-MYCOMP/src host% ls Makefile bye hello hello.c hello.o all.dp bye.df hello.bf hello.df host% rm -rf bye host% make merge /<work_dir>/build-MYCOMP/src/bye/bye.c -> \ tmp/MYSRC/MYCOMP/src/bye/bye.c /<work_dir>/build-MYCOMP/src/bye/bye.mf -> \ tmp/MYSRC/MYCOMP/src/bye/bye.mf merged tree installed in /<work_dir>/build-MYCOMP
The merge process in the ChorusOS system, is controlled by merge.rf files. These files contain commands that are executed by mkmerge. The syntax and semantics of these files are described in the mkmerge man page.
To have the bye subdirectory of the split tree appear as ciao in the merge tree, use a merge.rf file in the bye source directory as follows:
host% echo 'move ../ciao' > /tmp/MYSRC/MYCOMP/src/bye/merge.rf host% rm -rf bye
Run the merge command again and you will see that you have created a new subdirectory.
host% make merge
Rebuild the Makefiles using the make makemk command:
host% make makemk >> In build-MYCOMP/src makemk >> In build-MYCOMP/src/ciao makemk << In build-MYCOMP/src/ciao makemk done << In build-MYCOMP/src makemk done ...
You can create a library with mkmk by following this example. Create a .bf file, bye.bf, that calls the Library macro, putting the following information:
Library(ciao.a)
Type make merge.
host% make merge /<work_dir>/build-MYCOMP/src/ciao/bye.bf -> \ /tmp/MYSRC/MYCOMP/src/bye/bye.bf merged tree installed in /tmp/WORK/build-MYCOMP
This library will automatically include the list of object files given by getExport.
To link the hello actor to the new ciao.a library, the hello.bf file, in your MYCOMP/src directory, must be modified to contain the following information:
C__SRCS = hello.c LIBS = ciao/ciao.a $(OS_DIR)/lib/classix/libcx.a \ $(NUCLEUS_DIR)/lib/classix/libsys.s.a Actor(hello, $(LIBS)) Export(hello, $(MYCOMP_DIR)/root/bin)
Rebuild the Makefiles and the hello actor as follows:
host% make makemk host% make ... cc bye.c Makefile -> all.dp ar -> ciao.a ... sh /<work_dir>/build-DEVTOOLS/host/bin//../../tgt-make/genLink \ /<work_dir>build-NUCLEUS/ /<work_dir> -r -e _start -o hello -B ciao/ciao.a \ /<work_dir>/build-OS/lib/classix/libcx.a \ /<work_dir>/build-NUCLEUS/lib/classix/libsys.s.a ld -> hello.xpO hello.xpO -> hello.CT.o export hello << In src link done
You can have applications with multiple .mf files in your directory, particularly when using the mkmerge command to integrate specific or optional code. When a .mf file is created or changed, you must recreate the Makefile. To check this, create an empty directory, and put a .mf file, a.mf, in it. Type either make Makefiles or make mkmake and you will recreate the Makefile.
>> In <work_dir>/build-IOM/src/os/sys/sys/lib/gen makemk << In <work_dir>/build-IOM/src/os/iom/sys/sys/lib/gen makemk done
If the Makefile changes, the compilation options may have changed. Therefore all object files must be recompiled. When mkmake regenerates a Makefile, if the Makefile has changed, mkmake removes any object files which have been produced. Use the make command now to recompile the source code.
For imake components, the Imakefile is used to create the Makefile. The imake Makefile.src is similar to the Makefile.src file described for mkmk. If the MYCOMP component is built using the imake tool, its Makefile.src would be:
all:: MYCOMP.all MYCOMP.all:: DEVTOOLS.all NUCLEUS.all OS.all MYCOMP.all:: $(MYCOMP_DIR)/DONE $(MYCOMP_DIR)/DONE: rm -rf $(MYCOMP_DIR) sh $(DEVTOOLS_DIR)/ChorusOSMkMf $(BUILD_DIR) \ -s $(MYCOMP) -b $(MYCOMP_DIR) -d $(MYCOMP_DIR) cd $(MYCOMP_DIR); $(make) Makefiles cd $(MYCOMP_DIR); $(make) touch $(MYCOMP_DIR)/DONE
The Makefile.src contains the call to ChorusOSMkMf which will generate all Makefiles in the component. Then, make Makefile and make are called.
As the binary components have already been created, the Makefile.bin file of a component does not depend on the component's generation method. There is no difference between a Makefile.bin file for an imake component and a Makefile.bin file for a mkmk component.
The contents of the Makefile.bin are as follows.
COMPONENT += MYCOMP ROOT += $(MYCOMP_DIR)/root
ChorusOS 4.0 Introduction explains how to create a hello application with imake.
Components that do not use either the mkmk or the imake tool are free to use any build method in the $(MYCOMP_DIR)/DONE rule. There is a restriction that only one directory, $(MYCOMP_DIR) (in this example build-MYCOMP) can be considered as writable. If the build method produces binary files in source directories, the source files should be projected from $(MYCOMP) to $(MYCOMP_DIR) with mkmerge. Typing the following command.
<bin_dir>/host/bin/mkmerge -s $(MYCOMP) -t $(MYCOMP_DIR)
This command will populate MYCOMP_DIR with links that point back to your MYCOMP directory.