App-Staticperl

 view release on metacpan or  search on metacpan

bin/staticperl  view on Meta::CPAN


rcd() {
   cd "$1" || fatal "$1: cannot enter"
}

trace() {
   prefix="$1"; shift
#   "$@" 2>&1 | while read line; do
#      echo "$prefix: $line"
#   done
   "$@"
}

trap wait 0

#############################################################################
# clean

distclean() {
   verblock <<EOF
   deleting everything installed by this script (rm -rf $STATICPERL)
EOF

   rm -rf "$STATICPERL"
}

#############################################################################
# download/configure/compile/install perl

clean() {
   rm -rf "$STATICPERL/src"
}

realclean() {
   rm -f "$PERL_PREFIX/staticstamp.postinstall"
   rm -f "$PERL_PREFIX/staticstamp.install"
   rm -f "$STATICPERL/src/perl/staticstamp.configure"
}

fetch() {
(
   rcd "$STATICPERL"

   mkdir -p src
   rcd src

   if ! [ -d "perl" ]; then
      rm -rf unpack
      mkdir -p unpack

      case "$PERL_VERSION" in
         *:* )
            # url
            PERLURL="$PERL_VERSION"
            PERLTAR="$(basename "$PERL_VERSION")"
            ;;
         /* )
            # directory
            verbose "copying $PERL_VERSION"
            cp -Rp "$PERL_VERSION/." unpack/.
            chmod -R u+w unpack
            mv unpack perl
            return
            ;;
         * )
            PERLURL="$CPAN/src/5.0/perl-$PERL_VERSION.tar.bz2"
            PERLTAR=perl-$PERL_VERSION.tar.bz2
            ;;
      esac

      if ! [ -e "$PERLTAR" ]; then
         verblock <<EOF
downloading perl

trying to download from $PERLURL

you can configure a download cache directory via DLCACHE
in your .staticperlrc to avoid repeated downloads.

to manually download perl yourself, place a suitable tarball in
$DLCACHE/$PERLTAR

either curl or wget is required for automatic download.
curl is tried first, then wget.
EOF

         rm -f $PERLTAR~ # just to be on the safe side
         { [ "$DLCACHE" ] && cp "$DLCACHE"/$PERLTAR $PERLTAR~ >/dev/null 2>&1; } \
            || wget -O $PERLTAR~ "$PERLURL" \
            || curl -f >$PERLTAR~ "$PERLURL" \
            || fatal "$URL: unable to download"
         rm -f $PERLTAR
         mv $PERLTAR~ $PERLTAR
         if [ "$DLCACHE" ]; then
            mkdir -p "$DLCACHE"
            cp $PERLTAR "$DLCACHE"/$PERLTAR~$$~ && \
               mv "$DLCACHE"/$PERLTAR~$$~ "$DLCACHE"/$PERLTAR
         fi
      fi

      verblock <<EOF
unpacking perl
EOF

      case "$PERLTAR" in
         *.xz   ) UNCOMPRESS="xz -d"    ;;
         *.lzma ) UNCOMPRESS="lzma -d"  ;;
         *.bz2  ) UNCOMPRESS="bzip2 -d" ;;
         *.gz   ) UNCOMPRESS="gzip -d"  ;;
         *.tar  ) UNCOMPRESS="cat"      ;;
         * )
            fatal "don't know hot to uncompress $PERLTAR,\nonly tar, tar.gz, tar.bz2, tar.lzma and tar.xz are supported."
            exit 1
            ;;
      esac

      <"$PERLTAR" $UNCOMPRESS -d | ( cd unpack && tar xf - ) \
         || fatal "$PERLTAR: error during unpacking"

      if [ -d unpack/*/ ]; then
         chmod -R u+w unpack/*/
         mv unpack/*/ perl
         rmdir -p unpack
      else
         fatal "unpacking $PERLTAR did not result in a single directory, don't know how to handle this"
      fi

      rm "$PERLTAR"
   fi
) || exit
}

# similar to GNU-sed -i or perl -pi
sedreplace() {
   sed -e "$1" <"$2" > "$2~" || fatal "error while running sed"
   rm -f "$2"
   mv "$2~" "$2"
}

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

bin/staticperl  view on Meta::CPAN


#   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"

   verblock <<EOF
building $STATICPERL/src/perl
EOF

   rm -f "$PERL_PREFIX/staticstamp.install"

   "$MAKE" || fatal "make: error while building perl"

   postbuild || fatal "postbuild hook failed"
) || exit
}

_postinstall() {
   if ! [ -e "$PERL_PREFIX/staticstamp.postinstall" ]; then
      NOCHECK_INSTALL=+
      instcpan $STATICPERL_MODULES
      [ "$EXTRA_MODULES" ] && instcpan $EXTRA_MODULES

      postinstall || fatal "postinstall hook failed"

      : > "$PERL_PREFIX/staticstamp.postinstall"
   fi
}

install() {
(
   if ! [ -e "$PERL_PREFIX/staticstamp.install" ]; then
      build

      verblock <<EOF
installing $STATICPERL/src/perl
to $PERL_PREFIX
EOF

      ln -sf "perl/bin/" "$STATICPERL/bin"
      ln -sf "perl/lib/" "$STATICPERL/lib"

      mkdir "$STATICPERL/patched"

      ln -sf "$PERL_PREFIX" "$STATICPERL/perl" # might get overwritten
      rm -rf "$PERL_PREFIX"                    # by this rm -rf

      rcd "$STATICPERL/src/perl"

      "$MAKE" install || fatal "make install: error while installing"

      rcd "$PERL_PREFIX"

      # create a "make install" replacement for CPAN
      write_shellscript SP-make-make <<'end_of_make'
#! sh

bin/staticperl  view on Meta::CPAN

   open my $fh, ">$PREFIX.ccopts"
      or die "$PREFIX.ccopts: $!";
   print $fh $ccopts;

   print "$ccopts\n\n"
      if $VERBOSE >= 1;
}

my $ldopts;

{
   print "generating $PREFIX.ldopts... ";

   $ldopts = $STATIC ? "-static " : "";

   $ldopts .= "$Config{ccdlflags} $Config{ldflags} $EXTRA_LDFLAGS @libs $Config{archlibexp}/CORE/$Config{libperl} $Config{perllibs} $EXTRA_LIBS";

   my %seen;
   $ldopts .= " $_" for reverse grep !$seen{$_}++, reverse +($extralibs =~ /(\S+)/g);

   for (@staticlibs) {
      $ldopts =~ s/(^|\s) (-l\Q$_\E) ($|\s)/$1-Wl,-Bstatic $2 -Wl,-Bdynamic$3/gx;
   }

   $ldopts =~ s/([\(\)])/\\$1/g;

   open my $fh, ">$PREFIX.ldopts"
      or die "$PREFIX.ldopts: $!";
   print $fh $ldopts;

   print "$ldopts\n\n"
      if $VERBOSE >= 1;
}

if ($PERL or defined $APP) {
   $APP = "perl" unless defined $APP;

   my $build = "$Config{cc} $ccopts -o \Q$APP\E$Config{_exe} bundle.c $ldopts";

   print "build $APP...\n"
      if $VERBOSE >= 1;

   print "$build\n"
      if $VERBOSE >= 2;

   system $build;

   unlink "$PREFIX.$_"
      for qw(ccopts ldopts c h);

   print "\n"
      if $VERBOSE >= 1;
}

end_of_mkbundle
}

bundle() {
   MKBUNDLE="${MKBUNDLE:=$PERL_PREFIX/bin/SP-mkbundle}"
   catmkbundle >"$MKBUNDLE~" || fatal "$MKBUNDLE~: cannot create"
   chmod 755 "$MKBUNDLE~" && mv "$MKBUNDLE~" "$MKBUNDLE"
   CACHE="$STATICPERL/cache"
   mkdir -p "$CACHE"
   "$PERL_PREFIX/bin/perl" -- "$MKBUNDLE" --cache "$CACHE" "$@"
}

if [ $# -gt 0 ]; then
   while [ $# -gt 0 ]; do
      mkdir -p "$STATICPERL" || fatal "$STATICPERL: cannot create"
      mkdir -p "$PERL_PREFIX" || fatal "$PERL_PREFIX: cannot create"

      command="${1#--}"; shift
      case "$command" in
         version )
            echo "staticperl version $VERSION"
            ;;
         fetch | configure | build | install | clean | realclean | distclean )
            ( "$command" ) || exit
            ;;
         import )
            ( import "$1" ) || exit
            shift
            ;;
         instsrc )
            ( instsrc "$@" ) || exit
            exit
            ;;
         instcpan )
            ( instcpan "$@" ) || exit
            exit
            ;;
         perl )
            ( install ) || exit
            exec "$PERL_PREFIX/bin/perl" "$@"
            exit
            ;;
         cpan )
            ( install ) || exit
            PERL="$PERL_PREFIX/bin/perl"
            export PERL
            exec "$PERL_PREFIX/bin/cpan" "$@"
            exit
            ;;
         mkbundle )
            ( install ) || exit
            bundle "$@"
            exit
            ;;
         mkperl )
            ( install ) || exit
            bundle --perl "$@"
            exit
            ;;
         mkapp )
            ( install ) || exit
            bundle --app "$@"
            exit
            ;;
         help )
            podusage 2
            ;;

bin/staticperl  view on Meta::CPAN

=item AnyEvent

AnyEvent needs a backend implementation that it will load in a delayed
fashion. The L<AnyEvent::Impl::Perl> backend is the default choice
for AnyEvent if it can't find anything else, and is usually a safe
fallback. If you plan to use e.g. L<EV> (L<POE>...), then you need to
include the L<AnyEvent::Impl::EV> (L<AnyEvent::Impl::POE>...) backend as
well.

If you want to handle IRIs or IDNs (L<AnyEvent::Util> punycode and idn
functions), you also need to include C<"AnyEvent/Util/idna.pl"> and
C<"AnyEvent/Util/uts46data.pl">.

Or you can use C<--usepacklists> and specify C<-MAnyEvent> to include
everything.

=item Cairo

See Glib, same problem, same solution.

=item Carp

Carp had (in older versions of perl) a dependency on L<Carp::Heavy>. As of
perl 5.12.2 (maybe earlier), this dependency no longer exists.

=item Config

The F<perl -V> switch (as well as many modules) needs L<Config>, which in
turn might need L<"Config_heavy.pl">. Including the latter gives you
both.

=item Glib

Glib literally requires Glib to be installed already to build - it tries
to fake this by running Glib out of the build directory before being
built. F<staticperl> tries to work around this by forcing C<MAN1PODS> and
C<MAN3PODS> to be empty via the C<PERL_MM_OPT> environment variable.

=item Gtk2

See Pango, same problems, same solution.

=item Net::SSLeay

This module hasn't been significantly updated since OpenSSL is called
OpenSSL, and fails to properly link against dependent libraries, most
commonly, it forgets to specify -ldl when linking.

On GNU/Linux systems this usually goes undetected, as perl usually links
against -ldl itself and OpenSSL just happens to pick it up that way, by
chance.

For static builds, you either have to configure -ldl manually, or you
cna use the following snippet in your C<postinstall> hook which patches
Net::SSLeay after installation, which happens to work most of the time:

   postinstall() {
      # first install it
      instcpan Net::SSLeay
      # then add -ldl for future linking
      chmod u+w "$PERL_PREFIX"/lib/auto/Net/SSLeay/extralibs.ld
      echo " -ldl" >>"$PERL_PREFIX"/lib/auto/Net/SSLeay/extralibs.ld
   }

=item Pango

In addition to the C<MAN3PODS> problem in Glib, Pango also routes around
L<ExtUtils::MakeMaker> by compiling its files on its own. F<staticperl>
tries to patch L<ExtUtils::MM_Unix> to route around Pango.

=item Term::ReadLine::Perl

Also needs L<Term::ReadLine::readline>, or C<--usepacklists>.

=item URI

URI implements schemes as separate modules - the generic URL scheme is
implemented in L<URI::_generic>, HTTP is implemented in L<URI::http>. If
you need to use any of these schemes, you should include these manually,
or use C<--usepacklists>.

=back

=head2 RECIPES

=over 4

=item Just link everything in

To link just about everything installed in the perl library into a new
perl, try this (the first time this runs it will take a long time, as a
lot of files need to be parsed):

   staticperl mkperl -v --strip ppi --incglob '*'

If you don't mind the extra megabytes, this can be a very effective way of
creating bundles without having to worry about forgetting any modules.

You get even more useful variants of this method by first selecting
everything, and then excluding stuff you are reasonable sure not to need -
L<bigperl|http://staticperl.schmorp.de/bigperl.html> uses this approach.

=item Getting rid of netdb functions

The perl core has lots of netdb functions (C<getnetbyname>, C<getgrent>
and so on) that few applications use. You can avoid compiling them in by
putting the following fragment into a C<preconfigure> hook:

   preconfigure() {
      for sym in \
         d_getgrnam_r d_endgrent d_endgrent_r d_endhent \
         d_endhostent_r d_endnent d_endnetent_r d_endpent \
         d_endprotoent_r d_endpwent d_endpwent_r d_endsent \
         d_endservent_r d_getgrent d_getgrent_r d_getgrgid_r \
         d_getgrnam_r d_gethbyaddr d_gethent d_getsbyport \
         d_gethostbyaddr_r d_gethostbyname_r d_gethostent_r \
         d_getlogin_r d_getnbyaddr d_getnbyname d_getnent \
         d_getnetbyaddr_r d_getnetbyname_r d_getnetent_r \
         d_getpent d_getpbyname d_getpbynumber d_getprotobyname_r \
         d_getprotobynumber_r d_getprotoent_r d_getpwent \
         d_getpwent_r d_getpwnam_r d_getpwuid_r d_getsent \



( run in 0.551 second using v1.01-cache-2.11-cpan-39bf76dae61 )