Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I have to link these libraries twice for LLVM?

Tags:

c++

linker

llvm

I'm trying to compile a sample LLVM program. The linker step uses this command.

llvm-config-3.2 --ldflags --libs

That results in the following command.

g++  -o bin/Debug/test-llvm obj/Debug/main.o   -L/usr/lib/llvm-3.2/lib  -lpthread -lffi -ldl -lm  (a boat load of LLVM libraries here)

However, it fails to link. I get errors like this.

undefined reference to ffi_type_float

So, I added -lffi and -ldl to the end.

g++  -o bin/Debug/test-llvm obj/Debug/main.o   -L/usr/lib/llvm-3.2/lib  -lpthread -lffi -ldl -lm  (a boat load of LLVM libraries here) -lffi -ldl

So, yes, they show up TWICE in the command... but it works this way. Why? They are clearly referenced earlier in the arguments.

like image 535
TheBuzzSaw Avatar asked Mar 23 '23 14:03

TheBuzzSaw


2 Answers

One or more of the libraries appearing on the command line after -lffi and -ldl refer to symbol(s) defined in one of those libraries. But the linker has already finished scanning libffi and libdl and does not rescan them for these symbols. This circular dependency can be resolved by forcing the linker to scan those libraries again by re-listing their names at the end of the list.

A more scalable solution is to use --start-group archives --end-group option to list the libraries to link to. Quoting from the man page:

-( archives -)
--start-group archives --end-group The archives should be a list of archive files. They may be either explicit file names, or -l options.

The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched only once in the order that it is specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references are resolved.

Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.

So your command line would look like this:

g++ -o bin/Debug/test-llvm obj/Debug/main.o -L/usr/lib/llvm-3.2/lib --start-group -lpthread -lffi -ldl -lm ... --end-group
like image 191
Praetorian Avatar answered Apr 01 '23 02:04

Praetorian


Ah, I found the solution. Swapping the flags didn't actually change the order. I had to break it out into two separate calls.

llvm-config-3.2 --libs
llvm-config-3.2 --ldflags

And yeah, this is technically answered in that other question: Why does the order in which libraries are linked sometimes cause errors in GCC?

I still just think this question is relevant because doing what the docs told me to do led me into danger. :(

like image 38
TheBuzzSaw Avatar answered Apr 01 '23 04:04

TheBuzzSaw