Missing symbols when compiling

Hi,

I am trying to implement a class called Calibrator that makes use of another class called CalibrationConstants. I create the latter, compile it with

$ root.exe -b -q CalibrationConstants.cxx+

and then, when trying to compile the Calibrator I get:

$ root -b -q Calibrator.cxx+
Processing Calibrator.cxx+…
dlopen error: dlopen(/Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so, 9): Symbol not found: __ZTV20CalibrationConstants
Referenced from: /Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so
Expected in: dynamic lookup

Load Error: Failed to load Dynamic link library /Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so
*** Interpreter error recovered ***

I don’t understand what is happening… Any help? I attach both libraries.

Thanks,
Albert
CalibrationConstants.h (1.03 KB)
CalibrationConstants.cxx (3.1 KB)
Calibrator.h (5.72 KB)
Calibrator.cxx (2.38 KB)

I trimmed my example down so it is easier to have a look, I think I am missing some step but I just cannot see which one, neither in the documentation or looking up in forums:

CalibrationConstants.h

[code]#ifndef CALIBRATIONCONSTANTS_H
#define CALIBRATIONCONSTANTS_H
#include “TObject.h”
#include “TString.h”

class CalibrationConstants : public TObject {
private:
float m_defaultPrs;

public:
// Constructors
CalibrationConstants();
CalibrationConstants( TString name );
// ROOT
ClassDef( CalibrationConstants , 1 );
};

#endif[/code]

CalibrationConstants.cxx

[code]#include “CalibrationConstants.h”
#include

CalibrationConstants::CalibrationConstants() : m_defaultPrs( 11.0 ) {};

CalibrationConstants::CalibrationConstants( TString name ) : m_defaultPrs( 11.0 ) { std::cout << name << std::endl; };

#if !defined( CINT )
ClassImp( CalibrationConstants );
#endif[/code]

Calibrator.h

[code]#include
#include <TObject.h>
#include “CalibrationConstants.h”

class Calibrator : public TObject {
private:
CalibrationConstants* m_constantsInit;
public:
// Constructors and configuration
Calibrator();
ClassDef( Calibrator , 1 );
};[/code]

Calibrator.cxx

[code]#include “Calibrator.h”

#if !defined( CINT )
ClassImp( Calibrator );
#endif

Calibrator::Calibrator() {
m_constantsInit = new CalibrationConstants();
}
[/code]

Then I do:

[code]albert@res09-susp-399:~/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration$ root -q -b CalibrationConstants.cxx+


  •                                     *
    
  •    W E L C O M E  to  R O O T       *
    
  •                                     *
    
  • Version 5.22/00 17 December 2008 *
  •                                     *
    
  • You are welcome to visit our Web site *
  •      http://root.cern.ch            *
    
  •                                     *
    

ROOT 5.22/00 (trunk@26997, De 18 2008, 10:17:00 on macosx)

CINT/ROOT C/C++ Interpreter version 5.16.29, Jan 08, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0]
Processing CalibrationConstants.cxx+…
(class CalibrationConstants)43254704
albert@res09-susp-399:~/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration$ root -q -b Calibrator.cxx+


  •                                     *
    
  •    W E L C O M E  to  R O O T       *
    
  •                                     *
    
  • Version 5.22/00 17 December 2008 *
  •                                     *
    
  • You are welcome to visit our Web site *
  •      http://root.cern.ch            *
    
  •                                     *
    

ROOT 5.22/00 (trunk@26997, De 18 2008, 10:17:00 on macosx)

CINT/ROOT C/C++ Interpreter version 5.16.29, Jan 08, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0]
Processing Calibrator.cxx+…
Info in TUnixSystem::ACLiC: creating shared library /Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so
dlopen error: dlopen(/Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so, 10): Symbol not found: __ZN20CalibrationConstantsC1Ev
Referenced from: /Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so
Expected in: dynamic lookup

Load Error: Failed to load Dynamic link library /Users/albert/Arxiu/Fisica/LHCb/CaloCalibration/Calibration/analysis/PionCalibration/./Calibrator_cxx.so
Undefined symbols:
“CalibrationConstants::CalibrationConstants()”, referenced from:
Calibrator::Calibrator()in test1_cxx_ACLiC_dict.o
Calibrator::Calibrator()in test1_cxx_ACLiC_dict.o
"_main", referenced from:
start in crt1.10.5.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
*** Interpreter error recovered ***
[/code]

I don’t know if I have to link some libraries or how to do it… Thanks in advance!!

Albert

Hi,

Try in this order:$ root -l root [0] .L CalibrationConstants.cxx++ Info in <TUnixSystem::ACLiC>: creating shared library /Users/bellenot/rootdev/apuignav/./CalibrationConstants_cxx.so root [1] .L Calibrator.cxx++ Info in <TUnixSystem::ACLiC>: creating shared library /Users/bellenot/rootdev/apuignav/./Calibrator_cxx.so /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:48: warning: unused parameter 'option' /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:73: warning: unused parameter 'npar' /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:73: warning: unused parameter 'gin' /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:73: warning: unused parameter 'f' /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:73: warning: unused parameter 'par' /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:73: warning: unused parameter 'iflag' /Users/bellenot/rootdev/apuignav/./Calibrator.cxx: In member function 'void Calibrator::minimize()': /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:91: warning: 'gin' is used uninitialized in this function /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:91: warning: 'par' is used uninitialized in this function /Users/bellenot/rootdev/apuignav/./Calibrator.cxx:91: warning: 'iflag' is used uninitialized in this function root [2].q
So then the dependency will be fullfiled next time you load Calibrator.cxx:

$ root -l root [0] .L Calibrator.cxx+ root [1] .q
Cheers, Bertrand.

Thank you! It works! Could you clarify why does it work? And what is the difference between “+” and “++”?

Thanks,
Albert

Hi Albert,

It works because ACLiC set the already loaded libraries (in this case CalibrationConstants_cxx.so) as dependencies of the following ones (Calibrator_cxx.so)
A single ‘+’ means “compile and load only if the code is new or has been modified”, using “++” force the recompilation. See the user guide: http://root.cern.ch/drupal/content/users-guide and the online documentation: http://root.cern.ch/drupal/content/compiling-macros

Cheers, Bertrand.

Hi Betrand,

now I see… I understand it, so now that I am learning I’d like to add a further question: is this the best way to compile my libraries or is there any better way to compile them both in a go or in an easier way?

Cheers,
Albert

Hi,

To compile both file at the same you could use a third file:// File loader.C #include "CalibrationConstants.cxx" #include "Calibrator.cxx" #ifdef __MAKECINT__ // Since ACLiC only generate the dictionary for the script itself and its // header file, we must explicitly request the dictionary for the classes // in the included files #pragma link C++ class CalibrationConstants+; #pragma link C++ class Calibrator+; #endif
and doroot [] .L loader.C+

Cheers,
Philippe.

Now I see, and from PyROOT I should do

from ROOT import gROOT gROOT.LoadMacro("loader.C+") from ROOT import Calibrator c = Calibrator()

I also read in the forum that if I create a rootmap I would be able to do something like

from ROOT import Calibrator c = Calibrator()

So I don’t need the extra steps at the beginning if nothing has changed. How should I add this rootmap creation to the loader.C macro?

Thanks,
Albert

Hi,

you can simply create the .rootmap by hand; see the ones in $ROOTSYS/lib for the format.

Cheers, Axel.