1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<META name="GENERATOR" content="hevea 1.10">
<LINK rel="stylesheet" type="text/css" href="omniORB.css">
<TITLE>The IDL compiler</TITLE>
</HEAD>
<BODY >
<A HREF="omniORB004.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
<A HREF="omniORB006.html"><IMG SRC="next_motif.gif" ALT="Next"></A>
<HR>
<H1 CLASS="chapter"><A NAME="htoc64">Chapter 5</A>  The IDL compiler</H1><P>
<A NAME="chap:omniidl"></A></P><P>omniORB’s IDL compiler is called omniidl. It consists of a generic
front-end parser written in C++, and a number of back-ends written in
Python. omniidl is very strict about IDL validity, so you may find
that it reports errors in IDL which compiles fine with other IDL
compilers.</P><P>The general form of an omniidl command line is:</P><BLOCKQUOTE CLASS="quote"> <TT>omniidl </TT>[<I>options</I>]<TT> -b</TT><<I>back-end</I>><TT> </TT>[<I>back-end options</I>]<TT> </TT><<I>file 1</I>><TT> </TT><<I>file 2</I>><TT> </TT>…</BLOCKQUOTE><H2 CLASS="section"><A NAME="toc27"></A><A NAME="htoc65">5.1</A>  Common options</H2><P>The following options are common to all back-ends:</P><TABLE border=0 cellspacing=0 cellpadding=0><TR><TD ALIGN=left NOWRAP></TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-b</TT><I>back-end</I></TD><TD ALIGN=left NOWRAP>Run the specified back-end. For the C++ ORB, use <TT>-bcxx</TT>.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-D</TT><I>name</I>[<TT>=</TT><I>value</I>]</TD><TD ALIGN=left NOWRAP>Define <I>name</I> for the preprocessor.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-U</TT><I>name</I></TD><TD ALIGN=left NOWRAP>Undefine <I>name</I> for the preprocessor.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-I</TT><I>dir</I></TD><TD ALIGN=left NOWRAP>Include <I>dir</I> in the preprocessor search path.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-E</TT></TD><TD ALIGN=left NOWRAP>Only run the preprocessor, sending its output to stdout.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Y</TT><I>cmd</I></TD><TD ALIGN=left NOWRAP>Use <I>cmd</I> as the preprocessor, rather than the normal C
preprocessor.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-N</TT></TD><TD ALIGN=left NOWRAP>Do not run the preprocessor.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-T</TT></TD><TD ALIGN=left NOWRAP>Use a temporary file, not a pipe, for preprocessor output.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wp</TT><I>arg</I>[,<I>arg</I>…]</TD><TD ALIGN=left NOWRAP>Send arguments to the preprocessor.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wb</TT><I>arg</I>[,<I>arg</I>…]</TD><TD ALIGN=left NOWRAP>Send arguments to the back-end.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-nf</TT></TD><TD ALIGN=left NOWRAP>Do not warn about unresolved forward declarations.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-k</TT></TD><TD ALIGN=left NOWRAP>Keep comments after declarations, to be used by some back-ends.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-K</TT></TD><TD ALIGN=left NOWRAP>Keep comments before declarations, to be used by some back-ends.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-C</TT><I>dir</I></TD><TD ALIGN=left NOWRAP>Change directory to <I>dir</I> before writing output files.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-d</TT></TD><TD ALIGN=left NOWRAP>Dump the parsed IDL then exit, without running a back-end.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-p</TT><I>dir</I></TD><TD ALIGN=left NOWRAP>Use <I>dir</I> as a path to find omniidl back-ends.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-V</TT></TD><TD ALIGN=left NOWRAP>Print version information then exit.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-u</TT></TD><TD ALIGN=left NOWRAP>Print usage information.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-v</TT></TD><TD ALIGN=left NOWRAP>Verbose: trace compilation stages.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
</TD></TR>
</TABLE><P>Most of these options are self explanatory, but some are not
so obvious.</P><H3 CLASS="subsection"><A NAME="htoc66">5.1.1</A>  Preprocessor interactions</H3><P>IDL is processed by the C preprocessor before omniidl parses it.
omniidl always uses the GNU C preprocessor (which it builds with the
name omnicpp). The <TT>-D</TT>, <TT>-U</TT>, and <TT>-I</TT>
options are just sent to the preprocessor. Note that the current
directory is not on the include search path by default—use
‘<TT>-I.</TT>’ for that. The <TT>-Y</TT> option can be used to
specify a different preprocessor to omnicpp. Beware that line
directives inserted by other preprocessors are likely to confuse
omniidl.</P><H4 CLASS="subsubsection"><A NAME="htoc67">5.1.1.1</A>  Windows 9x</H4><P>The output from the C preprocessor is normally fed to the omniidl
parser through a pipe. On some Windows 98 machines (but not all!) the
pipe does not work, and the preprocessor output is echoed to the
screen. When this happens, the omniidl parser sees an empty file, and
produces useless stub files with strange long names. To avoid the
problem, use the ‘<TT>-T</TT>’ option to create a temporary file
between the two stages.</P><H3 CLASS="subsection"><A NAME="htoc68">5.1.2</A>  Forward-declared interfaces</H3><P>If you have an IDL file like:</P><DIV CLASS="lstlisting"><B>interface</B> I;
<B>interface</B> J {
<B>attribute</B> I the_I;
};</DIV><P>then omniidl will normally issue a warning:</P><PRE CLASS="verbatim"> test.idl:1: Warning: Forward declared interface `I' was never
fully defined
</PRE><P>It is illegal to declare such IDL in isolation, but it
<EM>is</EM> valid to define interface <TT>I</TT> in a separate file. If
you have a lot of IDL with this sort of construct, you will drown
under the warning messages. Use the <TT>-nf</TT> option to suppress
them.</P><H3 CLASS="subsection"><A NAME="htoc69">5.1.3</A>  Comments</H3><P>By default, omniidl discards comments in the input IDL. However, with
the <TT>-k</TT> and <TT>-K</TT> options, it preserves the comments
for use by the back-ends. The C++ back-end ignores this information,
but it is relatively easy to write new back-ends which <EM>do</EM> make
use of comments.</P><P>The two different options relate to how comments are attached to
declarations within the IDL. Given IDL like:</P><DIV CLASS="lstlisting"><B>interface</B> I {
<B>void</B> op1();
<I>// A comment</I>
<B>void</B> op2();
};</DIV><P>the <TT>-k</TT> flag will attach the comment to <TT>op1()</TT>;
the <TT>-K</TT> flag will attach it to <TT>op2()</TT>.</P><H2 CLASS="section"><A NAME="toc28"></A><A NAME="htoc70">5.2</A>  C++ back-end options</H2><P>When you specify the C++ back-end (with <TT>-bcxx</TT>), the
following <TT>-Wb</TT> options are available. Note that the
<TT>-Wb</TT> options must be specified <EM>after</EM> the
<TT>-bcxx</TT> option, so omniidl knows which back-end to give the
arguments to.</P><TABLE border=0 cellspacing=0 cellpadding=0><TR><TD ALIGN=left NOWRAP></TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbh=</TT><I>suffix</I></TD><TD ALIGN=left NOWRAP>Use <I>suffix</I> for generated header files. Default
‘<TT>.hh</TT>’.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbs=</TT><I>suffix</I></TD><TD ALIGN=left NOWRAP>Use <I>suffix</I> for generated stub files. Default
‘<TT>SK.cc</TT>.’</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbd=</TT><I>suffix</I></TD><TD ALIGN=left NOWRAP>Use <I>suffix</I> for generated dynamic files. Default
‘<TT>DynSK.cc</TT>.’</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wba</TT></TD><TD ALIGN=left NOWRAP>Generate stubs for TypeCode and Any.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbinline</TT></TD><TD ALIGN=left NOWRAP>Output stubs for <TT>#include</TT>d IDL files in line with the
main file.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbtp</TT></TD><TD ALIGN=left NOWRAP>Generate ‘tie’ implementation skeletons.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbtf</TT></TD><TD ALIGN=left NOWRAP>Generate flattened ‘tie’ implementation skeletons.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbsplice-modules</TT></TD><TD ALIGN=left NOWRAP>Splice together multiply-opened modules into one.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbexample</TT></TD><TD ALIGN=left NOWRAP>Generate example implementation code.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-WbF</TT></TD><TD ALIGN=left NOWRAP>Generate code fragments (for experts only).</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-WbBOA</TT></TD><TD ALIGN=left NOWRAP>Generate BOA compatible skeletons.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbold</TT></TD><TD ALIGN=left NOWRAP>Generate old CORBA 2.1 signatures for skeletons.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbold_prefix</TT></TD><TD ALIGN=left NOWRAP>Map C++ reserved words with prefix ‘<TT>_</TT>’ rather than
‘<TT>_cxx_</TT>’.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbkeep_inc_path</TT></TD><TD ALIGN=left NOWRAP>Preserve IDL ‘<TT>#include</TT>’ paths in generated
‘<TT>#include</TT>’ directives.</TD></TR>
<TR><TD ALIGN=left NOWRAP>
<TT>-Wbuse_quotes</TT></TD><TD ALIGN=left NOWRAP>Use quotes in ‘<TT>#include</TT>’ directives
(e.g. <TT>"foo"</TT> rather than <TT><foo></TT>.)</TD></TR>
</TABLE><P>Again, most of these are self-explanatory.</P><H3 CLASS="subsection"><A NAME="htoc71">5.2.1</A>  Stub / skeleton files</H3><P>By default, omniidl separates the normal stub and skeleton file (the
<TT>SK.cc</TT> file) from the ‘dynamic’ stubs (the <TT>DynSK.cc</TT>
file), so applications that do not need support for Any and TypeCode
for a particular IDL file do not waste space with unnecessary
definitions. It is possible to output both the normal stubs <EM>and</EM>
the dynamic stubs to a single file, by simply specifying the same
extension for both files. This command places both the normal stubs
and the dynamic stubs in <TT>aSK.cc</TT>:</P><BLOCKQUOTE CLASS="quote">
<TT>omniidl -bcxx -Wba -Wbd=SK.cc a.idl</TT>
</BLOCKQUOTE><H3 CLASS="subsection"><A NAME="htoc72">5.2.2</A>  Module splicing</H3><P>On ancient C++ compilers without namespace support, IDL modules map to
C++ classes, and so cannot be reopened. For some IDL, it is possible
to ‘splice’ reopened modules on to the first occurrence of the module,
so all module definitions are in a single class. It is possible in
this sort of situation:</P><DIV CLASS="lstlisting"><B>module</B> M1 {
<B>interface</B> I {};
};
<B>module</B> M2 {
<B>interface</B> J {
<B>attribute</B> M1::I ok;
};
};
<B>module</B> M1 {
<B>interface</B> K {
<B>attribute</B> I still_ok;
};
};</DIV><P>but not if there are cross-module dependencies:</P><DIV CLASS="lstlisting"><B>module</B> M1 {
<B>interface</B> I {};
};
<B>module</B> M2 {
<B>interface</B> J {
<B>attribute</B> M1::I ok;
};
};
<B>module</B> M1 {
<B>interface</B> K {
<B>attribute</B> M2::J oh_dear;
};
};</DIV><P>In both of these cases, the <TT>-Wbsplice-modules</TT>
option causes omniidl to put all of the definitions for module
<TT>M1</TT> into a single C++ class. For the first case, this will work
fine. For the second case, class <TT>M1::K</TT> will contain a reference
to <TT>M2::J</TT>, which has not yet been defined; the C++ compiler will
complain.</P><H3 CLASS="subsection"><A NAME="htoc73">5.2.3</A>  Flattened tie classes</H3><P>Another problem with mapping IDL modules to C++ classes arises with
tie templates. The C++ mapping says that for the interface
<TT>M::I</TT>, the C++ tie template class should be named
<TT>POA_M::I_tie</TT>. However, since template classes cannot be
declared inside other classes, this naming scheme cannot be used with
compilers without namespace support.</P><P>The standard solution is to produce ‘flattened’ tie class names, using
the <TT>-Wbtf</TT> command line argument. With that flag, the
template class is declared at global scope with the name
<TT>POA_M_I_tie</TT>. i.e. all occurrences of ‘<TT>::</TT>’ are
replaced by ‘<TT>_</TT>’.</P><H3 CLASS="subsection"><A NAME="htoc74">5.2.4</A>  Generating example implementations</H3><P>If you use the <TT>-Wbexample</TT> flag, omniidl will generate an
example implementation file as well as the stubs and skeletons. For
IDL file <TT>foo.idl</TT>, the example code is written to
<TT>foo_i.cc</TT>. The example file contains class and method
declarations for the operations of all interfaces in the IDL file,
along with a <TT>main()</TT> function which creates an instance of each
object. You still have to fill in the operation implementations, of
course.</P><H2 CLASS="section"><A NAME="toc29"></A><A NAME="htoc75">5.3</A>  Examples</H2><P>Generate the C++ headers and stubs for a file <TT>a.idl</TT>:</P><BLOCKQUOTE CLASS="quote">
<TT>omniidl -bcxx a.idl</TT>
</BLOCKQUOTE><P>Generate with Any support:</P><BLOCKQUOTE CLASS="quote">
<TT>omniidl -bcxx -Wba a.idl</TT>
</BLOCKQUOTE><P>As above, but also generate Python stubs (assuming omniORBpy
is installed):</P><BLOCKQUOTE CLASS="quote">
<TT>omniidl -bcxx -Wba -bpython a.idl</TT>
</BLOCKQUOTE><P>Just check the IDL files for validity, generating no output:</P><BLOCKQUOTE CLASS="quote">
<TT>omniidl a.idl b.idl</TT>
</BLOCKQUOTE><HR>
<A HREF="omniORB004.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
<A HREF="omniORB006.html"><IMG SRC="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
|