Tcl Dev Kit

Installing licenses under OS X Mountain Lion

Question: 

My license installer will not run on OS X 10.8

Answer: 

Gatekeeper is blocking the installer.

Right-clicking the license installer and selecting "Open" should
prevent Gatekeeper from getting in the way for now.

TDK 4.0.2 needs Tcl 8.5?

Question: 

I've installed TclDevKit 4.0.2 and ActiveTcl 8.4.16 to compile my Tcl scripts. The problem is that the .tbc files generated by the Tcl Compiler
are only usable with tbcload 1.7 and only for Tcl 8.5. The message in the installation dialog suggests to take the packages from an Tcl 8.4 distribution.

Answer: 

TDK 4.0 comes with support for both 8.4 and 8.5. The unversioned tclcompiler executable is for 8.5, and tclcompiler84 is for 8.4. If you are using TclApp and the checkbox for this, there is a version specifier combobox right next to it for your convenience. In addition, it will auto-detect the version of the basekit you are using.

Correctly using source and exec in TclApp

Question: 

When I wrap my Tcl application with TclApp, I get errors when my code tries to source or exec another wrapped tcl file.

Answer: 

This is usually a problem with relative paths within TclApp's vfs. Here is an example for how to work around this:

package require Tk

set ::DIR [file dirname [info script]]

button .b -text 'Kill!' -command {source $::DIR/sourced.tcl }

pack .b

This script is setting $::DIR to be the basepath of the current
script. You can use this value to source or exec other scripts either when
wrapped or running as a script, regardless of what CWD is.

What is the ECCN for the TDK?

Question: 

What is the Export Control Classification Number for the Tcl Developers Kit?

Answer: 

The Export Control Classification Number for TDK is EAR99 (self-classified). For a brief description of EAR99 and information on the difference between EAR99 and NLR (No License Required), see:

http://www.census.gov/foreign-trade/faq/reg/reg0031.html

TclApp can't find a package

Question: 

I try to wrap my TclApp application and TclApp says it can't find a package that I know I have installed. It's in my package search list -- what do I do?

Answer: 

If you're trying to wrap a package in TclApp and it can't find a dependent package that ships with ActiveTcl you have specified, try the following:

  • locate the .tap file in the package's directory
  • open the .tap file and ensure that the capitalization in the TclApp definition matches that found in the Package directive of the .tap file

Though the package's filename or directory may not be capitalized, it is what is found in the .tap file that matters for TclApp.

Wrapping executables in a TclApp application

Question: 

I've bundled a binary executable inside my TclApp application. My script can see it, but the OS claims it isn't there when I try to run it. How do I fix it?

Answer: 

When a TclApp application is created, it creates a virtual filesystem using the Tcl vfs module and puts what it needs in that virtual filesystem. While your application can see inside the VFS, the operating system can't -- hence the error.

The best solution is to extract the executable to a location in the regular filesystem and run it from there. The operating system will be able to see it, and it will work as expected.

Bundling images and libraries with TclApp

Question: 

Do you have an easy-to-follow example of how to bundle images and libraries using TclApp?

Answer: 

A question that is frequently asked is how to bundle images and dependent libraries with TclApp, such that the whole application can be distributed as a single .exe on Windows platforms. It's a great question -- it's easy to turn off users with complex installers or applications that bomb because they can't find splash.gif.

Suppose we wanted to make a simple application that displays a pretty picture and generates a UUID (Universally Unique IDentifier). UUIDs aren't terribly useful to humans, but webservers and other programs use them fairly frequently.

First, let's grab a pretty picture. It should be a reasonably standard picture format -- GIF, JPEG, PNG, TIFF, PostScript... Any of these will do. For a full list of supported formats, see the documentation on the Img package for Tk. I'll use a GIF in this example, because it's what I have sitting around. For the purposes of this demo, we'll call the image file mylogo.gif.

The second step is to write our Tcl/Tk source file. I've attached the version I'm using, and we'll take it apart line by line.

package require Tk
package require Tcl
package require uuid


proc MyUUID {} {
	return [::uuid::uuid generate]
}


proc Main {} {
        image create photo foo -file [file join [file dirname [info script]] mylogo.gif]
#        image create photo foo -file "lib/application/Documents and Settings/activetest/Desktop/myapp/aslogo.gif"
        label .l1 -image foo -bd 1 -relief sunken800
        pack .l1 -side top
	label .l2 -text [MyUUID]
	pack .l2 -side bottom
        label .l3 -text [file dirname [info script]]
        pack .l3 -side bottom
}

Main

The first few lines are fairly standard boilerplate:

package require Tk
package require Tcl
package require uuid

These bring in the Tk, Tcl, and uuid libraries respectively. uuid is part of Tcllib, which ships as part of ActiveTcl. If you're not using ActiveTcl, you can get Tcllib from their Sourceforge project page.

proc MyUUID {} {
    return [::uuid::uuid generate]
}

Here we define a procedure that returns a UUID. This code does not have to go in a procedure, of course -- it could be written in-line.

proc Main {} {
    image create photo foo -file [file join [file dirname [info script]] mylogo.gif]
    label .l1 -image foo -bd 1 -relief sunken
    pack .l1 -side top

Next, we define the Main procedure. This isn't strictly necessary to do, but I define a Main procedure so nothing executes without it being called specifically. I find it handy for debugging purposes, but your mileage may vary.

First up in Main is to load the image. We'll call the image foo, for lack of a better name. Notice the file specification -- there is a bit of a song and dance going on there that needs a little explanation. The easiest way to read it is from the inside out. [info script] returns the full pathname of the script. [file dirname] returns the directory name of its argument, and [file join] composes a pathname from its arguments, inserting the appropriate path separator.

So why all the song and dance? When you're packing an image inside your executable, it's not always obvious as to how to find it. One thing you can usually rely on is for [info script] to return the proper path to the script that's running, and from there you can simply chop off the script name and add on the image name, as we have done above. This works for any kind of file.

The label command puts the image on a label, which can be packed into a window. In this case, we're using the toplevel window. Next, we pack the label, so it is visible.

    label .l2 -text [MyUUID]
    pack .l2 -side bottom
    label .l3 -text [file dirname [info script]]
    pack .l3 -side bottom
}

Main

Now it's time to add the UUID. Because MyUUID returns the text of the UUID, we can use the -text option to add it directly to the label.

For a finishing touch, we add the directory name as it is seen by the script, executing inside the wrapper.

Finally, we call Main -- and that's the end of the Tcl file.

The next step is to use TclApp to create the executable. Open TclApp, and you will be presented with a screen that looks like (click to view larger image):

.

Click the button with the document on it, and select the files you would like to wrap. In this case, we'll just wrap the Tcl file and the image. Next, we choose the packages we would like to wrap in the package. Click on the button with the yellow box, and select tcllib-1.8. You will see an entry for the package appear. Now hit the "Scan" button, and it should find the rest of the packages you need for you:

To make TclApp generate an executable file, we need to set the prefix file. Because we're using Tk, we'll choose base-tk-thread-win32-ix86.exe:

Don't forget to set your output file, as it's no fun to go hunting for your new application.

Last, we click over to the "Run" tab, and click the "Wrap" button. This wraps our application and shows any problems that might occur

Now you can run your application. Try renaming your image file -- the application still works, as it's using the wrapped image. You can even install your application on another machine that doesn't have ActiveTcl or the TDK installed, and there is no problem.

Of course this is a fairly trivial example. Things can get hairy when you're wrapping larger, more complex applications. If you run into any problems, try signing onto the TDK mailing list and asking around. There are great people there.

TDK blurb

Are you serious about programming with Tcl? The Tcl Dev Kit (TDK) is ActiveState's feature packed collection of tools for the professional Tcl/Tk developer, available on Mac OS X, Windows, Linux, HP-UX, AIX and Solaris. Features include debugging, code coverage, a byte-code compiler, and creating stand-alone executables from Tcl code.

Quick links: