Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/program_options/doc/tutorial.xml @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 12.8 KB
Line 
1<?xml version="1.0" standalone="yes"?>
2<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
3     "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"
4[
5    <!ENTITY % entities SYSTEM "program_options.ent" >
6    %entities;
7]>
8
9<section id="program_options.tutorial">
10  <title>Tutorial</title>
11 
12  <para>In this section, we'll take a look at the most common usage scenarios
13  of the program_options library, starting with the simplest one. The examples
14  show only the interesting code parts, but the complete programs can be found
15  in the "BOOST_ROOT/libs/program_options/example" directory. Through all the
16  examples, we'll assume that the following namespace alias is in effect:
17<programlisting>namespace po = boost::program_options;</programlisting>
18  </para>
19
20  <section>
21    <title>Getting Started</title>
22
23  <para>The first example is the simplest possible: it only handles two
24    options. Here's the source code (the full program is in
25    "example/first.cpp"):
26
27<programlisting>
28// Declare the supported options.
29po::options_description desc(&quot;Allowed options&quot;);
30desc.add_options()
31    (&quot;help&quot;, &quot;produce help message&quot;)
32    (&quot;compression&quot;, po::value&lt;int&gt;(), &quot;set compression level&quot;)
33;
34
35po::variables_map vm;
36po::store(po::parse_command_line(ac, av, desc), vm);
37po::notify(vm);   
38
39if (vm.count(&quot;help&quot;)) {
40    cout &lt;&lt; desc &lt;&lt; &quot;\n&quot;;
41    return 1;
42}
43
44if (vm.count(&quot;compression&quot;)) {
45    cout &lt;&lt; &quot;Compression level was set to &quot; 
46 &lt;&lt; vm[&quot;compression&quot;].as&lt;int&gt;() &lt;&lt; &quot;.\n&quot;;
47} else {
48    cout &lt;&lt; &quot;Compression level was not set.\n&quot;;
49}
50</programlisting>
51  </para>
52
53  <para>We start by declaring all allowed options using the
54    &options_description; class. The <code>add_options</code> method of that
55    class returns a special proxy object that defines
56    <code>operator()</code>. Calls to that operator actually declare
57    options. The parameters are option name, information about value, and option
58    description. In this example, the first option has no value, and the second
59    one has a value of type <code>int</code>.
60  </para>
61 
62  <para>After that, an object of class <code>variables_map</code> is
63    declared. That class is intended to store values of options, and can store
64    values of arbitrary types. Next, the calls to <code>store</code>,
65    <code>parse_command_line</code> and <code>notify</code> functions cause
66    <code>vm</code> to contain all the options found on the command
67    line.</para>
68
69  <para>And now, finally, we can use the options as we like. The
70    <code>variables_map</code> class can be used just like
71    <code>std::map</code>, except that values stored there must be retrieved
72    with the <code>as</code> method shown above. (If the type specified in the
73    call to the <code>as</code> method is different from the actually stored
74    type, an exception is thrown.)
75  </para>
76
77  <para>It's now a good time to try compiling the code yourself, but if
78    you're not yet ready, here's an example session:
79<screen>
80$<userinput>bin/gcc/debug/first</userinput>
81Compression level was not set.
82$<userinput>bin/gcc/debug/first --help</userinput>
83Allowed options:
84  --help                 : produce help message
85  --compression arg      : set compression level
86$<userinput>bin/gcc/debug/first --compression 10</userinput>
87Compression level was set to 10.
88    </screen>
89  </para>
90   
91  </section>
92
93  <section>
94    <title>Option Details</title>
95   
96  <para>An option value, surely, can have other types than <code>int</code>, and
97  can have other interesting properties, which we'll discuss right now. The
98  complete version of the code snipped below can be found in
99  "example/options_description.cpp".</para>
100
101  <para>Imagine we're writing a compiler. It should take the optimization
102    level, a number of include paths, and a number of input files, and perform some
103    interesting work. Let's describe the options:
104    <programlisting>
105int opt;
106po::options_description desc(&quot;Allowed options&quot;);
107desc.add_options()
108    (&quot;help&quot;, &quot;produce help message&quot;)
109    (&quot;optimization&quot;, po::value&lt;int&gt;(&amp;opt)-&gt;default_value(10),
110  &quot;optimization level&quot;)
111    (&quot;include-path,I&quot;, po::value&lt; vector&lt;string&gt; &gt;(),
112  &quot;include path&quot;)
113    (&quot;input-file&quot;, po::value&lt; vector&lt;string&gt; &gt;(), &quot;input file&quot;)
114;
115</programlisting>
116  </para>
117
118  <para>The "--help" option should be familiar from the previous example.
119    It's a good idea to have this option in all cases.</para>
120
121  <para>The "optimization" option shows two new features. First, we specify
122    the address of the variable(<code>&amp;opt</code>). After storing values, that
123    variable will have the value of the option. Second, we specify a default
124    value of 10, which will be used if no value is specified by the user.
125  </para>
126
127  <para>The "include-path" option is an example of the only case where
128    the interface of the <code>options_description</code> class serves only one
129    source -- the command line. Users typically like to use short option names
130    for common options, and the "include-path,I" name specifies that short
131    option name is "I". So, both "--include-path" and "-I" can be used.
132  </para>
133   
134  <para>The "input-file" option specifies the list of files to
135    process. That's okay for a start, but, of course, writing something like:
136    <screen>
137<userinput>compiler --input-file=a.cpp</userinput>
138    </screen>
139    is a little non-standard, compared with
140    <screen>
141<userinput>compiler a.cpp</userinput>
142    </screen>
143    We'll address this in a moment.
144  </para>
145
146  <para>
147    The command line tokens which have no option name, as above, are
148    called "positional options" by this library. They can be handled
149    too. With a little help from the user, the library can decide that "a.cpp"
150    really means the same as "--input-file=a.cpp". Here's the additional code
151    we need:
152    <programlisting>
153po::positional_options_description p;
154p.add(&quot;input-file&quot;, -1);
155
156po::variables_map vm;
157po::store(po::command_line_parser(ac, av).
158          options(desc).positional(p).run(), vm);
159po::notify(vm);
160    </programlisting>   
161  </para>
162
163  <para>
164    The first two lines say that all positional options should be translated
165    into "input-file" options. Also note that we use the
166    &command_line_parser; class to parse the command
167    line, not the &parse_command_line;
168    function. The latter is a convenient wrapper for simple cases, but now we
169    need to pass additional information.
170  </para>
171
172  <para>By now, all options are described and parsed. We'll save ourselves the
173      trouble of implementing the rest of the compiler logic and only print the
174      options:
175    <programlisting>
176if (vm.count(&quot;include-path&quot;))
177{
178    cout &lt;&lt; &quot;Include paths are: &quot; 
179         &lt;&lt; vm[&quot;include-path&quot;].as&lt; vector&lt;string&gt; &gt;() &lt;&lt; &quot;\n&quot;;
180}
181
182if (vm.count(&quot;input-file&quot;))
183{
184    cout &lt;&lt; &quot;Input files are: &quot; 
185         &lt;&lt; vm[&quot;input-file&quot;].as&lt; vector&lt;string&gt; &gt;() &lt;&lt; &quot;\n&quot;;
186}
187
188cout &lt;&lt; &quot;Optimization level is &quot; &lt;&lt; opt &lt;&lt; &quot;\n&quot;;               
189</programlisting>
190  </para>
191
192  <para>Here's an example session:
193    <screen>
194$<userinput>bin/gcc/debug/options_description --help</userinput>
195Usage: options_description [options]
196Allowed options:
197  --help                 : produce help message
198  --optimization arg     : optimization level
199  -I [ --include-path ] arg : include path
200  --input-file arg       : input file
201$bin/gcc/debug/options_description
202Optimization level is 10
203$<userinput>bin/gcc/debug/options_description --optimization 4 -I foo a.cpp</userinput>
204Include paths are: foo
205Input files are: a.cpp
206Optimization level is 4
207</screen>
208  </para>
209
210  <para>
211    Oops, there's a slight problem. It's still possible to specify the
212    "--input-file" option, and usage message says so, which can be confusing
213    for the user. It would be nice to hide this information, but let's wait
214    for the next example.
215  </para>
216
217  </section>
218
219  <section>
220    <title>Multiple Sources</title>
221
222    <para>It's quite likely that specifying all options to our compiler on the
223    command line will annoy users. What if a user installs a new library and
224    wants to always pass an additional command line element? What if he has
225    made some choices which should be applied on every run? It's desirable to
226    create a config file with common settings which will be used together with
227    the command line.
228    </para>
229
230    <para>Of course, there will be a need to combine the values from command
231    line and config file. For example, the optimization level specified on the
232    command line should override the value from the config file. On the other
233    hand, include paths should be combined.
234    </para>
235
236    <para>Let's see the code now. The complete program is in
237      "examples/multiple_sources.cpp". The option definition has two interesting
238      details. First, we declare several instances of the
239      <code>options_description</code> class. The reason is that, in general,
240      not all options are alike. Some options, like "input-file" above, should
241      not be presented in an automatic help message. Some options make sense only
242      in the config file. Finally, it's nice to have some structure in the help message,
243      not just a long list of options. Let's declare several option groups:
244      <programlisting>
245// Declare a group of options that will be
246// allowed only on command line
247po::options_description generic(&quot;Generic options&quot;);
248generic.add_options()
249    (&quot;version,v&quot;, &quot;print version string&quot;)
250    (&quot;help&quot;, &quot;produce help message&quot;)   
251    ;
252   
253// Declare a group of options that will be
254// allowed both on command line and in
255// config file
256po::options_description config(&quot;Configuration&quot;);
257config.add_options()
258    (&quot;optimization&quot;, po::value&lt;int&gt;(&amp;opt)-&gt;default_value(10),
259          &quot;optimization level&quot;)
260    (&quot;include-path,I&quot;,
261         po::value&lt; vector&lt;string&gt; &gt;()-&gt;composing(),
262         &quot;include path&quot;)
263    ;
264
265// Hidden options, will be allowed both on command line and
266// in config file, but will not be shown to the user.
267po::options_description hidden(&quot;Hidden options&quot;);
268hidden.add_options()
269    (&quot;input-file&quot;, po::value&lt; vector&lt;string&gt; &gt;(), &quot;input file&quot;)
270    ;       
271</programlisting>
272      Note the call to the <code>composing</code> method in the declaration of the
273      "include-path" option. It tells the library that values from different sources
274      should be composed together, as we'll see shortly.
275    </para>
276
277    <para>   
278      The <code>add</code> method of the <code>options_description</code>
279      class can be used to further group the options:
280      <programlisting>
281po::options_description cmdline_options;
282cmdline_options.add(generic).add(config).add(hidden);
283
284po::options_description config_file_options;
285config_file_options.add(config).add(hidden);
286
287po::options_description visible(&quot;Allowed options&quot;);
288visible.add(generic).add(config);
289      </programlisting>
290    </para>
291
292    <para>The parsing and storing of values follows the usual pattern, except that
293      we additionally call <functionname>parse_config_file</functionname>, and
294      call the &store; function twice. But what
295      happens if the same value is specified both on the command line and in
296      config file? Usually, the value stored first is preferred. This is what
297      happens for the "--optimization" option. For "composing" options, like
298      "include-file", the values are merged.
299    </para>
300
301    <para>Here's an example session:
302<screen>
303$<userinput>bin/gcc/debug/multiple_sources</userinput>
304Include paths are: /opt
305Optimization level is 1
306$<userinput>bin/gcc/debug/multiple_sources --help</userinput>
307Allows options:
308
309Generic options:
310  -v [ --version ]       : print version string
311  --help                 : produce help message
312
313Configuration:
314  --optimization n       : optimization level
315  -I [ --include-path ] path : include path
316
317$<userinput>bin/gcc/debug/multiple_sources --optimization=4 -I foo a.cpp b.cpp</userinput>
318Include paths are: foo /opt
319Input files are: a.cpp b.cpp
320Optimization level is 4
321</screen>
322      The first invocation uses values from the configuration file. The second
323      invocation also uses values from command line. As we see, the include
324      paths on the command line and in the configuration file are merged,
325      while optimization is taken from the command line.
326    </para>
327     
328  </section>
329
330 
331
332 
333
334 
335       
336</section>
337
338<!--
339     Local Variables:
340     mode: xml
341     sgml-indent-data: t     
342     sgml-parent-document: ("program_options.xml" "section")
343     sgml-set-face: t
344     End:
345-->
Note: See TracBrowser for help on using the repository browser.