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++ -makefile ../../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 is used by GNUmakefile or to simplify making your own custom build. 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 this 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)
}

The following is a listing of the generated GNUmakefile excluding the boilerplate copyright notice. It uses some of the tools installed along with Babel to automated generating a static and shared library provided that the machine supports both. The babel-config provides information about which compilers and compiler flags to use, and babel-libtool manages the building of object files and libraries.


   1 include babel.make
   2 # please name the server library here
   3 LIBNAME=hello
   4 # please name the SIDL file here
   5 SIDLFILE=../../hello.sidl
   6 # extra include/compile flags 
   7 EXTRAFLAGS=
   8 # extra librarys that the implementation needs to link against
   9 EXTRALIBS=
  10 # library version number
  11 VERSION=0.1.1
  12 # PREFIX specifies the top of the installation directory
  13 PREFIX=/usr/local
  14 # the default installation installs the .la and .scl (if any) into the
  15 # LIBDIR
  16 LIBDIR=$(PREFIX)/lib
  17 # the default installation installs the stub header and IOR header files
  18 # in INCLDIR
  19 INCLDIR=$(PREFIX)/include
  20 
  21 # most of the rest of the file should not require editing
  22 
  23 ifeq ($(IMPLSRCS),)
  24   SCLFILE=
  25   BABELFLAG=--client=cxx
  26   MODFLAG=
  27 else
  28   SCLFILE=lib$(LIBNAME).scl
  29   BABELFLAG=--server=cxx
  30   MODFLAG=-module
  31 endif
  32 
  33 all : lib$(LIBNAME).la $(SCLFILE)
  34 
  35 CC=`babel-config --query-var=CC`
  36 CXX=`babel-config --query-var=CXX`
  37 INCLUDES=`babel-config --includes-cxx`
  38 CFLAGS=`babel-config --flags-c`
  39 CXXFLAGS=`babel-config --flags-cxx`
  40 LIBS=`babel-config --libs-cxx-client`
  41 
  42 STUBOBJS=$(STUBSRCS:.cxx=.lo)
  43 IOROBJS=$(IORSRCS:.c=.lo)
  44 SKELOBJS=$(SKELSRCS:.cxx=.lo)
  45 IMPLOBJS=$(IMPLSRCS:.cxx=.lo)
  46 
  47 PUREBABELGEN=$(IORHDRS) $(IORSRCS) $(STUBSRCS) $(STUBHDRS) $(SKELSRCS)
  48 BABELGEN=$(IMPLHDRS) $(IMPLSRCS)
  49 
  50 $(IMPLOBJS) : $(STUBHDRS) $(IORHDRS) $(IMPLHDRS)
  51 
  52 lib$(LIBNAME).la : $(STUBOBJS) $(IOROBJS) $(IMPLOBJS) $(SKELOBJS)
  53 	babel-libtool --mode=link --tag=CXX $(CXX) -o lib$(LIBNAME).la \
  54 	  -rpath $(LIBDIR) -release $(VERSION) \
  55 	  -no-undefined $(MODFLAG) \
  56 	  $(CXXFLAGS) $(EXTRAFLAGS) $^ $(LIBS) \
  57 	  $(EXTRALIBS)
  58 
  59 $(PUREBABELGEN) $(BABELGEN) : babel-stamp
  60 	@if test -f $@; then \
  61 	    touch $@; \
  62 	else \
  63 	    rm -f babel-stamp ; \
  64 	    $(MAKE) babel-stamp; \
  65 	fi
  66 
  67 babel-stamp: $(SIDLFILE)
  68 	@rm -f babel-temp
  69 	@touch babel-temp
  70 	babel $(BABELFLAG) $(SIDLFILE) 
  71 	@mv -f babel-temp $@
  72 
  73 lib$(LIBNAME).scl : $(IORSRCS)
  74 ifeq ($(IORSRCS),)
  75 	echo "lib$(LIBNAME).scl is not needed for client-side C bindings."
  76 else
  77 	-rm -f $@
  78 	echo '<?xml version="1.0" ?>' > $@
  79 	echo '<scl>' >> $@	
  80 	if test `uname` = "Darwin"; then scope="global"; else scope="local"; \
  81 	   fi ; \
  82           echo ' <library uri="'`pwd`/lib$(LIBNAME).la'" scope="'"$$scope"'" resolution="lazy" >' >> $@
  83 	grep __set_epv $^ /dev/null | awk 'BEGIN {FS=":"} { print $$1}' | sort -u | sed -e 's/_IOR.c//g' -e 's/_/./g' | awk ' { printf "    <class name=\"%s\" desc=\"ior/impl\" />\n", $$1 }' >>$@
  84 	echo "  </library>" >>$@
  85 	echo "</scl>" >>$@
  86 endif
  87 
  88 .SUFFIXES: .lo .cxx .c
  89 
  90 .c.lo:
  91 	babel-libtool --mode=compile --tag=CC $(CC) $(INCLUDES) $(CFLAGS) $(EXTRAFLAGS) -c -o $@ $<
  92 
  93 .cxx.lo:
  94 	babel-libtool --mode=compile --tag=CXX $(CXX) $(INCLUDES) $(CXXFLAGS) $(EXTRAFLAGS) -c -o $@ $<
  95 
  96 clean : 
  97 	-rm -f $(PUREBABELGEN) babel-temp babel-stamp *.o *.lo
  98 
  99 realclean : clean
 100 	-rm -f lib$(LIBNAME).la lib$(LIBNAME).scl
 101 	-rm -rf .libs
 102 
 103 install : install-libs install-headers install-scl
 104 
 105 
 106 install-libs : lib$(LIBNAME).la
 107 	-mkdir -p $(LIBDIR)
 108 	babel-libtool --mode=install install -c lib$(LIBNAME).la \
 109 	  $(LIBDIR)/lib$(LIBNAME).la
 110 
 111 install-scl : $(SCLFILE)
 112 ifneq ($(IORSRCS),)
 113 	-rm -f $(LIBDIR)/lib$(LIBNAME).scl
 114 	-mkdir -p $(LIBDIR)
 115 	echo '<?xml version="1.0" ?>' > $(LIBDIR)/lib$(LIBNAME).scl
 116 	echo '<scl>' >> $(LIBDIR)/lib$(LIBNAME).scl	
 117 	if test `uname` = "Darwin"; then scope="global"; else scope="local"; \
 118 	   fi ; \
 119           echo ' <library uri="'$(LIBDIR)/lib$(LIBNAME).la'" scope="'"$$scope"'" resolution="lazy" >' >> $(LIBDIR)/lib$(LIBNAME).scl
 120 	grep __set_epv $^ /dev/null | awk 'BEGIN {FS=":"} { print $$1}' | sort -u | sed -e 's/_IOR.c//g' -e 's/_/./g' | awk ' { printf "    <class name=\"%s\" desc=\"ior/impl\" />\n", $$1 }' >>$(LIBDIR)/lib$(LIBNAME).scl
 121 	echo "  </library>" >>$(LIBDIR)/lib$(LIBNAME).scl
 122 	echo "</scl>" >>$(LIBDIR)/lib$(LIBNAME).scl
 123 endif
 124 
 125 install-headers : $(IORHDRS) $(STUBHDRS)
 126 	-mkdir -p $(INCLDIR)
 127 	for i in $^ ; do \
 128 	  babel-libtool --mode=install cp $$i $(INCLDIR)/$$i ; \
 129 	done
 130 
 131 .PHONY: all clean realclean install install-libs install-headers install-scl

The details of this makefile deserve careful explanation.

line 1:
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.
line 3:
LIBNAME defines the name of the library file that will be generated. This is the only line that I had to edit in the babel-generated GNUmakefile.
line 7:
Use EXTRAFLAGS to define additional compile flags to be used when compiling files. For this example, it should be empty.
line 9:
EXTRALIBS should hold any extra libraries needed for your application. For this example, it should be empty.
line 11:
The VERSION should be three numbers separated by periods.
line 13:
The PREFIX is for libraries that will be installed.
line 21-end:
This part of the GNUmakefile works from the definitions above and usually does not require changes unless you are incorporating it into a more complex build system.
line 33:
The first build target in a Makefile is also the default target. Common convention is to make this target's name ``all.''
lines 35-40:
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 42-45:
Here you see some of the variables defined in babel.make and some fancy suffix substitution to define STUBOBJS, IOROBJS, SKELOBJS, and IMPLOBJS.
lines 53:
This is the rule to combine the .o files into a static and dynamic library using babel-libtool.
line 88:
This is a often misunderstood detail. To override the default suffix rules, one must give the list of new suffices to consider.
line 90-94:
Here we start to override make's default suffix rules for converting C and C++ sourcecode into .o files.
lines 96 & 99:
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.
line 103-129:
Here we define some simple rules for installing libraries into standard system locations.
line 131:
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.

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



babel-1.4.0
users_guide Last Modified 2008-10-16

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