RE: [ROOT] rootcint, templates and multiply defined symbols

From: Philippe Canal (pcanal@fnal.gov)
Date: Thu Sep 05 2002 - 19:32:29 MEST


Hi Dave,

This problem is actually due to the fact that both ADict and BDict define
the dictionary of the class A<int>.

This is due to the fact that, currently, CINT default to create the
dictionary entry for all new symbols encountered.  This is why, for example,
all linkdef file starts with '#pragma link off all classes'.   In your
example, it just so happens that for BDict.C the class A<int> is encountered
the first time at the time of the instantiation of the class B<int>.  The
class B<int> is instantiated as a result of the statement '#pragma link C++
B<int>;'.  Hence, BDict.C, inadvertently, is being asked to generate the
dictionary entry for A<int>.  Hence the duplication, which IS a problem.

To solve the problem, you can simple do:

	#pragma link off class A<int>;

in BLinkDef.h

You could also force the instantiation of B<int> before the start of the
linkdef proper by doing:

	B<int> *dummy;
      #ifdef __CINT__
      #pragma link off all globals;
	....

Cheers,
Philippe.

-----Original Message-----
From: owner-roottalk@pcroot.cern.ch
[mailto:owner-roottalk@pcroot.cern.ch]On Behalf Of David Morrison
Sent: Tuesday, August 20, 2002 10:43 AM
To: roottalk@pcroot.cern.ch
Subject: [ROOT] rootcint, templates and multiply defined symbols


Hi,

I've attached a tar file of a trivial project that illustrates a problem
I'm having with recent versions of ROOT.  I have a couple of classes,
related by inheritance, with a template involved.  The dictionaries
generated by rootcint multiply define a global initializer for the base
class.  This didn't happen with earlier versions of ROOT (3.02/x).
 Using 3.03/07 I get the following messages when attempting to build the
attached project:

rootcint -f ADict.C -c A.h ALinkDef.h
Class A<int>: Streamer() not declared
rootcint -f BDict.C -c B.h BLinkDef.h
Class B<int>: Streamer() not declared
Class A<int>: Streamer() not declared
g++ -c ADict.C -I. `root-config --cflags`
g++ -c BDict.C -I. `root-config --cflags`
g++ -shared -o libAB.so ADict.o BDict.o `root-config --libs`
BDict.o: In function `ROOT::GenerateInitInstance(A<int> const *)':
BDict.o(.text+0xd8): multiple definition of
`ROOT::GenerateInitInstance(A<int> const *)'
ADict.o(.text+0x0): first defined here
BDict.o: In function `ROOT::AlEintgR_IsA(void const *)':
BDict.o(.text+0x17c): multiple definition of `ROOT::AlEintgR_IsA(void
const *)'
ADict.o(.text+0xa4): first defined here
BDict.o: In function `ROOT::AlEintgR_Dictionary(void)':
BDict.o(.text+0x15c): multiple definition of
`ROOT::AlEintgR_Dictionary(void)'
ADict.o(.text+0x84): first defined here
collect2: ld returned 1 exit status
make: *** [all] Error 1

I see the following in the development notes:

2002-06-13 18:24  brun

	* utils/src/rootcint.cxx:
	New version  of rootcint from Philippe fixing several problems
	and side-effects of the recent changes by Victor.
	Philippe still working on a problem reported by Mathieu de Naurois
	when using namespaces and templates.


which sounds like it might be related to the problem I'm seeing.
 Assuming this is the case, has there been progress toward any solution?
  There doesn't seem to be any way to tell rootcint not to generate the
base class initializer.  Is this the case?

Dave

PS: To try the example, save the attachment and do: uudecode -o -
g.tar.gz.uu | tar zx ; cd g ; make

--
David Morrison  Brookhaven National Laboratory  phone: 631-344-5840
                Physics Department, Bldg 510 C    fax: 631-344-3253
                          Upton, NY 11973-5000



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:07 MET