Reputation: 56
I'm new to using C in Rust and im currently trying to use BFD to build a Binary-Loader. Using bindgen to generate the Rust bindings worked great.
In my build.rs
I've used:
println!("cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu/");
and
println!("cargo:rustc-link-lib=static=bfd");
This fails with several undefined reference to 'filename_cmp'
like errors.
However: When linking dynamically (println!("cargo:rustc-link-lib=bfd");
) everything works just fine.
What am I missing?
I've made sure that libbfd.a
is present in /usr/lib/x86_64-linux-gnu/
.
Upvotes: 1
Views: 104
Reputation: 61417
I wanted to learn how to use C-Libraries in Rust
In that case, you made a very unlucky choice. libbfd
is a rare exception
to the rule of that the shared verion of a library and the static version
define the same symbols (and leave the same symbols undefined). libbfd.a
does not
define all of the symbols that libbfd.so
defines, and filename_cmp
is one the deficit.
See:
$ nm -D /usr/lib/x86_64-linux-gnu/libbfd.so | grep filename_cmp
0000000000109930 T filename_cmp
There it is in libbfd.so
. T
= defined in text
section.
And:
$ nm /usr/lib/x86_64-linux-gnu/libbfd.a | grep filename_cmp
U filename_cmp
U filename_cmp
U filename_cmp
There are nothing but undefined references in members of libbfd.a
.
The symbols that are missing from libbfd.a
v. libbfd.so
are defined in
libiberty
. libiberty
itself is a decommissioned GNU package.
That would explain why the definitions it provides to libbfd
have been statically linked
into the libbfd.so
- which is a system runtime - but maintainers evidently haven't got
around to decoupling libbfd.a
. I don't know why. In Ubuntu, the libbfd
shared library
is packaged in with libbinutils
; a runtime package libiberty
does not exist but the
development package libiberty-dev
does and it installs libiberty.a
.
Anyhow, that means that a program you can successfully link dynamically against libbfd
by itself
will fail to link against it statically by itself. You have to install the libiberty
development
package and append libiberty
to the linkage. Here's a relevant demonstration:
$ cat main.c
#include <stdio.h>
extern int filename_cmp (const char *s1, const char *s2);
int main(void)
{
if (filename_cmp("filename_cmp.c","FilenameCmp.c")) {
puts("Not equal");
} else {
puts("Equal");
}
return 0;
}
Default dynamic linkage against libbfd
:
$ gcc -o prog main.c -lbfd
$ ./prog
Not equal
Now statically:
$ gcc -o prog main.c -Wl,-Bstatic -lbfd -Wl,-Bdynamic
/usr/bin/ld: /tmp/ccOy7HDt.o: in function `main':
main.c:(.text+0x1d): undefined reference to `filename_cmp'
collect2: error: ld returned 1 exit status
And now statically with -liberty
appended:
$ gcc -o prog main.c -Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic
$ ./prog
Not equal
Upvotes: 0