Thread overview
OT: Linux shared lib question
May 12, 2008
Bill Baxter
May 13, 2008
e-t172
May 13, 2008
Bill Baxter
May 12, 2008
Not really a D question, but I'm hoping someone out there knows the answer (it is for the purpose of getting my D Multiarray library working better on Linux, though.)

I want to create a shared .so from a .a library.

I found on a web page somewhere that a .so can be created from some .o files using something like the following:

  gcc -shared -Wl,-soname,lib${name}.so.1 -o lib${name}.so.1.1 \
      a.o b.o c.o

So I figured if it can do that then surely this would work:

  gcc -shared -Wl,-soname,lib${name}.so.1 -o lib${name}.so.1.1 \
      libmylibrary.a

where libmylibrary.a is a lib containing a.o, b.o, and c.o.  After all a .a archive is basically just a concatenation of .o files in a convenient package.

However, though the command runs without reporting an error, the resulting .so does not contain the contents of libmylibrary.a.

SO what I'm doing now in my "make .so from .a" script is basically this:
    mkdir tmp
    cd tmp
    ar x path/to/libmylibrary.a
    gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.1  *.o
    rm *.o
    cd ..
    rmdir tmp


Extract the .o's from the .a, make the shared lib using that, then clean up.

Is that really the best way to do this?  With MinGW you can directly create a dll from a .a, so I was a bit surprised to find out that the same gcc flags do not work on Linux to create a .so.  Is this a case where the Windows version of a GNU tool is actually easier to use than the Linux version?

--bb
May 13, 2008
Bill Baxter a écrit :
> So I figured if it can do that then surely this would work:
> 
>   gcc -shared -Wl,-soname,lib${name}.so.1 -o lib${name}.so.1.1 \
>       libmylibrary.a
> 
> where libmylibrary.a is a lib containing a.o, b.o, and c.o.  After all a .a archive is basically just a concatenation of .o files in a convenient package.
> 
> However, though the command runs without reporting an error, the resulting .so does not contain the contents of libmylibrary.a.

man ld:

"--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file  in  the  archive  in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared  library,  forcing every  object  to  be included in the resulting shared library.  This option may be used more than once.

Two  notes when using this option from gcc: First, gcc doesn’t know about this option, so you have to use -Wl,-whole-archive.  Second, don’t  forget  to  use  -Wl,-no-whole-archive  after  your  list  of archives,  because  gcc will add its own list of archives to your link and you may not want this flag to affect those as well."
May 13, 2008
e-t172 wrote:
> Bill Baxter a écrit :
>> So I figured if it can do that then surely this would work:
>>
>>   gcc -shared -Wl,-soname,lib${name}.so.1 -o lib${name}.so.1.1 \
>>       libmylibrary.a
>>
>> where libmylibrary.a is a lib containing a.o, b.o, and c.o.  After all a .a archive is basically just a concatenation of .o files in a convenient package.
>>
>> However, though the command runs without reporting an error, the resulting .so does not contain the contents of libmylibrary.a.
> 
> man ld:
> 
> "--whole-archive
> For each archive mentioned on the command line after the --whole-archive option, include every object file  in  the  archive  in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared  library,  forcing every  object  to  be included in the resulting shared library.  This option may be used more than once.
> 
> Two  notes when using this option from gcc: First, gcc doesn’t know about this option, so you have to use -Wl,-whole-archive.  Second, don’t  forget  to  use  -Wl,-no-whole-archive  after  your  list  of archives,  because  gcc will add its own list of archives to your link and you may not want this flag to affect those as well."

Ah ok, Thanks!

I had a magic invocation I used on Windows that looked like this:


-gcc -mno-cygwin -shared -o umfpack.dll -Wl,--out-implib=umfpackdll.lib -Wl,--export-all-symbols -Wl,--allow-multiple-definition -Wl,--enable-auto-import -Wl,--whole-archive Lib/libumfpack.a ../AMD/Lib/libamd.a -Wl,--no-whole-archive ../lib/liblapack.a ../lib/libf77blas.a ../lib/libatlas.a  -lg2c

But Linux gcc barfed on the --export-all-symbols.  So I assumed incorrectly that the rest of the bits there must be bogus for Linux too.

Thanks for the explanation.  Good tutorial explanations of this stuff from an ordinary developer perspective seem to be hard to find.

--bb