autotools-idl examples
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
- Install autoconf-orb.
- Install automake-idl.
- All of the examples have configure.ac
and Makefile.am.
Initially, you should run the following command in the root
directory:
./autogen.sh
or just run the following command in the directory of a subsequently
modified
example:
autoreconf
- All of the examples (except example6)
have almost the same configure.ac:
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
- 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.
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).
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.
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.
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.
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)
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.
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).
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
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).
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.
|