Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the g++ flags to build a true .so/MH_BUNDLE shared library on mac osx (not a dylib)?

I'm trying to create a .so on mac osx. There seems to be a distinction between .so and .dylib types.

$ file  some_real.so
some_real.so: Mach-O 64-bit bundle x86_64

dynamiclib flag produces a dylib as expected

$ g++ -dynamiclib -o libgtest-1.7.0.dylib  [my .o files]
$ file libgtest-1.7.0.dylib
libgtest-1.7.0.dylib: Mach-O 64-bit dynamically linked shared library x86_64
#### ^^^ as expected

shared flag is not giving what I want

$ g++ -shared -o libgtest-1.7.0.so  [my .o files]
$ file libgtest-1.7.0.so
libgtest-1.7.0.dylib: Mach-O 64-bit dynamically linked shared library x86_64
#### ^^^ not as expected; wanted bundle x86_64

This stackoverflow answer talks about it a bit, and mentions the -fPIC flag. I added that to the commandline and it still produces a dynlib

$ g++ -shared -fPIC -o libgtest-1.7.0.so  [my .o files]
$ file libgtest-1.7.0.so
libgtest-1.7.0.dylib: Mach-O 64-bit dynamically linked shared library x86_64
#### ^^^ not as expected; wanted bundle x86_64

(Why: I need this output to be of the .so/MH_BUNDLE type because I'm trying to create some google tests against something that is already in the .so format and the linker is refusing to link the gtest .dylib and my .so. )

like image 293
marathon Avatar asked Jul 01 '14 21:07

marathon


1 Answers

If you want to build a bundle use -bundle instead of -dynamiclib when you're making the file.

The most obvious difference between bundles and dylibs is that you can link to a dylib at compile time.

e.g. g++ -o testfile testcode.c -lmylib will link to libmylib.dylib, while if you attempt to link a bundle you get:

ld: can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB) file 'test.bundle' for architecture x86_64

This is the biggest difference - you can't link a bundle dynamically, but instead have to dlopen or use the Object File Image Functions. I'd steer away from the OS X only functions - they are deprecated, and you can get all the functionality you need from the dl* functions instead.

As to building each, I'll give an example:

object file test.o, making a dylib:

g++ -dynamiclib -o test.dylib test.o

making a bundle:

g++ -bundle -o test.bundle test.o

linking a bundle at run-time & getting a symbol:

void *v = dlopen("test.bundle", RTLD_LOCAL);
// declare func_ptr as a pointer to a fn taking void, returning an int
int (*func_ptr)(void);
func_ptr = (int (*)(void))dlsym(v, "symbol");

linking a bundle using old routines (seriously, don't do this):

#include <mach-o/dyld.h>

int rc;
NSObjectFileImage img;
NSModule handle;
NSSymbol sym;

rc = NSCreateObjectFileImageFromFile("test.bundle", &img);
if (rc != NSObjectFileImageSuccess) {
  fprintf(stderr, "Could not load libanswer.bundle.\n");
  exit(-1);
}

/* Get a handle for the bundle. */
handle = NSLinkModule(img, "test.bundle", FALSE);

/* Look up the get_answer function. */
sym = NSLookupSymbolInModule(handle, "_get_answer");
if (sym == NULL)
{
  fprintf(stderr, "Could not find symbol: _get_answer.\n");
  exit(-2);
}

int (*func_ptr)(void);
func_ptr = NSAddressOfSymbol(sym);

if you're compiling with clang, then you'll get a bunch of warnings like:

warning: 'NSCreateObjectFileImageFromFile' is deprecated: first deprecated in OS X 10.5

i.e. please don't use these functions.

like image 99
Petesh Avatar answered Oct 15 '22 12:10

Petesh