| || |
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
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
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
| || |
$ 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' .