Subject: Cygwin Python DLL and Shared Extension Patch
From: Jason Tishler <[email-masked]>
To: Python <[email-masked]>, Cygwin <[email-masked]>
Date: Thu, 9 Nov 2000 09:44:32 -0500

Attached is a patch that builds Cygwin Python with its core as a DLL --
similar to the way that one builds Win32 Python.  Once Cygwin Python
is built as a "shared library" (i.e., DLL), one can build extensions
using the same procedure as on other UNIX platforms that support shared
libraries.  It's as easy as copying Misc/Makefile.pre.in, creating a
Setup.in file, make -f Makefile.pre.in boot, make.

Actually, attached is two versions of the same patch.  The first one is
the real patch but requires autoconf.  The second one was generated after
I ran autoconf and hence only requires the more typical build environment.

Use the following procedure to patch and build Cygwin Python if you *have*
autoconf:

	$ tar -xvzf Python-2.0.tar.gz
	$ cd Python-2.0
	$ patch -p1 <../CygwinPython-2.0-minimal.patch
	$ autoheader
	$ autoconf
	$ configure --with-threads=no --with-libm= --with-suffix=.exe
	$ make
	$ make install

Use the following procedure to patch and build Cygwin Python if you *do not*
have autoconf:

	$ tar -xvzf Python-2.0.tar.gz
	$ gunzip CygwinPython-2.0-full.patch.gz
	$ cd Python-2.0
	$ patch -p1 <../CygwinPython-2.0-full.patch
	$ configure --with-threads=no --with-libm= --with-suffix=.exe
	$ make
	$ make install

To test out shared extensions, try the following:

	$ cd Demo/extend
	$ make_shared
	$ python
	Python 2.0 (#1, Nov  1 2000, 08:51:39)
	[GCC 2.95.2 19991024 (release-2)] on cygwin_nt-4.01
	Type "copyright", "credits" or "license" for more information.
	>>> import xx
	>>> dir(xx)
	['__doc__', '__file__', '__name__', 'bug', 'error', 'foo', 'new', 'roj']
	>>> xx.foo(2, 3)
	5

As a more realistic example, I was able to build python-ldap 1.10alpha3
(http://sourceforge.net/projects/python-ldap) with the following minimal
changes:

	1. replaced #ifdef WIN32 with #if defined(WIN32) || defined(__CYGWIN__)
	   as described in http://www.python.org/doc/FAQ.html#3.24
	2. added DL_EXPORT to init_ldap()

Note that there were no changes of any kind to the build files (i.e,
configure.in, Makefile.in, and Modules/Setup.in) or functionality changes
to the C source.

My goal is to ultimately submit the patch (redone against Python CVS) 
to the Python patch collector.  I am hoping interested people will help 
me refine the patch before submittal.

The following is an annotated ChangeLog for the patch:

Wed Nov  8 23:22:46 2000  Jason Tishler <[email-masked]>

	* Makefile.in: Add autoconf variable SET_DLLLIBRARY.
	* Makefile.in (altbininstall): Enhance altbininstall rule to also
	install the Cygwin Python DLL.
	* Makefile.in (libainstall): Change libainstall rule to install
	LDLIBRARY instead of LIBRARY.

	Will installing LDLIBRARY instead of LIBRARY break other
	platforms?  The terse description of LDLIBRARY in configure.in
	seems to indicate that possibly the original build procedure
	should be been installing it instead of LIBRARY.  Anyway, I am
	very willing to change the patch to install both LDLIBRARY and
	LIBRARY (if they are different) or some other suitable solution.

	* Modules/Makefile.in: Add autoconf variable SET_DLLLIBRARY.
	* Modules/Makefile.in ($(DLLLIBRARY)): Add $(DLLLIBRARY) rule to build
	the Cygwin Python DLL.

	Should the body of this rule be hidden in a shell script?  I have 
	stumbled across various platform specific scripts like BeOS/ar-fake
	that has me thinking that this may be desirable.  If not, then I will
	clean up the rule to use variables like LDSHARED instead of "gcc
	-shared", etc.

	* Modules/makesetup: Add shell variable module and default its value
	to "module".
	* Modules/makesetup: Add Cygwin specific definitions to set shell
	variables module, CygwinFlags, and CygwinLibs appropriately.

	Is it undesirable to put platform specific code in makesetup?

	* Modules/makesetup: Add .def to the list of known file types.
	* Modules/makesetup: Change object rule to include CygwinFlags.
	* Modules/makesetup: Change to use shell variable module instead of
	hardcoded "module".
	* Modules/makesetup: Change shared extension rule to include
	CygwinLibs.
	* acconfig.h: Add __CYGWIN__ guarded #defines for DL_IMPORT and
	DL_EXPORT.

	Is there a better way of accomplishing this without affecting config.h
	on all other autoconf supported platforms too?

	* configure.in: Add autoconf variable SET_DLLLIBRARY.
	* configure.in: Add Cygwin case to set LDLIBRARY and SET_DLLLIBRARY
	appropriately.

	I have chosen to call the import library libpython$(VERSION).dll.a
	and the DLL libpython$(VERSION).dll.  Recently there has been a
	proposal (http://sources.redhat.com/ml/cygwin/2000-10/msg01275.html)
	to name Cygwin DLLs cygfoo.dll instead of libfoo.dll in order
	to avoid clashing with Win32 versions of the same DLL.  I have stayed
	with libpython2.0.dll because it is more consistent with the UNIX
	naming convention and because there is no (current) possibility of
	clashing with the Win32 Python DLL, python20.dll.  Nevertheless, I
	am willing to change the name of the Cygwin Python DLL, if desired.

	* configure.in: Add Cygwin case to set MAKE_LDLIBRARY appropriately.
	* configure.in: Add Cygwin case to set SO appropriately.
	* configure.in: Add Cygwin case to set LDSHARED appropriately.

	Should LDSHARED contain more flags?  For example,
	-Wl,--enable-auto-image-base, etc.?

Any feedback is greatly appreciated.

Thanks,
Jason

-- 
Jason Tishler
Director, Software Engineering       Phone: +1 (732) 264-8770 x235
Dot Hill Systems Corporation         Fax:   +1 (732) 264-8798
82 Bethany Road, Suite 7             Email: [email-masked]
Hazlet, NJ 07730 USA                 WWW:   http://www.dothill.com
diff -rc Python-2.0.orig/Makefile.in Python-2.0/Makefile.in
*** Python-2.0.orig/Makefile.in	Mon Oct 16 17:50:06 2000
--- Python-2.0/Makefile.in	Wed Nov  1 07:37:11 2000
***************
*** 131,136 ****
--- 131,137 ----
  
  LIBRARY=	libpython$(VERSION).a
  LDLIBRARY=      @LDLIBRARY@
+ @SET_DLLLIBRARY@
  
  # Default target
  all:		$(LIBRARY) python$(EXE) sharedmods
***************
*** 247,252 ****
--- 248,257 ----
  			$(INSTALL_DATA) libpython$(VERSION).so $(LIBDIR); \
  		else	true; \
  		fi
+ 		if test -f "$(DLLLIBRARY)"; then \
+ 			$(INSTALL_DATA) $(DLLLIBRARY) $(BINDIR); \
+ 		else	true; \
+ 		fi
  
  # Install the manual page
  maninstall:
***************
*** 371,379 ****
  			else	true; \
  			fi; \
  		done
! 		@if test -d $(LIBRARY); then :; else \
! 			$(INSTALL_DATA) $(LIBRARY) $(LIBPL)/$(LIBRARY) ; \
! 			$(RANLIB) $(LIBPL)/$(LIBRARY) ; \
  		fi
  		$(INSTALL_DATA) Modules/config.c $(LIBPL)/config.c
  		$(INSTALL_DATA) Modules/python.o $(LIBPL)/python.o
--- 376,384 ----
  			else	true; \
  			fi; \
  		done
! 		@if test -d $(LDLIBRARY); then :; else \
! 			$(INSTALL_DATA) $(LDLIBRARY) $(LIBPL)/$(LDLIBRARY) ; \
! 			$(RANLIB) $(LIBPL)/$(LDLIBRARY) ; \
  		fi
  		$(INSTALL_DATA) Modules/config.c $(LIBPL)/config.c
  		$(INSTALL_DATA) Modules/python.o $(LIBPL)/python.o
diff -rc Python-2.0.orig/Modules/Makefile.pre.in Python-2.0/Modules/Makefile.pre.in
*** Python-2.0.orig/Modules/Makefile.pre.in	Mon Oct 16 17:49:33 2000
--- Python-2.0/Modules/Makefile.pre.in	Wed Nov  1 07:37:11 2000
***************
*** 105,110 ****
--- 105,111 ----
  
  LIBRARY=	../libpython$(VERSION).a
  LDLIBRARY=	../@LDLIBRARY@
+ @SET_DLLLIBRARY@
  
  # === Rules ===
  
***************
*** 126,131 ****
--- 127,140 ----
  		$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) $(MAINOBJ) \
  		  $(LDLIBRARY) $(MODLIBS) $(LIBS) $(SYSLIBS) -o python$(EXE) $(LDLAST)
  		mv python$(EXE) ../python$(EXE)
+ 
+ # This rule builds the Python DLL for Cygwin
+ $(DLLLIBRARY): $(LIBRARY)
+ 		test -d cygwin || mkdir cygwin
+ 		(cd cygwin; ar x ../$^)
+ 		dlltool --export-all --output-def $(basename $@).def cygwin/*.o
+ 		gcc -shared -Wl,--enable-auto-image-base -Wl,--out-implib=$(LDLIBRARY) -o $@ $(basename $@).def cygwin/*.o $(MODLIBS) $(LIBS) $(SYSLIBS)
+ 		rm -fr cygwin
  
  clean:
  		-rm -f *.o python$(EXE) core *~ [@,#]* *.old *.orig *.rej
diff -rc Python-2.0.orig/Modules/makesetup Python-2.0/Modules/makesetup
*** Python-2.0.orig/Modules/makesetup	Mon Oct 16 17:49:33 2000
--- Python-2.0/Modules/makesetup	Wed Nov  1 08:07:29 2000
***************
*** 79,84 ****
--- 79,102 ----
  NL='\
  '
  
+ # Default module names to so that their basename ends in "module"
+ module='module'
+ 
+ # Cygwin specific definitions:
+ #     1. do not append ${module} to the end of Cygwin module names
+ #     2. use -DUSE_DL_IMPORT when compiling shared extensions that are not
+ #        part of the Python core
+ #     3. use -L$(LIBPL) -lpython$(VERSION) when linking shared extensions
+ #        that are not part of the Python core
+ case `uname -s` in
+ CYGWIN*)	module=''
+ 		if test $srcdir != .
+ 		then
+ 			CygwinFlags='-DUSE_DL_IMPORT'
+ 			CygwinLibs='-L$(LIBPL) -lpython$(VERSION)'
+ 		fi;;
+ esac
+ 
  # Main loop
  for i in ${*-Setup}
  do
***************
*** 149,154 ****
--- 167,173 ----
  			*.so)		libs="$libs $arg";;
  			*.sl)		libs="$libs $arg";;
  			/*.o)		libs="$libs $arg";;
+ 			*.def)		libs="$libs $arg";;
  			*.o)		srcs="$srcs `basename $arg .o`.c";;
  			*.[cC])		srcs="$srcs $arg";;
  			*.cc)		srcs="$srcs $arg";;
***************
*** 196,202 ****
  			case $doconfig in
  			no)	cc="$cc \$(CCSHARED)";;
  			esac
! 			rule="$obj: $src; $cc $cpps \$(CFLAGS) -c $src"
  			echo "$rule" >>$rulesf
  		done
  		case $doconfig in
--- 215,221 ----
  			case $doconfig in
  			no)	cc="$cc \$(CCSHARED)";;
  			esac
! 			rule="$obj: $src; $cc $cpps \$(CFLAGS) $CygwinFlags -c $src"
  			echo "$rule" >>$rulesf
  		done
  		case $doconfig in
***************
*** 206,219 ****
  		do
  			case $objs in
  			*$mod.o*)	base=$mod;;
! 			*)		base=${mod}module;;
  			esac
  			file="$base\$(SO)"
  			case $doconfig in
  			no)	SHAREDMODS="$SHAREDMODS $file";;
  			esac
  			rule="$file: $objs"
! 			rule="$rule; \$(LDSHARED) $objs $libs -o $file"
  			echo "$rule" >>$rulesf
  		done
  	done
--- 225,238 ----
  		do
  			case $objs in
  			*$mod.o*)	base=$mod;;
! 			*)		base=${mod}${module};;
  			esac
  			file="$base\$(SO)"
  			case $doconfig in
  			no)	SHAREDMODS="$SHAREDMODS $file";;
  			esac
  			rule="$file: $objs"
! 			rule="$rule; \$(LDSHARED) $objs $libs $CygwinLibs -o $file"
  			echo "$rule" >>$rulesf
  		done
  	done
diff -rc Python-2.0.orig/acconfig.h Python-2.0/acconfig.h
*** Python-2.0.orig/acconfig.h	Mon Oct 16 17:50:06 2000
--- Python-2.0/acconfig.h	Wed Nov  1 07:37:11 2000
***************
*** 179,181 ****
--- 179,193 ----
  
  
  /* Leave that blank line there-- autoheader needs it! */
+ 
+ @BOTTOM@
+ 
+ #ifdef __CYGWIN__
+ #ifdef USE_DL_IMPORT
+ #define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
+ #define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
+ #else
+ #define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
+ #define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
+ #endif
+ #endif
diff -rc Python-2.0.orig/configure.in Python-2.0/configure.in
*** Python-2.0.orig/configure.in	Mon Oct 16 17:50:06 2000
--- Python-2.0/configure.in	Wed Nov  1 07:37:11 2000
***************
*** 217,226 ****
  # LDLIBRARY is the name of the library to link against (as opposed to the
  # name of the library into which to insert object files). On systems
  # without shared libraries, LDLIBRARY is the same as LIBRARY (defined in
! # the Makefiles). 
  AC_SUBST(MAKE_LDLIBRARY)
  AC_SUBST(LDLIBRARY)
  LDLIBRARY=''
  
  # LINKCC is the command that links the python executable -- default is $(CC).
  # This is altered for AIX in order to build the export list before 
--- 217,229 ----
  # LDLIBRARY is the name of the library to link against (as opposed to the
  # name of the library into which to insert object files). On systems
  # without shared libraries, LDLIBRARY is the same as LIBRARY (defined in
! # the Makefiles). On Cygwin LDLIBRARY is the import library, DLLLIBRARY is the
! # shared (i.e., DLL) library.
  AC_SUBST(MAKE_LDLIBRARY)
  AC_SUBST(LDLIBRARY)
+ AC_SUBST(SET_DLLLIBRARY)
  LDLIBRARY=''
+ SET_DLLLIBRARY=''
  
  # LINKCC is the command that links the python executable -- default is $(CC).
  # This is altered for AIX in order to build the export list before 
***************
*** 263,268 ****
--- 266,275 ----
  beos*)
        LDLIBRARY='libpython$(VERSION).so'
        ;;
+ cygwin*)
+       LDLIBRARY='libpython$(VERSION).dll.a'
+       SET_DLLLIBRARY='DLLLIBRARY=	$(basename $(LDLIBRARY))'
+       ;;
  esac
  AC_MSG_RESULT($LDLIBRARY)
  
***************
*** 272,278 ****
    LDLIBRARY='libpython$(VERSION).a'
    MAKE_LDLIBRARY="true"
  else
!   MAKE_LDLIBRARY='$(MAKE) $(LDLIBRARY)'
  fi
  
  AC_PROG_RANLIB
--- 279,288 ----
    LDLIBRARY='libpython$(VERSION).a'
    MAKE_LDLIBRARY="true"
  else
!   case $MACHDEP in
!     cygwin*) MAKE_LDLIBRARY='$(MAKE) -C Modules ../$(DLLLIBRARY)';;
!     *)       MAKE_LDLIBRARY='$(MAKE) $(LDLIBRARY)';;
!   esac
  fi
  
  AC_PROG_RANLIB
***************
*** 297,302 ****
--- 307,313 ----
  if test -z "$LN" ; then
  	case $ac_sys_system in
  		BeOS*) LN="ln -s";;
+ 		CYGWIN*) LN="ln -s";;
  		*) LN=ln;;
  	esac
  fi
***************
*** 539,550 ****
  AC_SUBST(CCSHARED)
  AC_SUBST(LINKFORSHARED)
  # SO is the extension of shared libraries `(including the dot!)
! # -- usually .so, .sl on HP-UX
  AC_MSG_CHECKING(SO)
  if test -z "$SO"
  then
  	case $ac_sys_system in
  	hp*|HP*)   SO=.sl;;
  	*)	   SO=.so;;
  	esac
  fi
--- 550,562 ----
  AC_SUBST(CCSHARED)
  AC_SUBST(LINKFORSHARED)
  # SO is the extension of shared libraries `(including the dot!)
! # -- usually .so, .sl on HP-UX, .dll on Cygwin
  AC_MSG_CHECKING(SO)
  if test -z "$SO"
  then
  	case $ac_sys_system in
  	hp*|HP*)   SO=.sl;;
+ 	CYGWIN*)   SO=.dll;;
  	*)	   SO=.so;;
  	esac
  fi
***************
*** 602,607 ****
--- 614,620 ----
  		fi;;
  	SCO_SV*) LDSHARED="cc -G -KPIC -Ki486 -belf -Wl,-Bexport";;
  	Monterey*) LDSHARED="cc -G -dy -Bdynamic -Bexport -L/usr/lib/ia64l64";;
+ 	CYGWIN*) LDSHARED="gcc -shared";;
  	*)	LDSHARED="ld";;
  	esac
  fi
--
Want to unsubscribe from this list?
Send a message to [email-masked]