(ref.doc)grahamd 051093
Next meyer 191193
Prev: bs 021093
Up: Usenet
From: [email protected] (Graham Dumpleton)
Newsgroups: comp.lang.c++
Subject: Re: Automatic dependency checking & alternatives to make
Date: 5 Oct 1993 10:32:47 GMT
Organization: Technical Development Group, Telstra International
Distribution: world
NNTP-Posting-Host: zeus.research.otc.com.au
In article <[email protected]>, [email protected] (Fergus James HENDERSON) writes:
> >You missed my point. Give *me* a few days with good old make and I will
> >*then* also be able to say "Here are are my source files: A, B, C, ... Z.
> >Give me my program."
>
> However, it is a lot harder with `good old make' than with say GNU Make.
> And it's harder with GNU Make than with cake.
>
> If it really is so easy with make that it takes only a few days work,
> why is it that >95% of people using make still don't generate their
> dependencies for C files completely automatically?
> If it was only going to take a few days to solve this problem, why hasn't
> someone solved it and made their solution available for others to use?
> The answer is that the so-called `good old make' makes it very difficult
> to solve problems like these and even harder to solve them in such a way
> that the solutions can easily be reused by other people for different
> projects.
You might want to look at "makeit". "makeit" is available and supplied with
OSE although it can be installed indepently of the C++ libraries. "makeit"
is a set of predefined makefiles for GNU make. With "makeit", in the
majority of cases the only thing you have to do is list the names of the
programs which should be created. For example, if you had two program code
files called A.cc and B.cc, and source code files C.cc to Z.cc. All that
the makefile need contain is:
MODULES := cc
include makeit/init.mk
PROGRAMS := A B
include makeit/modules.mk
As this is a standard makefile, there is no running programs on description
files to create a makefile and also generate dependencies. Once you have
created the makefile you can go into that directory and type:
makeit
and it will build everything. You can also be explicit and tell it to build
only certain things, for example:
makeit all - same as having no arguments
makeit programs - build the library and the programs
makeit lib - build just the library
makeit A - build program "A"
makeit A.o - build object file for program "A" but don't link it
makeit C.o - build ordinary object file from C.cc
There are a number of other standard targets included also, some of these
are:
makeit clean - remove everything that could be build
makeit depend - create a file of dependencies
Other special features/targets are included when you say that you want
special modules to be included. Optional features include a testing
environment, combining of libraries, forming template closure on C++
libraries, generating template repositories from C++ libraries ...
Anyway, if you want more information then pick up the documentation for
"makeit" (approx 100 pages). The description of the whole OSE package and
more information on "makeit" is included below.
WHAT:
Telstra International is making available publicly, the OTC Software
Environment (OSE). OSE has been developed over the past 2-3 years at
Telstra International, previously known as OTC, with the next major
release being version 3.0. The version currently available is 3.0b10.
This version is expected to be the last BETA version before version 3.0.
The package consists of three C++ class libraries, a build environment
based on GNU make, programs for documentation extraction and other
miscellaneous tools.
The C++ libraries use templates compatable with AT&T C++ 3.0. If you have
a C++ compiler which does not support templates then a template
preprocessor which is supplied can be used. C++ compilers which have
been successfully used in the past include:
AT&T C++ 2.1
AT&T C++ 3.0.1
Borland C++ 3.0 (OTCLIB only)
HP C++ 3.0
ObjectCenter 1.1
ObjectStore C++ 2.0
Sun C++ 2.1
Sun C++ 3.0.1
IBM XL C++ 1.1
Platforms which OSE has been ported to previously include:
HP 700 - HPUX 8.0
Sun 4 - Solaris 2.X
Sun 4 - SunOS 4.1.X
Pyramid - OS5.1 (UCB/ATT)
SCO UNIX
Tandem
IBM AIX
Support is also included within the make environment and libraries
for some third party products. These include:
Purify/Quantify/PureLink
ObjectStore OODBMS
WHERE:
OSE version 3.0b10 can be obtained via anonymous ftp from:
Australia:
csis.dit.csiro.au [192.41.146.1]
directory pub/otc
Europe:
ftp.th-darmstadt.de [130.83.55.75]
directory pub/programming/languages/C++/class-libraries/OSE
In the directory you will find the following files:
ose-3.0b10.tar.Z OSE 3.0b10 src code.
ose-doc-1.0.tar.Z OSE 1.0 documentation.
ose-doc-3.0b.tar.Z OSE 3.0 (DRAFT) documentation.
Please note that it may take a couple of days for the European site to
get updated.
REGISTRATION:
If you decide to use this software, please let us now who you are, what
C++ compiler you use, and on which platforms you install OSE, by sending
email to:
[email protected]
This information will be used if we need to contact someone with access
to a specific C++ compiler or platform, to which we do not have ready
access, in order to resolve any problems we may have with support for
that compiler or platform.
When you register, also indicate which version of OSE you have collected,
as we will then be able to notify you of fixes to any known problems which
may already exist for that version.
In addition to registration, the above address can also be used to report
problems, bugs, suggestions and to send general comments.
We ask that if you make extensions or modifications to this source
release, please make these extensions available to others, by sending
details of the changes you have made or a copy of the modified sources to
the above email address. This will help us evaluate your extensions for
inclusion in a future version. It also ensures your investment in these
extensions when new versions of the software are released.
A mailing list has been set up. If you would like to be placed on the
mailing list then let us know by sending email to the above address. The
address of the mailing list is:
[email protected]
The mailing list is used to distribute announcements of new versions when
they are available, and for current versions, descriptions of known
problems and how to fix them. It is recommended that you subscribe to the
mailing list, as ftp sites will not always be updated quickly, therefore
the mailing list will be the only mechanism for getting fixes quickly.
We ask you not to redistribute this software in source or binary form
without our permission. Although, if you use the software in a product,
you may distribute copies of the shared libraries.
The only recognised ftp sites for OSE are those listed above. Please do
not place OSE on your own or other ftp sites as we will not be able to
ensure that other sites have up to date copies of OSE.
COPYRIGHT:
TELSTRA CORPORATION LIMITED ACN 051 775 556 - 1993
This software is copyright.
Any person supplied this software by Telstra Corporation Limited may make
such use of it including copying and modification as that person desires
providing the copyright notice above appears on all copies and
modifications including supporting documentation AND PROVIDED ALWAYS that
Telstra Corporation Limited prohibits the redistribution or sale of
this software in source or binary form without its express permission.
(Contact Commercial Manager Tel: +61 2 287 3140)
The only conditions and warranties which are binding on Telstra
Corporation Limited in respect of the state, quality, condition or
operation of this software are those imposed and required to be binding
by statute (including the Trade Practices Act 1974) and to the extent
permitted thereby the liability, if any, of Telstra Corporation Limited
arising from the breach of such conditions or warranties shall be limited
to and completely discharged by the replacement of this software and
otherwise all other conditions and warranties whether express or implied
by law in respect of the state, quality, condition or operation of this
software which may apart from this paragraph be binding on Telstra
Corporation Limited are hereby expressly excluded and negatived.
Except to the extent provided in the paragraph immediately above Telstra
Corporation Limited shall have no liability (including liability in
negligence) to any person for any loss or damage consequential or
otherwise howsoever suffered or incurred by any such person in relation
to the software and without limiting the generality thereof in particular
any loss or damage consequential or otherwise howsoever suffered or
incurred by any such person caused by or resulting directly or indirectly
from any failure, breakdown, defect or deficiency of whatsoever nature or
kind of or in the software.
PREREQUISITES:
To compile the OSE C++ libraries requires a C++ compiler compatible with
version 2.1 or 3.0 of the AT&T compiler. Compilers which we know have
been successfully used to compile the library include:
AT&T C++ 2.1
AT&T C++ 3.0.1
Borland C++ 3.0 (OTCLIB only)
HP C++ 3.0
ObjectCenter 1.1
ObjectStore C++ 2.0
Sun C++ 2.1
Sun C++ 3.0.1
IBM XL C++ 1.1
Since the library uses templates, a modified version of the COOL template
preprocessor from Texas Instruments is provided for use with version 2.1
compilers. The main differences between the template preprocessor supplied
and the original COOL preprocessor are:
Supports ARM syntax for template classes and member functions.
Supports initialisers for static members of a template class.
The mechanism used to force templates to be expanded has also been
updated to make it is easier to use. New features have also been added to
allow overriding of template classes by users and for precompiling of
templates into libraries. The end result of all the changes is that it is
possible to write code which can be compiled with either a 2.1 or 3.0
compiler. Note though that in order to use the template preprocessor with
a 2.1 compiler, the compiler must provide a way of specifying an
alternate preprocessor to use.
Due to bugs or unimplemented features some C++ compilers cannot be used
to compile the library. The list of compilers, which we know cannot be
used, are:
DEC C++ 1.0
GNU C++ 2.0.0 -> 2.4.5
It is believed that DEC C++ 1.2 fixes the problem which prevented their
version 1.0 compiler from being used; we don't know if their 1.1 compiler
included the same fix. The problems with the GNU compiler have been
reported but as of version 2.4.5 it was still not capable of compiling
the library.
C++ LIBRARIES:
The three C++ class libraries which form the core of the package are
OTCLIB, OUXLIB and OTKLIB. The main classes in these libraries are:
Debugging and Error Reporting Classes
OTC_Logger
OTC_LogStream
OTC_Terminate
OTC_Tracer
OTC_TraceSwitch
^-- OTC_TraceTag
^
^-- OTC_TracePattern
Memory Management Classes
OTC_Arena
OTC_CommonPool
OTC_Heap
OTC_Pool
Resource Management Classes
OTC_Resource
OTC_CtrPtr<T>
OTC_CtrVecPtr<T>
OTC_ResPtr<T>
Collection Helper Classes
OTC_HashActions<T>
OTC_RankActions<T>
Simple Collection Classes
OTC_BoundedQueue<T>
OTC_BoundedStack<T>
OTC_PriorityQueue<T>
^-- OTC_AscendingQueue<T>
^
^-- OTC_DescendingQueue<T>
OTC_Queue<T>
OTC_SimpleList<T>
OTC_Stack<T>
OTC_Vector<T>
Resource Managed Collection Classes
OTC_BaseActions<T>
OTC_Collection<T>
^-- OTC_Bag<T>
^
^-- OTC_Deque<T>
^
^-- OTC_List<T>
^
^-- OTC_Map<T1,T2>
^
^-- OTC_OrderList<T>
^
^-- OTC_Set<T>
^
^-- OTC_UniqMap<T1,T2>
OTC_Iterator<T>
OTC_Modifier<T>
Text Manipulation Classes
OTC_Buffer
OTC_Pattern
^-- OTC_Globex
^
^-- OTC_Regex
^
^-- OTC_Regexp
OTC_Record
OTC_String
OTC_Symbol
OTC_SymbolTable
^-- OTC_InMemSymbolTable
Program Options Classes
OTC_Options
OTC_Program
^-- OUX_Program
Filesystem Classes
OTC_Pathname
^-- OUX_Pathname
OTC_Directory
^-- OUX_Directory
OTC_Stat
^-- OUX_Stat
UNIX Specific Classes
OUX_User
OUX_Group
OUX_SignalBlock
Construction Classes
OTC_AVLNode
^-- OTC_AVLLinkNode
OTC_AVLTree
OTC_Cursor<T>
^-- OTC_BucketCursor<T>
^
^-- OTC_RangeCursor
OTC_Linkable
^-- OTC_Anchor
^
^-- OTC_Link
^-- OTC_Bucket<T>
^
^-- OTC_Holder<T>
OTC_LinkIterator
OTC_LinkList
OTC_Range
Event Driven Systems Classes
OTC_Agent
OTC_Dispatcher
^-- OUX_Dispatcher
^
^-- OTK_Dispatcher
OTC_Event
^-- OTCEV_Alarm
^
^-- OTCEV_IOEvent
^
^-- OTCEV_Timeout
^
^-- OUXEV_Signal
OTC_Job
^-- OTC_EventJob
OTC_JobQueue
^-- OUX_JobQueue
^
^-- OTK_JobQueue
ObjectStore Classes
OTC_TypeSpec
Some of the major features of the library which distinguish this library
from others, include the fact that all major collection classes in the
libraries are templated. In addition, all collection classes may hold
either objects or pointers to objects. In other words you can write
OTC_List<int> or OTC_List<int*>. For the main collection class hierarchy,
ie., those derived from OTC_Collection, support is provided so that the
user can dictate special actions to be carried out when an item is added
or removed from a collection. This is important in the case of a
collection holding pointers to objects and provides a means to ensure
that objects are not deleted before they should be; conversely that
they are deleted, when no longer required.
An example illustrating this scheme makes use of the class OTC_Resource,
which allows an object to know how many times it is referenced and
deletes itself, when no longer referenced.
class EX_Object : public virtual OTC_Resource
{
public:
EX_Object(int theId)
: myId(theId) {}
int id() const
{ return myId; }
private:
int myId;
};
class OTC_BaseActions<EX_Object*>
{
public:
static EX_Object* add(EX_Object* theObject)
{ theObject->reference(); return theObject; }
static void removed(EX_Object* theObject)
{ theObject->unReference(); }
};
main()
{
OTC_List<EX_Object*> list;
for (int i=0; i<10; i++)
{
EX_Object* anObject;
anObject = new EX_Object(i);
list.addLast(anObject);
}
}
In normal situations, because the collection class can't know that it was
holding a pointer or an object, it wouldn't be able to invoke delete on an
item held by the collection, when the collection is destroyed. There is
also the problem of whether it should delete it anyway as something else
could still be using it.
Reference counting is one solution to this and the OTC_BaseActions class
allows one to provide special knowledge to a collection class, about what
it should do with an item of a particular type. Although the OTC_Resource
class is used here, you could use your own scheme for keeping a count of
the number of references to an object.
Note that it is only necessary to provide an explicit version of
OTC_BaseActions when you want to. If an explicit version for a type isn't
provided, then the default template version of OTC_BaseActions is used,
which does nothing. For example, you do not need to do anything special
to use OTC_List<int>.
A similar scheme to OTC_BaseActions is used to provide information about
how to generate a hash value for an item, or how to compare two items of
the same type to a collection class. The classes controlling this are
OTC_HashActions and OTC_RankActions. the default implementation of these
classes will attempt to convert an item into an int to generate a hash
value, or in order to compare items. As above, the default template
classes can be overriden for a particular type. Using EX_Object again we
can write:
class OTC_RankActions<EX_Object*>
{
public:
static int rank(EX_Object* item1, EX_Object* item2)
{ return OTC_RankActions<int>::rank(item1->id(),item2->id()); }
};
main()
{
OTC_OrderedList<EX_Object*> list;
for (int i=0; i<10; i+=2)
{
EX_Object* anObject;
anObject = new EX_Object(i);
list.add(anObject);
}
for (int j=1; j<10; j+=2)
{
EX_Object* anObject;
anObject = new EX_Object(j);
list.add(anObject);
}
OTC_Iterator<EX_Object*> iter;
iter = list.items();
for (iter.reset(); iter.isValid(); iter.next())
cout << iter.item()->id() << endl;
}
and have it write out the ID of each object in order from 0 to 9 rather
than in the order added to the list.
This scheme means that in the case of pointers it is possible for the
ranking of objects in an ordered collection to be based on some part of
the object being pointed at, instead of the value of the actual pointer.
Similarly, this applies to collections based on hashing, ie., the hash
value and comparision of objects can be based on the object pointed at,
instead of the address of the object in memory. Note though, that the use
of these classes is not restricted to pointers. If you need to hold
actual objects of type EX_Object in a collection you could just as easily
write:
class OTC_RankActions<EX_Object>
{
public:
static int rank(EX_Object const& item1, EX_Object const& item2)
{ return OTC_RankActions<int>::rank(item1.id(),item2.id()); }
};
As shown in the above example, the library also provides the ability to
obtain an iterator for any collection, or more precisely any collection
derived from OTC_Collection. From the user's perspective these iterators
are independent of the type of collection they are iterating over. Once
obtained, the iterators do not have to be maintained in the same scope as
the collection they came from, but may be passed between functions and may
even be passed back up to an enclosing scope. This is partially possible
due to the iterator state being maintained, independently of the actual
iterator object, with the state being reference counted by that object.
This ensures that the actual iterator state is only deleted when
absolutely no longer required. It also means that the user never has to
worry about deleting an iterator explicitly.
The iterator class is only available for collection classes derived from
OTC_Collection as it uses the OTC_BaseActions class to ensure integrity
in the case of collections holding pointers. In particular if we write:
OTC_List<EX_Object*> list;
EX_Object* anObject = new EX_Object(1);
list.add(anObject);
OTC_Iterator<EX_Object*> iter;
iter = list.items();
iter.reset();
list.removeAll();
cout << iter.item()->id() << endl;
what would usually happen is that the program would die due to the
iterator state being corrupted after the items had been removed from the
list, or the iterator would still be okay but the object being pointed at
would have been deleted resulting in an access to invalid memory.
Provided that OTC_BaseActions is defined appropriately for a pointer type
the integrity of iterators is always ensured. In particular an item held
by a collection will not be removed while an iterator is located on it.
An item and the bucket containing it are only removed from a collection
when nothing is interested in. It is only at this time that the remove()
function provided by an OTC_BaseActions class is applied to an object.
This scheme means that iterators will never be disassociated from the
collection it was created from and also means that it is safe to have
multiple iterators on one collection.
BUILD ENVIRONMENT:
The build environment, known as "makeit", is essentially a collection of
predefined makefiles for GNU make. The build environment has been
structured to remove as much as possible from developers the task of
writing makefiles. This is achieved through use of the GNU make "include"
directive and controlling the actions of the build environment through
variable settings.
A simple example of a makefile for makeit is:
MODULES := cc ose
include makeit/init.mk
PROGRAMS := foobar
include makeit/modules.mk
This simple makefile results in the inclusion of support for C++ code
with a ".cc" extension and will also result in the code in that directory
being compiled against, and linked with the OSE C++ class libraries. More
specifically, when makeit is run, all C++ code with an extension of ".cc"
in that directory, except for the program file "foobar.cc" will be
compiled and placed into a library. The program file "foobar.cc", when
compiled, will be linked against the library created from code in this
directory, as well as the OSE C++ class libraries.
Although some variables need to be set, such as PROGRAMS, to control how
targets are built, the majority of what to do is calculated by makeit
looking at what is in a directory in conjunction with which modules you
have enabled. As can be expected makeit, is not all seeing and so it is
necessary to following file naming conventions. Beyond that, there are few
requirements upon the developer in the majority of cases.
As well as support for C++ code, compilation of programs, generation of
libraries and linking of programs against the OSE C++ class libraries,
there is also support in the form of modules or options to makeit for:
C, Yacc, Lex, Rpcgen
Creation of Shell Scripts
Dependency Generation
Purify/Quantify Memory Analysis Tool
PureLink Incremental Linker
Building Shared Libraries
Combining of Libraries
Forming Closure on Libraries
Template Repositories
Program/Library Installation
Unit Testing
ObjectStore Database Schema Generation
By replacing the top level modules file with a customised version it is
possible for users to extend the set of modules available by
supplementing those available with others of their own creation. The user
still selects those required through the MODULES variable though, meaning
that any ordering constraints on the inclusion of predefined makefiles
can be hidden.
As well as the features listed above, makeit embodies two other
significant concepts. These are:
Variants or Compilation Environments
Selection of C++ Compiler
The first of these, allows the developer to hold the results of multiple
compilations, using different compiler options, in the same directory.
This is useful, as it allows inclusion of debugger support as the default
while developing code, but then allows you to build an optimised version
for release, without having to clean out the debugger version beforehand.
In makeit, there are four default variants. These are:
dbg - includes debugger support
opt - invokes the optimiser
prf - includes profiler support
std - no special options
A particular variant is selected by including in the make file
VARIANT := opt
or by defining VARIANT when makeit is invoked.
makeit all VARIANT=opt
If no variant is defined in the makefile, or on the command line, then the
default is used which is generally "dbg".
The compilation results for different variants are placed into separate
subdirectories to keep them apart. The appropriate compiler options
required for that variant are automatically provided by makeit, eg., -O
to enable the optimiser.
The second of the features highlighted is the ability to select a
particular C++ compiler to use. This is provided, as makeit supports a
site having a number of different C++ compilers available under different
names and locations. Since not all C++ compilers are the same, it is quite
often the case that different users have to use different compilers,
depending on what they are doing. So that users do not have to know where
the compilers are located, or what options are required to be used for a
compiler while working in a particular variant on a particular operating
system, the information is included in the makeit configuration when
installed. The user then needs only define in the makefile which
compiler is wanted by defining the C++COMPILER variable. For example:
C++COMPILER := SUN3.0.1
In this case the compiler selected would be Sun C++ 3.0.1.
Because makeit supports multiple C++ compilers it is possible to install
the OSE C++ class libraries for multiple compilers also. When linking
with the libraries, the correct version of the libraries for the compiler
being used will be linked in.
Note that makeit has to be used to compile the OSE C++ class libraries
and install OSE. Although it is feasible to use the OSE C++ class
libraries without using makeit, it is recomended that you do use it
unless you already have some build environment which you have to use. The
reason for this recommendation is that not all C++ compilers handle
template expansion the same and makeit hides all the differences such
that the user never needs to know how a particular compiler actually
handles it. There are also a number of bugs or unimplemented features in
various compilers which makeit silently works around.
DOCUMENTATION TOOLS:
It is important that documentation for classes in a C++ library be up to
date with respect to the code it describes. To assist in this task the
tool "class2man" is provided which is capable of extracting comments from
C++ class header files and formatting that into online or printed
documentation. Having the documentation with the actual classes makes
it easier to update the documentation when changes are made to code.
At present the documentation generated is in the form of UNIX style
manual pages. This does not however require the user to know anything
about using troff man macros though as class2man does all necessary
conversions of your comments into troff formatting commands, including
the conversion of generic font and structure directives. As well as
converting comments class2man also knows about the structure of C++
classes and is able automatically to associate a comment with the
function it is mean't to describe as long as the user follows some simple
formatting rules.
An example of a class commented in the style accepted by class2man is:
template<class T>
class OTC_BaseActions
// = TITLE
// Default actions for an item contained in a bucket.
//
// = DESCRIPTION
// This class encapsulates the default actions which are
// executed when an item is placed into a bucket and when a
// bucket is deleted.
//
// These may be overridden for a particular type in order to
// produce some class specific actions. For example, if <T> is
// a pointer to a class derived from <OTC_Resource> the actions
// may increment and decrement the reference count.
//
// = SEE ALSO
// <OTC_Bucket>
{
public:
// = ACTIONS
static T const& add(T const& theItem)
{ return theItem; }
// Executed when an item is placed into a
// bucket.
static void remove(T&)
{}
// Executed when a bucket is deleted.
};
All classes in the OSE C++ class libraries are documented in this way and
all manual pages for classes in the libraries are generated directly from
the comments in the header files, using class2man.
MISCELLANEOUS TOOLS:
In addition to the build environment and documentation tools, a number of
other useful tools are provided. These include "class2src" which is
capable of parsing a C++ header file and producing member function stubs
for use in a C++ code file, and "mksrc", a program to generate new header
files, code files or make files from prototypes. The files generated by
mksrc include headers describing the author and copyright holder. Also,
in the case of header files appropriate guards will be placed around the
header file to prevent multiple inclusion. Although defaults are provided
the tool can be extended to allow for new file formats and types.
--
Graham Dumpleton ([email protected])
automatically generated by info2www version 1.2.2.8