ChorusOS 4.0 Production Guide

Chapter 5 Creating a ChorusOS Component

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.

Introduction

A component must provide a set of Makefiles in order to be configured using the configure tool. These Makefiles are as follows:

The Makefile.src file is used to build a component. The component can be built using any build tool, such as the mkmk tool or the imake tool.

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.

mkmk Component

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.

Creating a Component

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

Makefile.bin

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.

Makefile.src

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:

Adding the Component to the System Configuration

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

Creating a Simple Hello Application

Create a subdirectory, src, within your MYCOMP directory.

To create a simple hello application,

  1. 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 hello.bf file declares:

      • 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.

  2. Build your component in your work directory using the make command:

    host% make
    
  3. Add the hello binary file to the target file system, using the following command:

    host% make root
    

Updating your Application with Source Files in Several Directories

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

Using Merge to Update your Build Directory

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
...

Creating a Library

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.

Linking your Application to the Library

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

Rebuilding a Makefile

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.

imake Component

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.

Other Components

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.