TABS - Tcl Automated Build System
Written by Wojciech Kocjan   
TABS (Tcl Automated Build System) is something I came across some time ago and forgot completely about it. Until recently... I've been playing with building Starkits and Starpacks and got tired with doing .bat/.sh scripts to run sdx all the time. So I learned the thing. After some learning of how it works from source code, I managed to get a good understanding of it.

When you run tabs, it will try to perform build in the current directory that the user is in. You can also specify the directory for performing build by using -directory attribute. The definition of the build process should be contained in the Tabsfile file in that directory. The file is sourced as a Tcl script and uses several commands. One or more targetss that are to be built have to be specified in the command line invocation.

The idea is that you define one or more targets that can depend on one another. A target can then define one or more jobs that should be performed. Targets are defined using target command.

A job is a definition of an operation to be performed. It is contained inside definition of a target. Based on type of the job, it does different things. Jobs to be run are defined using runjob command inside a body of a target definition. There are currently few job types defined:
  • copy - copies one or more files from one location to another
  • wrap - allows wrapping one or more files in a Starkit/Starpack or Etcl kit (*.etk); similar to copy, but also handles packaging it in a single file

A small example might be a target that copies directory sourceA and sourceB to destinationC.

Copying sourceA and sourceB as destinationC
target copydirectories -body {
    runjob copy \
        -output destinationC \
        -copy {
            sourceA .
            sourceB .
        }
}
 

Similarly in order to build destinationC.kit that takes its contents from sourceA and sourceB, all that's needed is to run the wrap job:

Copy sourceA and sourceB to a starkit file
target buildkit -body {
    runjob wrap \
        -output destinationC.kit \
        -starkit true \
        -copy {
            sourceA .
            sourceB .
        }
}
 

In my past projects I used to have a very common scenario that this tool fits into very often. I would have a lot of common code base and some code that needs to go into specific packages. All this gets even trickier if you want to include platform-dependant libraries. For simplicity, let's assume we want to make the following things wrapped:
  • Copy main.tcl file to project1.kit as main.tcl
  • Copy contents of src-common directory to project1.kit into lib directory
  • Copy contents of src-project1 directory to project1.kit into lib directory
  • Copy main.tcl file to project2.kit as main.tcl
  • Copy contents of src-common directory to project2.kit into lib directory
  • Copy contents of src-project2 directory to project2.kit into lib directory

This is exactly the way I did it a lot of times, but using shell or Tcl scripts to do the actual copying. With Tabs, it would look this way:

Building this with tabs
target build -body {
    runjob wrap \
        -output project1.kit \
        -starkit true \
        -copy {
            main.tcl main.tcl
            src-common lib
            src-project1 lib
        }
 
    runjob wrap \
        -output project2.kit \
        -starkit true \
        -copy {
            main.tcl main.tcl
            src-common lib
            src-project2 lib
        }
}
 

The definition contains a single target that has 2 jobs in it - to wrap project1.kit and project2.kit, both defining some files and directories that should be copied into the kit files. Option -starkit tells Tabs to include the prefix Tcl code that causes the main contents of Starkit archive to be read by Tcl.

Assuming we also want to build just project1 as Starpacks for 2 platforms and each of these would also some platform dependant files, the definition would be very similar:

Building starpacks for multiple platforms
target build -body {
    runjob wrap \
        -output project1-win32.exe \
        -binary bin/tclkit-win32.exe \
        -copy {
            main.tcl main.tcl
            src-common lib
            src-common-win32 lib
            src-project1 lib
        }
 
    runjob wrap \
        -output project1-linux \
        -binary bin/tclkit-linux \
        -copy {
            main.tcl main.tcl
            src-common lib
            src-common-linux lib
            src-project1 lib
        }
 
}
 

Option -binary tells Tabs to use an existing Starpack binary or base and copy new files into it. Option -starkit should not be used for Starpacks.

It's also possible to build zip files that can be used with Etcl by adding a proper switch:

Building for Etcl and TclKit
target build -body {
    runjob wrap \
        -output project1.etk \
        -driver zip \
        -copy {
            main.tcl main.tcl
            src-common lib
            src-project1 lib
        }
 
    runjob wrap \
        -output project2.kit \
        -starkit true \
        -copy {
            main.tcl main.tcl
            src-common lib
            src-project2 lib
        }
}
 

Option -driver tells Tabs to use zip driver for packing files. By default it is mk4 which maps is default Starkit/Starpacks VFS format. Option -starkit should not be used for zip based archives.

This is just a short introduction and my observations after using it for small projects. I hope you will find this quick guide useful.