[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Mingw-cross-env-list] Static vs. shared libraries (was: gtkmm support)
[Mingw-cross-env-list] Static vs. shared libraries (was: gtkmm support)
Sat, 19 Sep 2009 19:46:16 +0200
Mark de Wever <address@hidden> schrieb:
> For a project I'm working I use gtkmm [...] I haven't been able to
> create static libraries, but I managed to create shared libraries. For
> those shared libraries I also created shared libraries of some existing
This is a question of the future direction of the project, so
it would be great to get some opinions on that topic from you,
the mingw-cross-env developers and users:
What is your general opinion about static/shared libs?
What is your concrete practical need?
As a starting point, I'll try to explain the current state on
that issue. I hope it isn't too boring.
When mingw-cross-env started, it was mainly used by some of my
internal projects. In addition, it was used by Andreas Roever
for his free software projects. ( http://toppler.sf.net/ and
Andreas was a big fan of statically linked EXE files. He linked
in exactly the libraries he needed and he ran "strip" and "upx"
over the EXE files to make them as small as possible. He reduced
his programs to impressive small sizes.
Since most free libraries provide a win32 development version
(i.e. header and DLL files) and GCC can link directly against
existing DLL files, there was not much need to compile the
libraries yourself ... well, except when you want to link them
static. In that case you always had to build the libraries
yourself, and mingw-cross-env was designed to automate that
In addition, many packages provide Makefiles which work well
for creating shared libraries, but are unable to create proper
static libraries. So mingw-cross-env made a big effort to create
proper static libraries, mostly by correcting some parts in
configure/Makefile or by doing the final linking steps "by hand".
Despite those build issues, almost all libraries work well when
finally linked statically. In mingw-cross-env there are just two
exceptions: the libUSB and the GTK packages (glib, gdk, ...). 
For libUSB, the problem was fixed by making it a shared library.
Since it didn't depend on any other library, that was easy and
straight forward. It didn't conflict with any static library.
We decided to use the official DLL files of a project. So
mingw-cross-env only builds the stub library. It does not
build the DLL files of libUSB.
With GTK it is a bit more complicated. It depends on many other
libraries such as zlib (via libpng). For instance, if we build
GTK as shared library and zlib as static library, the final
application will not be able to use the zlib directly, because
zlib would be included in the GTK DLL file as well as the EXE
file, resulting in duplicate code, duplicate symbols and finally
in fatal linker errors.
This is a general issue and leads to the conclusion that you
should build either everything as static or everything as
We could provide both variants for each package in mingw-cross-env,
but that would raise some severe problems:
* You can't easily mix the static and shared libraries. At
least the *-config and pkg-config entries would make trouble.
In addition, it would be very hard to debug a linker problem
if some libraries accidently link to the wrong variant (static
or shared) of another library.
* The build rules would have very little in common. Thus, each
package would effectively have two different build rules, which
would duplicate the work for maintainance and testing.
So the problems outweigh the gained flexibility by far. Providing
both would be a very bad compromise. So I strive for a well
thought-out _decision_ on the topic.
Static libraries allow to build minimal EXE files which don't
depend on anything else. In addition, only those functions which
are really used go into the EXE file.
However, there's still the possibility of bloat, especially when
using interface libraries. For instance, sdl_mixer is a common
sound interface around libvorbis (for *.ogg) and smpeg (for *.mp3).
Both will be part of your EXE file, even if your application has
only *.ogg and no *.mp3 files. To create really a minimal application,
you'll have to edit the src/sdl_mixer.mk and disable smpeg by hand. 
When there are libraries such as GTK/Glade that really need to
have a DLL file, you always have the option to build one big DLL
file into which all needed libraries are linked statically. Then,
your application just links dynamically to that big DLL file.
I haven't tried it yet, but it might be a good workaround for
the GTK issue.
In addition, the EXE files and DLL files are technically very
similar - more similar than *.so and binary files on unix systems.
So the "g_module_symbol()" magic to retrieve an object from the
shared library might work on an EXE file as well. Maybe it really
needs just a small change in GTK/Glib to make that work?
Shared libraries on win32 can't be used in the same way as
on unix systems. Only recently via the .NET technology the
win32 platform got a suitable mechanism that allows many
variants of a shared library to co-exist. Outside .NET
there's still the "DLL hell".
However, if you simply ship all needed DLL files with your
application and put it into the same directory as your EXE
file, you can avoid the DLL hell altogether. However, your
package size might become bigger than a statically linked EXE.
On the other hand, you can simply leave out DLL files you
don't use - at least, if the corresponding interface libraries
are well-written. So for instance, one might hope that it's
sufficient to simply leave out the smpeg DLL file and expect
the sdl_mixer DLL to work fine, as long as the application
plays only *.ogg and no *.mp3 files. I don't know whether
this example would really work, but the idea behind it should
be clear. If not sdl_mixer, there are other interface DLLs
designed to load other DLLs just on demand.
It is an interesting question whether to build DLL files
oneself or whether to use the official DLLs of the respective
projects. In the latter case, only the stub libraries need
to be build. But even those are superfluous since GCC is
able to accept DLL files directly as command line argument.
So just take the "win32 development packages" provided by
the official projects! If all you want is to use them as
shared libraries, you don't need mingw-cross-env at all.
On the other hand, most win32 versions of libraries are
behind, because they aren't updated as quickly as the other
binary packages. Hardly any project provides read-to-use
build scripts. Some don't even have scripts, because a
single small package isn't worth the scripting effort.
That way, mingw-cross-env could offer a transparent and
automated replacement for their building task, allowing
them to provide the win32 packages and DLLs on time with
less effort. Instead of _using_ their work, mingw-cross-env
could _support_ their work.
As mentioned above, it is often simpler to build a shared
library than a static one. However, the code for building
static libraries in mingw-cross-env is already written and
debugged, so switching to shared libraries is still a lot
of initial work.
All in all, I see the following possible solutions. Maybe some of
them don't work, but at least they're worth a try. Please give your
opinion on each point, and don't hesitate to add other suggestions.
(A) Fix GTK to find their symbols in (statically linked) EXE files.
(B) Find a way to build GTK as shared library, but everything else
as static library.
(C) Don't change anything and rely on the developers to put their
application and libraries into one big DLL to be used with a
small runner EXE.
(D) Don't change anything and rely on the developers to download
the official GTK win32 development packages.
(E) Rewrite mingw-cross-env to build everything as shared libraries,
building own DLL files on the way.
(F) Rewrite mingw-cross-env to build everything as shared stub
libraries, to be used with the official project DLLs.
 The following discussions explain why some features of GTK work
only when GTK is compiled as shared library:
 Mingw-cross-env could make such things configurable. However, we
are not as big as the Gentoo community, and trying to maintain,
test and debug such a beast with all those possible variants
would be simply irresponsible. The project would quickly break
under its own weight.