Cameron is vice president of Phaseit, a consulting firm. He can be contacted at [email protected].
Since the publication of "GUI Construction with Perl" (DDJ, January 2001), one of the most frequent questions I've received is, "How do I compile Perl/Tk scripts?" This article is my answer.
Recall that Perl/Tk is a collection of modules and code that weds the Tk 8.0 widget toolkit to Perl 5. In other words, it is an interpreted scripting language for making widgets and programs with GUIs. The current release of Perl/Tk is based on the widget toolkit originally associated with the tool command language (Tcl) scripting language. However, Perl/Tk does not require any familiarity with Tcl, nor does its installation depend on any Tcl code (apart from the code which is packaged within Perl/Tk). Perl/Tk uses Perl 5 syntax, grammar, and data structures.
Perl/Tk releases are available from the modules/by-authors/Nick_Ing-Simmons/ directory on the Comprehensive Perl Archive Network (http://www.perl.com/CPAN-local/). The production release of Perl/Tk was primarily written by Nick Ing-Simmons. The Perl/Tk language is itself further extensible via the standard Perl 5 module mechanism. A number of composite widget and special character extensions to the language have been written using Perl modules. I maintain the Perl/Tk FAQ (http://www.cpan.org/authors/id/C/CL/CLAIRD/ptkFAQ.html) that explains where to find Perl/Tk resources.
For the purpose of this article, I think of an interpreter as a software machine that receives a source script or text, and immediately executes it. For example, suppose Perl 5.6.0 has been installed in a standard way on a Windows desktop and you've written a script like Example 1 named "myclock.pl." Double-clicking on myclock.pl or invoking it at the DOS command line gives the same result: The Perl interpreter begins processing, scans myclock.pl, and puts up a primitive clock like that in Figure 1.
However, for any number of reasons speed, size, packaging, or whatever you might also want to compile into an executable. To do this, you need a Perl/Tk compiler a machine that, in the Windows world, turns a source like myclock.pl into a separate myclock.exe that can be executed directly.
Two Commercial Compilers for Windows
Here's how compilation works with Perl/Tk. Keep in mind that I'm focusing on Win32 versions here. There is currently no Perl/Tk for MacOS, not because of any particular technical constraint, but just because no one's taken the time to put the pieces together. For UNIX, not only does Perl/Tk work well, but the compilers there are even more straightforward than those for Windows.
There are a couple of distinct Perl/Tk compilers fit for use under Windows, both proprietary: Perl2Exe from IndigoStar (http://www.indigostar.com/perl2exe.htm) and Perlapp from ActiveState (http://www .activestate.com/Products/Perl_Dev_Kit/ index.html). They're also both inviting, and you can be testing your first results within 10 minutes. This is all it takes to use IndigoStar's Perl2Exe:
1. Download an evaluation copy from the Perl2Exe homepage.
2. Unzip the installation package: unzip p2x56.zip.
3. Use the installed utility to compile your source code: perl2exe myclock.pl.
4. Launch the resulting myclock.exe. You can now copy myclock.exe to a machine without any installed Perl and it still runs!
Perlapp is a compiler bundled as part of ActiveState Tool's Perl Developer Kit (PDK) product. Although Perlapp runs under Windows NT/2000, it compiles output to run under any modern Windows.
While IndigoStar's Perl2Exe is as easy to use as possible for a command-line-oriented utility, ActivePerl is oriented more toward point-and-click. It has sophisticated capabilities. At the same time, my experience is that it's a bit more fragile than Perl2Exe. I've run into several situations with the ActiveState tool where a minor reordering of an argument or installation sequence led to indecipherable errors. Perl2Exe appears to have neither as much flexibility nor as many pitfalls.
To use Perlapp:
1. Download an installable PDK. (While IndigoStar's p2x56.exe is only 620,845 bytes, the PDK bundles many elements beside a compiler and occupies just over 2 MB of space.)
2. Double-click on Perl_Dev_Kit$version .msi or enter at the command-line: instmsi Perl_Dev_Kit$version.msi.
3. Request an evaluation license (http://www.activestate.com/cgibin/license/ Redirect.plex?page=TrialLicense& ProductID=PLDK20T). This adds another step compared to the IndigoStar scheme for evaluation copies; however, it takes barely a minute to request and receive a license.
4. When the license arrives as an e-mail attachment, copy it to \Perl\bin\PLDK.$key.lic.
5. In one case, it appeared that I needed to reinstall Tk after PDK. While I could exhibit this behavior with only erratic reliability, remember you can enter ppm install Tk and, at worst, it will update your host.
6. I found it necessary to add use Tk::Label; near the top of the source in myclock.pl. Although ActiveState documentation mentions a couple of alternatives to this, they never satisfied me. Explicit use of use Tk::SOMETHINGs sprinkled liberally cured all the symptoms that puzzled me with PDK. The PDK Release Notes explain the principle behind this: Perlapp is trying to be smart and only include code that it's sure is necessary. use... says, "Yes, I really want this module."
7. From the command line, enter: perlapp -f myclock.pl. This generates a working myclock.exe.
Why Compile?
With an investment of under an hour, you can begin to compile your Perl applications. Why would you want to? The usual reasons are performance, size, security, fashion, and packaging. Execution of a compiled My_Perl_app.exe is generally slightly slower than the corresponding My_Perl_app.pl, and rarely as much as 10 percent faster. So why do programmers look to a Perl compiler for a benefit it doesn't give?
Most of us like cheap speed fixes. We want them so much that, as with true love and improved health, we'll look for them in all the wrong places.
Perl compilation is also like a diet book in that there are even superficially plausible theories on why both should work. Many people have a notion that high-performance programs are written in compiled languages such as C and Fortran, while more entry-level languages like Basic are interpreted. Doesn't it make sense then that a compiled form of Perl will be faster than an interpreted one?
A more detailed version of the arguments focuses attention on Perl fragments such as:
$addend1 = 3;
$addend2 = 4;
$result = $addend1 + $addend2;
When the usual Perl processor interprets this, significant CPU times go to bookkeeping about the types of variables involved (integer, float, and so on). It's easy to imagine that a compiler could optimize all this away into just a few lines of machine code, load the integer constants into registers, and then add them. The only hitch is that the Perl compilers don't do this or at least they do little of it, for now. The ActiveState and IndigoStar compilers are designed mostly for purposes other than performance. Perhaps they'll learn such optimizations in the future. For now, compiling a Perl application to increase its speed is mostly a fantasy.
No Help with Memory Footprint
It's even more of a mistake to try to squash the memory requirement of an application by compiling it. With comments, the example myclock.pl fills about 500 bytes. Once it's compiled, it takes up between 1.5 MB (Perlapp version) or almost 1.7 MB (Perl2Exe).
There are plenty of engineering tricks available for those with true performance or memory needs. Perl compilers might someday emphasize these more. For now, it's simply a mistake to compile Perl for any simple-minded gains in these directions.
Keeping Source Code Secure
Quite a few people ask for a compiler because "I don't want my customers to read my source code." I usually distribute Perl applications as *.pl sources, designed to be readable both by Perl interpreters and humans. Few people find *.exes nearly as easy to understand.
So in that sense, compilation does disguise a program. It's a flimsy disguise, however. Motivated Perl experts can easily strip off the disguise and recover original source code from the output of the current generation of Perl compilers. In the most common case, the text of each source file is stored intact in the body of the *.exe, plainly viewable by anyone accustomed to wading through memory dumps.
Security and associated themes of property rights are a specialized subject beyond the scope of this article. If you believe you need different security features than the current Perl compilers provide, your best bet is to consult with an expert in the area.
Formal Constraint
Some organizations want compilers for no particular reason at all, or at least none they can articulate. I've encountered only a few cases of this companies requiring that compiled languages be used for some or all projects, without any particular technical significance. I generally put this in my mental category of fashion, or compiler idolatry. If you find yourself in this situation, feel free to report that, yes, Perl is a compiled language with a competitive, multivendor market for compilers. It's the truth.
Deployment Convenience
So why do these compilers really exist? Think, for a moment, about the motivation for Perl/Tk itself: As Gary Holcombe wrote about TransEDA PLC (his employer): "Perl/Tk was the language of choice for us due to the power of Perl, the ability to rapid prototype in Tk, and, probably most importantly, due to its portability." People like Perl/Tk's ability to deliver quality results quickly.
How does an organization turn such a result into a product? In other words, how does an organization make the transition from having one instance of a program running on one development machine, to having hundreds or thousands of satisfied customers using their own copies of the programs on their own machines? For several of Perl's classic application domains in system administration and web work, the answer is simple: Send a copy of myprogram.pl. In these controlled environments, it is reasonable to expect that there is an adequately maintained Perl installation on each target host.
That's not always the case, though and particularly, it is not the case for many Perl/Tk customers. The logic designers who buy TransEDA products aren't computing specialists in the way you likely are. They might not have Perl installed, they might not know how to install it, and they might not even want it installed.
Given a choice between:
1. Install Perl.
2. Copy program.pl into a working directory.
and
1. Copy program.exe into a working directory.
those logic designers might have a strong and even overriding preference for the latter.
That's the main reason why the ActiveState and IndigoStar compilers exist. They package Perl applications so they're easier to deploy.
And since that's the motivation, their basic approach is the simpleminded one of packing a complete copy of the Perl interpreter along with complete copies of all Perl sources, into a single file, along with a tiny executable header to start a process. That's why their outputs are so large and crackable: All the parts of a conventional Perl application are present, just smashed together into a single file.
Future Enhancements and Politics
Again, this isn't the only way to compile Perl. Perlapp already has a variety of options that control compression, memory layout, and other factors. Individual developers sometimes write special-purpose compilers to solve specific problems. Malcolm Beattie at Oxford University has done quite a bit of work on a bytecode compiler that operates much as Java compilers do; an experimental version was part of the 5.005 release.
I'm not certain any of these efforts will ever achieve the success of Perl2Exe and Perlapp, though. The two commercial compilers take good care of their customers' need for packaged Perl applications. Other potential benefits of compilation such as speed and space are much less crucial.
Before leaving the topic of Perl compilers, you should also be aware of its political dimension. If I understand them correctly, several prominent Perl programmers regard compilation as a corruption whose use they discourage. They sincerely believe that information about the proprietary IndigoStar and ActiveState products inherently promotes mistaken values. Experienced readers might recall that porting Perl to the MacOS inspired similar reactions.
DDJ