Re: [ROOT] Makefiles and Dictionaries

From: Christian Holm Christensen (cholm@hehi03.nbi.dk)
Date: Mon Mar 26 2001 - 23:06:56 MEST


Hi Tareq, 

I strongly recommend you use the GNU Autotools (automake, autoconf and
libtool) to build your thing. Suppose you have classes 

   Tintin, Milou, Haddock, Tournesol 

and programs 

   dupond, dupont

and classes Tintin and Milou go into one library libHerge, Haddock and
Tournesol another libMoulinsart. Then have directory structure like:  

       .
       |-- Makefile.am
       |-- acinclude.m4
       |-- config
       |   `-- config.mk
       |-- configure.in
       |-- detectives
       |   |-- Makefile.am
       |   |-- dupond.cxx
       |   `-- dupont.cxx
       |-- herge
       |   |-- Makefile.am
       |   |-- inc
       |   |   |-- HergeInc.h
       |   |   |-- HergeLinkDef.h
       |   |   |-- Milou.h
       |   |   `-- Tintin.h
       |   `-- src
       |       |-- Milou.cxx
       |       `-- Tintin.cxx
       `-- moulinsart
           |-- Makefile.am
           |-- inc
           |   |-- Haddock.h
           |   |-- MoulinsartInc.h
           |   |-- MoulinsartLinkDef.h
           |   `-- Tournesol.h
           `-- src
               |-- Haddock.cxx
               `-- Tournesol.cxx

The content of the files                          
       
       Milou.h   Milou.cxx   Haddock.h    Haddock.cxx
       Tintin.h	 Tintin.cxx  Tournesol.h  Tournesol.cxx

as well as 

      dupond.cxx  dupont.cxx

should be obvious, with only one cave-at: If you want to have 

  
 class Tintin { 
 private: 
   Milou*    fMilou;   // Has-a relation 

   friend class Haddock; 
 
   ...
  }

  class Haddock { 
  private: 
    Milou* fMilou;     // Hates-it's-guts-relation 
    ...
  public: 
    ....
    SetMilou(Tintin* tintin) { fMilou = tintin->fMilou; } 
  } 

you'd better have the lines 

  #ifndef TINTIN_H 
  #include "Tintin.h" 
  #endif 

in Haddock.h 

The contents of the files HergeLinkDef.h and MoulinsartLinkDef.h are
the standard stuff for the CINT dictionary. HergeInc.h and
MoulinsartInc.h should just include the headers for that library,
e.g., 

  #ifndef TINTIN_H
  #inclide "Tintin.h"
  #endif 
  #ifndef MILOU_H
  #include "Milou.h"
  #endif 

No for the interresting stuff. The toplevel Makefile.am should contain
only 

  # We're not native GNU 
  AUTOMAKE_OPTIONS	= foreign 

  # our subdiretories. 
  SUBDIRS	        = herge moulinsart detectives 

and configure.in should contain 

  dnl this is a comment		
  dnl this file _must_ exist
  AC_INIT(herge/src/Tintin.cxx) 
  dnl name of package and version number 
  AM_INIT_AUTOMAKE(adventure, 0.1.0)
  AC_PROG_CC
  AC_PROG_CXX
  AC_ROOT
  AC_ISC_POSIX
  AM_DISABLE_STATIC
  AM_PROG_LIBTOOL

  AC_OUTPUT([Makefile 
	     herge/Makefile 
	     moulinsart/Makefile
	     detectives/Makefile], [])

The file acinclude.m4 should contain all of build/misc/acinclude.m4
(just copy it) from the ROOT source tree. 

So far so good. The toplevel Makefile takes us to the three
subdirectories, and the configure script finds the ROOT installation
(macro AC_ROOT) C and C++ compiler, and writes al the Makefiles. No
this last step is ofcourse not at all automatic (wish it were); we
need to help out a bit. This is where config/config.h enters the
picture. In that file, we'll put some common stuff, here goes: 

  SOVERSION               = $(shell echo $(VERSION) | \
                              sed 's/\(.*\)\.\(.*\)\.\(.*\)/\1:\2:0/')
  ROOTCONF                = @ROOTCONF@
  ROOTCINT                = $(shell $(ROOTCONF) --prefix)/bin/rootcint
  ROOTLIBS                = $(shell $(ROOTCONF) --libs)
  ROOTGLIBS               = $(shell $(ROOTCONF) --glibs)
  ROOTCFLAGS              = $(shell $(ROOTCONF) --cflags)
  INCLUDES                = -Iinc -I$(top_srcdir)/include $(ROOTCFLAGS)
  CINTINCLUDES            = -Iinc -I$(top_srcdir)/include  
  LIBS                    = $(ROOTLIBS)
  CLEANFILES              = *Cint.cxx *Cint.h *~ core 

  vpath %.cxx src 
  vpath %.h   inc

  %Cint.cxx:inc/%Inc.h inc/%LinkDef.h
          $(ROOTCINT) -f $@ -c $(CINTINCLUDES) $^  

  all-local:
	  $(INSTALL) -d $(top_srcdir)/include 
	  $(INSTALLDATA) $(addprefix inc/,$(HEADERS)) $(top_srcdir)/include 


This file will be included into the Makefile.am's so that we only need
to do these things once. Notice the "@ROOTCONF@" that will be
substituted with the path to root-config, as found by the configure
script. 

Next, in each of the file herge/Makefile.am and
moulinsart/Makefile.am, we put the definitions needed to make each
library, for libHerge.so 

  lib_LTLIBRARIES     = libHerge.la 
  libHerge_la_SOURCES = Tintin.h    Tintin.cxx \
		        Minou.h     Minou.cxx \
                        HergeCint.h HergeCint.cxx 
  libHerge_la_LDFLAGS = -version-info $(SOVERSION)
  include_HEADERS     = Tintin.h Minou.h
  BUILT_SOURCES       = HergeCint.h HergeCint.cxx 

  include $(top_srcdir)/config/config.mk

and 

  lib_LTLIBRARIES          = libMoulinsart.la 
  libMoulinsart_la_SOURCES = Haddock.h        Haddock.cxx \
		             Tournesol.h      Tournesol.cxx \
                             MoulinsartCint.h MoulinsartCint.cxx 
  libMoulinsart_la_LDFLAGS = -version-info $(SOVERSION)
  include_HEADERS          = Haddock.h Tournesol.h
  BUILT_SOURCES            = MoulinsartCint.h MoulinsartCint.cxx 

  include $(top_srcdir)/config/config.mk

Never mind the odd .la in the names. It'll turn out right in the end. 
To make the program dupont and dupond, we need to link agianst
libHerge and libMoulinsart. Here's what we put in
detectives/Makefile.am: 

  bin_PROGRAMS        = dupond dupont
  dupond_SOURCES      = dupond.cxx  
  dupont_SOURCES      = dupont.cxx  
  dupond_LDADD        = ../herge/libHerge.la \
			../moulinsart/libMoulinsart.la
  dupont_LDADD        = ../herge/libHerge.la \
			../moulinsart/libMoulinsart.la
  
  include $(top_srcdir)/config/config.mk

That is it for the files. Now for the procedure. Cd into you package,
and do 

    automake -a 
    autoconf 
    

to make the Makefile.ins and the configure script. This step is only
needed if you change something in the diretories (add/remove
files). Then configure your sources, 

  ./configure --prefix=${HOME}/install 

(prefix should be set to somewhere you may write, default is
/usr/local). This step should always be done before building. Now all
the Makefiles are created (take a quick glance in some of them - they
are ugly, but very efficient). Now you can build 

   make 

and dosn't forget to install
(don't-eat-where-you-s**t-philosophy). That is it! 

Hope that helps you a bit. 

Yours, 

Christian  -----------------------------------------------------------
Holm Christensen                             Phone:  (+45) 35 35 96 91 
  Sankt Hansgade 23, 1. th.                  Office: (+45) 353  25 305 
  DK-2200 Copenhagen N                       Web:    www.nbi.dk/~cholm    
  Denmark                                    Email:       cholm@nbi.dk



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:40 MET