[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Simultaneous pic and non-pic convenience libs [Was: [RFC] New library "t

From: Charles Wilson
Subject: Simultaneous pic and non-pic convenience libs [Was: [RFC] New library "type" needed?]
Date: Sat, 31 Mar 2007 00:48:48 -0500
User-agent: Thunderbird (Windows/20070221)

Charles Wilson wrote:

I'd still like to be able to build my convenience library as both pic and non-pic tho. And I still want to prevent libiberty.a(non-pic) from getting the --whole-archive treatment when it comes to libbfd.a.
Several systems simply don't allow to mix PIC and non-PIC symbols.
On w32 this warning is pathetic, but on others we would have a problem
here.  (I can see why, on w32, you'd want to kill the warning here.)

No, you're missing the point of my statement: I *know* you don't want to mix pic and non-pic.

After doing a bit of reading, the statements above are a little too strong. It's not that you can't mix pic and non-pic (or at least, it's not obviously the case; we'll dig deeper -- see below). At the surface level, it is simply that where -fpic/-fPIC makes a difference, you cannot include non-pic in a shared library. However, there's no reason you can't include pic in a static library: you just lose a little efficiency (from the AutoBook)

"In practice, you can link PIC objects into a static archive for a small overhead in execution and load speed..."

e.g. shared << pic only
     static << pic and non-pic ok

Which I guess is why: if pic available, libtool defaults to using pic objects in the convenience lib, unless specifically directed otherwise. And yet, that same, single, convenience lib (which is pic) will be used when creating both static and shared libraries that depend on it.

Digging deeper:

On cygwin/mingw *at present*, the only difference between pic and non-pic is that the former objects were compiled with "-DPIC -DDLL_EXPORT". This could cause trouble for convenience libs that are sensitive to DLL_EXPORT (and isn't that the point? otherwise, why bother to -D it?) -- because while the machine code is more-or-less the same (that is, gcc doesn't generate machine instructions differently _on its own_) -- some packages might behave differently _at the source code level_ due to the different -Ddefines

One example is libltdl itself, as we discovered a few months ago:

#if !defined(LT_SCOPE)
#  if defined(__WINDOWS__) || defined(__CYGWIN__)
#    if defined(DLL_EXPORT)
#      define LT_SCOPE  extern __declspec(dllexport)
#    endif
#    if defined(LIBLTDL_DLL_IMPORT)
#      define LT_SCOPE  extern __declspec(dllimport)
#    endif
#  endif
#  if !defined(LT_SCOPE)
#    define LT_SCOPE    extern
#  endif

So, we come full circle: now it's clear that the libtool assumption of "hey, if pic available, then just always use pic when building convenience libs (unless instructed otherwise via no-pic/--without-pic); that way, the result is "safe" for use regardless", breaks down on cygwin/mingw!

So, perhaps it really is time to revisit this assumption...see

Alexandre Oliva, February 2001 [ignoring the bits about "installable convenience libraries (??!!)]
"And I wish convenience libraries could still come
in PIC and non-PIC versions, just like object files.  Currently, every
time you create a convenience archive, you don't get the non-PIC
objects, unless the PIC objects aren't available."

There's still some issues with convenience libs themselves (where the following discussion ignores ALL of the above, no new library types, no new -exclude-lib option), like:
 (a) we should build a pic version and stuff it inside .libs/ if
     -enable-shared, and put a regular version in . if -enable-static
 (b) When linking a shared lib where a convenience lib appears in the
     deps, use the one in the .libs/ directory
 (c) ??? when linking a PIE executable where a convenience lib appears
     in the deps, use the one in the .libs/ directory
 (d) when creating a static lib where a convenience lib appears in the
     deps, use the one in the . directory when doing the explode-and-
     incorporate thing.
 (e) when creating a next-level convenience lib that has THIS
     convenienece lib as a dep, again, create a pic version in .libs and
     a non-pic version in .  In each case, use the "matching" version of
     the dependency when doing the explode-and-incorporate thing.
 (f) In all other cases, use the "regular" lib

[replace 'explode-and-incorporate thing' with 'partial linking thing' if your platform supports it]

These improvements to "regular" convenience libraries are, IMO, necessary for proper operation where pic/no-pic makes a difference.

And, as detailed above w.r.t. "-DDLL_EXPORT", even when -fpic itself makes no difference.

I tried to figure out what it would take to do the above, but the maze of twisty little passages all the same made my head hurt. It *looks* like the build-a-convenience-lib codeflow "borrows" the "build an oldlib (e.g. static archive)" machinery, but jiggers with the list-of-objects. If so, then this task will be rather tricky (I think), because the build-a-convenience-lib codeflow will need to be disentangled, so that it has its own implementation that calls $old_archive_cmds directly, twice, with $pic_objects and $non_pic_objects respectively.

But exactly _where_ to fit that in escapes me at the moment.

There's this comment in ltmain.m4sh:
      # Objects from convenience libraries.  This assumes
      # single-version convenience libraries.  Whenever we create
      # different ones for PIC/non-PIC, this we'll have to duplicate
      # the extraction.
but that's talking about how to USE the convenience library once you've actually got two versions of it. Help?


P.S. I was experimenting with reloadable object files (I realize now that even if they worked, they won't solve my problem. I'm only bringing this up because they didn't even "work"):

------- foo/ ---------
libfoo_la_SOURCES = foo1.c foo2.c
libfoo_la_DEPENDENCIES = foo.lo
foo.lo: $(libfoo_la_OBJECTS)
        $(LINK) $(libfoo_la_OBJECTS)

------- bar/ ---------
libbar_la_SOURCES = bar1.c bar2.c
libbar_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libbar_la_LIBADD = ../foo/foo.lo

Here's what happened during the build of foo:

make[2]: Entering directory `/tmp/_buildfoo/foo'
/bin/sh ../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I../../foo/foo -g -O2 -c -o foo1.lo ../../foo/foo/foo1.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../../foo/foo -g -O2 -c ../../foo/foo/foo1.c -DDLL_EXPORT -DPIC -o .libs/foo1.o libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../../foo/foo -g -O2 -c ../../foo/foo/foo1.c -o foo1.o >/dev/null 2>&1 /bin/sh ../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I../../foo/foo -g -O2 -c -o foo2.lo ../../foo/foo/foo2.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../../foo/foo -g -O2 -c ../../foo/foo/foo2.c -DDLL_EXPORT -DPIC -o .libs/foo2.o libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../../foo/foo -g -O2 -c ../../foo/foo/foo2.c -o foo2.o >/dev/null 2>&1

So far, so good: both source files were compiled into "pic" and "non-pic" objects, and libtool objects were created.

/bin/sh ../libtool --tag=CC --mode=link gcc -g -O2 -o foo.lo foo1.lo foo2.lo libtool: link: /usr/i686-pc-cygwin/bin/ld.exe -r -o foo.o .libs/foo1.o .libs/foo2.o libtool: link: /usr/i686-pc-cygwin/bin/ld.exe -r -o foo.lo .libs/foo1.o .libs/foo2.o

But this is wierd. Two objects were created: foo.o and foo.lo -- where each contained the pic objects. (but foo.lo is a *regular* object, not a libtool object.) What I would have expected was:

libtool: link: /usr/i686-pc-cygwin/bin/ld.exe -r -o foo.o  foo1.o foo2.o
libtool: link: /usr/i686-pc-cygwin/bin/ld.exe -r -o ./libs/foo.o .libs/foo1.o .libs/foo2.o

with a foo.lo that looked like
# foo.lo - a libtool object file
# Generated by (GNU libtool 1.2442 2007/03/29 22:24:31) 2.1a
# Please DO NOT delete this file!
# It is necessary for linking the library.

# Name of the PIC object.

# Name of the non-PIC object

Is the observed behavior correct, and my expectations wrong, or vice versa?

reply via email to

[Prev in Thread] Current Thread [Next in Thread]