Tk/compile - making executables from perl/Tk scripts


  cd .../Tk800.013/compile
  make PROG=...path/to/script


This directory is for experimenting with compiling Tk apps. to executables. You need perl5.00556 (or later?) to have the right hooks in perl itself.

This has only been tested on Solaris 2.6 (but I doubt version makes much difference), and RedHat Linux 5.1 both with gcc. As far as I am aware other C compilers should work if 'Makefile' is tweaked appropriately. The Makefile is for GNU make as it uses $(shell ...). The Makefile could be converted to a script (contributions welcome), but having a makefile makes it easier for me to debug the stages.


build and install perl5.005_56 (suggest not as your _main_ perl). build and install Tk800.013 with perl5.005_56

cd to this directory Copy the script you want to compile to ( make PROG=.../script will do that ) type 'make'

wait ...

type 'trial' to test the executable.

copy 'trial' to your path.

How it Works

The script is "invoked" with two modules ahead of it on the command line and with perl's -c flag to "just compile". The most important of the modules is Malcolm Beatie's -MO=C "Compile" module. This installs an END {} block so that when perl has finished parsing the script the "C backend" gets control.

The other command line module is -MPreLoad (in this directory) this supplies another END {} block (which is run before Malcolm's), and overrides AutoLoader::import to pass the END {} block a list of modules that "use AutoLoader". The END {} block then loads _all_ the subs that module could load.

When Malcolm's END {} block gets control it then writes C code to build the same data structures that perl has just built. (This takes a long time and writes a large file - ../tiny takes 1:20 minutes and builds 3.5M of C). Lots of messages get written at the start - expect 'bootstrap' to be redefined a few times.

This C code (with version of B::C module in 5.00556) has one function which is very large. This stresses the C compiler, so makefile runs a perl script "splitfunc" which breaks that function down into smaller ones.

Then C code is compiled to an object file. This takes a long time (tiny takes 3:07 minutes). Beware enabling optimization or debug on this compile, it will take even longer.

Another perl script is run to find the shared objects which where loaded by DynaLoader (B::C module has listed them as comments in the C file). We also hunt down the DynaLoader.a library (just in case script will load something at run time).

Then all the above i.e. object files, shared objects, dynaloader are linked with libperl to produce the final executable.

tiny builds a 2.7M executable (stripped). Note though that due to fact that B::C and PreLoad include "everything" from modules, larger apps don't grow in proportion (ptked is 5M stripped).

Restrictions on Scripts

What gets compiled into the script is what gets built by perl up to, but stopping short of running the main script. This means that body of "use'd" modules is run, but "required" modules are not. The built executable is still (supposed to be) capable of loading other code (including binary modules), but will use "compiled-in" paths to do so.

So 'use Tk::widgets (...)' to load the widgets your script needs.

Only AutoLoader is handled by PreLoad. In particular SelfLoader will not work as DATA handle is lost between compile and running executable.

B::C's handing of initialized variables is still patchy. Thus if modules set global variables at "compile" time their values may be lost by time executable is run.

Showing Off

This file is being edited by compiled ptked on Linux.