My trials with Ruby and Tcl/Tk on Mac OS X
Ruby is 1.8.0 preview 7
Tcl/Tk 8.4 is the recent TclTk-Aqua build for that native OSX Aqua look
Mac OS X is 10.2.3
(1) ‘configure’ wasn’t finding Tcl/Tk, so I hacked up an OSX-only version
of ext/tcltklib/extconf.rb with hard-coded parameters
(which might be OK because of the frameworks)
···
=========
extconf.rb for tcltklib
HACKED for Mac OS X !!!
require ‘mkmf’
if RUBY_PLATFORM !~ /mswin32|mingw|cygwin|bccwin32/
have_library(“nsl”, “t_open”)
have_library(“socket”, “socket”)
have_library(“dl”, “dlopen”)
have_library(“m”, “log”)
end
these are left-over; they mean nothing
dir_config(“tk”)
dir_config(“tcl”)
dir_config(“X11”)
tklib = with_config(“tklib”)
tcllib = with_config(“tcllib”)
stubs = enable_config(“tcltk_stubs”) || with_config(“tcltk_stubs”)
stubs = true # force it
$CPPFLAGS += ’ -DUSE_TCL_STUBS -DUSE_TK_STUBS’ if stubs
$CPPFLAGS += ’ -D_WIN32’ if /cygwin/ =~ RUBY_PLATFORM
these two are needed because #include <tcl.h> isn’t “framework” friendly
$CPPFLAGS += ’ -I/Library/Frameworks/Tcl.framework/Headers’
$CPPFLAGS += ’ -I/Library/Frameworks/Tk.framework/Headers’
tell the compiler where the libraries are
$CPPFLAGS += ’ -framework Tcl -framework Tk’
let the linker know where the libraries are
$LDFLAGS += ’ -framework Tcl -framework Tk’
create_makefile(“tcltklib”)
You should be thoroughly disgusted with that. However, I was getting
tired of running the following, and didn’t know how to get the top-level
’make’ to add all those options when it configured the extension.
Would those options really get carried from the top-level "./configure"
all the way down to the extension?
ruby extconf.rb \
--with-tcl-include=/Library/Frameworks/Tcl.framework/Headers \
--with-tk-include=/Library/Frameworks/Tk.framework/Headers \
--with-tcl-lib=/Library/Frameworks/Tcl.framework/Tcl \
--with-tk-lib=/Library/Frameworks/Tk.framework/Tk \
--enable-tcltk_stubs --enable-tk_stubs
(2) Now, the extension gets configured and compiles OK.
Run-time is something else.
/usr/lib/ruby/1.6/tk.rb:7:in `require': tcltklib: tcltk_stubs init error(-1) (LoadError)
Debug printfs revealed that the stubs interface was looking for
a library of 'libtcl8.4.bundle'. That's no-good for several reasons:
- the Tcl and Tk libraries do not have a 'bundle' extension (DLEXT)
- their names are much different than that
I worked around this mismatch by defining two environment variables,
thanks to the clear foresight of the author of 'stubs.c'!
export RUBY_TCL_DLL=/Library/Frameworks/Tcl.framework/Tcl
export RUBY_TK_DLL=/Library/Frameworks/Tk.framework/Tk
(3) Now, when loading the ‘tcltklib’ extension, there was a new error:
/usr/lib/ruby/1.6/tk.rb:7:in `require': tcltklib: tcltk_stubs init error(-2) (LoadError)
The code showed that it couldn't find 'Tcl_CreateInterp'.
After digging around 'dln.c' and the 'dl' library, I noticed a
routine called 'dlsym_auto_underscore'. In the '#define' for DLSYM
I used it instead of 'dlsym'. It seems to work, since the extension
now loads without complaint.
(4) So, I run ‘demo/lines1.rb’, and a big window comes up, with the
translucent blue button in the Aqua style that says ‘Draw’. Looks good,
but there are a few problems:
- every click in the window gives: "SetFrontProcess failed, -606"
- the window cannot be dragged
- the window cannot be closed, neither from the title bar,
nor with a ^ or ^\ from the shell (a 'kill' from another window
works OK, though)
(5) According to some Apple documents, the correct macros to detect
Mac OS X are both DARWIN and APPLE. In some places (dln.c)
I see NeXT and APPLE, or else it assumes OPENSTEP. I doubt that’s
a problem, but it had me looking cross-eyed at it for a long time!
FWIW, the top-level ‘configure’ generates: HAVE_LIBDL, HAVE_DLOPEN,
and a DLEXT of “.bundle”
So, I hope all this rambling will help someone else figure out what’s going on.