Thread overview
Using the llvm D-bindings
Oct 06, 2010
Manuel König
Oct 06, 2010
Denis Koroskin
Oct 06, 2010
Manuel König
Re: Using the llvm D-bindings [solved]
Oct 06, 2010
Manuel König
Oct 06, 2010
Manuel König
Oct 06, 2010
mwarning
October 06, 2010
Hi,

did anyone have success using the llvm-2.7 D-bindings from the bindings project http://www.dsource.org/projects/bindings on x86_64 linux? I tried so far with ldc, but the compiler chokes about a mere 3570 lines of unresolved symbols when linking with ldc, compiling works fine.

Short version:
==============

I think the question boils down to "How do I create a D library and link it into a c++ program on x86_64 linux using ldc (or gdc or <any_other_D_compiler>)".

Long version:
=============
Here's a snip of the linker error messages I get from ldc:

// -- file main.d
import llvm.c.Core;

void main()
{
    auto context = LLVMGetGlobalContext();
}
// --

$ ldc -I=/path/to/llvm-2.7 \
-L=/usr/local/lib/libLLVM{Core,Support,System}.a main.d
/usr/local/lib/libLLVMCore.a(Core.o): In function `LLVMContextCreate':
Core.cpp:(.text+0x57): undefined reference to `operator new(unsigned
long)'
/usr/local/lib/libLLVMCore.a(Core.o): In function
`LLVMModuleCreateWithName':
Core.cpp:(.text+0x13a): undefined reference to `operator new(unsigned
long)'
/usr/local/lib/libLLVMCore.a(Core.o): In function
`LLVMModuleCreateWithNameInContext':
Core.cpp:(.text+0x195): undefined reference to `operator new(unsigned
long)'
/usr/local/lib/libLLVMCore.a(Core.o): In function `LLVMSetDataLayout':
Core.cpp:(.text+0x240): undefined reference to `std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string(char
const*, unsigned long, std::allocator<char> const&)'
Core.cpp:(.text+0x24f): undefined reference to `std::basic_string<char,
std::char_traits<char>, std::allocator<char>
>::assign(std::basic_string<char, std::char_traits<char>,
>std::allocator<char> > const&)'
Core.cpp:(.text+0x25e): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char>
>::_Rep::_S_empty_rep_storage'
Core.cpp:(.text+0x294): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char>
>::_Rep::_M_destroy(std::allocator<char> const&)'
> [...]

After scanning over the error messages, I think it's only operator, delete and std::* symbols that are missing. I also get the same error messages when I try to compile an equivalent C program that uses the llvm-c/* headers with gcc, but it works with g++, so I'm quite sure the problem is the missing c++ runtime, which is nonexistent in ldc.

I think there are only two ways to solve this:

(1) link the c++ runtime to ldc (I have no clue how to do that or if
    it's possible)
(2) Write a D library using the llvm D-bindings, define a semi-main
    function as extern(C), and write a c++ wrapper program that links
    to the D library and does nothing more than calling the semi-main
    function. The llvm symbols and c++ runtime will then be linked in
    using g++.

Option (2) seems easy, but ldc does not seem to have a linker swith to
build libraries, and doing

ldc -c myprog.d # produces myprog.o
ar -cq myprog.a myprog.o

to generate a library from the object file doesn't work because there are still undefined symbols to the main function or the module ctors in there, even when myprog.d doesn't define a main function. I could try to hack those missing functions back in by defining them in the C program, but there must be some simpler way to generate libraries, or am I at a loosing front here?

I also consider using other compilers than ldc as an option, but afaik the only other usable compiler might be gdc (is that stable by now?).
October 06, 2010
On Wed, 06 Oct 2010 16:20:41 +0400, Manuel König <manuelk89@gmx.net> wrote:

> Hi,
>
> did anyone have success using the llvm-2.7 D-bindings from the bindings
> project http://www.dsource.org/projects/bindings on x86_64 linux? I
> tried so far with ldc, but the compiler chokes about a mere 3570 lines
> of unresolved symbols when linking with ldc, compiling works fine.
>
> Short version:
> ==============
>
> I think the question boils down to "How do I create a D library and
> link it into a c++ program on x86_64 linux using ldc (or gdc or
> <any_other_D_compiler>)".
>
> Long version:
> =============
> Here's a snip of the linker error messages I get from ldc:
>
> // -- file main.d
> import llvm.c.Core;
>
> void main()
> {
>     auto context = LLVMGetGlobalContext();
> }
> // --
>
> $ ldc -I=/path/to/llvm-2.7 \
> -L=/usr/local/lib/libLLVM{Core,Support,System}.a main.d
> /usr/local/lib/libLLVMCore.a(Core.o): In function `LLVMContextCreate':
> Core.cpp:(.text+0x57): undefined reference to `operator new(unsigned
> long)'
> /usr/local/lib/libLLVMCore.a(Core.o): In function
> `LLVMModuleCreateWithName':
> Core.cpp:(.text+0x13a): undefined reference to `operator new(unsigned
> long)'
> /usr/local/lib/libLLVMCore.a(Core.o): In function
> `LLVMModuleCreateWithNameInContext':
> Core.cpp:(.text+0x195): undefined reference to `operator new(unsigned
> long)'
> /usr/local/lib/libLLVMCore.a(Core.o): In function `LLVMSetDataLayout':
> Core.cpp:(.text+0x240): undefined reference to `std::basic_string<char,
> std::char_traits<char>, std::allocator<char> >::basic_string(char
> const*, unsigned long, std::allocator<char> const&)'
> Core.cpp:(.text+0x24f): undefined reference to `std::basic_string<char,
> std::char_traits<char>, std::allocator<char>
>> ::assign(std::basic_string<char, std::char_traits<char>,
>> std::allocator<char> > const&)'
> Core.cpp:(.text+0x25e): undefined reference to `std::basic_string<char,
> std::char_traits<char>, std::allocator<char>
>> ::_Rep::_S_empty_rep_storage'
> Core.cpp:(.text+0x294): undefined reference to `std::basic_string<char,
> std::char_traits<char>, std::allocator<char>
>> ::_Rep::_M_destroy(std::allocator<char> const&)'
>> [...]
>
> After scanning over the error messages, I think it's only operator,
> delete and std::* symbols that are missing. I also get the same error
> messages when I try to compile an equivalent C program that uses the
> llvm-c/* headers with gcc, but it works with g++, so I'm quite sure the
> problem is the missing c++ runtime, which is nonexistent in ldc.
>
> I think there are only two ways to solve this:
>
> (1) link the c++ runtime to ldc (I have no clue how to do that or if
>     it's possible)
> (2) Write a D library using the llvm D-bindings, define a semi-main
>     function as extern(C), and write a c++ wrapper program that links
>     to the D library and does nothing more than calling the semi-main
>     function. The llvm symbols and c++ runtime will then be linked in
>     using g++.
>
> Option (2) seems easy, but ldc does not seem to have a linker swith to
> build libraries, and doing
>
> ldc -c myprog.d # produces myprog.o
> ar -cq myprog.a myprog.o
>
> to generate a library from the object file doesn't work because there
> are still undefined symbols to the main function or the module ctors
> in there, even when myprog.d doesn't define a main function. I could
> try to hack those missing functions back in by defining them in the C
> program, but there must be some simpler way to generate libraries,
> or am I at a loosing front here?
>
> I also consider using other compilers than ldc as an option, but afaik
> the only other usable compiler might be gdc (is that stable by now?).

You should probably ask LDC guys (irc://irc.freenode.net/ldc)
October 06, 2010
Am Wed, 06 Oct 2010 16:27:11 +0400
schrieb "Denis Koroskin" <2korden@gmail.com>:

> On Wed, 06 Oct 2010 16:20:41 +0400, Manuel König <manuelk89@gmx.net> wrote:
> 
> > Hi,
> >
> > did anyone have success using the llvm-2.7 D-bindings from the bindings project http://www.dsource.org/projects/bindings on x86_64 linux? I tried so far with ldc, but the compiler chokes about a mere 3570 lines of unresolved symbols when linking with ldc, compiling works fine.
> >
> > Short version:
> > ==============
> >
> > I think the question boils down to "How do I create a D library and link it into a c++ program on x86_64 linux using ldc (or gdc or <any_other_D_compiler>)".
> >
> > Long version:
> > =============
> > Here's a snip of the linker error messages I get from ldc:
> >
> > // -- file main.d
> > import llvm.c.Core;
> >
> > void main()
> > {
> >     auto context = LLVMGetGlobalContext();
> > }
> > // --
> >
> > $ ldc -I=/path/to/llvm-2.7 \
> > -L=/usr/local/lib/libLLVM{Core,Support,System}.a main.d
> > /usr/local/lib/libLLVMCore.a(Core.o): In function
> > `LLVMContextCreate': Core.cpp:(.text+0x57): undefined reference to
> > `operator new(unsigned long)'
> > /usr/local/lib/libLLVMCore.a(Core.o): In function
> > `LLVMModuleCreateWithName':
> > Core.cpp:(.text+0x13a): undefined reference to `operator
> > new(unsigned long)'
> > /usr/local/lib/libLLVMCore.a(Core.o): In function
> > `LLVMModuleCreateWithNameInContext':
> > Core.cpp:(.text+0x195): undefined reference to `operator
> > new(unsigned long)'
> > /usr/local/lib/libLLVMCore.a(Core.o): In function
> > `LLVMSetDataLayout': Core.cpp:(.text+0x240): undefined reference to
> > `std::basic_string<char, std::char_traits<char>,
> > std::allocator<char> >::basic_string(char const*, unsigned long,
> > std::allocator<char> const&)' Core.cpp:(.text+0x24f): undefined
> > reference to `std::basic_string<char, std::char_traits<char>,
> > std::allocator<char>
> >> ::assign(std::basic_string<char, std::char_traits<char>,
> >> std::allocator<char> > const&)'
> > Core.cpp:(.text+0x25e): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char>
> >> ::_Rep::_S_empty_rep_storage'
> > Core.cpp:(.text+0x294): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char>
> >> ::_Rep::_M_destroy(std::allocator<char> const&)'
> >> [...]
> >
> > After scanning over the error messages, I think it's only operator, delete and std::* symbols that are missing. I also get the same error messages when I try to compile an equivalent C program that uses the llvm-c/* headers with gcc, but it works with g++, so I'm quite sure the problem is the missing c++ runtime, which is nonexistent in ldc.
> >
> > I think there are only two ways to solve this:
> >
> > (1) link the c++ runtime to ldc (I have no clue how to do that or if
> >     it's possible)
> > (2) Write a D library using the llvm D-bindings, define a semi-main
> >     function as extern(C), and write a c++ wrapper program that
> > links to the D library and does nothing more than calling the
> > semi-main function. The llvm symbols and c++ runtime will then be
> > linked in using g++.
> >
> > Option (2) seems easy, but ldc does not seem to have a linker swith
> > to build libraries, and doing
> >
> > ldc -c myprog.d # produces myprog.o
> > ar -cq myprog.a myprog.o
> >
> > to generate a library from the object file doesn't work because there are still undefined symbols to the main function or the module ctors in there, even when myprog.d doesn't define a main function. I could try to hack those missing functions back in by defining them in the C program, but there must be some simpler way to generate libraries, or am I at a loosing front here?
> >
> > I also consider using other compilers than ldc as an option, but afaik the only other usable compiler might be gdc (is that stable by now?).
> 
> You should probably ask LDC guys (irc://irc.freenode.net/ldc)

Thanks, I'll try. But I think the development of LDC was put on hold due to lack of time and interest, let's see if I can find someone there :)

October 06, 2010
Am Wed, 6 Oct 2010 14:36:16 +0200
schrieb Manuel König <manuelk89@gmx.net>:

> > 
> > You should probably ask LDC guys (irc://irc.freenode.net/ldc)
> 
> Thanks, I'll try. But I think the development of LDC was put on hold due to lack of time and interest, let's see if I can find someone there :)
> 

Well, the channel was actually full of people, and the problem was solved quickly. Actually the solution was method (1), linking in the stdc++ lib. For the record, here are some usage instructions for the llvm bindings. I will commit them to the repositority later, but I'll wait a bit and see if you have something to add.

Initial setup:
==============

(1) checkout from svn
(2) cd /path/to/llvm-2.7
(3) run prebuild.sh, this builds Target.o and Ext.o which have
    to be passed to the linker. For convenience, these *.o files
    are also merged into a single library libllvm-c-ext.a.

Note: Target.o and Ext.o are usually not needed for the regular llvm c interface. But the D bindings add some extra bindings, because the official c interface just doesn't expose all functionality from the c++ interface. These are implemented as a "c++ to c to d" bridge (c++ to c is Target.cpp and Ext.cpp, c to d is Target.d and Ext.d).

Building your application:
==========================

To compile and link a file main.d, run

LLVMD=/path/to/llvm-dbindings
LLVM_LIBS=`llvm-config --libs | sed 's/-l/-L-l'`
ldc -I=$LLVMD \
    -L=$LLVMD/{Target,Ext}.o \
    $LLVM_LIBS \
    -L-ldl -L-lstdc++ -relocation-model=pic \
    main.d

Parameters:
LLVM_LIBS                 a list of all llvm libraries, formatted for
ldc -L=$LLVMD/{Target,Ext}.o  only needed when you use Target.d or Ext.d
-L-lstdc++                links in the c++ standard library (llvm at
it's core is c++) -relocation-model=pic     necessary for calling code
in your app from inside of the llvm vm

October 06, 2010
The previous "Initial setup" description didn't pass the "copy paste" test, now it's more instructive. The same should work for llvm 2.6 and 2.8, too (yes, 2.8 was just released and the bindings are already there :)

Initial setup:
==============

svn co http://svn.dsource.org/projects/bindings/trunk/llvm-2.7
cd llvm-2.7
./prebuild.sh

prebuild.sh builds Target.o and Ext.o which have to be passed to the linker. For convenience, these *.o files are also merged into a single library libllvm-c-ext.a.

Target.o and Ext.o are usually not needed for the regular
llvm c interface. But the D bindings add some extra bindings,
because the official c interface just doesn't expose all
functionality from the c++ interface. These are implemented as a
"c++ to c to d" bridge (c++ to c is Target.cpp and Ext.cpp, c to
d is Target.d and Ext.d).

Building your application:
==========================

To compile and link a file main.d, run

LLVMD=/path/to/llvm-dbindings
LLVM_LIBS=`llvm-config --libs | sed 's/-l/-L-l'`
ldc -I=$LLVMD \
    $LLVM_LIBS \
    -L=$LLVMD/libllvm-c-ext.a \
    -L-ldl -L-lstdc++ -relocation-model=pic \
    main.d

Parameters:
LLVM_LIBS                 a list of all llvm libraries, formatted for
ldc -L=$LLVMD/libllvm-c-ext.a only needed when you use Target.d or Ext.d
-L-lstdc++                links in the c++ standard library (llvm at
it's core is c++) -relocation-model=pic     necessary for calling code
in your app from inside of the llvm vm
October 06, 2010
On Wed, 06 Oct 2010 16:57:09 +0200, Manuel König wrote:

> LLVM_LIBS=`llvm-config --libs | sed 's/-l/-L-l'`

typo detected, you need:
sed 's/-l/-L-l/g'

:)