Newsgroups: comp.lang.tcl Subject: HOWTO: Using CYGWIN to build a Tcl extension on Windows Summary: Followup-To: Distribution: Organization: Keywords: Cc: I finally managed to build a Tcl extension on Windows using the Cygnus toolkit. This is with Cygwin release B20 and Tcl release 8.1.1. Here's what worked: + Download the Tcl 8.1.1 source distribution from Scriptics. You need this for the header files. (If you want to actually run the extension, get the Windows binary distribution too. :-) It's reportedly possible to build Tcl with CYGWIN, but I haven't tried that. [ Update: Don Porter points out that the binary distribution self-installer has an option to include the headers and libraries too. ] + Download 'gccstubs.zip', unpack it, and put "libtclstub81.a" somewhere convenient. (I found this file somewhere on the Neosoft archive, I forget where). | Update: It's at: | ftp://ftp.neosoft.com/pub/tcl/sorted/packages-8.0/devel/gccstubs.zip | Thanks to Jan Nijtmans for pointing this out. | It may also be possible to pull tclStubLib.c out of the Tcl source distribution and link with that instead. It requires a few minor hacks to work around missing #include files though. + Follow the instructions in the Scriptics "Building Extensions on Windows" HOWTO [1]. Basically, define the package initialization function like: int EXPORT Package_Init(Tcl_Interp *interp) { ... } where "EXPORT" is #define'd as "__declspec(dllexport)" if you're building under Windows, or "" otherwise. + Follow the instructions in the Scriptics "How to Use the Tcl Stubs Library" HOWTO [2]. Basically, compile everything with "-DUSE_TCL_STUBS", and call Tcl_InitStubs() in Package_Init(). Be sure to call Tcl_InitStubs *before* calling *any* other Tcl routine. + Compile all the source with gcc -DUSE_TCL_STUBS -mdll -mno-cygwin -mno-cygwin sets things up to use the Mingw32 libraries instead of the Cygwin libraries. MINGW32 is designed to be compatible with the MSVC runtime (and also prevents the binary from being GPL-infected). I'm not sure if -mno-cygwin is strictly necessary, but this combination is what worked for me. Mumit Khan has a lot of information on this subject at his web site [3] + In the next step, link the DLL with '-ltclstub81 -lmsvcrt'. + Follow the instructions in the Cygwin FAQ [4], question "How do I build a relocatable DLL?". Basically: - Add the following to the source code: int WINAPI DllEntryPoint(HINSTANCE hInst, DWORD reason, LPVOID reserved) { return TRUE; } - Create a file PACKAGE.DEF containing the following: EXPORTS Package_Init DllEntryPoint@12 - Follow the magic incantation listed in the FAQ: run ld, then dlltool, then ld, then dlltool, then ld again. Each of the five steps requires a bunch of options; see the FAQ [4] for what they're for and what they mean. There is reportedly an easier way to do this in later Cygwin releases, but I haven't found the proper voodoo yet. + Make a 'pkgIndex.tcl' file that looks something like: set path $dir ;# OR: set path [file dirname [info script]] set dll [info sharedlibextension] package ifneeded Package 1.0 \ [list load [file join $path libPackage1.0$dll]] (pkg_mkIndex might also do the trick, but I personally don't understand the auto-index, auto-package, auto-load mechanism well enough to trust it just yet :-) + Copy your pkgIndex.tcl and libPackage1.0.dll somewhere Tcl will find it. I created a directory: C:\Program Files\Tcl\Lib\Package1.0 and put everything there. I'm not sure if this is the Right Thing -- AFAIK, \Program Files\Tcl belongs to Scriptics -- but I can't figure out where else Tcl looks for packages without setting more environment variables. [ Don Porter adds: >That's my take on things too. IMHO, the "Right Thing" would be for >the root directory(s) [*] of the Tcl installation to hold only Tcl, >and have extensions installed elsewhere. However that's not the >"Tcl Way", and that's what you have to follow. [**] Each package >should be installed in its own directory (f.e. package1.0) which is >a sub-directory of a directory named "lib" which is a subdirectory >of Tcl's root directory (f.e. C:\Program Files\Tcl\Lib). The global >variable 'tcl_pkgPath' is supposed to be a list of directories in >which to install your package directories, but that's broken in >several Tcl releases -- notably Tcl 8.1.1 for Windows. > >[*] For Windows, the install directory you chose. For Unix, the >values of TCL_EXEC_PREFIX and TCL_PREFIX selected during configuration. > >[**] Unless of course, you are Scriptics. :) They have a habit of >installing their packages one directory level deeper, in .../lib/tclX.X/ . ] + Run tclsh81.exe under gdb, do a 'package require Package', and start tracking down GPFs :-) References: [1] [3] [4] --Joe English jenglish@flightlab.com