MacTcl

Much of the information on this page is old (2003?). Although there may be useful information here, it is probably not the best place to start.

MacTcl is the name the community has used over time for a version of Tcl that runs on MacOS operating systems.


The focus of this page is to provide pointers and brief tips on building Tcl/Tk (and extensions for it) on MacOS 7, 8, 9, and X.

For pointers on using Tcl on the Mac, including notes on installation of pre-built binaries, go to Apple Macintosh and Tcl/Tk instead.

For a quick overview of all Mac related pages on this wiki, try https://wiki.tcl-lang.org/Search?mac Also see pages MacOS and MacOS X.


Key MacTcl resources on the web


Building MacTcl on OS X 10.1.3 using ProjectBuilder 1.1.1

JCW - ok, here we go... Using ~/src for source code, and ~/pbout + ~/pbtmp for ProjectBuilder results and intermediates, respectively:

    cd ~
    mkdir src pbout pbtmp

Getting the latest source from SourceForge CVS as described by James Bonfield [L1 ] (hit <return> when asked for a password):

    cd src
    cvs -d:pserver:[email protected]:/cvsroot/tcl -z3 login
    cvs -d:pserver:[email protected]:/cvsroot/tcl -z3 co -r macosx-8-4-branch tcl
    cvs -d:pserver:[email protected]:/cvsroot/tktoolkit login
    cvs -d:pserver:[email protected]:/cvsroot/tktoolkit -z3 co -r macosx-8-4-branch tk

Start ProjectBuilder, which lives in /Developer/Applications/. If this is the first time it was started, it'll ask for the setup of the two directories listed above (pbout and pbtmp), else go to the "Project Builder", "Preferences", "Building" menu/tab and enter the two (absolute) pathnames. As Jim Ingham notes, this is required so that the Tk project will find the binaries of the Tcl project.

From PB, do "File", "Open" to open the src/tcl/macosx/Tcl.pbproj file. Click on the leftmost "hammer" to build the "Tcl From Scratch" target which should be showing in the top middle pop-up of the window. Time for coffee (if you have a PB/300 as I do)!

When this completes, the bottom left status will say something like "Build succeeded, 9 errors" (yah, well... just warnings, it seems).

Now, from PB, open the src/tk/macosx/Wish.pbproj file. You need to alter one setting (note thanks to Robert Ramsay [L2 ]):

  • click on the Targets vertical tab
  • select "Tk Library" in the top left targets pane
  • select the "Files & Build Phases" horizontal tab
  • at the bottom, section "Shell Script", set the "Run only when installing" checkmark to prevent PB from launching a non-existent BuildConfig script.

Then make sure "Wish Shell" is selected in the center pop-up menu, and again: click on the top left hammer icon and finish that coffee (FYI, this step takes a very long time).

When you see "Build succeeded (2 warnings)" in the status, bottom left, then: congratulations, you have just made your first Wish. To run it, type Command-R (it will run it from PB, not sure how to do it from the finder, the Tcl and Tk frameworks probably need to be placed in a standard place first?). That's it: Tcl => Tk => Aqua => Enjoy!

MacOS X specifics

  • terminology: Carbon(ized), Cocoa, packages, Quartz, .dmg files, frameworks [explain, or better still: point to web pages]
  • dynamic libraries [explain Mach-O], "two-level names", pre-binding
  • Project Builder (Interface Builder, AppleScript Studio)
  • where things live in the file system
  • X-windows, Oroboros (sp?), rootless X windows
  • running in the Classic environment within MacOS X

The Classic Mac Is Different

  • AppleScript
  • the lack of "exec" and pipes
  • socket differences
  • encoding [what about it?]
  • pathnames work differently (colons, but not in same place as slash)

Having just gone through the experience of converting a Unix/Windows app to MacOS X I (James Bonfield) thought I'd share my experiences and solutions with others. The project I work on involves our own dynamic libraries and our own Tk widgets using X11 calls. The good news is that this all works on the native aqua interface without need for XonX. I've kept the information here relevant to building extensions, rather than Tcl/Tk itself. Should this go elsewhere? (Feel free to move it if so.)

Compilers

These are free for MacOS X (based on gcc) and can be downloaded from [L3 ].

IncrTcl

It does work with Jim Ingham's aqua-tcl/tk, but it requires tweaks to the build system. I submitted a patch on this to SourceForge. Similarly for iwidgets - a patch is required to the tabnotebook to prevent continuous looping in Configure events.

Dynamic libraries

Dynamic library xyzzy is named libxyzzy.dylib. Instead of LD_LIBRARY_PATH you need to set DYLD_LIBRARY_PATH. Try man dyld for the full gory details. To compiled a dynamic library use the compiler option "-dynamiclib" instead of "-shared". "man ld" will give you more hints.

Frameworks

Frameworks are similar to dynamic libraries, but they contain resources, include files, etc. The prebuilt Tcl and Tk are distributed is this way. To link against a framework just specify "-framework Tcl". It'll automatically search for them in /Library/Frameworks.

Unfortunately the -framework command doesn't seem to add to the include search path, so for that you'll need to use a traditional -I flag. (Eg "-I/Library/Frameworks/Tcl.framework/Headers").

Note: It does, but not in the way you are accustomed to. #include <MyFrameWorkName/myheader.h> does work without -I, #include <myheader.h> requires the -I flag ([email protected]).

Common symbols

If you get errors in linking complaining about common symbols:

    ld: common symbols not allowed with MH_DYLIB output format 
    mac-binaries/fred.o definition of common ArrayError (size 4) 

Then it means that you've got a global variable in the library which has not been assigned a value. E.g. in this case if fred.c has "int ArrayError;" then change it to "int ArrayError = 0;" to remove this problem. Alternatively if it's really an external definition then make it explicit with "extern int ArrayError;".

Bundles

Installed packages come in "bundles". These are directories of certain names (prog.app, prog.framework, prog.bundle). It's not easy to construct these by hand, but I'm sure the command line utilities do exist for such things.

The Project Builder makes creating bundles very easy. Initially I created a "Carbon Application" that consisted of main.c and little else. This main.c then set the appropriate environment variables and execl()ed the Wish Shell interpreter. However this then brings up two icons on the desktop. A better solution was described by Jim Ingham:

 > The way that you are supposed to make a "Tcl/Tk" based app on Mac OS X is to 
 > put make a copy of the Wish.app package, and call it whatever you want - 
 > maybe TkCVS.app.  Then make a "Scripts" folder in 
 > TkCVS.app/Contents/Resources, and put a startup script in the Scripts folder 
 > with the name AppMain.tcl.  This will get sourced when the app is 
 > double-clicked.  Also, the Scripts folder is added to the auto_path, so if 
 > you put other tcl library files, or a tclIndex file there, your app will 
 > find the other bits it needs from.  You can also replace the Wish.icns file 
 > with an icon file for your App, if you want it to have a different 
 > desktop/Dock icon.  If you were being really complete about it you might 
 > also want to edit the info.plist, and set things like the version string to 
 > appropriate values. 

This works well for me, but it required fixes to tcl (see sourceforge) so that I could set the necessary environment variables used by our applications.

To create an icon you'll need to save a file in an image format supporting transparency for the background. I did this using gimp. Then use the IconComposer app to import your image file and produce a .icns file.

It's possible to also create .command files, which are then executed under shell (or perhaps whatever #! indicates - I'm not sure). However these also then bring up a terminal window and so this is not appropriate for pure graphical tools.

Tcl load command

As of approx. 15th February the Tcl load command has been updated. Prior to this date if an attempt to load a library produced an error then the application failed. Errors could be caused by the library not being found (and it did not check DYLD_LIBRARY_PATH) or the Tcl_???_SafeInit symbol not being present, neither of which are considered errors on other platforms.

These have now both been solved, but it's still worth noting some DYLD_LIBRARY_PATH problems. Although this can be adjusted within an application, the dyld code only reads it at startup (before main). Hence it's not possible to change DYLD_LIBRARY_PATH in any program, except by executing another one. My solution to this is to have a launcher application which sets the environment and executes a second application (the real one). To prevent have two icons on the dock the launcher needs to fork and exec with the parent exiting naturally.

JKB


Category Mac