Modify main.cpp to contain the following code.
#include <iostream>
#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 << "Exception: " << x.what() << std::endl;
std::cerr << "Aborted." << std::endl;
}
catch(...) {
std::cerr << "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.
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
.
The extra capability we’ve added to our program requires us to:
program_options
library,You have previously (step 5) downloaded and unpacked the Boost C++ library into your libraries directory; however, some of the libraries within Boost that we will be using need to be compiled, so let’s do that now. Start by double-clicking the bootstrap.bat file inside your BOOST_ROOT
directory. This will create the compile engine that Boost uses (called b2.exe) and will deposit a file named project-config.jam in the BOOST_ROOT
directory. This file will contain 3 lines, but edit it (use NotePad++ for this) and add one additional line that specifies the libraries we will need to compile (we only need program_options now, but we’ll go ahead and compile filesystem and system now to save having to do this later):
import option ;
using msvc ;
option.set keep-going : false ;
libraries = --with-program_options --with-filesystem --with-system ;
Important! Be sure to leave a space before the semicolon (;
) that terminates each line.
Not adding the “libraries” line will result in a very long wait because Boost will proceed to compile all libraries that need to be compiled. There is nothing wrong with compiling everything (you may need it later), so feel free to just use the default project-config.jam if you want.
To start the compile process, shift-right-click on the boost_1_71_0 directory and choose Open PowerShell window here from the popup menu, then type
.\b2.exe cxxflags="/std:c++14" -d 2
If all goes well, you should see something similar to the following output when the program exits:
The Boost C++ Libraries were successfully built!
The following directory should be added to compiler include paths:
C:\Users\Paul Lewis\Documents\libraries\boost_1_71_0
The following directory should be added to linker library paths:
C:\Users\Paul Lewis\Documents\libraries\boost_1_71_0\stage\lib
Create a new subdirectory of your libraries directory and name it static. Copy the following 6 files from the boost_1_71_0\stage\lib directory to the new static directory.
libboost_program_options-vc142-mt-gd-x64-1_71.lib
libboost_program_options-vc142-mt-x64-1_71.lib
libboost_filesystem-vc142-mt-gd-x64-1_71.lib
libboost_filesystem-vc142-mt-x64-1_71.lib
libboost_system-vc142-mt-gd-x64-1_71.lib
libboost_system-vc142-mt-x64-1_71.lib
These are the debug (containing “gd” in the name) and release versions of the 3 Boost libraries we compiled. These files that I am asking you to copy are the 64-bit versions (Boost also compiled 32-bit versions), so I am presuming you are using a 64-bit version of Windows here.
VSC19 needs to know where to find the Boost libraries that you compiled. Open the Configuration Properties dialog box again and choose VC++ Directories > Library Directories. Click the button at the end of the row to reveal the <Edit…> button, click that to edit, and add the path to your static library directory. For example, I entered this:
C:\Users\Paul Lewis\Documents\libraries\static
To specify command line arguments when your program is run inside the debugger, follow these steps:
Right-click on the strom project inside the strom solution in the Solution Explorer and choose Properties from the menu that pops up. Click on the Debugging item in Configuration Properties In the Command Arguments field, type
--treefile test.tre
Close the dialog box using the OK button at the bottom right and you should be good to go!
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
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).