|
25.4.3 A configure.in for DLLs
`configure.in' is used to generate the `configure' script:
|
# Process this file with autoconf to create configure.
AC_INIT(hello.h)
AM_CONFIG_HEADER(config.h:config.hin)
AM_INIT_AUTOMAKE(hello, 1.0)
AC_PROG_CC
AM_PROG_CC_STDC
AC_C_CONST
AM_PROG_LIBTOOL
AC_OUTPUT(Makefile)
|
The `AC_PROG_CC' and `AM_PROG_CC_STDC' macros in the
`configure.in' above will conspire to find a suitable compiler for
the C code in this example, and to discover any extra switches required
to put that compiler into an ANSI mode. I have used the
const keyword in the sources, so I need to specify the
`AC_C_CONST' macro, in case the compiler doesn't understand it, and
finally I have specified the `AM_PROG_LIBTOOL' macro since I want
the library to be built with Libtool.
In order to set the build environment up we need to create the
autogenerated files:
| $ ls
Makefile.in hello.c main.c
configure.in hello.h
$ aclocal
$ autoheader
$ libtoolize --force --copy
$ automake --foreign --add-missing --copy
automake: configure.in: installing ./install-sh
automake: configure.in: installing ./mkinstalldirs
automake: configure.in: installing ./missing
$ autoconf
$ ls
Makefile.am config.hin hello.c ltmain.sh stamp-h.in
Makefile.in config.sub hello.h main.c
aclocal.m4 configure install-sh missing
config.guess configure.in ltconfig mkinstalldirs
|
If you have already tried to build DLLs with Libtool, you have
probably noticed that the first point of failure is during the
configuration process. For example, running the new configure
script you might see:
| ...
checking if libtool supports shared libraries... yes
checking if package supports dlls... no
checking whether to build shared libraries... no
...
|
libtool provides a macro, `AC_LIBTOOL_WIN32_DLL', which
must be added to a package's `configure.in' to communicate to the
libtool machinery that the package supports DLLs.
Without this macro, libtool will never try to build a DLL
on Windows. Add this macro to `configure.in' before the
`AM_PROG_LIBTOOL' macro, and try again:
| $ make
cd . && aclocal
cd . && automake --foreign Makefile
cd . && autoconf
...
checking if libtool supports shared libraries... yes
checking if package supports dlls... yes
checking whether to build shared libraries... yes
...
gcc -DHAVE_CONFIG_H -I. -I. -I. -g -O2 -Wp,-MD,.deps/hello.pp \
-c -DDLL_EXPORT -DPIC hello.c -o .libs/hello.lo
gcc -DHAVE_CONFIG_H -I. -I. -I. -g -O2 -Wp,-MD,.deps/hello.pp \
-c hello.c -o hello.o >/dev/null 2>&1
mv -f .libs/hello.lo hello.lo
...
gcc -g -O2 -o ./libs/hello main.o .libs/libimp-hello-0-0-0.a \
-Wl,--rpath -Wl,/usr/local/lib
creating hello
...
$ ./hello
Hello, World!
|
If you run this and watch the full output of the `make' command,
Libtool uses a rather contorted method of building DLLs, with
several invocations each of dlltool and gcc . I have
omitted these from the example above, since they really are very ugly,
and in any case are almost incomprehensible to most people. To see it
all in its full horror you can always examine the output after running
the commands yourself! In a future release of Cygwin, recent work on
the binutils linker by DJ Delorie, will allow gcc to link
DLLs in a single pass using the same syntax used on other systems
to produce shared libraries. Libtool will adopt this method when it
becomes available, deprecating the use of dlltool .
I have extracted the interesting lines from amongst the many calls to
dlltool (67) and
gcc generated by make in the shell log. The main
thing to notice is that we have a `hello' binary, which is
executable, and which gives the right result when we run it! From the
partial log above, it certainly appears that it has built
`libhello' as a DLL and linked that into `hello', but
just to double check we can use ldd (68):
| $ libtool --mode=execute ldd ./hello
lt-hello.exe -> /tmp/.libs/lt-hello.exe
libhello-0-0-0.dll -> /tmp/.libs/libhello-0-0-0.dll
cygwin1.dll -> /usr/bin/cygwin1.dll
kernel32.dll -> /WINNT/system32/kernel32.dll
ntdll.dll -> /WINNT/system32/ntdll.dll
advapi32.dll -> /WINNT/system32/advapi32.dll
user32.dll -> /WINNT/system32/user32.dll
gdi32.dll -> /WINNT/system32/gdi32.dll
rpcrt4.dll -> /WINNT/system32/rpcrt4.dll
|
So now you know how to build and link a simple Windows DLL using
GNU Autotools: You add `-no-undefined' to the Libtool library
`LDFLAGS', and include the `AC_LIBTOOL_WIN32_DLL' macro in
your `configure.in'.
|