--- App-Staticperl/staticperl.pod 2010/12/06 21:12:21 1.4 +++ App-Staticperl/staticperl.pod 2010/12/08 23:03:21 1.16 @@ -1,6 +1,6 @@ =head1 NAME -staticperl - perl, libc, 50 modules all in one 500kb file +staticperl - perl, libc, 100 modules, all in one 500kb file =head1 SYNOPSIS @@ -16,6 +16,7 @@ staticperl instcpan modulename... # install modules from CPAN staticperl mkbundle # see documentation staticperl mkperl # see documentation + staticperl mkapp appname # see documentation Typical Examples: @@ -24,19 +25,22 @@ staticperl mkperl -M '"Config_heavy.pl"' # build a perl that supports -V staticperl mkperl -MAnyEvent::Impl::Perl -MAnyEvent::HTTPD -MURI -MURI::http # build a perl with the above modules linked in + staticperl mkapp myapp --boot mainprog mymodules + # build a binary "myapp" from mainprog and mymodules =head1 DESCRIPTION -This script helps you creating single-file perl interpreters, or embedding -a perl interpreter in your applications. Single-file means that it is -fully self-contained - no separate shared objects, no autoload fragments, -no .pm or .pl files are needed. And when linking statically, you can -create (or embed) a single file that contains perl interpreter, libc, all -the modules you need and all the libraries you need. - -With F and F on x86, you can create a single 500kb binary that -contains perl and 50 modules such as AnyEvent, EV, IO::AIO, Coro and so -on. Or any other choice of modules. +This script helps you to create single-file perl interpreters +or applications, or embedding a perl interpreter in your +applications. Single-file means that it is fully self-contained - no +separate shared objects, no autoload fragments, no .pm or .pl files are +needed. And when linking statically, you can create (or embed) a single +file that contains perl interpreter, libc, all the modules you need, all +the libraries you need and of course your actual program. + +With F and F on x86, you can create a single 500kb binary +that contains perl and 100 modules such as POSIX, AnyEvent, EV, IO::AIO, +Coro and so on. Or any other choice of modules. The created files do not need write access to the file system (like PAR does). In fact, since this script is in many ways similar to PAR::Packer, @@ -83,6 +87,11 @@ build and possibly fiddling with some modules. PAR is likely to produce results faster. +Ok, PAR never has worked for me out of the box, and for some people, +F does work out of the box, as they don't count "fiddling with +module use lists" against it, but nevertheless, F is certainly +a bit more difficult to use. + =back =head1 HOW DOES IT WORK? @@ -186,9 +195,12 @@ =item F -Runs F in the perl source directory (and potentially -cleans up other intermediate files). This can be used to clean up -intermediate files without removing the installed perl interpreter. +Deletes the perl source directory (and potentially cleans up other +intermediate files). This can be used to clean up files only needed for +building perl, without removing the installed perl interpreter, or to +force a re-build from scratch. + +At the moment, it doesn't delete downloaded tarballs. =item F @@ -238,6 +250,16 @@ to include that module. I found out about these dependencies by carefully watching any error messages about missing modules... +Instead of building a new perl binary, you can also build a standalone +application: + + # build the app + staticperl mkapp app --boot eg/httpd \ + -MAnyEvent::Impl::Perl -MAnyEvent::HTTPD -MURI::http + + # run it + ./app + =head3 OPTION PROCESSING All options can be given as arguments on the command line (typically @@ -289,9 +311,10 @@ (that means that the uncompressed file size is a bit larger, but the files compress better, e.g. with F). -Last not least, in the unlikely case where C is too slow, or some -module gets mistreated, you can specify C to not mangle included -perl sources in any way. +Last not least, if you need accurate line numbers in error messages, +or in the unlikely case where C is too slow, or some module gets +mistreated, you can specify C to not mangle included perl sources in +any way. =item --perl @@ -305,6 +328,28 @@ # build a new ./perl with only common::sense in it - very small :) staticperl mkperl -Mcommon::sense +=item --app name + +After writing out the bundle files, try to link a new standalone +program. It will be called C, and the bundle files get removed after +linking it. + +The difference to the (mutually exclusive) C<--perl> option is that the +binary created by this option will not try to act as a perl interpreter - +instead it will simply initialise the perl interpreter, clean it up and +exit. + +This switch is automatically used when F is invoked with the +C command (instead of C): + +To let it do something useful you I add some boot code, e.g. with +the C<--boot> option. + +Example: create a standalone perl binary that will execute F when +it is started. + + staticperl mkbundle --app myexe --boot appfile + =item --use module | -Mmodule Include the named module and all direct dependencies. This is done by @@ -384,6 +429,18 @@ add file2 myfiles/file2 add file3 myfiles/file3 +=item --binadd "file" | --add "file alias" + +Just like C<--add>, except that it treats the file as binary and adds it +without any processing. + +You should probably add a C prefix to avoid clashing with embedded +perl files (whose paths do not start with C), and/or use a special +directory, such as C. + +You can later get a copy of these files by calling C. + =item --static When C<--perl> is also given, link statically instead of dynamically. The @@ -404,7 +461,7 @@ =back -=head2 F CONFIGURATION AND HOOKS +=head2 F CONFIGURATION AND HOOKS During (each) startup, F tries to source the following shell files in order: @@ -430,61 +487,73 @@ The e-mail address of the person who built this binary. Has no good default, so should be specified by you. -=back +=item C -=head4 Variables you I to override +The URL of the CPAN mirror to use (e.g. L). -=over 4 +=item C -=item C +Additional modules installed during F. Here you can +set which modules you want have to installed from CPAN. -The perl version to install - default is currently C<5.12.2>, but C<5.8.9> -is also a good choice (5.8.9 is much smaller than 5.12.2, while 5.10.1 is -about as big as 5.12.2). +Example: I really really need EV, AnyEvent, Coro and AnyEvent::AIO. -=item C + EXTRA_MODULES="EV AnyEvent Coro AnyEvent::AIO" -The URL of the CPAN mirror to use (e.g. L). +Note that you can also use a C hook to achieve this, and +more. -=item C, C, C, C +=back -These flags are passed to perl's F script, and are generally -optimised for small size (at the cost of performance). Since they also -contain subtle workarounds around various build issues, changing these -usually requires understanding their default values - best look at the top -of the F script for more info on these. +=head4 Variables you might I to override + +=over 4 =item C The directory where staticperl stores all its files (default: F<~/.staticperl>). -=item C - -The prefix where perl gets installed (default: F<$STATICPERL/perl>), -i.e. where the F and F subdirectories will end up. - -=item C, C, others +=item C, C, ... Usually set to C<1> to make modules "less inquisitive" during their installation, you can set any environment variable you want - some modules (such as L or L) use environment variables for further tweaking. -=item C +=item C -Additional modules installed during F. Here you can -set which modules you want have to installed from CPAN. +The perl version to install - default is currently C<5.12.2>, but C<5.8.9> +is also a good choice (5.8.9 is much smaller than 5.12.2, while 5.10.1 is +about as big as 5.12.2). -Example: I really really need EV, AnyEvent, Coro and IO::AIO. +=item C - EXTRA_MODULES="EV AnyEvent Coro IO::AIO" +The prefix where perl gets installed (default: F<$STATICPERL/perl>), +i.e. where the F and F subdirectories will end up. -Note that you can also use a C hook to achieve this, and -more. +=item C + +Additional Configure options - these are simply passed to the perl +Configure script. For example, if you wanted to enable dynamic loading, +you could pass C<-Dusedl>. To enable ithreads (Why would you want that +insanity? Don't! Use L instead!) you would pass C<-Duseithreads> +and so on. + +More commonly, you would either activate 64 bit integer support +(C<-Duse64bitint>), or disable large files support (-Uuselargefiles), to +reduce filesize further. + +=item C, C, C, C + +These flags are passed to perl's F script, and are generally +optimised for small size (at the cost of performance). Since they also +contain subtle workarounds around various build issues, changing these +usually requires understanding their default values - best look at the top +of the F script for more info on these. =back -=head4 Variables you I to override +=head4 Variables you probably I to override =over 4 @@ -519,13 +588,21 @@ =over 4 +=item preconfigure + +Called just before running F<./Configur> in the perl source +directory. Current working directory is the perl source directory. + +This can be used to set any C variables, which might be costly +to compute. + =item postconfigure Called after configuring, but before building perl. Current working directory is the perl source directory. -Could be used to tailor/patch config.sh (followed by F<./Configure -S>) or -do any other modifications. +Could be used to tailor/patch config.sh (followed by F) +or do any other modifications. =item postbuild @@ -550,6 +627,164 @@ =back +=head1 ANATOMY OF A BUNDLE + +When not building a new perl binary, C will leave a number of +files in the current working directory, which can be used to embed a perl +interpreter in your program. + +Intimate knowledge of L and preferably some experience with +embedding perl is highly recommended. + +C (or the C<--perl> option) basically does this to link the new +interpreter (it also adds a main program to F): + + $Config{cc} $(cat bundle.ccopts) -o perl bundle.c $(cat bundle.ldopts) + +=over 4 + +=item bundle.h + +A header file that contains the prototypes of the few symbols "exported" +by bundle.c, and also exposes the perl headers to the application. + +=over 4 + +=item staticperl_init () + +Initialises the perl interpreter. You can use the normal perl functions +after calling this function, for example, to define extra functions or +to load a .pm file that contains some initialisation code, or the main +program function: + + XS (xsfunction) + { + dXSARGS; + + // now we have items, ST(i) etc. + } + + static void + run_myapp(void) + { + staticperl_init (); + newXSproto ("myapp::xsfunction", xsfunction, __FILE__, "$$;$"); + eval_pv ("require myapp::main", 1); // executes "myapp/main.pm" + } + +=item staticperl_xs_init (pTHX) + +Sometimes you need direct control over C and C, in +which case you do not want to use C but call them on your +own. + +Then you need this function - either pass it directly as the C +function to C, or call it from your own C function. + +=item staticperl_cleanup () + +In the unlikely case that you want to destroy the perl interpreter, here +is the corresponding function. + +=item PerlInterpreter *staticperl + +The perl interpreter pointer used by staticperl. Not normally so useful, +but there it is. + +=back + +=item bundle.ccopts + +Contains the compiler options required to compile at least F and +any file that includes F - you should probably use it in your +C. + +=item bundle.ldopts + +The linker options needed to link the final program. + +=back + +=head1 RUNTIME FUNCTIONALITY + +Binaries created with C/C contain extra functions, which +are required to access the bundled perl sources, but might be useful for +other purposes. + +In addition, for the embedded loading of perl files to work, F +overrides the C<@INC> array. + +=over 4 + +=item $file = staticperl::find $path + +Returns the data associated with the given C<$path> +(e.g. C, C), which is basically +the UNIX path relative to the perl library directory. + +Returns C if the file isn't embedded. + +=item @paths = staticperl::list + +Returns the list of all paths embedded in this binary. + +=back + +=head1 FULLY STATIC BINARIES - BUILDROOT + +To make truly static (Linux-) libraries, you might want to have a look at +buildroot (L). + +Buildroot is primarily meant to set up a cross-compile environment (which +is not so useful as perl doesn't quite like cross compiles), but it can also compile +a chroot environment where you can use F. + +To do so, download buildroot, and enable "Build options => development +files in target filesystem" and optionally "Build options => gcc +optimization level (optimize for size)". At the time of writing, I had +good experiences with GCC 4.4.x but not GCC 4.5. + +To minimise code size, I used C<-pipe -ffunction-sections -fdata-sections +-finline-limit=8 -fno-builtin-strlen -mtune=i386>. The C<-mtune=i386> +doesn't decrease codesize much, but it makes the file much more +compressible. + +If you don't need Coro or threads, you can go with "linuxthreads.old" (or +no thread support). For Coro, it is highly recommended to switch to a +uClibc newer than 0.9.31 (at the time of this writing, I used the 20101201 +snapshot) and enable NPTL, otherwise Coro needs to be configured with the +ultra-slow pthreads backend to work around linuxthreads bugs (it also uses +twice the address space needed for stacks). + +If you use C, then you should also be aware that +uClibc shares C between all threads when statically linking. See +L for a +workaround (And L for discussion). + +C support is also recommended, especially if you want +to play around with buildroot options. Enabling the C +package will probably enable all options required for a successful +perl build. F itself additionally needs either C +(recommended, for CPAN) or C. + +As for shells, busybox should provide all that is needed, but the default +busybox configuration doesn't include F which is needed by perl - +either make a custom busybox config, or compile coreutils. + +For the latter route, you might find that bash has some bugs that keep +it from working properly in a chroot - either use dash (and link it to +F inside the chroot) or link busybox to F, using it's +built-in ash shell. + +Finally, you need F inside the chroot for many scripts to work +- F or bind-mounting your F will +both provide this. + +After you have compiled and set up your buildroot target, you can copy +F from the C distribution or from your +perl f directory (if you installed it) into the F +filesystem, chroot inside and run it. + =head1 AUTHOR Marc Lehmann