Re: [ROOT] Makefile question

From: Christian Holm Christensen (cholm@hehi03.nbi.dk)
Date: Tue Jun 19 2001 - 12:51:59 MEST


Hi Patois, 

On Mon, 18 Jun 2001 14:37:39 +0200 (CEST)
"Patois Yannick" <patois@ganil.fr> wrote
concerning ": [ROOT] Makefile question":
> Hello rooters,
> 
> Even if this is not directly a ROOT question, but more a make one, I
> think that some people here certainly had to do such things and could
> help.

My suggestion would be to use Autotools instead.  Plain and simple.
See my mail to RootTalk 

   http://root.cern.ch/root/roottalk/roottalk01/1108.html

> So, I have a ROOT project, with an 'src' and and 'include' dir.
> I use a toplevel Makefile made like this:

I personally prefer not to have "include" and "src" sub-directories,
at least not for bigger projects, since it's so much easier to open
files from Emacs if they are in the same directory, and then I only
have subdirectories for components.  But that's ofcourse a matter of
preference.  

If you don want "include" and "src" sub-directories, I strongly
suggest you have a Makefile in each of those directories, and you'll
be over all those problems. 

> <<<< extracts from File Makefile
> 
> # The following line seems hugly to me
> ABSPATH :=      $(shell pwd)
> 
> SRC      =      $(ABSPATH)/src
> 
> OBJECTS       = $(SRC)/source1.o $(SRC)/source2.o ...
> OBJECTSDICT   = $(INC)/header1.dict_o $(INC)/header2.dict_o ...
> 
> 
> # Generation C++ objects
> %.o : %.cpp
> 	$(CXX) $(CXXFLAGS) $< -c -o $@
> 
> # Compiling dictionnaries
> %.dict_o : %.C
>         $(CXX) $(CXXFLAGS) $< -c -o $@
> 
> #Creating dictionnaries
> %.C : %.H
>         rootcint -f $@ -c $<
> 
> >>>>

I'd suggest rules and variables like (I'm assuming a GNU system here): 

  DESTDIR	  = $(HOME) 

  LIBNAME	  = Foo
  LIBRARY	  = lib$(LIBNAME).so 
  LIBOBJS	  = source1.o source2.o header1Cint.o header2Cint.o 
  LIBMAJOR	  = 1
  LIBMINOR	  = 0
  LIBREVIS	  = 0
  LIBVERS	  = $(LIBMAJOR).$(LIBMINOR).$(LIBREVIS)

  HEADERS	  = ../include/header1.h ../include/header2.o 
  
  PROGRAM	  = bar 
  PROGOBJS	  = source3.o source4.o 

  ROOTCINT	  = $(shell root-config --prefix)/bin/rootcint
  ROOTCFLAGS	  = $(shell root-config --cflags)
  ROOTLIBS	  = $(shell root-config --libs)

  CPPFLAGS	  = -I../include $(ROOTCFLAGS)
  CXX		  = g++ -c 
  CXXFLAGS	  = -Wall -O2 -g 
  SO              = g++ -shared 
  SOFLAGS	  = -Wl,-soname,
  LD		  = g++ -rdynamic 
  LDFLAGS	  = -L./ -l$(LIBNAME) $(ROOTLIBS) 
  LNS		  = ln -sf 

  %.o:%.cxx 
	    $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -o $@ 

  %Cint.cxx %Cint.h:%.h 
	    $(ROOTCINT) -f $*.cxx -c $(CPPFLAGS) $< 

  %Cint.cxx %Cint.h:%Inc.h %LinkDef.h 
	    $(ROOTCINT) -f $*.cxx -c $(CPPFLAGS) $^ 

  %.so.$(LIBVERS):
	    $(SO) $(SOFLAGS)$*.so.$(LIBMAJOR) -o $@ $^ 
	    $(LNS) $@ $*.$(LIBMAJOR).$(LIBMINOR) 
	    $(LNS) $*.so.$(LIBMAJOR).$(LIBMINOR) $*.so.$(LIBMAJOR)
	    $(LNS) $*.so.$(LIBMAJOR) $*.so

  %:
	    $(LD) $(LDFLAGS) -o $@ $^ 

  vpath %.h ../include 

  .PHONY: all install clean realclean 


  all: $(LIBRARY).$(LIBVERS) $(PROGRAM) 

  install:all 
	      $(MKDIR) $(DESTDIR)/bin 
	      $(MKDIR) $(DESTDIR)/lib
	      $(MKDIR) $(DESTDIR)/include
	      $(INSTALL) $(PROGRAM) $(DESTDIR)/bin
	      $(INSTALL) $(LIBRARY)* $(DESTDIR)/lib
	      $(INSTALL) $(HEADERS)  $(DESTDIR)/include 
	      
  clean:
	rm -f *~ core *.o *Cint.{h,cxx} 

  realclean:clean
        rm -f $(LIBRARY) $(PROGRAM) 

   
To make GNU Make look in ../include for headers and linkdef files, you
can put in your src/Makefile 

  vpath %.h ../include 

However, if you project is bigger than say 3-4 classes, I strongly
recommend you use Autotools. 

> This works well.
> I can create my targets from the sources files, and link everything OK.
> 
> But, I dont really like this 'ABSPATH', so I tried to change it to '.' :
> ABSPATH = .

Ehr, it would be nice also to see the definition of INC, CPPFLAGS,
CXXFLAGS, CXX, and so on in your makefile. 
 
> But, when I compile, I got the following error:
> 
> rootcint -f include/GTDataParameters.C -c include/GTDataParameters.H
> g++ -g -D_REENTRANT -I/usr/local/root/prod/include -fPIC -I/home/patois/work/code/ganil_tape/include -Iinclude
> include/GTDataParameters.C -c -o include/GTDataParameters.dict_o
> In file included from include/GTDataParameters.C:5:
> include/GTDataParameters.h:29: include/GTDataParameters.H: Aucun fichier
> ou répertoire de ce type                                   ^^^^^^^^^^^^^
  ^^^^^^^^^^^^^^^^^^^^^^^^                                   ||||||||||||| 
  ||||||||||||||||||||||||                                   |||||||||||||

  It would make it much easier to help you if your error messages were
  in english (after all, that's the language of roottalk), so please
  unset you LANG environment, before "cut-and-paste"'ing into mails. 

> make: *** [include/GTDataParameters.dict_o] Error 1
> 
> rootcint generates it's file with a line inside like:
> #include "include/GTDataParameters.H"
> 
> Which is wrong as this file already reside in include.
> What is a good way to solve this problem ?

It's not nessecarily wrong since you are buildling from the parent
directory of "src" and "include", and anyway, the compiler looks for
files relative to the current directory, not releative to the header. 

The easist solution is for you to use Autotools. 

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:49 MET