8.2 Testing program options

(Mac version)

< 8.1 | 8.2 | 9.0 >

Modify main.cpp to contain the following code.

#include &lt;iostream&gt; 
#include "strom.hpp"

using namespace strom;

// static data member initializations
std::string  Strom::_program_name        = "strom";
unsigned     Strom::_major_version       = 1;
unsigned     Strom::_minor_version       = 0;
const double Node::_smallest_edge_length = 1.0e-12;

int main(int argc, const char * argv[]) {
    Strom strom;
    try {
        strom.processCommandLineOptions(argc, argv);
        strom.run();
    }
    catch(std::exception & x) {
        std::cerr &lt;&lt; "Exception: " &lt;&lt; x.what() &lt;&lt; std::endl;
        std::cerr &lt;&lt; "Aborted." &lt;&lt; std::endl;
    }
    catch(...) {
        std::cerr &lt;&lt; "Exception of unknown type!\n";
    }

    return 0;
}   

The main function now creates a Strom object, then passes argc and argv off to the Strom object’s processCommandLineOptions function, and finally calls the Strom object’s run method. Any exceptions thrown are caught and their error messsages displayed to the user.

The main.cpp file will not change very much from now on. Any new options will be added to the Strom class instead.

Static data members

Some data members (_program_name, _major_version, and _minor_version) of the Strom class were declared static. We must therefore initialize these in main.cpp, as it is our only source code file, just like we have been doing for Node::_smallest_edge_length.

Compiling the Boost program_options library

The extra capability we’ve added to our program requires us to:

Compile the Boost program_options library

Open the Terminal or iTerm2 app and navigate to where you previously installed the Boost headers (~/Documents/libraries/boost_1_71_0), then enter the following command:

./bootstrap.sh --with-toolset=clang --with-libraries=program_options,filesystem,system

Note that I’ve added filesystem and system to the list of Boost libraries to compile. We will make use of these later, so we might as well compile them now so that we do not need to rerun the bootstrap.sh script again.

The bootstrap.sh script will fairly quickly return, instructing you to type ./b2 to perform the actual compilation.

./b2 cxxflags="-std=c++11" -d 2

Note that I’ve added cxxflags="-std=c++11" to ensure that the Boost libraries are compiled under the same C++ dialect used to compile the main strom program. This will ensure that the libraries can be linked to the strom executable. I’ve also specified -d 2 to specify debugging level 2, which causes the Boost build system to display the compile and link commands it is using (this helps when trying to diagnose what happened if the compiling or linking fails).

Assuming the compilation was successful, you should now see something similar to the following output:

The Boost C++ Libraries were successfully built!

The following directory should be added to compiler include paths:

    /home/plewis/Documents/libraries/boost_1_71_0

The following directory should be added to linker library paths:

    /home/plewis/Documents/libraries/boost_1_71_0/stage/lib

Copy the files libboost_program_options.a, libboost_filesystem.a, and libboost_system.a to the ~/lib/static folder.

Tell Xcode about program options

In the Xcode main menu, choose View > Navigators > Show Project Navigator, then click on the blue project icon :blueproject: labeled strom at the top of the Project Navigator. Click on the Build Phases tab. Click the + sign in Link Binary With Libraries and (after clicking the Add Other… button) navigate to the directory ~/lib/static and select the libboost_program_options.a, libboost_filesystem.a, and libboost_system.a files. This informs Xcode where to find the compiled library code for purposes of linking the library into your program’s executable file.

You have already specified the $(BOOST_ROOT) custom path in the “Header Search Paths” section of Build Settings, and you’ve specified ~/lib/static in the Library Search Paths section of Build Settings, so there is nothing more that needs to be done.

Running strom

Specifying command line arguments

To specify command line arguments when your program is run inside the debugger, follow these steps:

At the top of the Xcode window, to the right of the :arrow_forward: (run program in debugger) and :stop_button: (stop program running in debugger) buttons, click on the button labeled “strom” (attached to the button labeled “My Mac”).

Choose “Edit Scheme…” from the popup menu, then choose the “Arguments” tab and click the + button under “Arguments Passed On Launch”.

Click the + button 1 more time so that there are places for a total of 2 arguments

You can now close the dialog box using the Close button at the bottom right and run the program.

Expected output

Here is the output you should see if everything is working correctly:

Note: configuration file (strom.conf) not found
Starting...
storing read block: TAXA
storing read block: TREES

Read 14 trees from file
Topology 1 seen in these 4 trees:
  10 11 12 13 
Topology 2 seen in these 2 trees:
  8 9 
Topology 3 seen in these 8 trees:
  0 1 2 3 4 5 6 7 

Topologies sorted by sample frequency:
            topology            frequency
                   3                    8
                   1                    4
                   2                    2

Finished!

If the lines in your output are flooded with lines such as “Creating Node object” and “Destroying Node object”, then you failed to heed the advise in the section “Lost at sea” at the very bottom of the Test the TreeSummary class page.

You may have wondered about this line:

Note: configuration file (strom.conf) not found

The Boost program_options library makes it possible to store command line options inside a configuration file rather than entering them from the command line. If you create a file named strom.conf inside the install directory (~/Documents/strom/distr) containing these two lines…

# this is a comment
treefile = test.tre

you should be able to run the program without specifying any command line options (try unchecking or deleting both --treefile and test.tre rows under “Arguments Passed On Launch”).

Note that in the config file the convention is to use key/value pairs, whereas on the command line, -- is the convention. Be sure to use one key/value pair per line, and note that lines starting with # are ignored (this feature can be used to insert comments into your configuration files).

< 8.1 | 8.2 | 9.0 >