Tutorial Pages‎ > ‎

Freewrap-Gnocl

The Basics

For those of us who write their own Tcl code, scripts are probably fine but for almost everyone  else executables are needed.

Freewrap is probably the easiest to use utility ever produced to generate executables from Tcl scripts. There are other alternatives around, such as Starkits, but when all gnocl sharables are in their own place and available for other apps or scripts, what more could be desired? So, how are the executables made? Firstly, obtain a copy of Freewrap from Sourceforge. Both pre-compiled binaries and source tarballs are available so take your choice. Next, copy the executable into some location in the system path such as /usr/local/bin and then you're ready to create some standalone apps.

In order to use Gnocl it's necessary to load binary packages in the right way. Its no longer possible to simply use the familiar ‘package require’ instruction, the alternative load command needs to be used. One way to load these libraries would be to include a unique copy with the application executable, indeed application specific modules can be accessed in this way. The Gnocl libraries are intended to be shared and so these ought to be accessed from their appropriate installations. To do this with the load command the full path and file name needs to be provided. For local copies this would be:


load ./gnocl.so

or even,

load ./lib/gnocl.so

Whereas in order to access a system wide installation of the Gnocl libraries this might be something like:

load /usr/lib/tcl/tcl8.5/gnocl0.9.95.so

With this in mind then, an absolute minimal script looks something  like this:

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

load "./gnocl.so"
puts "Gnocl Version [gnocl::info version]"

set but1 [gnocl::button -text "Hello World!" -onClicked {gnocl::beep} ]
gnocl::window -child $but1 -onDelete {exit}

gnocl::mainLoop

This can then be turned into an executable using the command:

freewrapTCLSH hello.tcl

From this an executable named ‘hello’ would be generated.

Standalone Apps

You've slaved for months to develop that killer Linux app in Tcl/Gnocl and you want to share it with the world.
But, what about your potential users? What if they don't know anything about Gnocl or, most likely, do not want to go through the whole process of downloading tarballs, dependencies and building apps from sourcecode? Relax, this is not a problem. Freewrap can allow the wrapping of both script and binary packages into itself. The bottom line is then, there's no need even to install Gnocl or any other module for that matter. Yay! I hear you cry. How is this done?


The FreewrapTCLSH command can take a number of parameters which instruct it on how to proceed. A simple list of files will tell it what to included in a wrapped script. Returning to the familiar hello.tcl script, the gnocl.so shared library can be wrapped together with the script using like this:


freewrapTCLSH hello.tcl gnocl.so

Previously the separate gnocl.so module was accessed using the load command. Wrapped packages cannot be read directly and so need to be installed and then loaded. The ::freewrap::unpack command does it for you. Here's how the hello.tcl script is modified:

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# unpack, load and delete
set fpath [::freewrap::unpack gnocl.so]
load $fpath
file delete -force $fpath

puts "Gnocl Version [gnocl::info version]"

set but1 [gnocl::button \
    -text "Hello World!"  \
    -onClicked {gnocl::beep} ]


gnocl::window \
    -child $but1 \
    -onDelete {exit}


gnocl::mainLoop

Here the gnocl.so file is unpacked (the default directory is /usr/tmp) and the path returned to the calling script. This can then be loaded as usual before any clearing up of temp files takes place. This cluster of commands is ripe for modification into a more general purpose procedure which typically would look something like this:

proc freewrap_load {packages} {
    foreach package $packages {
        set pkg [::freewrap::unpack $package]
        if {$pkg == ""} {
            error "Package $package not found."
            }
          load $
pkg
          file delete -force $
pkg
    }
}

Automating the Process

When things get more complicated, alternative solutions are necessary.

Although the process of adding new packages is simple in principle, no-one wants to type lengthy options each time a fresh wrap is needed. The following shell script shows how it's possible to draw in the 'core' Gnocl package set and bring them together into a single wrapped application. Here, fresh copies of shared objects are assembled during each wrap session, useful if the packages too are still in development.


#---------------
# wrap.sh
#---------------
# William J Giddings
# 23/04/2010
#---------------

TCL_SOURCES=hello_2.tcl
BINARY_NAME=testApp
GNOCL_VERSION=0.9.95
PACKAGE_BASE_PATH=/usr/lib/tcl/tcl8.5

TEST=1

echo "----------------------------------------"
echo "Building $BINARY_NAME from $TCL_SOURCES"
echo "----------------------------------------"

echo "1) Copying packages"
cp $PACKAGE_BASE_PATH/gnocl$GNOCL_VERSION/gnocl.so ./
cp $PACKAGE_BASE_PATH/gnoclCanvas$GNOCL_VERSION/gnoclCanvas.so ./
cp $PACKAGE_BASE_PATH/gnoclGnome$GNOCL_VERSION/gnoclGnome.so ./
cp $PACKAGE_BASE_PATH/gnoclGconf$GNOCL_VERSION/gnoclGconf.so ./
cp $PACKAGE_BASE_PATH/gnoclVFS$GNOCL_VERSION/gnoclVFS.so ./

echo "2) Wrapping"
freewrapTCLSH $TCL_SOURCES \
    gnocl.so \
    gnoclCanvas.so \
    gnoclGnome.so \
    gnoclGconf.so \
    gnoclVFS.so \
    -o $BINARY_NAME

echo "3) Cleaning up"
rm *.so

if test $TEST -eq 1
then
echo "4) Testing $BINARY_NAME"
echo "----------------------------------------"
./$BINARY_NAME
fi

exit 0