chicken-users
[Top][All Lists]
Advanced

[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?




reply via email to

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