As you could see in the previous example, Tclkit can be used as a replacement for tclsh
, because it is able to run .tcl
scripts. This feature, although useful, is nothing new. What is really innovative is that Tclkit is also capable of executing Starkits.
What is Starkit? It is a technology that allows you to pack (or wrap) the entire directory structure containing your scripts and other files crucial for your application into a single file with a virtual system inside of it. Having read the previous sections of this chapter, it won't be a surprise for you that Metakit, along with the appropriate VFS driver, is used to achieve this goal.
The structure and naming convention of directories and files to pack is precisely defined, so Tclkit will be able to locate appropriate scripts inside it and start your application.
The word 'Starkit' also refers to any file created with this technology. Such a file contains your application, is very portable, installation-free, and has no external dependencies. As a convention, these files are named using the .kit
extension.
To create a Starkit file (we will also refer to it simply as 'starkit'), you may use the utility called SDX available at http://www.equi4.com/starkit/sdx.html. What is interesting is that SDX is nothing more than another application delivered in the form of Starkit, and the file is simply called sdx.kit
.
SDX accepts a number of command-line options, where the most important ones are:
qwrap
—a convenient way for the quick creation of the .kit
file, when your application comes in the form of a single-file Tcl scriptlsk
—lists the content of a .kit
fileunwrap
—unpacks a .kit
file, so you can easily inspect its contents with the file manager of your choicewrap
—allows the creation of .kit
files based on a strictly defined directory structure that reflects VFS contentsLet's focus on the quick creation of the starkit first. Surely, you still remember our "Hello World" example, constituted from one single file named main.tcl
. It is a perfect candidate to be wrapped into a .kit
file. For better readability, we will rename main.tcl
as hello.tcl
, in order to more clearly reflect what the script does. To wrap up our example, put Tclkit and SDX in the same directory, and use the following command:
c:workspaceTclHelloWorld>tclkitsh-win32.upx.exe sdx.kit qwrap hello.tcl
5 updates applied
Once finished, you will notice that a new file called hello.kit
is created. Now you can verify if it is working according to your expectations:
c:workspaceTclHelloWorld>tclkitsh-win32.upx.exe hello.kit
Hello World one more time!
At first glance, there is no logical reason to wrap this script, because you simply replace one file with another—but you will see what the differences are in a later section.
To unpack the file you have just created, use the unwrap
command:
c:workspaceTclHelloWorld>tclkitsh-win32.upx.exe sdx.kit unwrap hello.kit
5 updates applied
As a result of this command, the hello.vfs
directory is created. This directory reflects the contents of the virtual file system stored inside hello.kit
. What you will obviously notice first is that this directory contains more files than just hello.tcl
. As mentioned before, the structure of starkit's VFS is strictly defined, so SDX's qwrap
command works like a wizard and adds all the necessary files and directories. The structure will be explained in more detail later.
Although the qwrap
command is handy, it does not cover more complex variants. Imagine the opposite situation: instead of retrieving the full VFS structure from the .kit
file, you would actually wrap your already prepared directory tree along with sources of your valuable application. This is where the wrap
command becomes handy:
c:workspaceTclHelloWorld>tclkitsh-win32.upx.exe sdx.kit wrap hello2.kit hello.vfs
5 updates applied
The wrap
command runs with two parameters—the name of the file to create and the name of the directory to wrap. Therefore, in this case, we simply wrapped the hello.vfs
directory into the hello2.kit
starkit file. Note that we describe the latest available version of SDX at the time of writing; the earlier releases had a slightly different syntax for this command.
The second parameter can be skipped. In this case, if first parameter is in the form of<app-name>.kit
. The wrapper will search for the<app-name>.vfs
directory to wrap, so the command line will be:
c:workspaceTclHelloWorld>tclkitsh-win32.upx.exe sdx.kit wrap hello.kit
5 updates applied
It is important to notice that, by default, the starkits produced by SDX are read-only. If you would like your application to have the ability to modify or write files inside a wrapped VFS, you will have to specify the -writable
flag:
c:workspaceTclHelloWorld>tclkitsh-win32.upx.exe sdx.kit wrap hello.kit -writable
5 updates applied
If you are thinking seriously about using Starkit technology, the structure of VFS inside it can not be any mystery to you. Let's first inspect the hello.vfs directory from the previous example, and then discuss how to improve it with additional files crucial for your application.
The top-level directory contains:
app-your_application_name
, so in this case, the name is app-hello
.Let's focus on main.tcl
first. In our case, this file was generated automatically by SDX's qwrap
command, and its contents are:
package require starkit starkit::startup package require app-hello
The first line is obvious and causes the starkit
package to be loaded. This package is an integral part of Tclkit, responsible for proper handling of the entire Starkit technology. Once this package is loaded, the starkit::startup
command is available to be called. The command performs two important actions:
auto_path
variable, so it includes the lib
subdirectory, effectively causing all packages stored there to be available for your application. starkit::topdir
variable. The value of this variable is a (virtual) path that points to the directory where main.tcl
is located.After the starkit::startup
command is run, we can assume that the packages from the lib
subdirectory can easily be loaded—regardless of whether we run main.tcl
from hello.vfs
, a starkit, or a Starpack (which is described later). This feature provides great flexibility for code development—you don't have to generate a starkit after each change, because you will still be able to run the script in the normal way.
The starkit::startup
command also returns a value that may be used to distinguish how the script was invoked. It returns the following values:
unwrapped
—the script was executed in a normal way, using the command tclkit hello.vfs/main.tcl
starkit
—the script is executed as a part of starkit, using the command tclkit hello.kit
starpack
—the script is executed as a part of Starpack (discussed in the next section), for example, hello.exe
sourced
—the script was sourced from the another script using the command source hello.vfs/main.tcl
This value can be used for altering the operations of the script depending on the way it was executed.
At this point, package require app-hello
can be called successfully, causing your wrapped application code to be executed. What really happens is that the pkgIndex.tcl
file is sourced. Its content is:
package ifneeded app-hello 1.0 [list source [file join $dir hello.tcl]]
Therefore, effectively, it sources the hello.tcl
file. If you look inside it, you will find that this is basically the original file you wrapped in, with a slight modification to the first line:
package provide app-hello 1.0 puts "Hello World one more time!"
The line with the package information was automatically added by qwrap
.
It is important to mention at this point, that this structure is not obligatory. The mandatory items are only the main.tcl
file and, in case you want to use some packages that are not built into Tclkit, the lib
directory. You can put your entire application code into main.tcl
, or some other files inside the VFS structure of your choice. You could even sacrifice the starkit::topdir
variable (while handling the lib
directory) and not use the starkit
package at all. However, we do not recommend such a daring move—coding standards were not invented only to be, but also to facilitate understanding and development for other people. Just imagine what would happen if you wanted to maintain some weird code written by a bold programmer who believes standards are not his concern!
Often, your application will consist not only of script files, but also other items as well—for example, graphical images or sound files. There is no problem in putting additional files and directories inside the contents of the VFS, and the wrap
command will put them all inside the starkit file. Assuming you placed a file, say image.jpg
in a VFS subdirectory called images
(images/image.jpg
), you can refer to it in your scripts as follows:
$starkit::topdir/images/image.jpg
As mentioned earlier, the starkit::startup
command extends the $auto_path
variable so it includes the lib
directory. Therefore, adding additional packages is nothing more than putting them into this directory. Then the extension is available and you can use it in your code in the standard Tcl way:
package require <name_of_extension>
If you display hello.kit
(or any other .kit
file) with any text viewer/editor, you will notice that it starts like a normal script file:
#!/bin/sh # exec tclkit "$0" ${1+"$@"} package require starkit starkit::header mk4 readonly
After this header comes the binary data (that forms the content of the Metakit database lying below the VFS). Such a header allows you to run .kit
files directly on any Unix-like system by simply adding executable permissions and putting tclkit in your system path. On a Windows system, you will have to associate the .kit
extension with a Tclkit program in order to achieve this functionality.
When the header is interpreted by Tcl, the starkit
package is loaded. This package is included in all Tclkit versions. The last line causes the starkit package to mount the VFS and start processing the files stored inside it.
Your application does not have to be limited to only one starkit file. It is possible to use the Tcl command source
with .kit
files, for example:
source hello.kit
It may seem a little magical at first, but as we already mentioned, a .kit
file starts with normal Tcl script commands, and after interpreting the data, it effectively executes main.tcl
inside that starkit. If that script includes a call to the starkit::startup
command, it will expand the auto_path
variable including libraries (extensions) from the new .kit
file, and also replace the starkit::topdir
variable's value (so it is important to store its value before sourcing):
set topdir $starkit::topdir source hello.kit set starkit::topdir $topdir
The main disadvantage is that the entire main.tcl
file will be executed, and if you just want to make packages from another .kit
file available, this is undesired behavior. In such a situation, instead of sourcing the .kit
file, it is better to:
vfs::mk4::Mount /path/to/file.kit /path/to/file.kit -readonly append ::auto_path /path/to/file.kit /path/to/file.kit/lib
The first line mounts the hypothetical file.kit
file (located at /path/to)
at the mountpoint named /path/to/file.kit
(that's right, a good standard in case of VFS is to mount it under the same name as the original file containing it). On the other hand, the second line extends the auto_path
variable.
Starkit files are perfect candidates for delivering ready-to-use pieces of code like extensions/packages. This idea is implemented in terms of sdarchive
(found at the website http://tcl.tk/starkits)
, which is nothing more than a collection of ready-to-download and ready-to-use starkits. If your application uses a lot of packages, it is up to you to decide whether to put all of them into one main .kit
file or use some starkits from sdarchive
.
3.135.201.217