3.2.  Creating Ports and Components

Let's create a component. First make sure that your current working directory is inside the project directory:



$   pwd




/data/user1/myProject
$ 


It is important to be in the project directory (or its subdirectories) when you invoke bocca because it picks up all of the context for your project from there (similar to CVS or Subversion). Go ahead and create the component now:



$   bocca create component emptyComponent











Updating the cxx implementation of component myProject.emptyComponent ...
$ 


You will notice that this takes a little time and that bocca has selected myProject as the default package name for emptyComponent since no package name was specified when creating the component. Bocca will default to the project name as the package name for both ports and components, unless a different default package name was specified when the project was created. Note we have named our component emptyComponent because it has no uses nor provides ports and thus is rather uninteresting. Nonetheless all of the necessary make system scaffolding and code have been generated for the component, including the setServices call. Here we use as an example the case where LANG is cxx:

 


$  ls components/myProject.emptyComponent/




BOCCA		 make.vars.user
glue		 myProject_emptyComponent_Impl.cxx
Makefile	 myProject_emptyComponent_Impl.hxx
make.rules.user  myProject_emptyComponent_Impl.hxx.rej
$ 


Components created in Fortran, C, and Python will contain similar files in the respective language. In the components directory a new directory, myProject.emptyComponent, has been created to hold your component. And inside there is the code already generated for the component (again continuing with LANG = cxx) in the files: myProject_emptyComponent_Impl.cxx, myProject_emptyComponent_Impl.hxx with some Babel glue code in the glue subdirectory. Note the file ending in .rej named myProject_emptyComponent_Impl.hxx.rej. This file produced by the bocca splicing process. It records code fragments that bocca discarded while generating myProject_emptyComponent_Impl.hxx and can usually be ignored and even deleted.

In order to have some exportable or importable functionality in a component we must have some uses and provides ports. Bocca will also create the scaffolding and code for ports. Just as in the pre-built application of Chapter 2, Assembling and Running a CCA Application we will want to create a Function, an Integrator, and a Driver. Before we can do that we will have to create some ports for these components to use and provide. We wish to create a FunctionPort and an IntegratorPort:



$  bocca create port IntegratorPort




Updating makefiles (for myProject.IntegratorPort)...
$ 




$  bocca create port FunctionPort




Updating makefiles (for myProject.FunctionPort)...
$ 


Notice that we have opted for the default package myProject that is created for us transparently for all components and ports unless otherwise specified. Now, create a set of components similar to those that you used in Chapter 2, Assembling and Running a CCA Application, specifying that they will provide or use the appropriate ports:




$  bocca create component Function --provides=FunctionPort:thisFunction




Updating the cxx implementation of component myProject.Function ...
$ 




$  bocca create component Integrator --provides=IntegratorPort:integrate \
    --uses=FunctionPort:integrateThis




$ 




$  bocca create component Driver --uses=IntegratorPort:integrate \
    --go=run





$ 


This last bocca create decorates our component with a CCA standard GoPort, which is not specified as part of this project. Since gov.cca.ports.GoPort is a part of the CCA specification, bocca takes care of knowing where to find the SIDL definition of this port. The special --go option allows bocca to generate a default go implementation which prefetches the uses ports so that all the user needs to do for our example is add numerical code. In languages which are not object-oriented, this substantially reduces the errors in handling ports, exceptions, and memory deallocation.

[Note] Note

It is not necessary to know at component creation time all ports that will be used or provided or other implementation details. Bocca provides various commands for changing project entities, e.g., adding or removing uses and provides ports.

As we have defined a number of new things, make would be a good thing to do now:



$   make





# =======================================================================
# No SIDL files in external/sidl, skipping build for external
# =======================================================================

# =======================================================================
# Building in ports/, languages: cxx
# =======================================================================
## Building ports...

[c] using Babel to generate cxx client code for myProject.FunctionPort...
[c] creating library: libmyProject.FunctionPort-cxx.la...
[c] using Babel to generate cxx client code for myProject.IntegratorPort...
[c] creating library: libmyProject.IntegratorPort-cxx.la...
# =======================================================================
# Building in components/clients/, languages: cxx
# =======================================================================
## Building clients...

# =======================================================================
# Building in components/, languages: cxx
# =======================================================================


[s] Building component myProject.Driver:
[s] using Babel to generate cxx implementation code from myProject.Driver.sidl...
[s] compiling sources...
[s] creating component library: libmyProject.Driver.la ...
[s] finished libtooling: components/myProject.Driver/libmyProject.Driver.la ...
[s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)...

[s] Building component myProject.Function:
[s] using Babel to generate cxx implementation code from myProject.Function.sidl...
[s] compiling sources...
[s] creating component library: libmyProject.Function.la ...
[s] finished libtooling: components/myProject.Function/libmyProject.Function.la ...
[s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)...

[s] Building component myProject.Integrator:
[s] using Babel to generate cxx implementation code from myProject.Integrator.sidl...
[s] compiling sources...
[s] creating component library: libmyProject.Integrator.la ...
[s] finished libtooling: components/myProject.Integrator/libmyProject.Integrator.la ...
[s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)...

[s] Building component myProject.emptyComponent: doing nothing -- library is up-to-date.

Build summary:
SUCCESS building myProject.Driver
SUCCESS building myProject.Function
SUCCESS building myProject.Integrator

### To test instantiation of successfully built components, run 'make check' ###

################ Finished building everything #################
####### You can run some simple tests with 'make check' #######

$ 



Note that this operation can be very time-consuming when your project is managing many ports and components with the fully supported set of Babel language bindings.

Running make check will test whether the components you've created can be instantiated successfully in the Ccaffeine framework:



$  make check




make --no-print-directory --no-builtin-rules -C components check

### Test library load and instantiation for the following languages: cxx
Running instantiation tests only
Test script: /data/user1/myProject/components/tests/instantiation.gen.rc
SUCCESS:
==> Instantiation tests passed for all built components (see /data/user1/myProject/components/tests/instantiation.gen.rc.log).
make --no-print-directory --no-builtin-rules check-user
$ 



If you were to run the GUI (Section 2.1, “Using the GUI Front-End to Ccaffeine”) or do the command-line equivalent in Ccaffeine (Section 2.2, “Running Ccaffeine Using an rc File”), you would find that the components are decorated with the ports you expect, and they can even be connected (an operation of the framework, not of the components or the ports being connected). But of course they have not yet been implemented, so attempting to run an application with these components would cause it to do nothing.