现在的位置: 首页 > 综合 > 正文

ld and WIN32 (cygwin/mingw) lib名搜索顺序

2014年02月14日 ⁄ 综合 ⁄ 共 9898字 ⁄ 字号 评论关闭

ld
and WIN32 (cygwin/mingw)

http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/win32.html

 

This section describes some of the win32 specific ld
issues.
See Section 3.1 Command Line Options

for detailed decription of the
command line options mentioned here.

import libraries

The standard Windows linker creates and uses so-called import
libraries, which contains information for linking to dll's. They are
regular static archives and are handled as any other static
archive. The cygwin and mingw ports of ld
have specific
support for creating such libraries provided with the
-out-implib
command line option.

exporting DLL symbols

The cygwin/mingw ld
has several ways to export symbols for dll's.

using auto-export functionality

By default ld
exports symbols with the auto-export functionality,
which is controlled by the following command line options:

  • -export-all-symbols [This is the default]

  • -exclude-symbols

  • -exclude-libs

If, however, -export-all-symbols
is not given explicitly on the
command line, then the default auto-export behavior will be disabled
if either of the following are true:

  • A DEF file is used.

  • Any symbol in any object file was marked with the __declspec(dllexport) attribute.

using a DEF file

Another way of exporting symbols is using a DEF file. A DEF file is
an ASCII file containing definitions of symbols which should be
exported when a dll is created. Usually it is named <dll
name>.def

and is added as any other object file to the linker's
command line. The file's name must end in .def
or .DEF
.

gcc -o <output> <objectfiles> <dll name>.def

Using a DEF file turns off the normal auto-export behavior, unless the
-export-all-symbols
option is also used.

Here is an example of a DEF file for a shared library called xyz.dll
:

LIBRARY "xyz.dll" BASE=0x10000000

EXPORTS
foo
bar
_bar = bar

This example defines a base address and three symbols. The third
symbol is an alias for the second. For the complete format
specification see ld/deffilep.y in the binutils sources.

While linking a shared dll, ld
is able to create a DEF file
with the -output-def <file>
command line option.

Using decorations

Another way of marking symbols for export is to modify the source code
itself, so that when building the DLL each symbol to be exported is
declared as:

__declspec(dllexport) int a_variable
__declspec(dllexport) void a_function(int with_args)

All such symbols will be exported from the DLL. If, however,
any of the object files in the DLL contain symbols decorated in
this way, then the normal auto-export behavior is disabled, unless
the -export-all-symbols
option is also used.

Note that object files that wish to access these symbols must not
decorate them with dllexport. Instead, they should use dllimport,
instead:

__declspec(dllimport) int a_variable
__declspec(dllimport) void a_function(int with_args)

This complicates the structure of library header files, because
when included by the library itself the header must declare the
variables and functions as dllexport, but when included by client
code the header must declare them as dllimport. There are a number
of idioms that are typically used to do this; often client code can
omit the __declspec() declaration completely. See
-enable-auto-import
and automatic data imports
for more
imformation.

 

automatic data imports

The standard Windows dll format supports data imports from dlls only
by adding special decorations (dllimport/dllexport), which let the
compiler produce specific assembler instructions to deal with this
issue. This increases the effort necessary to port existing Un*x
code to these platforms, especially for large
c++ libraries and applications. The auto-import feature, which was
initially provided by Paul Sokolovsky, allows one to omit the
decorations to archieve a behavior that conforms to that on POSIX/Un*x
platforms. This feature is enabled with the -enable-auto-import
command-line option, although it is enabled by default on cygwin/mingw.
The -enable-auto-import
option itself now serves mainly to
suppress any warnings that are ordinarily emitted when linked objects
trigger the feature's use.

auto-import of variables does not always work flawlessly without
additional assistance. Sometimes, you will see this message

"variable '<var>' can't be auto-imported. Please read the
documentation for ld's -enable-auto-import
for details."

The -enable-auto-import
documentation explains why this error
occurs, and several methods that can be used to overcome this difficulty.
One of these methods is the runtime pseudo-relocs
feature, described
below.

For complex variables imported from DLLs (such as structs or classes),
object files typically contain a base address for the variable and an
offset (addend
) within the variable-to specify a particular
field or public member, for instance. Unfortunately, the runtime loader used
in win32 environments is incapable of fixing these references at runtime
without the additional information supplied by dllimport/dllexport decorations.
The standard auto-import feature described above is unable to resolve these
references.

The -enable-runtime-pseudo-relocs
switch allows these references to
be resolved without error, while leaving the task of adjusting the references
themselves (with their non-zero addends) to specialized code provided by the
runtime environment. Recent versions of the cygwin and mingw environments and
compilers provide this runtime support; older versions do not. However, the
support is only necessary on the developer's platform; the compiled result will
run without error on an older system.

-enable-runtime-pseudo-relocs
is not the default; it must be explicitly
enabled as needed.

 

direct linking to a dll

The cygwin/mingw ports of ld
support the direct linking,
including data symbols, to a dll without the usage of any import
libraries. This is much faster and uses much less memory than does the
traditional import library method, expecially when linking large
libraries or applications. When ld
creates an import lib, each
function or variable exported from the dll is stored in its own bfd, even
though a single bfd could contain many exports. The overhead involved in
storing, loading, and processing so many bfd's is quite large, and explains the
tremendous time, memory, and storage needed to link against particularly
large or complex libraries when using import libs.

Linking directly to a dll uses no extra command-line switches other than
-L
and -l
, because ld
already searches for a number
of names to match each library. All that is needed from the developer's
perspective is an understanding of this search, in order to force ld to
select the dll instead of an import library.

For instance, when ld is called with the argument -lxxx
it will attempt
to find, in the first directory of its search path,

libxxx.dll.a
xxx.dll.a
libxxx.a
cygxxx.dll (*)
libxxx.dll
xxx.dll

before moving on to the next directory in the search path.

(*) Actually, this is not cygxxx.dll
but in fact is <prefix>xxx.dll
,
where <prefix>
is set by the ld
option
-dll-search-prefix=<prefix>
. In the case of cygwin, the standard gcc spec
file includes -dll-search-prefix=cyg
, so in effect we actually search for
cygxxx.dll
.

Other win32-based unix environments, such as mingw or pw32, may use other
<prefix>
es, although at present only cygwin makes use of this feature. It
was originally intended to help avoid name conflicts among dll's built for the
various win32/un*x environments, so that (for example) two versions of a zlib dll
could coexist on the same machine.

The generic cygwin/mingw path layout uses a bin
directory for
applications and dll's and a lib
directory for the import
libraries (using cygwin nomenclature):

bin/
cygxxx.dll
lib/
libxxx.dll.a (in case of dll's)
libxxx.a (in case of static archive)

Linking directly to a dll without using the import library can be
done two ways:

1. Use the dll directly by adding the bin
path to the link line

gcc -Wl,-verbose  -o a.exe -L../bin/ -lxxx

However, as the dll's often have version numbers appended to their names
(cygncurses-5.dll
) this will often fail, unless one specifies
-L../bin -lncurses-5
to include the version. Import libs are generally
not versioned, and do not have this difficulty.

2. Create a symbolic link from the dll to a file in the lib
directory according to the above mentioned search pattern. This
should be used to avoid unwanted changes in the tools needed for
making the app/dll.

ln -s bin/cygxxx.dll lib/[cyg|lib|]xxx.dll[.a]

Then you can link without any make environment changes.

gcc -Wl,-verbose  -o a.exe -L../lib/ -lxxx

This technique also avoids the version number problems, because the following is
perfectly legal

bin/
cygxxx-5.dll
lib/
libxxx.dll.a -> ../bin/cygxxx-5.dll

Linking directly to a dll without using an import lib will work
even when auto-import features are exercised, and even when
-enable-runtime-pseudo-relocs
is used.

Given the improvements in speed and memory usage, one might justifiably
wonder why import libraries are used at all. There are two reasons:

1. Until recently, the link-directly-to-dll functionality did not
work with auto-imported data.

2. Sometimes it is necessary to include pure static objects within the
import library (which otherwise contains only bfd's for indirection
symbols that point to the exports of a dll). Again, the import lib
for the cygwin kernel makes use of this ability, and it is not
possible to do this without an import lib.

So, import libs are not going away. But the ability to replace
true import libs with a simple symbolic link to (or a copy of)
a dll, in most cases, is a useful addition to the suite of tools
binutils makes available to the win32 developer. Given the
massive improvements in memory requirements during linking, storage
requirements, and linking speed, we expect that many developers
will soon begin to use this feature whenever possible.

symbol aliasing
adding additional names

Sometimes, it is useful to export symbols with additional names.
A symbol foo
will be exported as foo
, but it can also be
exported as _foo
by using special directives in the DEF file
when creating the dll. This will affect also the optional created
import library. Consider the following DEF file:

LIBRARY "xyz.dll" BASE=0x61000000

EXPORTS
foo
_foo = foo

The line _foo = foo
maps the symbol foo
to _foo
.

Another method for creating a symbol alias is to create it in the
source code using the "weak" attribute:

void foo () { /* Do something.  */; }
void _foo () __attribute__ ((weak, alias ("foo")));

See the gcc manual for more information about attributes and weak
symbols.

renaming symbols

Sometimes it is useful to rename exports. For instance, the cygwin
kernel does this regularly. A symbol _foo
can be exported as
foo
but not as _foo
by using special directives in the
DEF file. (This will also affect the import library, if it is
created). In the following example:

LIBRARY "xyz.dll" BASE=0x61000000

EXPORTS
_foo = foo

The line _foo = foo
maps the exported symbol foo
to
_foo
.

Note: using a DEF file disables the default auto-export behavior,
unless the -export-all-symbols
command line option is used.
If, however, you are trying to rename symbols, then you should list
all
desired exports in the DEF file, including the symbols
that are not being renamed, and do not
use the
-export-all-symbols
option. If you list only the
renamed symbols in the DEF file, and use -export-all-symbols
to handle the other symbols, then the both the new names and
the original names for the the renamed symbols will be exported.
In effect, you'd be aliasing those symbols, not renaming them,
which is probably not what you wanted.

抱歉!评论已关闭.