App-Staticperl
view release on metacpan or search on metacpan
bin/staticperl view on Meta::CPAN
#!/bin/sh
#############################################################################
# configuration to fill in (or to replace in your .staticperlrc)
STATICPERL=~/.staticperl
CPAN=http://mirror.netcologne.de/cpan # which mirror to use
EMAIL="read the documentation <rtfm@example.org>"
DLCACHE=
# perl build variables
MAKE=make
PERL_VERSION=http://stableperl.schmorp.de/dist/latest.tar.gz # 5.12.5 and 5.8.9 are good choices for small builds
PERL_CC=cc
PERL_CONFIGURE="" # additional Configure arguments
PERL_CCFLAGS="-g -DPERL_DISABLE_PMC -DPERL_ARENA_SIZE=16376 -DNO_PERL_MALLOC_ENV -D_GNU_SOURCE -DNDEBUG"
PERL_OPTIMIZE="-Os" # -Os -ffunction-sections -fdata-sections -finline-limit=8 -ffast-math"
ARCH="$(uname -m)"
#case "$ARCH" in
# i*86 | x86_64 | amd64 )
# PERL_OPTIMIZE="$PERL_OPTIMIZE -mpush-args -mno-inline-stringops-dynamically -mno-align-stringops -mno-ieee-fp" # x86/amd64
# case "$ARCH" in
# i*86 )
# PERL_OPTIMIZE="$PERL_OPTIMIZE -fomit-frame-pointer -march=pentium3 -mtune=i386" # x86 only
# ;;
# esac
# ;;
#esac
# -Wl,--gc-sections makes it impossible to check for undefined references
# for some reason so we need to patch away the "-no" after Configure and before make :/
# --allow-multiple-definition exists to work around uclibc's pthread static linking bug
#PERL_LDFLAGS="-Wl,--no-gc-sections -Wl,--allow-multiple-definition"
PERL_LDFLAGS=
PERL_LIBS="-lm -lcrypt" # perl loves to add lotsa crap itself
# some configuration options for modules
PERL_MM_USE_DEFAULT=1
PERL_MM_OPT="MAN1PODS= MAN3PODS="
#CORO_INTERFACE=p # needed without nptl on x86, due to bugs in linuxthreads - very slow
#EV_EXTRA_DEFS='-DEV_FEATURES=4+8+16+64 -DEV_USE_SELECT=0 -DEV_USE_POLL=1 -DEV_USE_EPOLL=1 -DEV_NO_LOOPS -DEV_COMPAT3=0'
export PERL_MM_USE_DEFAULT PERL_MM_OPT
# which extra modules to install by default from CPAN that are
# required by mkbundle
STATICPERL_MODULES="ExtUtils::MakeMaker ExtUtils::CBuilder common::sense Pod::Strip PPI PPI::XS Pod::Usage"
# which extra modules you might want to install
EXTRA_MODULES=""
# overridable functions
preconfigure() { : ; }
patchconfig() { : ; }
postconfigure() { : ; }
postbuild() { : ; }
postinstall() { : ; }
# now source user config, if any
if [ "$STATICPERLRC" ]; then
. "$STATICPERLRC"
else
[ -r /etc/staticperlrc ] && . /etc/staticperlrc
[ -r ~/.staticperlrc ] && . ~/.staticperlrc
[ -r "$STATICPERL/rc" ] && . "$STATICPERL/rc"
fi
#############################################################################
# support
# work around ExtUtils::CBuilder and others
export CC="$PERL_CC"
export CFLAGS="$PERL_CFLAGS"
export LD="$PERL_CC"
export LDFLAGS="$PERL_LDFLAGS"
unset LIBS
PERL_PREFIX="${PERL_PREFIX:=$STATICPERL/perl}" # where the perl gets installed
unset PERL5OPT PERL5LIB PERLLIB PERL_UNICODE PERLIO_DEBUG
unset PERL_MB_OPT
LC_ALL=C; export LC_ALL # just to be on the safe side
# prepend PATH - not required by staticperl itself, but might make
# life easier when working in e.g. "staticperl cpan / look"
PATH="$PERL_PREFIX/perl/bin:$PATH"
# set version in a way that Makefile.PL can extract
VERSION=VERSION; eval \
$VERSION="1.46"
fatal() {
printf -- "\nFATAL: %s\n\n" "$*" >&2
exit 1
}
verbose() {
printf -- "%s\n" "$*"
}
verblock() {
bin/staticperl view on Meta::CPAN
configure_failure() {
cat <<EOF
***
*** Configure failed - see above for the exact error message(s).
***
*** Most commonly, this is because the default PERL_CCFLAGS or PERL_OPTIMIZE
*** flags are not supported by your compiler. Less often, this is because
*** PERL_LIBS either contains a library not available on your system (such as
*** -lcrypt), or because it lacks a required library (e.g. -lsocket or -lnsl).
***
*** You can provide your own flags by creating a ~/.staticperlrc file with
*** variable assignments. For example (these are the actual values used):
***
PERL_CC="$PERL_CC"
PERL_CCFLAGS="$PERL_CCFLAGS"
PERL_OPTIMIZE="$PERL_OPTIMIZE"
PERL_LDFLAGS="$PERL_LDFLAGS"
PERL_LIBS="$PERL_LIBS"
EOF
exit 1
}
configure() {
(
fetch
rcd "$STATICPERL/src/perl"
[ -e staticstamp.configure ] && return
verblock <<EOF
configuring $STATICPERL/src/perl
EOF
rm -f "$PERL_PREFIX/staticstamp.install"
"$MAKE" distclean >/dev/null 2>&1
sedreplace '/^#define SITELIB/d' config_h.SH
# I hate them for this
grep -q -- -fstack-protector Configure && \
sedreplace 's/-fstack-protector/-fno-stack-protector/g' Configure
# what did that bloke think
grep -q -- usedl=.define hints/darwin.sh && \
sedreplace '/^usedl=.define.;$/d' hints/darwin.sh
preconfigure || fatal "preconfigure hook failed"
# trace configure \
sh Configure -Duselargefiles \
-Uuse64bitint \
-Dusemymalloc=n \
-Uusedl \
-Uusethreads \
-Uuseithreads \
-Uusemultiplicity \
-Uusesfio \
-Uuseshrplib \
-Uinstallusrbinperl \
-A ccflags=" $PERL_CCFLAGS" \
-Dcc="$PERL_CC" \
-Doptimize="$PERL_OPTIMIZE" \
-Dldflags="$PERL_LDFLAGS" \
-Dlibs="$PERL_LIBS" \
-Dprefix="$PERL_PREFIX" \
-Dbin="$PERL_PREFIX/bin" \
-Dprivlib="$PERL_PREFIX/lib" \
-Darchlib="$PERL_PREFIX/lib" \
-Uusevendorprefix \
-Dsitelib="$PERL_PREFIX/lib" \
-Dsitearch="$PERL_PREFIX/lib" \
-Uman1dir \
-Uman3dir \
-Usiteman1dir \
-Usiteman3dir \
-Dpager=/usr/bin/less \
-Demail="$EMAIL" \
-Dcf_email="$EMAIL" \
-Dcf_by="$EMAIL" \
$PERL_CONFIGURE \
-Duseperlio \
-Uversiononly \
-dE || configure_failure
sedreplace '
s/-Wl,--no-gc-sections/-Wl,--gc-sections/g
s/ *-fno-stack-protector */ /g
' config.sh
patchconfig || fatal "patchconfig hook failed"
sh Configure -S || fatal "Configure -S failed"
postconfigure || fatal "postconfigure hook failed"
: > staticstamp.configure
) || exit
}
write_shellscript() {
{
echo "#!/bin/sh"
echo "STATICPERL=\"$STATICPERL\""
echo "PERL_PREFIX=\"$PERL_PREFIX\""
echo "MAKE=\"$MAKE\""
cat
} >"$PERL_PREFIX/bin/$1"
chmod 755 "$PERL_PREFIX/bin/$1"
}
build() {
(
configure
rcd "$STATICPERL/src/perl"
bin/staticperl view on Meta::CPAN
execute F<appfile> when it is started.
staticperl mkbundle --app myexe --boot appfile
=item C<--ignore-env>
Generates extra code to unset some environment variables before
initialising/running perl. Perl supports a lot of environment variables
that might alter execution in ways that might be undesirablre for
standalone applications, and this option removes those known to cause
trouble.
Specifically, these are removed:
C<PERL_HASH_SEED_DEBUG> and C<PERL_DEBUG_MSTATS> can cause undesirable
output, C<PERL5OPT>, C<PERL_DESTRUCT_LEVEL>, C<PERL_HASH_SEED> and
C<PERL_SIGNALS> can alter execution significantly, and C<PERL_UNICODE>,
C<PERLIO_DEBUG> and C<PERLIO> can affect input and output.
The variables C<PERL_LIB> and C<PERL5_LIB> are always ignored because the
startup code used by F<staticperl> overrides C<@INC> in all cases.
This option will not make your program more secure (unless you are
running with elevated privileges), but it will reduce the surprise effect
when a user has these environment variables set and doesn't expect your
standalone program to act like a perl interpreter.
=item C<--static>
Add C<-static> to F<bundle.ldopts>, which means a fully static (if
supported by the OS) executable will be created. This is not immensely
useful when just creating the bundle files, but is most useful when
linking a binary with the C<--perl> or C<--app> options.
The default is to link the new binary dynamically (that means all perl
modules are linked statically, but all external libraries are still
referenced dynamically).
Keep in mind that Solaris doesn't support static linking at all, and
systems based on GNU libc don't really support it in a very usable
fashion either. Try uClibc if you want to create fully statically linked
executables, or try the C<--staticlib> option to link only some libraries
statically.
=item C<--staticlib> libname
When not linking fully statically, this option allows you to link specific
libraries statically. What it does is simply replace all occurrences of
C<-llibname> with the GCC-specific C<-Wl,-Bstatic -llibname -Wl,-Bdynamic>
option.
This will have no effect unless the library is actually linked against,
specifically, C<--staticlib> will not link against the named library
unless it would be linked against anyway.
Example: link libcrypt statically into the final binary.
staticperl mkperl -MIO::AIO --staticlib crypt
# ldopts might now contain:
# -lm -Wl,-Bstatic -lcrypt -Wl,-Bdynamic -lpthread
=item C<--extra-cflags> string
Specifies extra compiler flags, used when compiling the bundle file. The
flags are appended to all the existing flags, so can be sued to override
settings.
=item C<--extra-ldflags> string
Specifies extra linker flags, used when linking the bundle.
=item C<--extra-libs> string
Extra linker flags, appended at the end when linking. The difference to
C<--extra-ldflags> is that the ldflags are appended to the flags, before
the objects and libraries, and the extra libs are added at the end.
=back
=back
=head3 EXTENDED GLOB PATTERNS
Some options of F<staticperl mkbundle> expect an I<extended glob
pattern>. This is neither a normal shell glob nor a regex, but something
in between. The idea has been copied from rsync, and there are the current
matching rules:
=over 4
=item Patterns starting with F</> will be a anchored at the root of the library tree.
That is, F</unicore> will match the F<unicore> directory in C<@INC>, but
nothing inside, and neither any other file or directory called F<unicore>
anywhere else in the hierarchy.
=item Patterns not starting with F</> will be anchored at the end of the path.
That is, F<idna.pl> will match any file called F<idna.pl> anywhere in the
hierarchy, but not any directories of the same name.
=item A F<*> matches anything within a single path component.
That is, F</unicore/*.pl> would match all F<.pl> files directly inside
C</unicore>, not any deeper level F<.pl> files. Or in other words, F<*>
will not match slashes.
=item A F<**> matches anything.
That is, F</unicore/**.pl> would match all F<.pl> files under F</unicore>,
no matter how deeply nested they are inside subdirectories.
=item A F<?> matches a single character within a component.
That is, F</Encode/??.pm> matches F</Encode/JP.pm>, but not the
hypothetical F</Encode/J/.pm>, as F<?> does not match F</>.
=back
=head2 F<STATICPERL> CONFIGURATION AND HOOKS
bin/staticperl view on Meta::CPAN
=item C<EXTRA_MODULES>
Additional modules installed during F<staticperl install>. Here you can
set which modules you want have to installed from CPAN.
Example: I really really need EV, AnyEvent, Coro and AnyEvent::AIO.
EXTRA_MODULES="EV AnyEvent Coro AnyEvent::AIO"
Note that you can also use a C<postinstall> hook to achieve this, and
more.
=back
=head4 Variables you might I<want> to override
=over 4
=item C<STATICPERL>
The directory where staticperl stores all its files
(default: F<~/.staticperl>).
=item C<DLCACHE>
The path to a directory (will be created if it doesn't exist) where
downloaded perl sources are being cached, to avoid downloading them
again. The default is empty, which means there is no cache.
=item C<PERL_VERSION>
The perl version to install - C<5.12.5> is a good choice for small builds,
but C<5.8.9> is also a good choice (5.8.9 is much smaller than 5.12.5), if
it builds on your system.
You can also set this variable to the absolute URL of a tarball (F<.tar>,
F<.tar.gz>, F<.tar.bz2>, F<.tar.lzma> or F<.tar.xz>), or to the absolute
path of an unpacked perl source tree, which will be copied.
The default is currently
F<http://stableperl.schmorp.de/dist/latest.tar.gz>, i.e. the latest
stableperl release.
=item C<PERL_MM_USE_DEFAULT>, C<EV_EXTRA_DEFS>, ...
Usually set to C<1> to make modules "less inquisitive" during their
installation. You can set (and export!) any environment variable you want
- some modules (such as L<Coro> or L<EV>) use environment variables for
further tweaking.
=item C<PERL_PREFIX>
The directory where perl gets installed (default: F<$STATICPERL/perl>),
i.e. where the F<bin> and F<lib> subdirectories will end up. Previous
contents will be removed on installation.
=item C<PERL_CONFIGURE>
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<forks> 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<PERL_CC>, C<PERL_CCFLAGS>, C<PERL_OPTIMIZE>, C<PERL_LDFLAGS>, C<PERL_LIBS>
These flags are passed to perl's F<Configure> 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<staticperl> script for more info on these, and use a
F<~/.staticperlrc> to override them.
Most of the variables override (or modify) the corresponding F<Configure>
variable, except C<PERL_CCFLAGS>, which gets appended.
The default for C<PERL_OPTIMIZE> is C<-Os> (assuming gcc), and for
C<PERL_LIBS> is C<-lm -lcrypt>, which should be good for most (but not
all) systems.
For other compilers or more customised optimisation settings, you need to
adjust these, e.g. in your F<~/.staticperlrc>.
With gcc on x86 and amd64, you can get more space-savings by using:
-Os -ffunction-sections -fdata-sections -finline-limit=8 -mpush-args
-mno-inline-stringops-dynamically -mno-align-stringops
And on x86 and pentium3 and newer (basically everything you might ever
want to run on), adding these is even better for space-savings (use
-mtune=core2 or something newer for much faster code, too):
-fomit-frame-pointer -march=pentium3 -mtune=i386
=back
=head4 Variables you probably I<do not want> to override
=over 4
=item C<MAKE>
The make command to use - default is C<make>.
=item C<MKBUNDLE>
Where F<staticperl> writes the C<mkbundle> command to
(default: F<$STATICPERL/mkbundle>).
=item C<STATICPERL_MODULES>
Additional modules needed by C<mkbundle> - should therefore not be changed
unless you know what you are doing.
=back
=head3 OVERRIDABLE HOOKS
In addition to environment variables, it is possible to provide some
shell functions that are called at specific times. To provide your own
commands, just define the corresponding function.
The actual order in which hooks are invoked during a full install
from scratch is C<preconfigure>, C<patchconfig>, C<postconfigure>,
C<postbuild>, C<postinstall>.
Example: install extra modules from CPAN and from some directories
at F<staticperl install> time.
postinstall() {
rm -rf lib/threads* # weg mit Schaden
instcpan IO::AIO EV
instsrc ~/src/AnyEvent
instsrc ~/src/XML-Sablotron-1.0100001
instcpan Anyevent::AIO AnyEvent::HTTPD
}
=over 4
=item preconfigure
Called just before running F<./Configure> in the perl source
directory. Current working directory is the perl source directory.
This can be used to set any C<PERL_xxx> variables, which might be costly
to compute.
=item patchconfig
Called after running F<./Configure> in the perl source directory to create
F<./config.sh>, but before running F<./Configure -S> to actually apply the
config. Current working directory is the perl source directory.
Can be used to tailor/patch F<config.sh> or do any other modifications.
=item postconfigure
Called after configuring, but before building perl. Current working
directory is the perl source directory.
=item postbuild
Called after building, but before installing perl. Current working
directory is the perl source directory.
I have no clue what this could be used for - tell me.
=item postinstall
Called after perl and any extra modules have been installed in C<$PREFIX>,
but before setting the "installation O.K." flag.
The current working directory is C<$PREFIX>, but maybe you should not rely
on that.
This hook is most useful to customise the installation, by deleting files,
or installing extra modules using the C<instcpan> or C<instsrc> functions.
The script must return with a zero exit status, or the installation will
fail.
=back
=head1 ANATOMY OF A BUNDLE
When not building a new perl binary, C<mkbundle> 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<perlembed> and preferably some experience with
embedding perl is highly recommended.
( run in 1.005 second using v1.01-cache-2.11-cpan-39bf76dae61 )