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("Allowed options"); 30desc.add_options() 31 ("help", "produce help message") 32 ("compression", po::value<int>(), "set compression level") 33; 34 35po::variables_map vm; 36po::store(po::parse_command_line(ac, av, desc), vm); 37po::notify(vm); 38 39if (vm.count("help")) { 40 cout << desc << "\n"; 41 return 1; 42} 43 44if (vm.count("compression")) { 45 cout << "Compression level was set to " 46 << vm["compression"].as<int>() << ".\n"; 47} else { 48 cout << "Compression level was not set.\n"; 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 <filename>example/options_description.cpp</filename>.</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("Allowed options"); 107desc.add_options() 108 ("help", "produce help message") 109 ("optimization", po::value<int>(&opt)->default_value(10), 110 "optimization level") 111 ("include-path,I", po::value< vector<string> >(), 112 "include path") 113 ("input-file", po::value< vector<string> >(), "input file") 114; 115</programlisting> 116 </para> 117 118 <para>The <literal>"help"</literal> option should be familiar from 119 the previous example. It's a good idea to have this option in all cases. 120 </para> 121 122 <para>The <literal>"optimization"</literal> option shows two new features. First, we specify 123 the address of the variable(<code>&opt</code>). After storing values, that 124 variable will have the value of the option. Second, we specify a default 125 value of 10, which will be used if no value is specified by the user. 126 </para> 127 128 <para>The <literal>"include-path"</literal> option is an example of the 129 only case where the interface of the <code>options_description</code> 130 class serves only one 131 source -- the command line. Users typically like to use short option names 132 for common options, and the "include-path,I" name specifies that short 133 option name is "I". So, both "--include-path" and "-I" can be used. 134 </para> 135 136 <para>Note also that the type of the <literal>"include-path"</literal> 137 option is <type>std::vector</type>. The library provides special 138 support for vectors -- it will be possible to specify the option several 139 times, and all specified values will be collected in one vector. 140 </para> 141 142 <para>The "input-file" option specifies the list of files to 143 process. That's okay for a start, but, of course, writing something like: 144 <screen> 145<userinput>compiler --input-file=a.cpp</userinput> 146 </screen> 147 is a little non-standard, compared with 148 <screen> 149<userinput>compiler a.cpp</userinput> 150 </screen> 151 We'll address this in a moment. 152 </para> 153 154 <para> 155 The command line tokens which have no option name, as above, are 156 called "positional options" by this library. They can be handled 157 too. With a little help from the user, the library can decide that "a.cpp" 158 really means the same as "--input-file=a.cpp". Here's the additional code 159 we need: 160 <programlisting> 161po::positional_options_description p; 162p.add("input-file", -1); 163 164po::variables_map vm; 165po::store(po::command_line_parser(ac, av). 166 options(desc).positional(p).run(), vm); 167po::notify(vm); 168 </programlisting> 169 </para> 170 171 <para> 172 The first two lines say that all positional options should be translated 173 into "input-file" options. Also note that we use the 174 &command_line_parser; class to parse the command 175 line, not the &parse_command_line; 176 function. The latter is a convenient wrapper for simple cases, but now we 177 need to pass additional information. 178 </para> 179 180 <para>By now, all options are described and parsed. We'll save ourselves the 181 trouble of implementing the rest of the compiler logic and only print the 182 options: 183 <programlisting> 184if (vm.count("include-path")) 185{ 186 cout << "Include paths are: " 187 << vm["include-path"].as< vector<string> >() << "\n"; 188} 189 190if (vm.count("input-file")) 191{ 192 cout << "Input files are: " 193 << vm["input-file"].as< vector<string> >() << "\n"; 194} 195 196cout << "Optimization level is " << opt << "\n"; 197</programlisting> 198 </para> 199 200 <para>Here's an example session: 201 <screen> 202$ <userinput>bin/gcc/debug/options_description --help</userinput> 203Usage: options_description [options] 204Allowed options: 205 --help : produce help message 206 --optimization arg : optimization level 207 -I [ --include-path ] arg : include path 208 --input-file arg : input file 209$ <userinput>bin/gcc/debug/options_description</userinput> 210Optimization level is 10 211$ <userinput>bin/gcc/debug/options_description --optimization 4 -I foo -I another/path --include-path third/include/path a.cpp b.cpp</userinput> 212Include paths are: foo another/path third/include/path 213Input files are: a.cpp b.cpp 214Optimization level is 4 215</screen> 216 </para> 217 218 <para> 219 Oops, there's a slight problem. It's still possible to specify the 220 "--input-file" option, and usage message says so, which can be confusing 221 for the user. It would be nice to hide this information, but let's wait 222 for the next example. 223 </para> 224 225 </section> 226 227 <section> 228 <title>Multiple Sources</title> 229 230 <para>It's quite likely that specifying all options to our compiler on the 231 command line will annoy users. What if a user installs a new library and 232 wants to always pass an additional command line element? What if he has 233 made some choices which should be applied on every run? It's desirable to 234 create a config file with common settings which will be used together with 235 the command line. 236 </para> 237 238 <para>Of course, there will be a need to combine the values from command 239 line and config file. For example, the optimization level specified on the 240 command line should override the value from the config file. On the other 241 hand, include paths should be combined. 242 </para> 243 244 <para>Let's see the code now. The complete program is in 245 "examples/multiple_sources.cpp". The option definition has two interesting 246 details. First, we declare several instances of the 247 <code>options_description</code> class. The reason is that, in general, 248 not all options are alike. Some options, like "input-file" above, should 249 not be presented in an automatic help message. Some options make sense only 250 in the config file. Finally, it's nice to have some structure in the help message, 251 not just a long list of options. Let's declare several option groups: 252 <programlisting> 253// Declare a group of options that will be 254// allowed only on command line 255po::options_description generic("Generic options"); 256generic.add_options() 257 ("version,v", "print version string") 258 ("help", "produce help message") 259 ; 260 261// Declare a group of options that will be 262// allowed both on command line and in 263// config file 264po::options_description config("Configuration"); 265config.add_options() 266 ("optimization", po::value<int>(&opt)->default_value(10), 267 "optimization level") 268 ("include-path,I", 269 po::value< vector<string> >()->composing(), 270 "include path") 271 ; 272 273// Hidden options, will be allowed both on command line and 274// in config file, but will not be shown to the user. 275po::options_description hidden("Hidden options"); 276hidden.add_options() 277 ("input-file", po::value< vector<string> >(), "input file") 278 ; 279</programlisting> 280 Note the call to the <code>composing</code> method in the declaration of the 281 "include-path" option. It tells the library that values from different sources 282 should be composed together, as we'll see shortly. 283 </para> 284 285 <para> 286 The <code>add</code> method of the <code>options_description</code> 287 class can be used to further group the options: 288 <programlisting> 289po::options_description cmdline_options; 290cmdline_options.add(generic).add(config).add(hidden); 291 292po::options_description config_file_options; 293config_file_options.add(config).add(hidden); 294 295po::options_description visible("Allowed options"); 296visible.add(generic).add(config); 297 </programlisting> 298 </para> 299 300 <para>The parsing and storing of values follows the usual pattern, except that 301 we additionally call <functionname>parse_config_file</functionname>, and 302 call the &store; function twice. But what 303 happens if the same value is specified both on the command line and in 304 config file? Usually, the value stored first is preferred. This is what 305 happens for the "--optimization" option. For "composing" options, like 306 "include-file", the values are merged. 307 </para> 308 309 <para>Here's an example session: 310<screen> 311$ <userinput>bin/gcc/debug/multiple_sources</userinput> 312Include paths are: /opt 313Optimization level is 1 314$ <userinput>bin/gcc/debug/multiple_sources --help</userinput> 315Allows options: 316 317Generic options: 318 -v [ --version ] : print version string 319 --help : produce help message 320 321Configuration: 322 --optimization n : optimization level 323 -I [ --include-path ] path : include path 324 325$ <userinput>bin/gcc/debug/multiple_sources --optimization=4 -I foo a.cpp b.cpp</userinput> 326Include paths are: foo /opt 327Input files are: a.cpp b.cpp 328Optimization level is 4 329</screen> 330 The first invocation uses values from the configuration file. The second 331 invocation also uses values from command line. As we see, the include 332 paths on the command line and in the configuration file are merged, 333 while optimization is taken from the command line. 334 </para> 335 336 </section> 337 338 339 340 341 342 343 344</section> 345 346<!-- 347 Local Variables: 348 mode: nxml 349 sgml-indent-data: t 350 sgml-parent-document: ("program_options.xml" "section") 351 sgml-set-face: t 352 End: 353--> 354