automake
[Top][All Lists]
Advanced

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

Re: Questions on exporting functions from a shared library


From: Jef Driesen
Subject: Re: Questions on exporting functions from a shared library
Date: Thu, 02 Oct 2008 17:08:55 +0200
User-agent: Thunderbird 2.0.0.17 (X11/20080925)

Ralf Wildenhues wrote:
Hello Jef,

* Jef Driesen wrote on Tue, Sep 23, 2008 at 08:44:47PM CEST:
Brian Dessent wrote:
There are two aspects to the symbol visibility stuff:
[ snip nice explanation ]

Now that I start to understand all the differences, I only need to find a way how to incorporate everything nicely in my automake build system. Suggestions? I guess I'm not the first one struggling with this, so I'm surprised there is not more information available. Most projects (at least the ones I checked) seems to be using -export-symbols.

Well, as you don't seem to say exactly what you need: you can
- add -export-symbols* to libfoo_la_LDFLAGS, or
- add visibility annotations right to your source files
  (preferably through a #define so you can factor for different
  spellings).

You can get better help if you describe more precisely what you already
tried, and more importantly, which way you decided to go now.

What I want to achieve is the following (in order of importance):
1. Only export the functions that are part of the public api. It is important that the solution is supported by at least gcc/autotools and msvc. It should also have little to no impact on the users of the library, so the library remains easy to use. (Having to add stuff to the build system of the library is of course fine, because that would go into the shipped autotools or msvc project files.)
2. Take advantage of the visibility/dllimport performance improvements.

Currently, I'm using -export-symbols with a separate "mylib.symbols" file. However, since my library has multiple backends, that are not always enabled, the contents of this file is not static. I solved this by using the C preprocessor:

/* File: mylib.symbols */

mylib_abc
#ifdef MYLIB_XYZ_SUPPORT
   mylib_xyz
#endif

/* File: Makefile.am */

if XYZ
mylib_la_SOURCES += xyz.h xyz.c
endif

mylib_la_LDFLAGS = -no-undefined -export-symbols mylib.exp
mylib_la_DEPENDENCIES = mylib.exp

mylib.exp: mylib.symbols
if XYZ
  $(CPP) -P -DMYLIB_XYZ_SUPPORT - < mylib.symbols | sed -e '/^$$/d' > $@
else
  $(CPP) -P - < mylib.symbols | sed -e '/^$$/d' > $@
endif

CLEANFILES = mylib.exp
EXTRA_DIST = mylib.symbol

One of the downside of this method is that I need to maintain the separate symbols file (not a real issue). But more important is that this setup is not supported by the msvc compiler. That compiler does not export any function by default, unless a DEF file or the dllexport attribute is used. But I don't know if it is possible to do a similar trick for msvc, and generate the DEF file on the fly. And I don't want to maintain two almost identical symbol files.

If I could use the dllexport (win32) or visibility (unix) mechanism, that would work for both the gcc and msvc compiler. And in addition, I would be able to take advantage of the performance improvements.

So I tried with this (following the gcc visibility guide):

/* File: Makefile.am */

mylib_la_CFLAGS = -fvisibility=hidden -DMYLIB_BUILD

Note: How do can I detect whether the visibility attribute is supported?

/* File: Makefile.am */

#ifdef WIN32
  #define IMPORT __declspec(dllimport)
  #define EXPORT __declspec(dllexport)
#else
  #define IMPORT __attribute__ ((visibility("default")))
  #define EXPORT __attribute__ ((visibility("default")))
#endif

#ifndef MYLIB_STATIC
#  ifdef MYLIB_BUILD
#    define API EXPORT
#  else
#    define API IMPORT
#  endif
#else
#   define API
#endif

where MYLIB_BUILD is always defined when building the library, and MYLIB_STATIC should be defined for static building and linking.

And that last one is where the problem is, because libtool builds both a static and dynamic library (unless I explicitly disable one of them with ./configure --disable-* of course). This happens regardless of the platform (windows mingw or linux gcc). The result is that MYLIB_STATIC is never defined when building the library, and the static library gets build with EXPORT. I'm not really sure this is a allowed (it seems to work).

A closely related problem is when I try to build the examples. Those examples are part of my package, but they are located in a different directory than the library code. When linking against the shared library everything is fine, but when I try to link against the static library I get this error (on Windows): "undefined reference to `__imp__myfunction'". Obviously because MYLIB_STATIC was not defined and the compiler tries to dllimport my functions.

BTW, is it possible to force automake to link my examples against the static library, in case both the static and shared library are build? Now I'm using a separate build tree with ./configure --disable-shared, thus affecting the complete project, when I need statically linked examples.





reply via email to

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