autotools-idl examples
Download


Common setup
Example1 - a single IDL file
Example2 - two IDL files
Example3 - two IDL files in different directories without subdir-objects
Example4 - two IDL files in different directories with subdir-objects
Example5 - mixed targets (generated and custom written source files)
Example6 - multi-ORB builds
Example7 - without automake (autoconf only)
Example8 - customization of the names of the generated source files
Example9 - customization of the names of the generated source files without automake
Example10 - package-wide restriction of supported ORBs





Common setup

  1. Install autoconf-orb.
  2. Install automake-idl.
  3. All of the examples have configure.ac and Makefile.am. Initially, you should run the following command in the root directory:

  4. ./autogen.sh

    or just run the following command in the directory of a subsequently modified example:

      autoreconf

  5. All of the examples (except example6) have almost the same configure.ac:

  6. AC_INIT([autotools-idl-examples],[1])
    AM_INIT_AUTOMAKE(foreign)
    AC_CONFIG_HEADERS(config.h)

    AC_PROG_CC
    AM_PROG_CC_C_O
    AC_PROG_CXX
    AC_PROG_RANLIB
    AI_CHECK_ORB
    if test "x$ORB" = "xno"
    then
        AC_MSG_ERROR([an ORB is required])
    fi

    AC_CONFIG_FILES([Makefile])
    AC_OUTPUT

  7. All Makefile.ams should contain the following lines in the beginning (these will be omitted for brevity from now on):

    AM_CFLAGS = $(ORB_CFLAGS)
    AM_CXXFLAGS = $(ORB_CXXFLAGS)
    AM_CPPFLAGS = $(ORB_CPPFLAGS)
    AM_LDFLAGS = $(ORB_LDFLAGS)
    LDADD = $(ORB_LIBS)

    You may also add the various $ORB_* variables only to specific targets, instead. But in case your Makefile.am doesn't contain targets which have nothing to do with the ORB, this is the recommended approach. Including a generated by the IDL compiler header or linking to a stub/skeleton object definitely has something to do with the ORB.
    Note that if you have a target-specific $*_LDADD variable, automake will not add $LDADD to it. You should do it yourself. See example5 and example6.




Example1

Create a single IDL file called Simple.idl. Now we want all the client-side objects in a library libsimple_client.a, and all the server-side objects in libsimple_server.a.
Here is the needed Makefile.am:

noinst_LIBRARIES = libsimple_client.a libsimple_server.a

libsimple_client_a_SOURCES = Simple.idl
nodist_libsimple_client_a_SOURCES = Simple.cpp

libsimple_server_a_SOURCES = Simple.idl
nodist_libsimple_server_a_SOURCES = SimpleServer.cpp

Note:
1. Every target which contains an object of an IDL-generated source should contain the corresponding IDL file in its _SOURCES variable.
2. You should put the needed generated C++ sources in the target's nodist_..._SOURCES variable. Distributing IDL-generated sources is pointless, since different ORB's IDL compilers generate incompatible sources.

Things to try:
1. Well, build it:

autoreconf -i
./configure
make

2. Try different standard automake targets, like clean, distclean, dist, etc.
3. Try different configure options (specifying a different ORB, etc).
4. See what goes in config.h (as a result of using the autoconf-orb macros).





Example2

Create another IDL file called Complex.idl. Make it include Simple.idl.
Here is the needed Makefile.am:

noinst_LIBRARIES = libsimple_client.a libsimple_server.a

libsimple_client_a_SOURCES = Complex.idl Simple.idl
nodist_libsimple_client_a_SOURCES = Complex.cpp Simple.cpp

libsimple_server_a_SOURCES = Complex.idl Simple.idl
nodist_libsimple_server_a_SOURCES = ComplexServer.cpp SimpleServer.cpp

Things to try:
1. Build it, then touch Simple.idl and rebuild. See what is being rebuilt.
2. Build it, then touch Complex.idl and rebuild. See what is being rebuilt.
3. Change the order of the IDL and C++ files in Makefile.am at will. The build shouldn't depend on this order.
4. Try a build without automatic dependencies tracking.





Example3

Move Simple.idl to a subdirectory called sub. Change Complex.idl to include it from there. Don't use automake's subdir-objects option.
Here is the needed Makefile.am:

noinst_LIBRARIES = libsimple_client.a libsimple_server.a

libsimple_client_a_SOURCES = Complex.idl sub/Simple.idl
nodist_libsimple_client_a_SOURCES = Complex.cpp Simple.cpp

libsimple_server_a_SOURCES = Complex.idl sub/Simple.idl
nodist_libsimple_server_a_SOURCES = ComplexServer.cpp SimpleServer.cpp

Note:
1. Only Simple.idl should be specified being in the subdirectory. The generated C++ source files (which are actually objects for the IDL compiler) will be built in the main directory because subdir-objects was not used.





Example4

The same as the previous example, but now with subdir-objects specified.
Here is the needed Makefile.am:

AUTOMAKE_OPTIONS = subdir-objects

AM_CPPFLAGS += -Isub

noinst_LIBRARIES = libsimple_client.a libsimple_server.a

libsimple_client_a_SOURCES = Complex.idl sub/Simple.idl
nodist_libsimple_client_a_SOURCES = Complex.cpp sub/Simple.cpp

libsimple_server_a_SOURCES = Complex.idl sub/Simple.idl
nodist_libsimple_server_a_SOURCES = ComplexServer.cpp sub/SimpleServer.cpp

Note:
1. Now the generated C++ source files are in the subdirectory, too.
2. Since automake-idl guarantees that the generated sources always include the generated headers without a path, you should manually add sub to the C++ compiler include directories. Otherwise the C++ build will fail.





Example5

This example shows how to arrange Makefile.am for mixed targets (which contain generated and custom written source files (e.g. servant implementations)). Let's write an implementation for the Simple interface. It will be contained in Simple_i.hpp and Simple_i.cpp. The main() function will be contained in SimpleMain.cpp. The resulting executable will be named simple_server. The C++ source for this example is not discussed here because it requires only general CORBA knowledge.
The first which comes to mind is to write Makefile.am like this:

bin_PROGRAMS = simple_server

simple_server_SOURCES = Simple.idl Simple_i.hpp Simple_i.cpp SimpleMain.cpp
nodist_simple_server_SOURCES = SimpleServer.hpp SimpleServer.cpp

The build will be unsuccessful, because make will (or least might) try to compile Simple_i.cpp first. Simple_i.cpp includes Simple_i.hpp. Simple_i.hpp includes SimpleServer.hpp which does not exist at this time. But because the dependencies are computed as a side effect of the compilation, make still doesn't know that SimpleServer.hpp must be built first (the compilation of Simple.idl).
The most obvious solution to this problem is to use BUILT_SOURCES (see http://www.gnu.org/software/automake/manual/html_node/Built-sources-example.html). But this will work only for the all, check, and install targets. A better solution is to state the dependency of the hand-written source files on the generated ones (pay attention to the last line):

simple_server_idl_sources = Simple.idl
simple_server_idl_generated_sources = SimpleServer.hpp SimpleServer.cpp
simple_server_non_idl_sources = Simple_i.hpp Simple_i.cpp SimpleMain.cpp

bin_PROGRAMS = simple_server

simple_server_SOURCES = $(simple_server_idl_sources) $(simple_server_non_idl_sources)
nodist_simple_server_SOURCES = $(simple_server_idl_generated_sources)
$(simple_server_non_idl_sources): $(simple_server_idl_generated_sources)


This way the example will work in most cases with one known exception: FreeBSD/OpenBSD make and a build in a separate directory. This is not an autotools-idl issue and is described in this page from the autoconf manual. In order to work around this peculiarity of FreeBSD/OpenBSD make we must not state any explicit dependencies for hand-written source files (which is done with the last line). Even though it is these source files which directly depend on the generated ones, we can state the dependency for their object files. The drawback is that the resulting Makefile.am will have one more variable to be maintained manually. Here is the final version:

simple_server_idl_sources = Simple.idl
simple_server_idl_generated_sources = SimpleServer.hpp SimpleServer.cpp
simple_server_non_idl_sources = Simple_i.hpp Simple_i.cpp SimpleMain.cpp
simple_server_non_idl_objects = Simple_i.$(OBJEXT) SimpleMain.$(OBJEXT)

bin_PROGRAMS = simple_server

simple_server_SOURCES = $(simple_server_idl_sources) $(simple_server_non_idl_sources)
nodist_simple_server_SOURCES = $(simple_server_idl_generated_sources)
$(simple_server_non_idl_objects): $(simple_server_idl_generated_sources)





Example6

This example shows how to build the executables from example5 for multiple ORBs with a single ./configure && make step. Since a single configure script can detect only one IDL compiler (this is not an autotools-idl limitation - e.g. the same is true for the C and C++ compilers), the build for different ORBs must be made with one subpackage per supported ORB (each having its own configure script). Let's put all the non-generated sources in the top package directory and have a subdirectory per supported ORB (omniORB_build, TAO_build, etc). An ORB-related subpackage does not contain any real program sources - it will contain only configure.ac and Makefile.am which perform the build for the specific ORB only.
Here is the top configure.ac:

AC_INIT([autotools-idl-examples],[6])
AM_INIT_AUTOMAKE(foreign)

AC_CONFIG_SUBDIRS(omniORB_build TAO_build ...)

AI_ORB_ARGS

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

AI_ORB_ARGS is used to include the --with and --enable command-line options in the output of configure --help. These options have meanings only to the ORB-specific subpackages and are present here only to be passed down to their configure scripts. The AC_CONFIG_SUBDIRS macro tells autoconf that it must descend in every one of the argument directories and rerun itself with the configure.ac found there. Later, the top configure would call the subdirectories' configures, too.

Here is the (pretty simple) top Makefile.am:

SUBDIRS = omniORB_build TAO_build ...

Let's see what happens in an ORB-specific subpackage's subdirectory (omniORB_build will be used for the explanations):
Here is the omniORB's configure.ac:

AC_INIT([autotools-idl-examples-omniORB],[6])
AM_INIT_AUTOMAKE(foreign)
AC_CONFIG_HEADERS(config.h)

AC_PROG_CC
AC_PROG_CXX
AM_PROG_CC_C_O

AI_CHECK_ORB([], [omniORB])
AM_CONDITIONAL(OMNIORB, test "x$OMNIORB" = "xyes")


AC_CONFIG_FILES([Makefile])
AC_OUTPUT

AI_CHECK_ORB([], [omniORB]) means that omniORB will be tried unless the --disable-omniorb option is given to this configure script explicitly (via the top configure script). If you want to achieve the opposite (do no try to detect omniORB unless an explicit --enable-omniorb option is given) then you may use the following macro call:
AI_CHECK_ORB([dummy], [omniORB])

The OMNIORB conditional is used to instruct automake to generate an almost no-op Makefile in case omniORB is not found or not desired by the user at all. However, note that Makefile is always produced, and make always descends to all the ORB-specific subdirectories - while this may seem meaningless with most of the targets (e.g. all, install) it is needed for the non-build-related targets like dist.

Here is the omniORB's Makefile.am:

AM_CPPFLAGS += -I.
AM_IDLCPPFLAGS = -I..


if OMNIORB

simple_server_idl_sources = ../Simple.idl
simple_server_idl_generated_sources = SimpleServer.hpp SimpleServer.cpp
simple_server_non_idl_sources = ../Simple_i.hpp ../Simple_i.cpp ../SimpleMain.cpp

bin_PROGRAMS = simple_server_omniORB

simple_server_omniORB_SOURCES = $(simple_server_idl_sources) $(simple_server_non_idl_sources)
nodist_simple_server_omniORB_SOURCES = $(simple_server_idl_generated_sources)
$(simple_server_non_idl_sources): $(simple_server_idl_generated_sources)

endif

Notice that subdir-objects should not be used - we want the generated sources here but not in the subdirectory of the IDL source file (.. in this case).
Remember that make always descends in every ORB-specific subdirectory. It should not produce any errors in case omniORB's version of our package should not be built. That's why the build-related targets are enclosed in the OMNIORB conditional so that make has nothing to do in case omniORB is not detected or not desired by the user.
The build-related targets are almost the same as in example5 with two exclusions:
1. The real sources are prefixed with ../ .
2. The resulting executable is suffixed by _omniORB so that it would not overwrite the executables for other ORBs if installed with the install target.

One final note: it is generally a bad idea to name MICO's build directory "mico" or even "MICO". If you do this, and add -I.. to the includes in the MICO-specific build directory, then #include <mico/config.h> (which is used in MICO's headers) might happen to include your config.h, and not MICO's one. This will make the compilation fail.





Example7

This example demonstrates how to use autoconf-orb without automake-idl. This might be needed for legacy build systems which cannot be converted to automake, or in case automake is simply undesirable. The main difference with example5 is that it doesn't have a Makefile.am, but a very simplified Makefile.in, so it won't be described in detail. Note that you need to provide idlfix yourself (autoreconf won't do it for you).





Example8

This is example5 with demonstration of how the names of the generated source files can be customized. The following variables' initializations from Makefile.am:

IDL_HEADER_EXT = hh

IDL_SOURCE_EXT = cc
IDL_CLIENT_SUFFIX = Stub
IDL_SERVER_SUFFIX = Skeleton

specify that the generated source files for Simple.idl will be:

SimpleStub.hh

SimpleSkeleton.hh
SimpleStub.cc
SimpleSkeleton.cc

Next, all the references to a generated source file must be changed (both in Makefile.am and the impementation sources):

Simple.hpp
-> SimpleStub.hh
SimpleServer.hpp -> SimpleSkeleton.hh
Simple.cpp -> SimpleStub.cc
SimpleServer.cpp -> SimpleSkeleton.cc





Example9

This is example7 with demonstration of how the names of the generated source files can be customized. The differences between this example and example7 in principal are the same as the differences between example8 and example5 with one addition:

The Makefile.in variable $(IDLCXXFLAGS_P) must be used instead of $(IDLCXXFLAGS).





Example10

This is example1 with demonstration of how to use package-wide restriction of supported ORBs. The only difference is the call to AI_CHECK_ORB:

AI_CHECK_ORB([MICO omniORB], [omniORB TAO MICO orbitcpp])

Here are some examples of what configure would do depending on its parameters:
configure parameters
Tried ORBs in this order
Comment

MICO omniORB
If the user does not express any special preferences then only the developer-preferred ORBs are tried in the specified order.
--disable-mico
omniORB
The ORBs which are explicitly disabled by the user are not tried, even if they are preferred by the developer.
--enable-orbitcpp --enable-tao
TAO orbitcpp
Only the ORBs which are explicitly enabled by the user are tried, even if they are not preferred by the developer. The order cannot be specified.
--enable-orbix --disable-tuxedo
MICO omniORB The options for unallowed ORBs are ignored.