Discussion:
Generation of static libraries is broken for a Rust sub-library (librsvg)?
Federico Mena Quintero
2018-02-07 00:38:01 UTC
Permalink
Hi, everyone,

I'm trying to figure out why librsvg's build setup is broken for static
libraries. The automake/libtool machinery works fine to build
librsvg.la, but the resulting librsvg.a is broken.

Librsvg gets built from a bunch of .o files from C, and a
librsvg_internals.a library built by Rust/Cargo. Rust properly
compiles this internals library with PIC.

After the .o files and the librsvg_internals.a are built, we use
libtool in the usual fashion:

RUST_LIB=@abs_top_builddir@/rust/target/@RUST_TARGET_SUBDIR@/librsvg_internals.a

***@RSVG_API_MAJOR_VERSION@_la_LIBADD = \
$(LIBRSVG_LIBS) \
$(LIBM) \
$(RUST_LIB)

That is, LIBADD contains the librsvg_internals.a.

The resulting librsvg.la is built just fine. However, the static
librsvg.a is broken. For example, this is the output of "ar -t":

$ cd ~/src/librsvg
$ ar -t .libs/librsvg-2.a
librsvg_internals.a <- this is the Rust sub-library
librsvg_2_la-librsvg-enum-types.o
librsvg_2_la-librsvg-features.o
librsvg_2_la-rsvg-base-file-util.o
[... a bunch of other .o files here ...]

While I don't know all the details of how .a files are made from
libtool, it sounds like that librsvg_internals.a should really be
exploded into the individual .o files, and *those* put into the final
librsvg.a library.

Indeed if I have a tiny program foo.c:

#include <librsvg/rsvg.h>
int main(){
RsvgHandle *svg = rsvg_handle_new_from_data (NULL, 0, NULL);
}

and build it like this:

$ gcc -o foo foo.c `pkg-config --cflags librsvg-2.0` librsvg-2.a `pkg-
config --libs cairo-fc gobject-2.0 gio-2.0 libxml-2.0` -lm

it doesn't work; it gives me this output:

librsvg-2.a(librsvg_2_la-rsvg-base.o): In function `add_node_to_handle':
/home/federico/src/librsvg-latest/rsvg-base.c:207: undefined reference to `rsvg_node_ref'
librsvg-2.a(librsvg_2_la-rsvg-base.o): In function `node_set_atts':
/home/federico/src/librsvg-latest/rsvg-base.c:396: undefined reference to `rsvg_node_set_atts'
/home/federico/src/librsvg-latest/rsvg-base.c:402: undefined reference to `rsvg_node_get_type'
[... tons more of undefined symbols ...]

Those symbols are indeed in the librsvg_internals.a sub-library.

How can I make libtool create the toplevel librsvg.a correctly, out of
a bunch of .o files and a librsvg_internals.a library that is already
PIC-compiled?

(This also breaks --disable-shared for the configure script.)

Any suggestions are appreciated.

(For reference, this is mentioned in both
https://gitlab.gnome.org/GNOME/librsvg/issues/159 (Linux) and
https://github.com/Homebrew/homebrew-core/issues/23772 (MacOS)).

Thanks,

Federico
Andrew W. Nosenko
2018-02-08 00:16:02 UTC
Permalink
What about marking librsvg_internals.a as 'noinst_'?
I never linked static library into static library (and even unsure that it
is correct at all), so cannot to say about your question directly, but from
what I know about noinst_ libtool "libraries", it can lead to result
desired by you.
Post by Federico Mena Quintero
Hi, everyone,
I'm trying to figure out why librsvg's build setup is broken for static
libraries. The automake/libtool machinery works fine to build
librsvg.la, but the resulting librsvg.a is broken.
Librsvg gets built from a bunch of .o files from C, and a
librsvg_internals.a library built by Rust/Cargo. Rust properly
compiles this internals library with PIC.
After the .o files and the librsvg_internals.a are built, we use
/librsvg_internals.a
$(LIBRSVG_LIBS) \
$(LIBM) \
$(RUST_LIB)
That is, LIBADD contains the librsvg_internals.a.
The resulting librsvg.la is built just fine. However, the static
$ cd ~/src/librsvg
$ ar -t .libs/librsvg-2.a
librsvg_internals.a <- this is the Rust sub-library
librsvg_2_la-librsvg-enum-types.o
librsvg_2_la-librsvg-features.o
librsvg_2_la-rsvg-base-file-util.o
[... a bunch of other .o files here ...]
While I don't know all the details of how .a files are made from
libtool, it sounds like that librsvg_internals.a should really be
exploded into the individual .o files, and *those* put into the final
librsvg.a library.
#include <librsvg/rsvg.h>
int main(){
RsvgHandle *svg = rsvg_handle_new_from_data (NULL, 0, NULL);
}
$ gcc -o foo foo.c `pkg-config --cflags librsvg-2.0` librsvg-2.a `pkg-
config --libs cairo-fc gobject-2.0 gio-2.0 libxml-2.0` -lm
/home/federico/src/librsvg-latest/rsvg-base.c:207: undefined reference to `rsvg_node_ref'
/home/federico/src/librsvg-latest/rsvg-base.c:396: undefined reference to
`rsvg_node_set_atts'
/home/federico/src/librsvg-latest/rsvg-base.c:402: undefined reference to
`rsvg_node_get_type'
[... tons more of undefined symbols ...]
Those symbols are indeed in the librsvg_internals.a sub-library.
How can I make libtool create the toplevel librsvg.a correctly, out of
a bunch of .o files and a librsvg_internals.a library that is already
PIC-compiled?
(This also breaks --disable-shared for the configure script.)
Any suggestions are appreciated.
(For reference, this is mentioned in both
https://gitlab.gnome.org/GNOME/librsvg/issues/159 (Linux) and
https://github.com/Homebrew/homebrew-core/issues/23772 (MacOS)).
Thanks,
Federico
--
Andrew W. Nosenko <***@gmail.com>
Loading...