Note: if you have yet to install the MINOS software then please
follow
the installation instructions for either
msrt or
install_minossoft
When you want to develop code in a package, you do this in a so
called "test" release. This is a release which is in your own area
but is supported by the "base" release which is either the
"development" or one of the "frozen" releases. Be warned that
developing against a frozen release can lead to problems when
porting it to the latest development release. In general, it is
best to have your test releases based on the development release.
The following assumes that your environment is setup to use the
"development" base release.
- Choose a location for you test release. You may have
multiple test releases.
shell> cd </path/tosome/dir>
- Create an empty test release based on the "development" base:
shell> newrel -t development test
This will create a directory called "test"
which contains a main GNUmakefile and empty sub-directories
bin, doc, include, etc. The -t option
indicates that this is a test release and not a base release.
- Enter the new "test" directory and set up your SRT environment
to use this test release.
shell> cd test
shell> srt_setup -a
When compiling code or running executables, any libraries or
executables will be looked for in this "test" release before
being looked for in the associated base release.
There are two ways to add a package into a test release. One way
will check out a copy of the source code and the other will just
create a symlink to the package in the base release. You use the
former if you want to modify the code and the latter If you don't.
As an example consider if we want to modify the Algorithm package.
(Note: this is a framework package and it is unlikely a user would
actually need or want to modify it).
- Check out the package to modify from the repository
shell> addpkg -h Algorithm
This will check out the most recent (or "HEAD") version of the
package into and create a symlink in the include/
directory to this package directory.
- You can now modify any files in this package. Fix some bugs,
add some features (add some bugs). Play around, have fun.
- To build the package you can either run "make" in the package
directory, or from the top level by doing:
shell> gmake Algorithm.all
See also this page for ways to
speed up building your test release.
- Libraries and object files for the package can be removed by
running "make clean" in the package directory or from the top level
by doing:
shell> gmake Algorithm.clean
Running "make clean" on at the top level will clean the
libraries and object files from all packages.
- If you have changed any of the packages header files, then you
must check that any other packages that depend on this one are not
adversely effected. Do do this, follow these steps:
- First find out what package depend on the one you modified
with SRT's depend command:
shell> depend Algorithm
Looking in release development...
These packages in release development use \
include files from package Algorithm:
Algorithm
BubbleSpeak
CandClusterSR
CandDigit
CandEvent
CandEventSR
CandFitTrackSR
CandShowerSR
CandSliceSR
CandStripSR
CandTrackSR
CandVtx
Candidate
DeMux
DynamicFactory
Note: the output may look different depending on what
dependent packages exist in the base release.
- Add all these packages to your "test" release. Because
you probably don't need to actually modify any of these
dependent packages we only symlink them using
lnkpkg instead of adding them proper like we did with
the original package:
shell> lnkpkg BubbleSpeak
shell> lnkpkg CandClusterSR
shell> lnkpkg CandDigit
shell> lnkpkg CandEvent
shell> lnkpkg CandEventSR
shell> lnkpkg CandFitTrackSR
shell> lnkpkg CandShowerSR
shell> lnkpkg CandSliceSR
shell> lnkpkg CandStripSR
shell> lnkpkg CandTrackSR
shell> lnkpkg CandVtx
shell> lnkpkg Candidate
shell> lnkpkg DeMux
shell> lnkpkg DynamicFactory
- Now, rebuild all these packages
shell> cd test
shell> gmake all
This will invoke GNU make and build the libraries and any
executables that may be defined (note that test
executables are not built by default, they must be built
by gmake tbin). All other libraries and header
files that were not included by doing lnkpkg will
be taken from the base release.
- Any packages failing to build because of changes to the
original package's header files will need to be fixed. To
do this you need to check out a copy that can be modified.
For example, assume BubbleSpeak needed fixing,
you would do:
shell> rmpkg BubbleSpeak
shell> addpkg -h BubbleSpeak
There are a few things to help you get information about the
building of your packages:
- You can see internal SRT makefile variables by doing:
shell> gmake echo_<VARIABLE>
or
shell> gmake Algorithm.echo_<VARIABLE>
The VARIABLE you are most likely to want to see
is CPPFLAGS.
- Normally, SRT makefiles will not show much information.
You can change this by setting the environment variable
MINOS_VERBOSE, eg:
tcsh> setenv MINOS_VERBOSE on
bash> export MINOS_VERBOSE=on
When the user is happy with the changes they can commit them
back to the CVS repository. See the section
for developers in the
MINOS Software Repository page.
To remove a package from your test release use
shell> cd $SRT_PRIVATE_CONTEXT
shell> gmake mypackage.clean
shell> rmpkg mypackage
If you have limited disk space in your home area then it is possible to
divert the lib, bin and tmp areas to another disk. To do this
create a file: $HOME/.srtrc which contains:
extra_dirs="$extra_dirs \
tmp>/data_02/lartey/tmp \
bin>/data_02/lartey/bin \
lib>/data_02/lartey/lib"
This file gets sourced when you run newrel to create your test
release. It will make tmp, bin and lib appear as links to the
directory you specified.
If your base release uses a read-only repository access method and you
wish to commit any modifications to packages in your test release, you
will have to explicitly tell addpkg to use the read-write
access method. See the page on the MINOS
Software Repository for information on gaining read-write access.
To explicitly use the read-write access method replace the calls to
addpkg above with
shell> addpkg -d minoscvs@minoscvs.fnal.gov:/cvs/minoscvs/rep1 <package>
If you already used addpkg and have read-only access, you can
change to read-write access with SRT's cvsmigrate script.
For example:
shell> cd <my-package-directory>
shell> cvsmigrate -o \
:pserver:anonymous@minoscvs.fnal.gov:/cvs/minoscvs/rep1 -d \
minoscvs@minoscvs.fnal.gov:/cvs/minoscvs/rep1
shell> cvsmigrate --help for more info
This will need to be done in package directory for which you want have
read-write access.
The following assumes that you have the frozen base release,
R<version> and you want to modify the package Algorithm within
a test release called test. It assumes you have sourced the setup
file described in the installation instructions.
shell> cd <your_dir>
shell> newrel -t R<x.y.z> test
This will create a directory called test under <your_dir>
which contains a main GNUmakefile and empty sub-directories bin,
doc, include etc. The -t option indicates that this is a user's
test release and not an official release. The test release does not
contain any packages yet.
shell> cd test
shell> srt_setup -a
This will set the local SRT context to the current test release.
This means that the bin area of your test release will be put into
your path before the base release for example.
shell> addpkg -n Algorithm
This checks out the package Algorithm from the base release area
and places it in the user's test release. Note that it is important
to specify the -n option. Addpkg without the -n option or with -h
option will checkout the code from CVS. It creates a soft link
between the test release include area and the package. We will
assume that the user wishes to modify some of the include files that
are in the package Algorithm. These include files may be used by
other packages and so in order for the user to fully test their changes
they must rebuild all the packages that use the modified include files.
However, they do not need to actually modify any of the other packages.
To determine which packages depend on Algorithm use the depend
command and carry the same procedure above as done for the
developmental test release.
The convention for tagging a release is:
shell> cvs rtag V<XX-YY-ZZ> <package>
where ZZ indicates a bug fix release, YY is an API backward compatible
release, and XX is a major release.
If a user wants to remove a release.
-
prompt> cd $SRT_DIST/releases
-
rmrel R<x.y.z>
Often the developer may wish to create a new package in their test
release.
- After executing the three steps in Creating a
test release for doing code development the user needs to
shell> mkdir mypackage
shell> cd $SRT_PRIVATE_CONTEXT/include
shell> ln -s ../mypackage mypackage
- Create the source and header files and a GNUmakefile
for the package. An example of
a simple GNUmakefile for a package that only builds a single
library. Look at existing MINOS packages for more examples.
- When happy with the code, create a CVS module and check the
code in. This allows other users to add your package to their
test release.
- In order for a package to get added to the base release it
must be listed in the packages-development file. Please contact
Ed Tetteh-Lartey to get your
package added once the offline group has agreed that it should
be included.
Notes:
- If your package includes test code then it should be placed in a
test directory which should build a library containing the test code.
- The test executables should be added to the tbin target and
only get built if the user runs gmake tbin. Examples of GNUmakefiles
for packages with test code can be found in the
examples.
If you have root macros you can put them in the main package
directory or in a macros directory. You need to make sure that the
macros get moved to the releases/development/macros directory. There are
examples of this on the examples
page. If you get stuck then please send mail to
lartey@fnal.gov.
Here is an outline the steps to necessary create a new class showing how to
incorporate the ROOT dictionary so that it can be written out.
- First create its header (MyClass.h):-
#ifndef MYCLASS_H
#define MYCLASS_H
#include <string>
#include "TObject.h"
class MyClass : public TObject {
public:
MyClass(const char* name = "Anonymous") { fName = name; }
~MyClass() {}
void SetName(const char* name) { fName = name; }
void Speak() const;
private:
string fName;
ClassDef(MyClass,1) // Example class
};
#endif // MYCLASS_H
note the ClassDef which is a macro defined by ROOT to declare further
members for your class.
- Next write its implementation file (MyClass.cxx):-
#include <stdio.h>
#include "mypackage/MyClass.h"
ClassImp(MyClass)
void MyClass::Speak() const {
cout << "Hi, I am " << fName << endl;
}
This time the ClassImp macro defines these new members.
- You will also need a LinkDef.h:-
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class MyClass+;
#endif
This is going to be used by ROOT's rootcint utility to define
a dictionary for your class. The plus at the end of MyClass tells
rootcint to use the new I/O system. That's what MINOS uses and
it will eventually be the default.
- The last file is the GNUmakefile:-
# Makefile for mypackage package
# Define whether rootcint should be run to generate ROOT
# dictionaries
ROOTCINT:= YES
# library
LIB:= lib$(PACKAGE)
#library contents
LIBCXXFILES:= $(wildcard *.cxx)
########################################################################
include SoftRelTools/standard.mk
include SoftRelTools/arch_spec_root.mk
This tells SRT that you want rootcint and the the library will
take the default name, which as your package is called mypackage, will
be libmypackage (.so for shareable) and consists of all the .cxx files
in the directory.
- Now you are ready to build you library:-
prompt> cd $SRT_PRIVATE_CONTEXT
prompt> gmake mypackage.all
which should produce output like this:-
<**all**> mypackage
Generating mypackageCint.cc dictionary...
<**compiling**> MyClass.cxx
<**compiling**> mypackageCint.cc
<**building library**> libmypackage
- Now you can run ROOT and try to communicate with your object:-
prompt> root -b
First load the mypackage library:-
root [0] gSystem.Load("libmypackage.so");
if this fails then something is wrong with your LD_LIBRARY_PATH.
Next try to create and talk to objects on the heap and the stack:-
root [1] MyClass jim("Jim");
root [2] jim.Speak();
Hi, I am Jim
root [3] MyClass* fred = new MyClass;
root [4] fred->Speak();
Hi, I am Anonymous
root [5] fred->SetName("Fred");
root [6] fred->Speak();
Hi, I am Fred
Finally use the ROOT .class command to see what ROOT knows
about your class:-
root [7] .class MyClass
===========================================================================
class MyClass //Example class
size=0x10
...
compiled) 0:0 0 public: MyClass MyClass(MyClass&);
(compiled) 0:0 0 public: void ~MyClass(void);
root [8] .q
- Now, in the mypackage subdirectory
create a ROOT macro MakeTree.c containing:-
{
TFile myFile("mypackage.root","RECREATE");
// Create a ROOT Tree
TTree *tree = new TTree("myTree","A tree containing a MyClass object");
MyClass *myObject = 0;
// Create one branch.
tree->Branch("myclass", "MyClass", &myObject);
// Fill the tree a few times.
myObject = new MyClass("Joe");
tree->Fill();
myObject.SetName("Bill");
tree->Fill();
tree.Write();
myFile.Close();
}
and a second ROOT macro ReadTree.c containing:-
{
MyClass *myObject = new MyClass(); //object must be created before
// setting the branch address
TFile myFile("mypackage.root");
TTree* T = (TTree*) myFile.Get("myTree");
if ( ! T ) {
cout << "Cannot find tree !! " << endl;
}
else {
T.SetBranchAddress("myclass",&myObject);
Int_t nevent = T.GetEntries();
for (Int_t i=0; i<nevent; i++) {
cout << "Event " << i << endl;
T->GetEvent(i);
myObject.Speak();
}
}
}
If the use of TTrees is new to you take a look the Companion's
TTree crib
- Finally run ROOT again and run both macros to write and then
read back your objects:-
root [0] gSystem.Load("libmypackage.so");
root [1] .x mypackage/MakeTree.C
TFile** mypackage.root
TFile* mypackage.root
OBJ: TTree myTree A tree containing a MyClass object : 0
KEY: TTree myTree;1 A tree containing a MyClass object
root [2] .x mypackage/ReadTree.C
Event 0
Hi, I am Joe
Event 1
Hi, I am Bill
root [3]
|