Compiling to shared library with static dependencies

Tanel L via Digitalmars-d digitalmars-d at puremagic.com
Wed Dec 14 14:17:25 PST 2016


First of all thanks Johan for urging me to compile it with only 
with that flag. It worked! Previously I tried to compile it with 
only BUILD_SHARED or both - and that failed. But I got it 
working. Thanks! More details below.

On Wednesday, 14 December 2016 at 21:41:53 UTC, Relja 
Ljubobratovic wrote:
> On Wednesday, 14 December 2016 at 20:46:15 UTC, Tanel L wrote:
>> Hi, thanks for the answer.
>>
>> I had tried disabling all imports, but now I created a clean 
>> new project to test this - it worked.
>
> Awesome. So LDC compile-link is ok, and also python runtime 
> linking is good.
>
>>
>> After that I moved the compiling and linking over to DUB, with 
>> dependencies:
>>
>> dependency "dcv" version="0.1.7"
>> dependency "mir" version="0.22.0"
>> targetPath "output"
>> targetType "dynamicLibrary"
>> dflags "-defaultlib=phobos2"
>
> Why are you defining defaultlib explicitly here? - wouldn't 
> this work fine without it? Also, like I said before, try 
> removing mir from dependencies since its included with dcv.
>
Yes it probably would, call it inexperience :) I'm now much 
smarter b/c I got it working :D
>>
>> The library source:
>> import std.stdio;
>> import dcv;
>> import core.runtime:Runtime;
>> extern (C) int doit(int a, int b) {
>> 	return a*b + dcv.imread("1.jpg").width.to!int;
>> }
>
> Did you actually call Runtime.initialize before calling doit? 
> Also, did you try the same code in ordinary D app? Anyways, 
> this works for me:
>
No, I will use your example as an example for the future, but It 
seems it is not required. Although I really did it with 
Initialize, I just forgot it from the sample I pasted here - it 
didn't make a difference.
> D source
> ========
> import std.stdio;
> import core.runtime;
>
> extern (C) void initd()
> {
>     Runtime.initialize;
> }
>
> extern (C) void terminated()
> {
>     Runtime.terminate();
> }
>
> extern (C) void showim()
> {
>     import dcv;
>     auto im = imread("img.jpg");
>     imshow(im);
>     waitKey();
> }
> ========
>
Thanks, I will use this as a template in the future.

> Python source
> ========
> from ctypes import *
>
> d = CDLL("libctypestest.so")
> d.initd()
> d.showim()
> d.terminated()
> ========
>
>>
>> This created an .so with huge amount of all kinds of external 
>> so deps, but it still failed with the same error:
>> OSError: libdynlibtest.so: undefined symbol: _d_eh_personality
>
> All kinds of external deps are expected since dcv is linking to 
> ggplotd and ffmpeg, which also link to whole lotta libraries. 
> I'm not sure about the binary size though. If you can, use only 
> dcv:core which has no other dependencies other than Mir. Also, 
> dcv:io links to ffmpeg at the moment, but if you need only 
> image i/o and would like to avoid linking to ffmpeg, you could 
> use just dcv:core with imageformats[1] (dcv wraps it's io 
> methods in imread). If you need help with this let me know.
>
Thanks, I don't need ffmpeg and I will surely use your advice. I 
am not worried about the size much. Is there any way to include 
many/most of them into the binary? Or should I just ship the deps 
alongside the shared lib?
>>
>> Otherwise:
>> Linux Mint 18 (basically Ubuntu 16.04)
>> LDC - the LLVM D compiler (1.1.0-beta6):
>>   based on DMD v2.071.2 and LLVM 3.9.0
>>   built with LDC - the LLVM D compiler (1.0.0)
>> gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
>> DUB version 1.1.1, built on Nov 30 2016
>>
>> Thank you for helping! :)
>
> Hey, no sweat - its a pleasure! I'm really glad you'd like to 
> use D (and Mir and DCV for that matter). I'd really like to 
> help you out as much as I can, so this can work out for you! :)
>
> Cheers,
> Relja

So I got it working.
Going to leave a mark behind about what I did incase someone else 
runs into this.

First of all, I successfully compiled ldc2 with:
cmake .. -DBUILD_SHARED_LIBS=ON
make -j 7

I then removed the installed "dmd" DEB package because it would 
always link with its libphobos2.so. I installed only "dub" from 
the apt repo instead.

Added the "lflags" param to dub, to have a final dub.sdl:
targetPath "output"
targetType "dynamicLibrary"
--dflags "-defaultlib=phobos2-ldc"
lflags "-L/home/tanel/thirdparty/ldc-dynamic-working/build/lib/"

Mucked around figuring out why dub enforces a 
"-defaultlib=phobos2" argument to ldc2 - didn't figure it out. 
LDC won't compile because it doesn't exists and if I add my own 
to dub.sdl LDC whines that the flag is declared twice.
So i created a symlink in the dynamic ldc lib dir and removed the 
"dflags" from my .sdl:
ln -s libphobos2-ldc.so libphobos2.so

Then it still couldn't find it, so I discovered that I had used 
LD_LIBRARY_PATH, instead of LIBRARY_PATH - doh! Fixed it.
In .bashrc:
export 
LIBRARY_PATH=/home/tanel/thirdparty/ldc-dynamic-working/build/lib/

$ dub run --config=library --compiler=ldc2
$ python -c "from ctypes import *; print 
CDLL('libdynlibtest.so').doit(10,10)"
> 2020

Success!
Thank you both so much. With this I can successfully move forward 
with using D in our company :)







More information about the Digitalmars-d mailing list