[xml] Dynamic Linkage And MSCC



Hello there.

Dear libxml2 developers, I woul like to hear an opinion from you.

Few enthusiastic Windows programmers who use Microsoft's compiler have
expressed an interrest in using a shared version of libxml2 in their
programs :-). A sad lot that we are, we can only compile a static version of
libxml2 in this environment so far. I would like to hear what you think
about possible ways to change that and if it is worth the trouble.

Producing a shared version of libxml2 under Win32/MSCC is not an easy task.
Why? There is a problem: a way to export symbols under MSCC. MSCC requires
each exportable symbol to be declared as such.

There are two ways to declare a symbol as exportable. Let's risk a glimpse
on both ways.


The one way to declare a symbol as exportable is to write a .DEF file and
list the symbols there. Here is how such file looks like:

    LIBRARY somelib
    EXPORTS
        somefunc
        ul

This file basicaly lists the names of all exportable symbols, one per line.
The MSCC linker reads this file and exports the listed symbols. This does
not modify the sources and keeps MSCC-specific stuff far away from the rest.
Everytime a new function is added to libxml2, its name must be listed in
this file. This can be done by anyone and those who write new functions need
not care about MSCC specifics. 

Unfortunately, there is a problem with .DEF files. They do not support
something like #ifdef. This means that we cannot conditionally declare a
symbol as exportable, depending on if a particular feature has been enabled
or not. If a .DEF file specifies a symbol which cannot be found in any of
the object files, the linker reports an 'unresolved external symbol' error.
If we use a .DEF file, then everything in include/libxml/xmlversion.h must
forever remain the same for Win32/MSCC platform.


The other way to export a symbol is to declare it as exportable in the
source code, by using MSCC-specific declaration statement
'__declspec(dllexport)'. Here is how that looks like:

    __declspec(dllexport) int somefunc(int i, char c);
    __declspec(dllexport) unsigned long ul;

One cannot simply use these declarations in a public header file, because if
you include such header file in your libxml2-based program, then these
declarations would cause MSCC to reexport these symbols from that program.
'__declspec(dllexport)' must be there only when compiling libxml2 itself.
When the public header file is included by a libxml2-based program, then
declarations must look either like this:

    int somefunc(int i, char c);
    unsigned long ul;

or, optionally, like this:

    __declspec(dllimport) int somefunc(int i, char c);
    __declspec(dllimport) unsigned long ul;

Someone had tried to do this in the past. We can observe the macro
LIBXML_DLL_IMPORT, which can be found in the include/win32config.h file.
This macro tries to expand to the right declaration, depending on the
environment. For this to work, every function and every variable exported
from libxml2 must have LIBXML_DLL_IMPORT as a part of the declaration. This
would then look like this:

    LIBXML_DLL_IMPORT int somefunc(int i, char c);
    LIBXML_DLL_IMPORT unsigned long ul;

and the macro LIBXML_DLL_IMPORT would then expand to either
'__declspec(dllexport)', or nothing, depends on if we are compiling libxml2
itself or not. (In order to make clear what the whole thing does, we could
rename the macro to, say, 'LIBXML_PUBLIC'.)

You know very good that patching header files to get this is not exactly a
two-minute job. More, it certainly disturbs people who program under UNIX,
because in order to avoid extensive patching, they would have to use this
macro everytime they add a new function to libxml2.


My opinion is the following:

The .DEF file solution is the most comfortable one, bacause it does not
affect anyone except those who actually use it. On the other side, it
destroys the possibility to dis/enable particular features of libxml2 at
whim. Nevertheless, I would prefer this option. Have a .DEF file for a
dynamic library, which includes all available features. If a feature needs
to be disabled, then build a static library.

The 'LIBXML_PUBLIC' macro thing is a more functional solution, but it does
affect everyone. I should hear from you first, but I doubt that those who do
not use Win32/MSCC (the majority) would agree on using the macro
consistently. The only thing they might find interresting is that this could
ease the porting to other platforms in the future, should we come across
another compiler with similar declaration requirements, but the chance for
this to happen is rather small.


Now, what do you think about the whole? If by some unlikely chance the
community agrees on using this 'LIBXML_PUBLIC' macro, then I would get the
most recent snapshot from the CVS and adapt the public headers. Otherwise, I
would make the .DEF file.


Your turn
Igor




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