GNU CommonC++ is a cross-platform library for writing C++ applications. See the project homepage for more information.
Contents |
Before you can start using CommonC++ in an application on SUSE Linux, you will need to make some modifications to your Makefile. Specifically, you need to tell your Makefile how to find the header files for CommonC++, and also which libraries need to be included in order to use CommonC++.
The CommonC++-devel package includes a tool called ccgnu2-config. This tool will tell you exactly what flags you need to include in your application's Makefile in order to use CommonC++. For starters, type:
ccgnu2-config --help
to get an idea of the options you have with ccgnu2-config. The options you care most about are - -includes and - -stdlibs.
ccgnu2-config --includes will tell us what flags we need to provide in order to include the proper files for CommonC++:
-I/usr/include -I/usr/include/cc++2
If I look, I can see that on SUSE Linux, CommonC++ header files are installed in the following directory:
/usr/include/cc++2/cc++
CommonC++ header files reference each other with the cc++ prefix, like this:
<cc++/headerfile.h>
All I need to do is to add the output from ccgnu2-config - -includes to my Makefile as a compiler argument for the preprocessor step and I'm good to go. Note that I happen to know that /usr/include is the default include directory so it is unnecessary on SUSE Linux for me to add that directory. I simply add:
-I/usr/include/cc++2
Most IDEs will have a location where you configure your project in which you tell it to add this as a compiler flag; if you are editing your own makefile, just edit your makefile accordingly.
Before I found out about ccgnu2-config, I had figured out the includes flag on my own, but figuring out the libraries was really beating me up. Fortunately, running ccgnu2-config - -stdlibs will tell me exactly what libraries I need to reference. The output of that command on my system returns:
-L/usr/lib -lccext2 -lccgnu2 -L/usr/lib -lxml2 -lz -lpthread -lm -lz -ldl -lrt -pthread
Again, note that the inclusion of -L/usr/lib is technically unnecessary since this is the default library directory; however, it won't hurt to include it. I add this also to my Makefile as a compiler argument for the linking step. Now I should be able to use CommonC++ in my application without any problems.
As a reference, this is what the command should look like to compile ccpptest.cpp into ccpptest using g++ and CommonC++:
g++ -I/usr/include -I/usr/include/cc++2 -o ccpptest ccpptest.cpp -L/usr/lib -lccext2 -lccgnu2 -L/usr/lib -lxml2 -lz -lpthread -lm -lz -ldl -lrt -pthread <pre>
CommonC++ includes several classes to help me handle command line parameters elegantly. We'll start with an example that shows us processing two possible arguments.
// These are normal include files for C++ applications.
#include <iostream>
#include <cstdlib>
// I include this in order to pull in the CommonC++ functionality.
#include <cc++/common.h>
using namespace std;
// ost is the namespace for CommonC++ classes, etc.
using namespace ost;
int main(int argc, char *argv[])
{
// Create an empty list of command line options.
CommandOption* optsList = 0;
// Declare each command option argument, and assign it to the command line options list.
// See http://www.gnu.org/software/commoncpp/docs/refman/html/class_command_option.html
// for details on what the parameters are for.
CommandOptionNoArg helparg("help","h","Print Usage Information",false,&optsList);
CommandOptionNoArg verbosearg("verbose","v","Provide Verbose Output",false,&optsList);
// Create a CommandOptionParse object from the options list and from the supplied
// command line arguments.
CommandOptionParse* parsedOptionsPtr = makeCommandOptionParse(argc, argv, "", optsList);
// Handle the command line arguments.
if( helparg.numSet )
{
cerr << parsedOptionsPtr->printUsage() << endl;
exit (0);
}
bool isVerbose( verbosearg.numSet ? true : false );
if( parsedOptionsPtr->argsHaveError() )
{
cerr << parsedOptionsPtr->printErrors() << endl;
cerr << parsedOptionsPtr->printUsage() << endl;
exit (1);
}
cout << "Regular output" << endl;
if ( isVerbose )
{
cout << "Verbose output" << endl;
}
return EXIT_SUCCESS;
}
The class CommandOptionNoArg specifies a command line option that does not include an argument. I specify both the long and short flags for each option, a description of that argument, whether it is required, and the CommandOption list that it will become a part of. The function makeCommandOptionParse creates an object of type CommandOptionParse which parses the input given to the program. Then all I have to do is check the options to see if they were set and perform the correct actions if so.
Here's the output of the program executed normally, with no options:
~/fissle/debug/src> ./fissle Regular output
Here's the output of the program if I ask for help:
~/fissle/debug/src> ./fissle --help
./fissle
-h, --help - Print Usage Information
-v, --verbose - Provide Verbose Output
Notice the output is the same if I use the other form for the same option:
~/fissle/debug/src> ./fissle -h
./fissle
-h, --help - Print Usage Information
-v, --verbose - Provide Verbose Output
Here's the verbose output:
~/fissle/debug/src> ./fissle -v Regular output Verbose output
Here's the output if I provide an unknown flag:
~/fissle/debug/src> ./fissle --undefined
Unknown/malformed option '--undefined'
./fissle
-h, --help - Print Usage Information
-v, --verbose - Provide Verbose Output
Notice the quality of command line parsing I get with just a little bit of code? I get excellent handling and reporting of issues, especially housekeeping issues, without a lot of superfluous code. This allows me to focus on getting the work of the application done.
© 2008 Novell, Inc. All Rights Reserved.