Glib2

Charles Wilson cwilson@ece.gatech.edu
Fri Dec 20 04:17:00 GMT 2002


[Back on list, just to make sure it's archived.  Max and I have bounced 
some emails back-n-forth privately, so you're coming in on the middle of 
a conversation... See Gen Zhang's original message on 12/4/2002]

Also, this is kinda stream of conciousness...because I end up at the end 
of the message somewhere other than where I thought I was going... <g>

Okay, from Zhang's report:
 > After re-libtoolize-ing the sources (to allow it to produce shared
 > libs) the compilation is fine through glib and will produce
 > libglib-2.0.la, but will complain about undefined references to
 > things like '_g_free' and '_g_log' (which I presume is in
 > libglib-2.0.la). I've attached the output from make (upon a second
 > run, after it going through glib).

The error was not in creating the DLL in the first place(*).  The error was

 > /bin/bash ../libtool --mode=link gcc  -g -O2 -Wall -D_REENTRANT   -o
 > glib-genmarshal.exe  glib-genmarshal.o ../glib/libglib-2.0.la -liconv
 > -lintl -liconv
 > gcc -g -O2 -Wall -D_REENTRANT -o .libs/glib-genmarshal.exe
 > glib-genmarshal.o  ../glib/.libs/libglib-2.0.dll.a -L/usr/lib
 > -L/lib/w32api -luser32 -lkernel32 /usr/lib/libintl.dll.a
 > /usr/lib/libiconv.dll.a -Wl,--rpath -Wl,/usr/local/lib
 > glib-genmarshal.o(.text+0x1807): In function `complete_in_arg':
 > /usr/src/glib-2.0.7/gobject/glib-genmarshal.c:218: undefined reference
 > to `_g_log'
 > ...

(*) unless the DLL itself exported no symbols at all.  But, new libtool 
DOES NOT USE def files anymore.  AT ALL.  (and, you can't even give it 
one as an argument...)

Max Bowsher wrote:

 >>> .def files are passed as -Wl,-retain-symbols-file deffile, not,
 >>> as is correct, the first 'object' file.

Which means this ^^^^^ is wrong.

"-Wl,--retain-symbols-file -Wl,filename" is perfectly okay -- see the ld 
manpage.  However, $export_symbols contains a filename whose contents 
are a list of exports -- like a def file, but not exactly; it's more 
unix-focused.  If you trace the code in ld.exe, you find that 
--retain-symbol-file's argument is handled in a COMPLETELY different 
manner than a def file would be (it mainly acts to prevent the given 
symbols from being stripped; it doesn't "trigger" the necessary hooks to 
export those symbols in a DLL on cygwin/mingw).  So, 
--retain-symmbols-file is okay on other unices, but not really the right 
switch for libtool to pass to ld, on cygwin.

On cygwin, what you end up with is
   "don't strip these symbols"
and
   "there is no def file, so by default, export all symbols(*)"

(*) unless there are symbols that have been specifically decorated with 
__declspec(dllexport), in which case ONLY those decorated symbols are 
exported.  It turns out that THIS is the root of the problem with 
glib+cygwin.

So, on cygwin, this definition of archive_expsym_cmds is probably wrong 
-- but not in the way you thought.  Because **archive_expsym_cmds** is 
NOT USED (much).  [except in glib...sigh...]

Cygwin defines "always_export_symbols" as "no" (unless you use the 
'--export-symbols <FILENAME>' switch when calling libtool), and 
"export_symbols_regex" is empty unless you explicitly call libtool with 
the '--export-symbols-regex <REGEX>' switch.  Given those typical 
definitions, we use "archive_cmds" NOT "archive_expsym_cmds" almost 100% 
of the time.  Only when either '--export-symbols <FILENAME>' or 
'--export-symbols-regex <REGEX>' are specified do we, on cygwin, use 
"archive_expsym_cmds".

And glib does.  It uses '--export-symbols glib.def' (on OS_WIN32, but 
not CYGWIN).  More below.

Further, as far as ld is concerned, the def file doesn't need to be the 
FIRST object file.  That was the case for dlltool (or you could 
explicitly say "--def def.file"), but not for ld once the functionality 
was absorbed.  For ld, the def file just needs to appear as one of the 
arguments to ld.  (see gld_${EMULATION_NAME}_unrecognized_file in 
binutis/ld/emultempl/pe.em)

 > But I'm worried about just assuming that the -export-symbols file is
 > a def file. There was some code in libtool somewhere (recently
 > removed) which searched for EXPORTS to try and determine if it was a
 > def file, and else tries to make one.
 >
 > I'm not sure how export-symbols works on other platforms.

Explained above.  Now, IF someone were to specify --export-symbols-regex 
or --export-symbols on cygwin, then the archive_expsyms_cmd would be 
used -- and we need something like

_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o
$output_objdir/$soname $export_symbols
${wl}--out-implib,$lib'

(e.g. no retain-symbols argument, just include $export_symbols as one of 
the "object" files)

There's just one problem: ld tests "unknown objects" filenames to see if 
they end in ".def" or ".DEF".  $export_symbols is (usually) libname.exp. 
  Badness.

So, for this to work as we expect, we must
   (a) change $export_symbols to "libname.def" not "libname.exp".  Old 
versions of libtool (back in dlltool days) did
   cp $export_symbols $output_objdir/$soname-def
(dlltool was less picky about the actual name of the .def file; you'd 
just say "--def foo" and it was happy.  We'd need to
   cp $export_symbols $output_objdir/$soname.def
to insure that the file ended with .def.

   (b) change $export_symbols_cmds so that it prepends "EXPORTS".  Now, 
since always_export_symbols is false by default, the only time 
$export_symbols_cmds ever gets called is when you need to GENERATE an 
exports list -- and since '--export-symbols <FILENAME>' takes an 
argument, you don't need to generate it in that case (it's in 
<FILENAME>).  So, the only time, on cygwin, that $export_symbols_cmds is 
ever called, is when you've done '--export-symbols-regex <REGEX>'  Which 
makes things EVER so much more complicated.  Sigh.

Anyway, perhaps something like $export_symbols_cmds =
   "\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //'
   | sort | uniq | \$SED -e '1iEXPORTS' > \$export_symbols"
(note the final $SED command)

However, that still doesn't differentiate between DATA and function 
exports; the .def file, if used, must identify DATA exports.  Which 
means $export_symbols_cmds has be a LOT more complicated:

$NM $libobjs $convenience | \$global_symbol_pipe | \
\$SED -e '/^[BCDG] /s/^\([BCDG]\) \(_[_A-Za-z0-9]*\) 
\([_A-Za-z0-9]*\)/\3 DATA/' | \
\$SED -e '/^[AISTW] /s/^\([AISTW]\) \(_[_A-Za-z0-9]*\) 
\([_A-Za-z0-9]*\)/\3/' | \
sort | uniq | \$SED -e '1iEXPORTS' > \$export_symbols"

Old libtools used to use a specialized program (impgen) to do this, and 
a combination of dlltool calls.  But we want to stay away from that, and 
stick with ld, gcc, and nm.  So, we'll have to work harder...

Worse, if you actually specify --export-symbols=FOO on the libtool 
command line (e.g "use the file 'FOO', which already exists and 
specifies the symbols to export, as $export_symbols") then 
$export_symbols_cmds is NOT called, AND you lose platform 
cross-compatibility in the $export_symbols file.  On unix, the file 
$export_symbols should just contain
   bob
   fred
But on windows, it should contain
   EXPORTS
   bob
   fred DATA
because we're using it (in my "proposal" above) as a def file.

Basically, what you're trying to do is build an .def file on the fly. 
This USED to be very helpful -- before the auto-import, auto-export 
functionality was added to ld.exe itself.  Now, it just messes things up 
on cygwin.  (It might still be useful on other platforms, but not here).

I think this whole concept (on-the-fly def file created by libtool) was 
a kludge, because dlltool NEEDED a def file (during its 'make a dll' 
mode), so libtool created one (by calling dlltool in its 'make a def 
file' mode).  Now, we don't use dlltool anymore, and ld can 
automatically figure out what, and how (DATA or function) to export.  So 
none of this is needed on windows anymore, in general.

The only time you need any of this "specially restrict the export list 
or specifically export a known list of symbols" is when you're doing 
something *special*.  And that requires developer intervention....

In cygwin/mingw, the typical library needs to do one of the following:
   1) export everything (almost always, this is what you want)
   2) export everything EXCEPT ...
   3) export only ...
   4) export everything, BUT you've specifically decorated some symbols 
(like structs) with __declspec(dllexport).  If it weren't for libtool's 
paranoia about passing flags to the linker, you'd just say 
'--export-all' and be done.  But libtool won't let you do that, so life 
is hard.   This is the glib case.

If you want #1, you just let ld do the work.  No need for export_symbols 
or any of that junk.

If you want #2, the *Developer* should specify that in the makefile. 
E.g. libfoo_la_LDFLAGS=.... --exclude-symbols SYMBOL,SYMBOL,... or 
--exclude-libs LIB,LIB,... (to avoid exporting symbols pulled in from 
static convenience libraries).  But that's a *developer* thing; libtool 
shouldn't attempt to do that itself.  It isn't clairvoyant.  Perhaps the 
developer should insure that the Makefile only puts --exclude-symbols 
... when building for cygwin/mingw by using conditionals.  But it's a 
developer thing.

Now, if on unix, a developer used --export-symbols or 
--export-symbols-regex as a means of NOT exposing certain symbols to 
clients, then we need to take special care when porting to windows. 
Create a .def file and add it (conditionally) to the _SOURCES [BUZZ! 
doesn't work], or add --exclude-[lib|symbol] to _LDFLAGS (conditionally) 
[BUZZ! Doesn't work.  Damn, but libtool is picky about the flags it 
passes to the linker], etc.  But this should be RARE.

If you want #3, then the *developer* should specify a .def file as one 
of the library's dependencies (perhaps conditional on cygwin/mingw). End 
of story.

And --export-symbols/--expoprt-symbols-regex should continue to be 
handled on cygwin exactly as it is handled on other unixes: strip or 
don't strip.  It shouldn't affect the "windowsish" exporting process. 
That's the job of --exclude-[lib|symbobs] and .def file, if such 
functionality is needed.

But apparently Tor Lilqvist disagrees:

Now, having said all of that, it appears that this is EXACTLY what the 
glib folks have done.  They explicitly add "-export-symbols glib.def" IF 
and ONLY IF OS_WIN32 (eg. not for cygwin, which has PLATFORM_WIN32 true, 
but OS_WIN32 false).  IMO, that is a *misunderstanding* of what 
--export-symbols does in CURRENT libtool, even if it was correct for OLD 
libtool -- but Tor Lilqvist [the gtk on windows dude] uses a forked 
version of libtool anyway, so...

As it happens, they've managed to outsmart the auto-export code when 
they try this OLD libtool usage with a NEW libtool program.  Auto-export 
ONLY happens if BOTH of the following are true
   1) there is no .def file
   2) there are no explicit __declspec(dllexport) decorations on any 
symbols.

1) is true, because the .def file is only used for OS_WIN32 (not 
cygwin).  However, 2) is false, because there are five symbols that are 
explicitly decorated:
   g_io_watch_funcs  in glib/giowin32.c
   g_timeout_funcs   in glib/gmain.c
   g_idle_funcs      in glib/gmain.c
   g_ascii_table     in glib/gstrfuncs.c
   g_thread_functions_for_glib_use   in glib/gthread.c

These are the only DATA exports from glib that are "complex" (see 'info 
ld' and search on 'auto-import').

So, the "right thing" on cygwin is one of these three things:

include the .def file -- but as explained exhaustively above, you can't 
do it the way Tor does, the (new) "real" libtool doesn't use 
--export-symbols the way he thinks (although the old libtool did).  So, 
you'd have to conditionally include it as a part of glib_la_SOURCES. But 
THAT doesn't work EITHER -- because libtool says "what's this random 
file doing in my argument list, it's not a .lo, it's not .la,  throw it 
out"  So, Tor's solution is the only one that can work -- but it 
requires that $archive_expsyms_cmd be fixed up etc etc... (*)

or

add --export-all-symbols as one of the glib_la_LDFLAGS switches (this 
will re-enable the auto-export feature of ld, even though SOME symbols 
are explicitly decorated).  However, libtool does not pass 
"--export-all-symbols" thru to the linker, so this might require a patch 
to libtool.  Probably not the best way to do this.

or

remove the explicit decorations on those five variables, and rely on the 
  runtime-pseudo-relocs feature of binutils.  This won't work until 
cygwin-1.3.18 is released; it's a very new feature.  And 
--enable-runtime-pseudo-relocs is not the default for ld yet, so you 
need to add that flag to LDFLAGS...but libtool refuses to pass that 
switch to the linker!  So this won't work until (a) the new cygwin 
kernel comes out, and (b) --enable-runtime-pseudo-relocs becomes the 
default on cygwin's ld.  (b) won't happen for quite some time, yet.

-----

So, it appears that that the only way to address this in the short term 
is...restore some form of the old libtool-1.4.x code for 
$archive_expsym_cmd.

Fixup the official libtool so that IF '--export-symbols <FILENAME>' is 
specified, then on cygwin/mingw assume that the file contains a 
.def-format specification, and $archive_expsyms_cmd includes it as "just 
one of the object files" and doesn't use the --retain-symbols-file at 
all.  (On other platforms, go ahead and use --retain-symbols-file, etc). 
  This means that it would be up to the developer to do the following, 
IF he wants to restrict the list of export symbols on both unix and windows:
   1) provide foo.exp which is just a list of symbols
   2) provide foo.def which is a def-format list of symbols, with DATA 
specifiers, etc
   3) conditionally add "--export-symbols foo.exp" on unix, and 
"--export-symbols foo.def" on windows.

This would require all of the changes to $export_symbols_cmds described 
above, too, so that libtool's --export-symbols-regex switch could still 
work (currently, that is hopelessly broken on cygwin).

Now that I've thought about it, I believe that this IS what should 
happen in the libtool codebase.  It seems that some of the "old stuff" 
that was kept around for dlltool and was recently removed, should be 
retained so that the new-and-improved, 
use-auto-import-as-much-as-possible libtool can properly handle corner 
cases like these.

But, that's a separate issue from "how to get glib working on cygwin". 
IF all of those changes were in the current libtool, then yeah -- do it 
that way.  But they are not (yet).  The long-term solution is to remove 
the __declspec decorators on those five symbols when __CYGWIN__, and 
rely on --enable-runtime-pseudo-relocs once it becomes default, and on 
the latest cygwin kernel which should be out in a few days.  (If you 
wanted to try this method out BEFORE --enable-runtime-pseudo-relocs 
becomes the default, the only way to pass that flag thru libtool appears 
to be create a shell script and pretend that it is your compiler:

--gcc--
/path/to/real/gcc -Wl,--enable-runtime-pseudo-relocs $*
-------

Because libtool is REALLY picky about what it passes thru to the linker. 
  Sheesh!

Eventually pseudo-relocs will be the default on cygwin -- and maybe 
mingw -- but not for a number of months, I'm sure.)

Anyway, thanks for bringing up this issue; it appears that the current 
libtool is not quite ready for absolutely every possible use that people 
want...Looks like there are a few things I need to do over Christmas 
break... :-)

--Chuck


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list