Building Starkits and Starpacks using a Makefile

On Starpack, someone asked, could someone post some clues on how to automate the creation of a Starpack or Starkit through the use of a Makefile? Currently I use mktclapp which is okay, but getting dated.

JP I automate building starkits and starpacks with GNU Make under Cygwin. See my makefile at for an example.

LV the above request is a bit vague. Do you understand how to use makefiles? If so, then I'm uncertain exactly what you want. It's hard to list specific mechanical steps for creating a starkit the first time, unless all you want is a generic starkit:

 my.kit: my.tcl
  sdx qwrap my.tcl

Beyond that, it depends on what it is exactly that you want to do to the starkit.

As for automating the creation of a starpack:

 my.exe: my.kit
  sdx wrap my.kit -runtime /path/to/appropriate/tclkit

Again, anything more than this is probably going to be application specific.

Ok, say I have a Tcl/Tk program which some of the source files are "sourced" and others are within packages. How do I automate the starkit creation using a Makefile? I want to create a single file executable. Currently, I can do this with the mktclapp and it seems to work most of the time. However, this is maybe being deprecated and I would like to work with starkits, but they seem to be extremely complex and difficult to automate.

FPX: Here's what I use for creating Starkits and Starpacks for Password Gorilla.

First, some background:

  • All of the code for Password Gorilla is kept in a CVS repository. The below Makefile only allows me to build Starkits and Starpacks for checked-in code. That's by design, I don't like to send out builds that can not be traced to a specific revision.
  • As shown below, the Makefile is set up for use on Windows, within Cygwin. But with a few path adjustments in the setup section, it works the same on Unix.

Note: When copying and pasting from this page into your own Makefile, remember that all code lines in the wiki are preceded by a space character, which must be removed. Make is extremely picky when it comes to formatting.

Okay, some setup:

 VERSION = current
 CVSTAG = -D now
 WINKIT = c:/Software/tclkit/tclkit-with-encodings.exe
 SDX = c:/Software/tclkit/tclkitsh c:/Software/tclkit/sdx.kit

WINKIT sets the path to the Tclkit to use for building a Windows Starpack. In my case, this is a custom Tclkit, extended with the full set of codeset encodings, as described in [L1 ].

SDX is the command line for the sdx command.

VERSION is the version string to embed in the resulting Starkit's file name, and CVSTAG is the CVS tag to pull from the CVS repository. So, by default, "gorilla-current.kit" is built from the current code in CVS, using the "now" timestamp.

        @echo "usage: make <dist> VERSION=\"<version>\" CVSTAG=\"<tag>\""
        @echo "where:"
        @echo "   <dist>    is tgz, zip, kit, exe or dist"
        @echo "   <version> is the file's version suffix"
        @echo "   <tag>     is the CVS tag or date, e.g., \"-D now\""

Just a reminder to myself that the VERSION and CVSTAG options can be set on the command line, i.e., make kit VERSION="1.1" CVSTAG="-r release-1.1" will build a Starkit for the 1.1 release.

 TGZDIST = gorilla-$(VERSION).tar.gz
 ZIPDIST = gorilla-$(VERSION).zip
 KITDIST = gorilla-$(VERSION).kit
 WINDIST = gorilla-$(VERSION).exe

 dist: tgz zip kit exe
 tgz: $(TGZDIST)
 zip: $(ZIPDIST)
 kit: $(KITDIST)
 exe: $(WINDIST)

The dist target builds the .zip, .tar.gz, .kit and .exe distributions, but they can all be built individually, e.g., using make kit.

Okay, now to build the Starkit:

        rm -rf temp
        mkdir temp
        (cd temp; cvs export $(CVSTAG) gorilla)

First, create a local temp directory, and export the code from CVS, which will be in the temp/gorilla subdirectory.

        (cd temp/gorilla; $(SDX) qwrap gorilla.tcl)
        (cd temp/gorilla; $(SDX) unwrap gorilla.kit)

Use sdx to create the Starkit's directory structure. This will create the temp/gorilla/gorilla.vfs subdirectory, which contains the app-gorilla package, which at this point only contains the single file, gorilla.tcl. But it needs some support files, and some additional packages, so let's copy them into the future Starkit.

        (cp temp/gorilla/LICENSE.txt temp/gorilla/help.txt \
                temp/gorilla/isaac.tcl \

These support files are copied into the app-gorilla package, where gorilla.tcl can then simply source them.

        (cp -R temp/gorilla/blowfish temp/gorilla/pwsafe \
        cp -R BWidget-1.7.0 temp/gorilla/gorilla.vfs/lib

Now add some packages to the Starkit. The blowfish and pwsafe packages are part of the CVS tree, while BWidget is not. Copy them all to the gorilla.vfs/lib directory. At runtime, these packages can be loaded using package require.

Almost done. We can now create the Starkit:

        (cd temp/gorilla; $(SDX) wrap gorilla.kit)
        mv temp/gorilla/gorilla.kit $@
        rm -rf temp

This creates the Starkit, moves it out of the temp directory and into the current directory, then deletes the temp directory. Our Starkit is complete.

Now, to build the Windows Starpack:

 gorilla-$(VERSION).exe: gorilla-$(VERSION).kit
        rm -rf temp
        mkdir temp
        cp $^ temp/gorilla.kit
        (cd temp; $(SDX) unwrap gorilla.kit)

The Starpack depends on the Starkit. Again, we create a temp directory. Then we copy the Starkit into the temp directory, and unwrap it.

        cp pics/gorilla.ico temp/gorilla.vfs/tclkit.ico

Add the Windows icon.

        (cd temp; $(SDX) wrap gorilla.kit -runtime $(WINKIT))

And wrap it using the Windows Tclkit runtime.

        mv temp/gorilla.kit $@
        rm -rf temp

Then, move the freshly built executable to the current directory, and get rid of the temp directory.

Not shown here are the Makefile sections for building the .tar.gz and .zip distributions, or the clean target, which are not relevant here. For the complete example, just download the source distribution of Password Gorilla.

LV 2007 July 11

Turns out that, while I am not trying to do this via a Makefile, I have an interest in automating the build process a bit.

In my case, trying to point people to obscure various Windows folder paths is annoying. so I thought that I would build a tcl script that would point to pieces, and at the same time, execute the steps that one would do in the simplest case.

So I wrote this script, which I called bldexe.tcl:

 #! tclsh

 if { $::argc == 0 } {
        puts stderr "USAGE: $::argv0 ScriptToWrap"
        return 1

 set basename [file rootname $::argv]

 set p [pwd]            ; # Change to the tclkit / sdx.kit folder

 exec $p/tclkit.exe $p/sdx.kit qwrap $::argv

 exec $p/tclkit.exe $p/sdx.kit unwrap $::basename.kit

 exec $p/tclkit.exe $p/sdx.kit wrap $::basename.exe $p/base-tk8.5-architecture.exe

So, I go to Windows, and I create helloworld.tcl, which contains the single line

 puts "hello, world"

And I run bldexe.tcl . And there are at least two problems with the results.

  1. For some reason, when I run this script, on Windows, an empty frame appears. I have no idea what the source of it is. I don't see the empty frame on Unix.
  2. The resulting .exe file, on Windows, doesn't work. I can run the .kit created without problem. But for some reason, the exe just sits there and never terminates. On Unix, the exe runs fine...

dcd 2007/08/21

For another example try Building Starkits and Starpacks using a Makefile 2.

mho? For another approach see Windows batch script for 'compiling' starpacks.

EF Or you could use my make library [L2 ], build on top of code gathered from the Wiki, among other things.