Arjen Markus (6 january 2004) This is the fourth part of the tutorial How to make a Tcl application
7. Delivering your application
Let us return now to the first example, that of finding files. We want to make this available as a tool for our clients (or colleagues, friends, anybody). How do we do that? That, unfortunately, is not that easily done:
7.1 Installation on UNIX/Linux
First we go for the easy situation: our client has Tcl/Tk installed and he/she knows enough about programming to be able to put the application in some directory and make sure that directory is in the path.
Now on a UNIX/Linux system we can use a little trick to make the Tcl script behave as any ordinary shell script:
#!/bin/sh # \ exec tclsh "$0" ${1+"$@"}
(Note: remove the leading space from at least the first line!)
What does this do? Well the first line is shell script magic: the "#!" is a magic sequence that instructs any UNIX/Linux shell program to load the program named after that and let that handle the file. So, in this case, the Bourne shell is started and that starts interpreting our Tcl file ...
The third line in our file now causes the Bourne shell to hand over execution to a Tcl shell (tclsh or wish, whichever you need) passing on all the arguments that were given in the first place, including the full name of the original script file (that is what the weird incantation is all about). This allows us to circumvent hardcoding the path to the Tcl shell in our source code.
Now, the really unexpected bit, the Tcl shell is started and that considers the first three lines to be comments: the first two because of the # sign and the third because the Tcl parser has seen a backslash at the previous line and therefore joins up the third line with the second one.
So, in this strange way, the Tcl shell program is started automatically and our application can go ahead ...
All that is needed now is a suitable place to put our source code - preferably in the user's path - and eh presto!, the installation is ready.
An alternative is, of course, to create a small shell script that resides in some convenient directory (~/bin might be a good idea) and that starts the application via:
#!/bin/sh APPDIR=/usr/local/myapp exec tclsh $APPDIR/bin/myapp.tcl "${1+"$@"}
7.2 Installation on Windows
If we again assume that Tcl/Tk has been installed or will be installed on the target system, then the installation process has created some file association between a Tcl shell and the file extension ".tcl".
With some versions of Windows (notably NT and XP) this should be enough to be able to start the program in a DOS box:
c:\> myapp.tcl
(It will certainly be enough to start it via a file manager.)
If this does not work, then the following procedure is guaranteed to work:
@echo off "...path1...\tclsh.exe" "...path2...\myapp.tcl" %1 %2 %3 %4 %5 %6 %7 %8 %9
7.3 Installation on Mac OS X
P.M. - unfortunately
7.4 Things to consider: the directory structure
The above discourse assumes that you have made your application so that it can reside anywhere and be run anywhere. This is fairly easy to do when it consists of a single source file and does not need anything else. But if you need to source some library files or need access to data files, then you must be more careful.
Here are some tips:
.../myapp/ bin/ - directory holding the sources doc/ - directory with information about the application lib/ - directory with some configuration files for instance README - quick overview myapp.bat - short Windows/DOS batch file to start the program myapp - short UNIX/Linux shell script to start the program
Here is a small, nonsensical, example:
# myapp.tcl -- # # # Procedure: Print the welcome message # proc hello {text} { puts $text } # # Procedure: Print the goodbye message # proc goodbye {text} { puts $text } # main -- # Initialise the application (read the configuration file) # # Note: # Store the directory where the main source file resides # for later use. We need to do it in the main code outside # any procedure as the information is "volatile". # # set appdir [file dirname [info script]] # # The messages file is a small Tcl source file that defines the # variable hellotext and goodbyetext, but to be save, set defaults # here # set hellotext "Starting the application ..." set goodbyetext "Done" source [file join $appdir ".." "lib" "messages"] # # Start the application # hello $hellotext # # After all the processing, we are done # goodbye $goodbyetext
7.5 Things to consider: wrapping
The scenarios we have described sofar assume that Tcl/Tk is installed on the system (and it is useable by the client of our application) and we are willing to deliver the source code. If either condition fails, these scenarios will not work.
There is a very good alternative to installing Tcl/Tk: you can wrap your application. There are several methods to do this, and as a side effect, your code becomes unreadable (at least for ordinary users). If you need to hide your source code altogether, then the use of Tclpro may be a solution for you.
Here are a few possibilities:
This tutorial describes the third option in some detail, as the process is simple, elegant and very general:
tclkit sdx qwrap myapp.tcl
tclkit sdx unwrap myapp.kit
tclkit sdx unwrap myapp.kit
Et voila, you application is ready for shipping. Just deliver it together with the tclkit for the platform in question.
The other solutions mentioned here may use different methods, but the effect is pretty much the same: a standalone executable that does not rely on anything else to be installed on the target machine.
DKF: FWIW, the modern tclpro (a.k.a TclDevKit) wrapping utility builds starkits too (with minor differences IIRC).
7.6 Things to consider: the desktop
Modern practice on many computer systems nowadays demands that applications be started from the Start menu of the desktop or by some other graphical means.
This may be a general practice, but the details are extremely platform-dependent. See chapter 8 .... for more information.
One problem that such a procedure introduces is: what is the start-up directory? If you use a command shell, then the start-up directory is whatever the working directory is. But when you launch a program via the desktop, there is a fixed directory that needs to have been defined beforehand.
Depending on the features of your application, that may or may not be suitable: a word processor is not likely to mind too much, whereas a tool for finding files is probably best started in some relevant directory.