next up previous contents index
Next: Writing the Fortran 90 Implementation Up: Minimal Makefiles: static linked Previous: Minimal Makefiles: static linked   Contents   Index


Writing the C++ Implementation

We will write the C++ implementation in the minimal/libCxx/ subdirectory of hello/. The first step is to run the Babel code generator on the SIDL file and have it generate the appropriate code. The simplified command to generate the Babel library code (assuming Babel is in your PATH) is 5.1:

% cd minimal/libCxx
% babel -sC++ ../../hello.sidl

In this Babel command, the ``-sC++'' flag, or its long form ``-server=C++'', indicates that we wish to generate C++ bindings for an implementation5.2. This command will generate a large number of C and C++ header and source files. It is often surprising to newcomers just how much code is generated by Babel. Rest assured, each file has a purpose and there is a lot of important things being done as efficiently as possible under the hood.

Files are named after the fully-qualified class-name. For instance, a package Hello and class World would have a fully qualified name (in SIDL) as Hello.World. This corresponds to file names beginning with Hello_World5.3. For each class, there will be files with _IOR, _Skel, or _Impl appended after the fully qualified name. Stubs often go without the _Stub suffix. IOR files are always in ANSI C (source and headers), containing Babel's Intermediate Object Representation. Impl files contain the actual implementation, and can be in any language that Babel supports, in this case, they're C++ files. Impl files are the only files that a developer need look at or touch after generating code from the SIDL source. Skel files perform translations between the IORs and the Impls. In some cases (like Fortran) the Skels are split into a few files: some in C, some in the Impl language. In the case of C++, the Skels are pure C++ code wrapped in extern "C" {} declarations. If the file is neither an IOR, Skel, nor Impl, then it is likely a Stub. Stubs are the proxy classes of Babel, performing translations between the caller language and the IOR. Finally, the file babel.make is a Makefile fragment that will simplify writing the Makefile necessary to compile the library. You may ignore the babel.make file if you wish. There are also babel.make.depends and babel.make.package files. These were added by external contributors, and we will ignore them in thid document.

The only files that should be modified by the developer (that's you since you're implementing Hello World) are the ``Impls'', which are in this case files ending with _Impl.hxx or _Impl.cxx Babel generates these implementation files as a starting point for developers. These files will contain the implementation of the Hello library. Every implementation file contains many pairs of comment ``splicer'' lines such lines 4 and 6 in the following sample:


   1 ::std::string
   2 Hello::World_impl::getMsg_impl () 
   3 {
   4   // DO-NOT-DELETE splicer.begin(Hello.World.getMsg)
   5   // Insert-Code-Here {Hello.World.getMsg} (getMsg method)
   6   // DO-NOT-DELETE splicer.end(Hello.World.getMsg)
   7 }

Any modifications between these splicer lines will be saved after subsequent invocations of the Babel tool. Any changes outside the splicer lines will be lost. This splicer feature was developed to make it easy to do incremental development using Babel. By keeping your edits within the splicer blocks, you can add new methods to the hello.sidl file and rerun Babel without the loss of your previous method implementations. You shouldn't ever need to edit the file outside the splicer blocks.

For our hello application, the implementation is trivial. Add the following return statement between the splicer lines in the lib/Hello_World_Impl.cxx file:


::std::string
Hello::World_impl::getMsg_impl () 
{
  // DO-NOT-DELETE splicer.begin(Hello.World.getMsg)
  return "Hello from C++!";
  // DO-NOT-DELETE splicer.end(Hello.World.getMsg)
}

To keep the Makefile minimal, the GNU gcc and g++ compilers are hard coded into this example. Put the following Makefile in the minimal/libCxx subdirectory to compile the files and create a linked library named libhello.a:

NOTE:Static libraries will limit us to compiled languages (e.g. C/C++ & Fortran). To use compiled implementations in more dynamic languages like Java and Python, they must be built as dynamic loaded libraries (a.k.a. run-time linking in some circles). Building these kinds of libraries is harder and often misunderstood, so we will postpone them until later.


   1 # A minimal makefile for a C++ Babel Impl.
   2 # Assumes babel-config is in the current path.
   3 # Assumes babel -sC++ ../../hello.sidl has already run.
   4 
   5 include babel.make
   6 
   7 OBJS = $(IMPLSRCS:.cxx=.o) $(IORSRCS:.c=.o) \
   8         $(SKELSRCS:.cxx=.o) $(STUBSRCS:.cxx=.o)
   9 
  10 all: libhello.a
  11 
  12 .SUFFIXES: 
  13 .SUFFIXES: .cxx .c .o
  14 .cxx.o:
  15 	g++ `babel-config --includes-c++` -c $<
  16 .c.o:
  17 	gcc `babel-config --includes-c++` -c $< 
  18 
  19 libhello.a: $(OBJS)
  20 	ar cru $@ $(OBJS) 
  21 	ranlib $@
  22 
  23 .PHONY: clean new
  24 
  25 clean:
  26 	$(RM) *.o babel.make.depends babel.make.package *~
  27 
  28 new: clean
  29 	$(RM) $(IORHDRS) $(IORSRCS) $(SKELSRCS) $(STUBHDRS) \
  30 	$(STUBSRCS) libhello.a

The details of this makefile deserve careful explanation.

line 5:
babel.make is a file that Babel generates when it generates code. It defines some standard names so our makefiles don't have to know every SIDL type declared in the file.
lines 7-8:
Here you see some of the variables defined in babel.make and some fancy suffix substitution so that the makefile variable $(OBJS) is a list of all .o files.
line 10:
The first build target in a Makefile is also the default target. Common convention is to make this target's name ``all.''
line 12-17:
Here we start to override make's default suffix rules for converting C and C++ sourcecode into .o files.
line 12:
This is a often misunderstood detail. To override the default suffix rules, one must give the list of new suffices to consider. But before that, one must wipe out the old suffices as we do here.
lines 15 & 17:
Note that we use a script called babel-config to hand us some information. This tool is very useful for getting the same information that Babel's configure script was given as Babel configuring itself. Increasingly, it is being used to also get information about tools and flags used in Babel's makefiles, and its utility for getting at this level of information is limited...mostly because we rely on a multilayered stack of tools and some are less forthcoming than others.
lines 19-21:
This is the rule to combine the .o files into a static library.
line 23:
Technically, any phony targets like ``clean'' and ``new'' are supposed to be listed in this variable. Many makefile implementations will work well if you skip this line, but.
lines 25-29:
How you go about various levels of cleanliness in your makefiles largely depends on matters of taste. The important point here is what is not removed. One thing not cleaned up is babel.make it is generated by Babel, but the makefile won't work without the file present because of the include in line 5. Another important thing to not remove is the Impl files, since they have hand-edited regions in the generated file.

With the makefile in place we can simply go to that directory and build everything by typing make.


next up previous contents index
Next: Writing the Fortran 90 Implementation Up: Minimal Makefiles: static linked Previous: Minimal Makefiles: static linked   Contents   Index


babel-0.99.0
users_guide Last Modified 2006-06-27

http://www.llnl.gov/CASC/components
components@llnl.gov