use Config;
use Cwd;
# List explicitly here the variables you want Configure to
# generate. Metaconfig only looks for shell variables, so you
# have to mention them as if they were shell variables, not
# %Config entries. Thus you write
# $startperl
# to ensure Configure will look for $Config{startperl}.
# Wanted: $archlibexp
# This forces PL files to create target in same directory as PL file.
# This is so that make depend always knows where to find PL derivatives.
chdir dirname($0);
print "Extracting $file (with variable substitutions)\n";
# In this section, perl variables will be expanded during extraction.
# You can use $Config{...} to use Configure variables.
print OUT <<"!GROK!THIS!";
eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
if \$running_under_some_shell;
# In the following, perl variables are not expanded during extraction.
print OUT <<'!NO!SUBS!';
# Version 2.0, Simon Cozens, Thu Mar 30 17:52:45 JST 2000
# Version 2.01, Tom Christiansen, Thu Mar 30 08:25:14 MST 2000
# Version 2.02, Simon Cozens, Sun Apr 16 01:53:36 JST 2000
# Version 2.03, Edward Peschko, Mon Feb 26 12:04:17 PST 2001
# Version 2.04, Enache Adrian,Fri, 18 Jul 2003 23:15:37 +0300
use strict;
use warnings;
use 5.006_000;
use FileHandle;
use Config;
use Cwd;
our $VERSION = 2.04;
$| = 1;
use subs qw{
};
sub opt(*); # imal quoting
sub is_win32();
sub is_msvc();
our ($logfh);
our ($cfile);
our (@begin_output); # output from BEGIN {}, for testsuite
# eval { main(); 1 } or die;
main();
sub main {
parse_argv();
run_code();
_die("XXX: Not reached?");
}
#######################################################################
sub choose_backend {
# Choose the backend.
$Backend = 'C';
if (opt(B)) {
$Backend = 'Bytecode';
}
# die "$0: Do you want me to compile this or not?\n";
delete $Options->{S};
}
}
sub generate_code {
} else {
if ($Backend eq 'Bytecode') {
compile_byte();
} else {
}
}
}
sub run_code {
run("$Output @ARGV");
exit(0);
}
# usage: vprint [level] msg args
sub vprint {
my $level;
if (@_ == 1) {
$level = 1;
} elsif ($_[0] =~ /^\d$/) {
$level = shift;
} else {
# well, they forgot to use a number; means >0
$level = 0;
}
my $msg = "@_";
{
}
}
sub parse_argv {
# disallows using long arguments
# Getopt::Long::Configure("bundling");
# no difference in exists and defined for %ENV; also, a "0"
# argument or a "" would not help cc, so skip
$Options = {};
'L:s', # lib directory
'I:s', # include directories (FOR C, NOT FOR PERL)
'o:s', # Output executable
'v:i', # Verbosity level
'e:s', # One-liner
'r', # run resulting executable
'B', # Byte compiler backend
'O', # Optimised C backend
'c', # Compile only
'h', # Help me
'S', # Dump C files
'r', # run the resulting executable
'T', # run the backend using perl -T
't', # run the backend using perl -t
'static', # Dirty hack to enable -shared/-static
'shared', # Create a shared library (--shared for compat.)
'log:s', # where to log compilation process information
'Wb:s', # pass (comma-sepearated) options to backend
'testsuite', # try to be nice to testsuite
);
$Options->{v} += 0;
warn "Can't specify both -T and -t, -t ignored";
$Options->{t} = 0;
}
if (opt(e)) {
warn "$0: using -e 'code' as input file, ignoring @ARGV\n" if @ARGV;
# We don't use a temporary file here; why bother?
# XXX: this is not bullet proof -- spaces or quotes in name!
} else {
# DWIM modules. This is bad but necessary.
warn "$0: using $Input as input file, ignoring @ARGV\n" if @ARGV;
check_read($Input);
check_perl($Input);
sanity_check();
}
}
sub opt(*) {
my $opt = shift;
}
sub compile_module {
die "$0: Compiling to shared libraries is currently disabled\n";
}
sub compile_byte {
my $command = "$BinPerl -MO=Bytecode,-H,-o$Output $Input";
$Input =~ s/^-e.*$/-e/;
if (@$error_r && $? != 0) {
_die("$0: $Input did not compile:\n@$error_r\n");
} else {
warn "$0: Unexpected compiler output:\n@error" if @error;
}
exit 0;
}
sub compile_cstyle {
my $stash = grab_stash();
# What are we going to call our output C file?
my $lose = 0;
my ($cfh);
my $testsuite = '';
if( $addoptions ) {
}
# don't look at that: it hurts
qq[-e"print q{$bo}",] .
q{-e"open(Test::Builder::TESTOUT\054 '>&STDOUT') or die $!",} .
q{-e"open(Test::Builder::TESTERR\054 '>&STDERR') or die $!",};
}
# We need to keep it.
if (opt(e)) {
$cfile = "a.out.c";
} else {
# File off extension if present
# hold on: plx is executable; also, careful of ordering!
$cfile .= ".c";
}
check_write($cfile);
} else {
# Don't need to keep it, be safe with a tempfile.
$lose = 1;
close $cfh; # See comment just below
}
my $max_line_len = '';
$max_line_len = '-l2000,';
}
# This has to do the write itself, so we can't keep a lock. Life
# sucks.
my $command = "$BinPerl $taint -MO=$Backend,$addoptions$testsuite$max_line_len$stash,-o$cfile $Input";
if (@error && $? != 0) {
_die("$0: $Input did not compile, which can't happen:\n@error\n");
}
is_msvc ?
if ($lose) {
}
}
sub cc_harness_msvc {
my $obj = "${Output}.obj";
my $link = "-out:$Output $obj";
$link .= " perl5$Config{PERL_VERSION}.lib kernel32.lib msvcrt.lib";
system("$Config{cc} $compile");
system("$Config{ld} $link");
}
sub cc_harness {
$command .= " -lperl";
system("$Config{cc} $command");
}
# Where Perl is, and which include path to give it.
sub yclept {
my $command = "$^X ";
# DWIM the -I to be Perl, not C, include directories.
for (split /\s+/, opt(I)) {
if (-d $_) {
push @INC, $_;
} else {
warn "$0: Include directory $_ not found, skipping\n";
}
}
}
return $command;
}
# Use B::Stash to find additional modules and stuff.
{
my $_stash;
sub grab_stash {
warn "already called get_stash once" if $_stash;
my $command = "$BinPerl $taint -MB::Stash -c $Input";
# Filename here is perfectly sanitised.
if (@error && $? != 0) {
_die("$0: $Input did not compile:\n@error\n");
}
# band-aid for modules with noisy BEGIN {}
foreach my $i ( @stash ) {
push @begin_output, $i;
}
chomp $stash[0];
$stash[0] =~ s/^.*?-u/-u/s;
chomp $stash[0];
}
}
# Check the consistency of options if -B is selected.
# To wit, (-B|-O) ==> no -shared, no -S, no -c
sub checkopts_byte {
warn "$0: Will not create a shared library for bytecode\n";
}
for my $o ( qw[c S] ) {
if (opt($o)) {
warn "$0: Compiling to bytecode is a one-pass process--",
"-$o ignored\n";
delete $Options->{$o};
}
}
}
sub sanity_check {
if ($Input eq 'a.out') {
_die("$0: Compiling a.out is probably not what you want to do.\n");
# You fully deserve what you get now. No you *don't*. typos happen.
} else {
warn "$0: Will not write output on top of input file, ",
"compiling to a.out instead\n";
$Output = "a.out";
}
}
}
sub check_read {
my $file = shift;
unless (-r $file) {
_die("$0: Input file $file is a directory, not a file\n") if -d _;
unless (-e _) {
_die("$0: Input file $file was not found\n");
} else {
_die("$0: Cannot read input file $file: $!\n");
}
}
unless (-f _) {
warn "$0: WARNING: input $file is not a plain file\n";
}
}
sub check_write {
my $file = shift;
if (-d $file) {
_die("$0: Cannot write on $file, is a directory\n");
}
if (-e _) {
_die("$0: Cannot write on $file: $!\n") unless -w _;
}
unless (-w cwd()) {
_die("$0: Cannot write in this directory: $!\n");
}
}
sub check_perl {
my $file = shift;
unless (-T $file) {
warn "$0: Binary `$file' sure doesn't smell like perl source!\n";
print "Checking file type... ";
system("file", $file);
_die("Please try a perlier file!\n");
}
local $_ = <$handle>;
if (/^#!/ && !/perl/) {
}
}
# File spawning and error collecting
sub spawnit {
my ($command) = shift;
my $errname;
{
open (S_OUT, "$command 2>$errname |")
or _die("$0: Couldn't spawn the compiler.\n");
}
close S_ERROR;
close S_OUT;
}
sub helpme {
print "perlcc compiler frontend, version $VERSION\n\n";
{ no warnings;
exec "pod2usage $0";
exec "perldoc $0";
exec "pod2text $0";
}
}
sub relativize {
my ($args) = @_;
return() if ($args =~ m"^[/\\]");
return("./$args");
}
sub _die {
print STDERR @_;
exit(); # should die eventually. However, needed so that a 'make compile'
# can compile all the way through to the end for standard dist.
}
sub _usage_and_die {
$0: Usage:
}
sub run {
my (@commands) = @_;
}
sub interruptrun
{
my (@commands) = @_;
local(*FD);
my $text;
my $needalarm =
($ENV{PERLCC_TIMEOUT} &&
$command =~ m"(^|\s)perlcc\s");
eval
{
alarm(0) if ($needalarm);
};
if ($@)
{
eval { kill 'HUP', $pid };
}
close(FD);
return($text);
}
END {
}
=head1 NAME
perlcc - generate executables from Perl programs
=head1 SYNOPSIS
$ perlcc hello # Compiles into executable 'a.out'
$ perlcc -o hello hello.pl # Compiles into executable 'hello'
$ perlcc -O file # Compiles using the optimised C backend
$ perlcc -B file # Compiles using the bytecode backend
$ perlcc -c file # Creates a C file, 'file.c'
$ perlcc -S -o hello file # Creates a C file, 'file.c',
# then compiles it to executable 'hello'
$ perlcc -c out.c file # Creates a C file, 'out.c' from 'file'
$ perlcc -e 'print q//' # Compiles a one-liner into 'a.out'
$ perlcc -c -e 'print q//' # Creates a C file 'a.out.c'
$ perlcc -I /foo hello # extra headers (notice the space after -I)
$ perlcc -L /foo hello # extra libraries (notice the space after -L)
$ perlcc -r hello # compiles 'hello' into 'a.out', runs 'a.out'.
$ perlcc -r hello a b c # compiles 'hello' into 'a.out', runs 'a.out'.
# with arguments 'a b c'
$ perlcc hello -log c # compiles 'hello' into 'a.out' logs compile
# log into 'c'.
=head1 DESCRIPTION
F<perlcc> creates standalone executables from Perl programs, using the
code generators provided by the L<B> module. At present, you may
either create executable Perl bytecode, using the C<-B> option, or
generate and compile C files using the standard and 'optimised' C
backends.
The code generated in this way is not guaranteed to work. The whole
codegen suite (C<perlcc> included) should be considered B<very>
experimental. Use for production purposes is strongly discouraged.
=head1 OPTIONS
=over 4
=item -LI<library directories>
Adds the given directories to the library search path when C code is
passed to your C compiler.
=item -II<include directories>
Adds the given directories to the include file search path when C code is
passed to your C compiler; when using the Perl bytecode option, adds the
given directories to Perl's include path.
=item -o I<output file name>
Specifies the file name for the final compiled executable.
=item -c I<C file name>
Create C code only; do not compile to a standalone binary.
=item -e I<perl code>
Compile a one-liner, much the same as C<perl -e '...'>
=item -S
Do not delete generated C code after compilation.
=item -B
Use the Perl bytecode code generator.
=item -O
Use the 'optimised' C code generator. This is more experimental than
everything else put together, and the code created is not guaranteed to
compile in finite time and memory, or indeed, at all.
=item -v
Increase verbosity of output; can be repeated for more verbose output.
=item -r
Run the resulting compiled script after compiling it.
=item -log
Log the output of compiling to a file rather than to stdout.
=back
=cut
close OUT or die "Can't close $file: $!";
chdir $origdir;