[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Chicken-users] address@hidden: Re: gettext cvs, woe32 dlls]
From: |
John Cowan |
Subject: |
[Chicken-users] address@hidden: Re: gettext cvs, woe32 dlls] |
Date: |
Fri, 12 May 2006 11:07:18 -0400 |
User-agent: |
Mutt/1.3.28i |
Here's a followup to my previous barking-dog post. Presumably
what is laid down should be more widely applicable.
----- Forwarded message from Bruno Haible <address@hidden> -----
From: Bruno Haible <address@hidden>
To: Charles Wilson <address@hidden>
Date: Fri, 12 May 2006 14:36:24 +0200
Cc: address@hidden
Subject: Re: gettext cvs, woe32 dlls
Hello Charles,
Thank you for your long explanations. I believe that I have committed to
the gettext CVS a solution that, like yours, supports building DLLs on
Cygwin, but also satisfies the following additional goals:
A) No source code in .h and .c files change. Only some infrastructure is
added in separate files and in Makefile.ams and configure.acs.
B) For public libraries, the same .h file is valid regardless whether
the user will link with the shared or with the static library. No
STATIC_LIBRARY_FOO flags.
C) The boundaries between private libraries (here: between libgettextlib
and libgettextsrc) does not require source code changes. I.e. a
module can be moved from libgettextsrc to libgettextlib or vice
versa without source code changes. (This is important because most of
libgettextlib is shared code from gnulib. It must not carry the name
of the library into which it gets compiled.) So no
LIBGETTEXTSRC_DLL_VARIABLE etc. macros.
Let me explain, because some things would be simpler if libtool had the
adequate support for it.
> (This lack of meshing well with libtool is why most other packages --
> and libtool -- signed on to the auto-import bandwagon)
GNU ld's --enable-auto-import has three fatal drawbacks:
- It produces executables and shared libraries with relocations in the
.text segment, defeating the principles of virtual memory.
- For some constructs such as
extern int var;
int * const b = &var;
it creates an executable that will give an error at runtime, rather
than either a compile-time or link-time error or a working executable.
(This is with both gcc and g++.) Whereas this code, not relying on
auto-import:
extern __declspec (dllimport) int var;
int * const b = &var;
gives a compile-time error with gcc and works with g++.
- It doesn't work in some cases (references to a member field of an
exported struct variable, or to a particular element of an exported
array variable), requiring code modifications. One platform dictates
code modifications on all platforms.
This is unacceptable. Therefore I disable this option, through the
woe32-dll.m4 autoconf macro.
----------------------------------------------------------------
gettext has 3 kinds of libraries:
1) Public libraries which export only functions.
2) Public libraries which export also variables.
3) Private libraries which export functions and libraries.
Namely
1) libasprintf
2) libintl, libgettextpo
3) libgettextlib, libgettextsrc
1) This case is well handled by libtool and ld already. The .h file doesn't
need modifications; __declspec(dllimport) on functions is not needed.
The function names are exported because GNU ld does an implicit
--export-all-symbols if no symbols are explicitly exported.
2) For this case, when --enable-shared is specified, I preprocess the .h file
so that exported variables are marked with __declspec(dllimport). A simple
sed statement:
sed -e 's/export \([^()]*\);/export __declspec(dllimport) \1;/'
After this header file is installed, it must be valid for both the
shared and the static library. (You cannot expect that users of the
library really think of setting a STATIC_XYZ flag when using the static
library.) When a user compiles code that accesses a variable, the compiler
will generate a reference to _imp__variable. These _imp__* pointer
variables are normally generated for the DLL by the compiler or linker when
__declspec(dllexport) is used. But we need them also in the static
library! So I create a C file that generates these _imp__* pointer
variables:
#include "cygwin/export.h"
VARIABLE(variable1) // defines _imp__variable1
VARIABLE(variable2) // defines _imp__variable2
...
and compile this into both the static and the shared library. So I don't
need to provide the __declspec(dllexport) alternative in the header file;
it's ok to use __declspec(dllimport) always.
The linker needs to be given the --export-all-symbols flag explicitly in
this case.
3) For this case, where no .h file needs to be installed, the same approach
can be used. However, a small modification is possible: Since the
library is a private one, no .h file is installed, and the static
library doesn't need to be installed. If --enable-shared was specified, the
static library is not even used. (The programs and the testsuite do not
link statically.) The .h file contains
export PRIVATE_DLL_VARIABLE int variable1;
export PRIVATE_DLL_VARIABLE struct { ... } variable2;
...
and PRIVATE_DLL_VARIABLE is defined in config.h through
#if defined __CYGWIN__ && (--enable-shared was specified)
#define PRIVATE_DLL_VARIABLE __declspec(dllimport)
#else
#define PRIVATE_DLL_VARIABLE
#endif
Notes:
- You see that DLL_EXPORT (set by libtool) is never used: in case 2 because
we don't need/want a LIBFOO_DLL_VARIABLE macro for every library, in case 3
because the code compiled without DLL_EXPORT is not used at all.
- The process of adding the _imp__* pointer variables to the .a and .dll.a
file, and the --export-all-symbols flag, could be done by libtool.
- The only drawback I can see of this technique is that a static library
built alone (with --disable-shared) will be slightly more efficient
than the static library built together with the shared one - due to the
_imp__* indirections. But hey, if it has taken 11 years to port gettext
with shared libraries to Cygwin, it is because the Woe32 DLLs are
optimized excessively for performance at the expense of standards compliance
and ease of use. (Like the floating-point hardware that was in use before
IEEE 754: it produced wrong results but did so very efficiently.)
- Unlike --enable-auto-import, which operates on the code that _uses_
a shared library, this technique operates on the library itself; the
code that uses the library sees the dllimports in the header file and
does not need further fixup.
> Yes, in general you are right: we have four states (per library)
> building the library as shared : declspec(dllexport)
> building the library as static : <no decorator> (*)
> building a client of the library, intending to link shared :
> extern declspec(dllimport)
> building a client of the library, intending to link static :
> extern (*)
With the technique above, the last two states are collapsed into one.
Bruno
_______________________________________________
address@hidden
http://lists.gnu.org/mailman/listinfo/bug-gnu-utils
----- End forwarded message -----
--
Said Agatha Christie / To E. Philips Oppenheim John Cowan
"Who is this Hemingway? / Who is this Proust? address@hidden
Who is this Vladimir / Whatchamacallum, http://www.ccil.org/~cowan
This neopostrealist / Rabble?" she groused.
--author unknown to me; any suggestions?
- [Chicken-users] address@hidden: Re: gettext cvs, woe32 dlls],
John Cowan <=