4

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.

TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58

3 Answers3

5

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
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • The --start/--end-group is a crutch, not a real solution. Here it will "fix" the problem, but is the wrong soltion. The right solution is to order libraries correctly. – Employed Russian Jun 14 '13 at 03:57
  • @EmployedRussian It's definitely not an ideal solution, but given several libraries with circular dependencies to link to, ordering them manually turns into enough of a maintenance nightmare that the *crutch* starts to look very attractive. – Praetorian Jun 14 '13 at 03:59
2

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. :(

Community
  • 1
  • 1
TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58
1

Why do I have to link these libraries twice

Because the order of archive libraries on command line matters, and yours is wrong.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • I tried swapping the `--ldflags` and the `--libs` to no avail. Is there another way I can adjust them? So far, I don't know what else to do other than put them in twice. =/ – TheBuzzSaw Jun 14 '13 at 03:53
  • Once you read and understand the linked document, you *should* know what else you can do. – Employed Russian Jun 14 '13 at 03:55