# This makefile is freely available from the website of Cygnus Solutions # at http://www.cygnus.com on the cygwin32 home page. The author is # Fergus Henderson http://www.cs.mu.oz.au/~fjh # Before using this file you should read and understand the documentation # on the Cygnus website. # This file comes with a suitable disclaimer; i.e., # This is provided AS IS, with absolutely NO WARRANTY EITHER EXPRESSED # OR IMPLIED. #-----------------------------------------------------------------------------# # Makefile.DLLs, version 0.7. # This Makefile contains rules for creating DLLs on Windows using gnu-win32. #-----------------------------------------------------------------------------# # The SYM_PREFIX is used as a prefix for the symbols in the files # that this makefiles automatically generates. # # The default SYM_PREFIX for libfoo.dll is `libfoo'. # But you can override this by setting `SYM_PREFIX-libfoo = blah'. SYM_PREFIX = $(firstword $(SYM_PREFIX-$*) $*) GUARD_MACRO = $(SYM_PREFIX)_GLOBALS_H DEFINE_DLL_MACRO = $(SYM_PREFIX)_DEFINE_DLL USE_DLL_MACRO = $(SYM_PREFIX)_USE_DLL IMP_MACRO = $(SYM_PREFIX)_IMP GLOBAL_MACRO = $(SYM_PREFIX)_GLOBAL IMPURE_PTR = $(SYM_PREFIX)_impure_ptr # This rule creates a `.def' file, which lists the symbols that are exported # from the DLL. We use `nm' to get a list of all the exported text (`T') # symbols and data symbols -- including uninitialized data (`B'), # initialized data (`D'), read-only data (`R'), and common blocks (`C'). # We also export `_impure_ptr', suitably renamed, so that the # main program can do the necessary initialization of the DLL's _impure_ptr. # (Since there can be more than one DLL, we must rename _impure_ptr as # $(SYM_PREFIX)_impure_ptr to prevent name collisions.) %.def: %.a echo EXPORTS > $@ echo $(IMPURE_PTR) = _impure_ptr >> $@ nm $< | sed -n '/^........ [BCDRT] _/s/[^_]*_//p' >> $@ # We need to use macros to access global data: # the user of the DLL must refer to `bar' as `(*__imp_bar)'. # This rule creates a pair of files `foo_dll.h' and `foo_globals.h' # which contains macros for doing this. # # The DLL may also contain some references to _impure_ptr # (e.g. stdin is defined as a macro which expands to _impure_ptr.stdin). # We need to provide a definition for this (otherwise it will link in # the definition in libccrt.o, which causes lots of problems, # eventually leading to undefined symbol `WinMain'). # The DLL's entry function (below) will initialize the _impure_ptr variable # in the DLL so that they point to the main program's reent_data struct. %_dll.h: echo "/* automatically generated by Makefile.DLLs */" > $@ echo "#ifndef $(GUARD_MACRO)" >> $@ echo "#define $(GUARD_MACRO)" >> $@ echo "" >> $@ echo "#if defined(__GNUC__) && defined(__CYGWIN32__)" >> $@ echo " #if defined($(USE_DLL_MACRO))" >> $@ echo " #define $(IMP_MACRO)(name) __imp_##name" >> $@ echo " #define $(GLOBAL_MACRO)(name) (*$(IMP_MACRO)(name))" >> $@ echo " #include \"$*_globals.h\"" >> $@ echo " #endif /* $(USE_DLL_MACRO) */" >> $@ echo "#endif /* __GNUC__ && __CYGWIN32__ */" >> $@ echo "" >> $@ echo "#endif /* $(GUARD_MACRO) */" >> $@ %_globals.h: %.a echo "/* automatically generated by Makefile.DLLs */" > $@ for sym in $(IMPURE_PTR) \ `nm $< | grep '^........ [BCDR] _' | sed 's/[^_]*_//'`; \ do \ echo "#define $$sym $(GLOBAL_MACRO)($$sym)" >> $@; \ done %_dll.c: echo "/* automatically generated by Makefile.DLLs */" > $@ echo "void *_impure_ptr;" >> $@ # This rule creates the export object file (`foo.exp') which contains the # jump table array; this export object file becomes part of the DLL. # This rule also creates the import library (`foo_dll.a') which contains small # stubs for all the functions exported by the DLL which jump to them via the # jump table. Executables that will use the DLL must be linked against this # stub library. %.exp %_dll.a : %.def dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \ --def $< \ --dllname $*.dll \ --output-exp $*.exp \ --output-lib $*_dll.a # The `sed' commands below are to convert DOS-style `C:\foo\bar' # pathnames into Unix-style `//c/foo/bar' pathnames. CYGWIN32_LIBS = $(shell echo \ -L`dirname \`gcc -print-file-name=libgcc.a | \ sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \ -L`dirname \`gcc -print-file-name=libcygwin.a | \ sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \ -L`dirname \`gcc -print-file-name=libkernel32.a | \ sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \ -lgcc -lcygwin -lkernel32 -lgcc) # Making relocatable DLLs doesn't seem to work. # Not quite sure why. The --image-base values below # where chosen at random, they seem to work on my machine. # DYNRELOC=no is the default # DLLDFLAGS-libgc += --image-base=0x2345000 # DLLDFLAGS-libmer += --image-base=0x1234000 # DLLDFLAGS-libmercury += --image-base=0x3456000 ifeq "$(strip $(DYNRELOC))" "yes" # to create relocatable DLLs, we need to do two passes # (warning: this is untested) %.dll: %.exp %.a %_dll.o dll_init.o dll_fixup.o $(DLLD) $(DLLDFLAGS) $(DLLDFLAGS-$*) --dll -o $*.base \ -e _dll_entry@12 \ $*.exp $*.a $*_dll.o \ dll_init.o dll_fixup.o \ $(LDLIBS) $(LDLIBS-$*) \ $(CYGWIN32_LIBS) # untested dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \ --def $*.def \ --dllname $*.dll \ --base-file $*.base \ --output-exp $*.exp $(DLLD) $(DLLDFLAGS) $(DLLDFLAGS-$*) --dll -o $*.base \ -e _dll_entry@12 \ $*.exp $*.a $*_dll.o \ dll_init.o dll_fixup.o \ $(LDLIBS) $(LDLIBS-$*) \ $(CYGWIN32_LIBS) dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \ --def $*.def \ --dllname $*.dll \ --base-file $*.base \ --output-exp $*.exp # end untested stuff $(DLLD) $(DLLDFLAGS) $(DLLDFLAGS-$*) --dll --base-file $*.base -o $@ \ -e _dll_entry@12 \ $*.exp $*.a $*_dll.o \ dll_init.o dll_fixup.o \ $(LDLIBS) $(LDLIBS-$*) \ $(CYGWIN32_LIBS) rm -f $*.base else %.dll: %.exp %.a %_dll.o dll_fixup.o dll_init.o $(DLLD) $(DLLDFLAGS) $(DLLDFLAGS-$*) --dll -o $@ \ -e _dll_entry@12 \ $*.exp $*.a $*_dll.o \ dll_init.o dll_fixup.o \ $(LDLIBS) $(LDLIBS-$*) \ $(CYGWIN32_LIBS) endif # This black magic piece of assembler needs to be linked in in order to # properly terminate the list of imported DLLs. dll_fixup.s: echo '.section .idata$$3' > dll_fixup.s echo '.long 0,0,0,0,0' >> dll_fixup.s dll_fixup.o: dll_fixup.s $(AS) $(ASFLAGS) -o dll_fixup.o dll_fixup.s # Windows requires each DLL to have an initialization function # that is called at certain points (thread/process attach/detach). # This one just initializes `_impure_ptr'. dll_init.c: echo '#include ' > dll_init.c echo 'extern struct _reent *_impure_ptr;' >> dll_init.c echo 'extern __declspec(dllimport) struct _reent reent_data;' >> dll_init.c echo '__attribute__((stdcall))' >> dll_init.c echo 'int dll_entry(int handle, int reason, void *ptr)' >> dll_init.c echo '{ _impure_ptr = reent_data; return 1; }' >> dll_init.c # The following rule is just there to convince gcc # to keep otherwise unused intermediate targets around. dont_throw_away: dll_fixup.o dll_init.o