How to build a shared library on MacOSX?

Dear (Mac-)ROOTers,

I am having trouble producing and using a ROOT shared library under MacOSX. I have Mac OSX 10.4.9, gcc 4.0.1. My ROOT version is 5.15/08
(so don’t tell me to upgrade to the latest version!).

I am trying to build the simplest possible shared library, starting from the
canonical three files myClass.cc, myClass.h and myClass_LinkDef.h

myClass.cc:

#include "myClass.h"
ClassImp(myClass)
myClass::myClass() {} // Constructor
myClass::~myClass() {} // Destructor

myClass.h:

#include "TObject.h"
class myClass : public TObject
{
public:

myClass(); // Constructor
~myClass(); // Destructor
ClassDef(myClass,1)
};

myClass_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

I compile myClass with -fPIC option:

g++ myClass.cc -c root-config --cflags --libs -fPIC

No problem, this gives me myClass.o

Then I create the dictionary file:

rootcint -f myClass_dict.cc -c myClass.h myClass_LinkDef.h

again no problem, I get myClass_dict.cc and myClass_dict.h
as expected, let’s compile those too:

g++ myClass_dict.cc -c root-config --cflags --libs -fPIC

Now we’re ready to build our shared library:
On my LINUX box, I would just do

g++ -shared -o myClass.so myClass.o myClass_dict.o

which gives me myClass.so, which I can then load in a ROOT
session like this:

root [0] gSystem->Load("./myClass.so");

On MacOSX, I presume the corresponding command is simply

g++ -dynamic -o myClass.so myClass.o myClass_dict.o

but this gives me
/usr/bin/ld: Undefined symbols:
_main
TVersionCheck::TVersionCheck(int)
ROOT::TGenericClassInfo::SetImplFile(char const*, int)
etc. (many more methods are listed)

Why does the linker insist on _main, I just want a class packaged as
a shared library! Does anyone know what I’m doing wrong here?

Many thanks in advance!

Thomas

Hi Thomas,

on the Mac you need to make a “bundle” which is a plugin, i.e. a library which can be loaded at run-time. To do that do:

g++ -bundle -undefined dynamic_lookup -o myClass.so myClass.o myClass_dict.o

The -shared option is for a dylib (a dynamic library against which you link, buit which cannot loaded at run-time).

Cheers, Fons.

Dear Fons

thanks so much for the very helpful reply - I can now link and load my dummy shared library.

The actual library I am working on is slightly more complicated than the one listed above, and here I run right into the next problem: it compiles and links okay, but upon loading it, ROOT misses some plugin:

root [0] gSystem->Load("./H5root.so");
Error in TPluginHandler::SetupCallEnv: class TRootGuiFactory not found in plugin Gui

*** Break *** bus error
/Users/thomas/svnwork/H5Root/911: No such file or directory.
Attaching to process 911.
Reading symbols for shared libraries . done
Reading symbols for shared libraries … done
0x9002a667 in wait4 ()

========== STACKS OF ALL THREADS ==========

Thread 1 (process 911 thread 0xd03):
#0 0x9002a667 in wait4 ()
#1 0x9004796b in system ()
#2 0x010af649 in TUnixSystem::StackTrace ()
#3 0x010b2ba9 in TUnixSystem::DispatchSignals ()
etc. etc.

Again, no such troubles under linux, so it must be a Mac issue. For my ROOT, I simply downloaded the precompiled tarball from root.cern.ch. Is there anything else I need??

Many thanks again,

Thomas

Have you set ROOTSYS env var so that $ROOTSYS/etc/system.rootrc can be found?

Cheers, Fons.

Yes:

thomas@ts69mac_63>ls -l $ROOTSYS/etc/system.rootrc
-rw-r–r-- 1 thomas thomas 27650 May 30 14:15 /sw/root/5.15.08/etc/system.rootrc

I should add that I can run a regular ROOT session without problem, AND that I can make full use of my custom application, as long as I link it into a main executable. The problem only occurs when I try to load my objects into a running ROOT session as a shared library… on a Mac that is.

Any ideas?

Thomas

No idea. What do you link in this “slightly” more complex plugin. I’ve no problems on Mac like this when loading a plugin. I would need a full debug trace. Can you try recompile ROOT from source.

Cheers, Fons.

Hi Fons

I am attaching a tar ball that contains the relevant parts of my application. I stripped away all calls to external libraries, so the application is totally useless, but should be enough to demonstrate my problem.

May I ask you to do the following (won’t take more than a minute):

tar -xzf H5Root.tar.gz
cd H5Root
make (this will build the standalone application, assuming you have ROOTSYS etc. set in the usual way)
./H5root (this will run the standalone application, i.e. fire up a GUI)

…up to here there is no problem on my Mac. But then when I try to build the shared library and load it into ROOT, disaster strikes:
make shlib (this will build the shared library)
—> Building shared library H5root.so …
done

root -l
root [0] gSystem->Load("./H5root.so");

Error in TPluginHandler::SetupCallEnv: class TRootGuiFactory not found in plugin Gui

*** Break *** bus error
/Users/schietinger/root/test_shlib/H5Root/3127: No such file or directory.
Attaching to process 3127.
Reading symbols for shared libraries . done
Reading symbols for shared libraries …
… done
0x9002a667 in wait4 ()

========== STACKS OF ALL THREADS ==========

Thread 1 (process 3127 thread 0xd03):
#0 0x9002a667 in wait4 ()
#1 0x9004796b in system ()
#2 0x010af649 in TUnixSystem::StackTrace ()
#3 0x010b2ba9 in TUnixSystem::DispatchSignals ()
#4 0x010b2cdd in SigHandler ()
#5
etc. etc.

Do you reproduce the problem?
Thank you for trying out…

Cheers,
Thomas
H5Root.tar.gz (49.1 KB)

Could load

root [0] gSystem->Load("./H5root.so"); without the mentioned error:

(Error in TPluginHandler::SetupCallEnv: class TRootGuiFactory not found in plugin Gui) :laughing:

However there are NO symbold loaded from the H5root.so:

root [1] TH5

is empty. :confused:

Andreas

Hello again,

encouraged by Andreas’ positive result, I simply reverted to my old ROOT 5.12/00 and there, bingo, everything worked just fine (with -bundle -undefined dynamic_lookup of course), including retrieving the symbols from the loaded shared library (TH5).

(The reason Andreas could not see the symbols from the loaded shared lib was that his OSTYPE is darwin8.0 (and not just darwin), and my GNUmakefile did not check for that, so he was still compiling with the -dynamic flag.)

When working in 5.15/08 we both run into the
Error in TPluginHandler::SetupCallEnv: class TRootGuiFactory not found in plugin Gui…
problem when loading the shared library. We conclude that there is something wrong in 5.15/08. It would be good if somebody could have a look at this. I will shortly upload a new tarball with the proper GNUmakefile just for MacOSX (to avoid any confusion from $OSTYPE = darwin/darwin8.0/not found at all by make…).

Thomas

OK, so here’s the new tar ball. I just changed the GNUmakefile to make sure it passes on the correct shared lib options for all Darwins (but this will now no longer work under linux).

The claim now is: when you execute the sequence below on MacOSX:

tar -xzf H5Root.tar.gz
cd H5Root
make shlib
root -l
root [0] gSystem->Load("./H5root.so");

you either get (5.12.00, 5.14.00) the next ROOT prompt, from which you can use the functions of the library, for instance

root [1]TH5Style::SetStyle();

OR, if you’re in 5.15.08, you get

Error in TPluginHandler::SetupCallEnv: class TRootGuiFactory not found in plugin Gui

*** Break *** bus error

I hope this can still be fixed for 5.16…
Thanks,

Thomas
H5Root.tar.gz (49 KB)

Hello again,

I just upgraded to 5.16, and the problem persists. :frowning:
I will file a bug report.

Thomas

Hi Thomas,

thanks for the test case. this bug is now fixed in the cvs head.

Cheers, Fons.

Hello,
I have the same library loading problem as Thomas when loading a library:

Error in TPluginHandler::SetupCallEnv: class TRootGuiFactory not found in plugin Gui

Hoping to solve it I downloaded the last example by Thomas and updated ROOT to 5.17.01 (CVS HEAD).
Still, it doesn’t work.

.L H5root.so

Am I doing something wrong?

My gcc version is:
Using built-in specs.
Target: i686-apple-darwin8
Configured with: /private/var/tmp/gcc/gcc-5367.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=nocona --with-tune=generic --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8
Thread model: posix
gcc version 4.0.1 (Apple Computer, Inc. build 5367)

Best Regards,
Alessandro

After my recent fixes, that are in the cvs head, I cannot reproduce these problems. It just works fine.

Cheers, Fons.