next_inactive up previous


Make-system evaluation for Hall-D software

D. Lawrence
Jefferson Lab


Hall-D-NOTE 71















introduction

In this document I present an evaluation of ``Make-systems'' which could be used for the Hall-D software. A make-system is the software used to orchestrate the compiling and linking of executable programs and libraries from the source code. A good make system is essential for efficient software development of any large software project.

Currently, the Hall-D software imploys the GNU Makefile system(gmake) implemented through a series of independant Makefiles. The gmake system is by far the most commonly used make system for the platforms commonly used in experimental particle physics. Because the Hall-D software was basically built one program at a time, it does not employ a common system throughout, leading to situations which will grow into hard to manage problems over time. Some of these are:

Before simply implementing a system based on gmake, a quick evaluation was made to explore what other options exist. The gmake system has a few short-comings which might be overcome by newer systems. A simple program was used to evaluate three make systems and compare them. A review of documentation for a few others was also done. This note presents the results of this study.

Evaluation Program

Before begining the evaluation, a simple source tree was constructed with which to test the systems. An outline of the directory/file structure is shown in figure 1. Note that this is not intended to be an exact represenatation of the directory sturcture the Hall-D software will have. In particular, the bin and lib directories will likely not reside in the ``src'' directory. However, it served for the purposes of this test.

Figure 1: Directory tree of source code used in evaluations. (``Darwin'' is the uname for Mac OSX. The environment variable OSNAME was used to identify the platform directories for the binaries.)
\begin{figure}\begin{center}
\epsfig{figure=src_tree.eps, width=14cm}\end{center}\end{figure}

The source code itself is quite simple and is included in Appendix A for completeness.

gmake

GNU Make or ``gmake'' is the clearly accepted standard for software development on Linux. It takes a ``Makefile'' as input which defines a set of rules that gmake uses to build the binaries.

Here is the top-level Makefile used:




LIBS = -Llib/$(OSNAME) -lmyprog

bin/$(OSNAME)/myprog:
	make -C mylib -f ../Makefile.common
	make -C myprog -f ../Makefile.common
	ranlib lib/$(OSNAME)/libmyprog.a
	$(CXX) $(CXXFLAGS) $(LIBS) -o $@



I did this in a slightly unconventional way by not actually putting a makefile in the mylib or myprog directories. They both used the exact same makefile, ``Makefile.common'', which was explicitly referenced in the top level Makefile. Here is the Makefile.common file:

CXXFLAGS = -I../include
CXXSRC	= $(wildcard *.cc)
OBJS	= $(CXXSRC:.cc=.o)

all:../lib/$(OSNAME)/libmyprog.a($(OBJS))
../lib/$(OSNAME)/libmyprog.a($(OBJS)):

Here are some observations about gmake:

Summary: The gmake system is ubiquitous. It is installed on every Linux system which has a C/C++ compiler installed. It is the most commonly used make system in particle physics. This makes it the yardstick by which other make systems are measured. The single biggest drawback to gmake is the lack of an implicit rule for dependancy scanning. Every reasonably large software project which uses gmake must overcome this in basically the same way.

CONS

CONS is based on perl and has the capability to include perl code in the configuration files. The top level ``Construct'' file looked like:




$BINDIR = "$ENV{'PWD'}/bin/$ENV{'OSNAME'}";
$LIBDIR = "$ENV{'PWD'}/lib/$ENV{'OSNAME'}";

$env = new cons(
	CC			=> 'gcc',
	CXX		=> 'g++',
	CPPPATH	=> 'include',
	LIBPATH	=> $LIBDIR,
	LIBS		=> '-lmylib',
);

Export qw(env BINDIR LIBDIR);

Build qw(

	myprog/Construct
	mylib/Construct
);



And here is the Construct file in mylib looked like:

$core_name = mylib;
$libname = "lib$core_name.a";

Import qw(env BINDIR LIBDIR);

$csrc = `cd $core_name; ls *.cxx`;
Library $env  $libname, 'myclassA.cxx', 'myclassB.cxx';

Install $env $LIBDIR, $libname;



Here are a few observations about the CONS make system:

Summary : Using perl as a platform for this gives you the powerful flexibility of a programming language. This means there is certainly a way to overcome the shortcomings of cons by programming around it. But then, what's the point? CONS has one main advantage over gmake which is built-in dependancy scanning (looking for include files and rebuilding if they change). This may be a debatable point though. See the conclusion for a discussion. Another advantage CONS has over gmake is the ability to pass the build environment (i.e. CC, CXX, LD ,...) easily down through the heirachy of Construct files. The lack of housekeeping is a big minus IMHO for CONS.

SCONS

SCONS is a make utility very similar to CONS. SCONS, however, is built on python as the underlying language. The top level ``SConstruct'' file looked like:




import os
BINDIR = os.environ["PWD"]+'/bin/'+os.environ["OSNAME"]
LIBDIR = os.environ["PWD"]+'/lib/'+os.environ["OSNAME"]

env = Environment(
	CC			= 'gcc',
	CXX		= 'g++',
	CPPPATH	= '../include',
	LIBPATH	= LIBDIR,
	LIBS		= '-lmylib'
)

Export('env', 'BINDIR', 'LIBDIR');

SConscript(['myprog/SConstruct',
            'mylib/SConstruct'])



And here is the SConstruct file in mylib looked like:

Import('env', 'BINDIR', 'LIBDIR')

list = Split('myclassA.cc myclassB.cc')
env.Library('mylib', list);

env.Install(LIBDIR, 'libmylib.a')

Here are a few observations about the SCONS make system:

Summary : SCONS might have a few slight advantages over CONS, mainly in the documentation. The choice for an individual programmer though, would probably be driven by whether they liked perl or python better since they seem so philosophically ans structurally similar. The same arguments given for/against CONS would therefore apply here as well.

Other Make Systems

Several other make systems exist. A nice list can be found on the web at http://directory.google.com/Top/Computers/Software/Build_Management/Make_Tools. I found at least one other web page which listed make tools, but it seemed to be a subset of this one.

Here's a summary of observations gathered from the documentation of several of these packages (note that only freeware packages were considered):

Conclusion

A few make systems were evaluated (GMAKE, CONS, and SCONS) and several others were briefly reviewed. As was pointed out earlier, the gmake system is the most commonly used, by far in the Unix environment. It is also the only one that comes standard on any Linux system with a C/C++ compiler installed. As such it is the default choice unless significant benefit can be gained from another package. The benefit must be measured by a single parameter: How many manhours the collaboration, as a whole, spends on configuring and using the make system. Anything other than gmake already carries a deficit just in the time it takes to download and install a non-standard system on each computer that the Hall-D software will be compiled on. Any problems encountered by a collaborator will either trigger them spending a day to learn system-X in order to fix it, or an exchange of e-mails to have an expert do it. This is, of course, a little hard to predict.

The biggest shortfall of gmake is its implimentation of dependancy scanning. This is also where other systems seem to surpass it. Gmake does have a recommended method, however which relies on using gcc or g++ with the -M or -MM parameter.

Most other packages (Jam perhaps being the exception) don't do as good of a job in housekeeping as gmake. Lingering objects not only uneccessarily clutter directories, but have the potential of causing link errors.

My reccomendation is to use gmake. This is capable of doing what is required with sufficient compententcy. The advantages of the other systems do not appear suffcient to warrant deviating from the standard. The one reservation is that the makefiles must be thoughtfully written and centralized. See the discussion below for some ideas along this line.

Considerations for the Hall-D make system

Here are some things to consider for the Hall-D make system:


Appendix: Source code




myprog.h
#include "myclassA.h"
#include "myclassB.h"




myprog.cc
#include "myprog.h"

int main(int argc, char argv[])
{

    myclassA mcA;
    mcA.DoA("classA message");

    myclassB mcB;
    mcB.DoB("classB message");

    return 0;
}




myclassA.h
class myclassA
{
    public:
    myclassA();
    ~myclassA();
    
    int DoA(char *mess);
};




mclassA.cc
#include <iostream>
#include <iomanip>
using namespace std;

#include "myclassA.h"

myclassA::myclassA()
{
}

myclassA::~myclassA()
{
}

int myclassA::DoA(char *mess)
{
    cout<<mess<<endl;

	return 0;
}




myclassB.h
class myclassB
{
    public:
    myclassB();
    ~myclassB();
    
    int DoB(char *mess);
};




myclassB.cc
#include <iostream>
#include <iomanip>
using namespace std;

#include "myclassB.h"

myclassB::myclassB()
{
}

myclassB::~myclassB()
{
}

int myclassB::DoB(char *mess)
{
    cout<<mess<<endl;

	return 0;
}


next_inactive up previous
Hall D Account 2004-05-13