| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use 5.006; |
|---|
| 4 | use strict; |
|---|
| 5 | use FindBin; |
|---|
| 6 | BEGIN { chdir $FindBin::RealBin }; |
|---|
| 7 | use inc::Module::Install; |
|---|
| 8 | use lib 'inc'; |
|---|
| 9 | use Cwd; |
|---|
| 10 | use Config; |
|---|
| 11 | use ExtUtils::Embed; |
|---|
| 12 | use Carp; |
|---|
| 13 | |
|---|
| 14 | my ($ghc, $ghc_version, $ghc_flags, $ghc_pkg) = assert_ghc(); |
|---|
| 15 | my $threaded = (try_compile_and_run("main :: IO ()\nmain = return ()", $ghc, "-threaded")) ? '-threaded' : ''; |
|---|
| 16 | if ($threaded && $ENV{PUGS_NO_THREADS}) { |
|---|
| 17 | warn << '.'; |
|---|
| 18 | *** Thread support disabled due to explicit request in PUGS_NO_THREADS. |
|---|
| 19 | |
|---|
| 20 | . |
|---|
| 21 | $threaded = ''; |
|---|
| 22 | } |
|---|
| 23 | |
|---|
| 24 | my $embed_flags = "-I" . cwd(); |
|---|
| 25 | my $ccdlflags = ""; |
|---|
| 26 | my $flags = "$Config{ccflags} $Config{ccdlflags} "; |
|---|
| 27 | |
|---|
| 28 | if ($flags =~ /\S/) { |
|---|
| 29 | $flags =~ s{([\\"'])}{\\$1}g; |
|---|
| 30 | my @flags = grep { length $_ } split /\s+/, $flags; |
|---|
| 31 | |
|---|
| 32 | if ($^O eq 'MSWin32') { |
|---|
| 33 | if ($Config{libperl} =~ /lib(\w+)\.a/) { |
|---|
| 34 | $embed_flags .= " -optl-l$1 "; |
|---|
| 35 | } |
|---|
| 36 | elsif (defined &Win32::BuildNumber) { |
|---|
| 37 | # We are on ActivePerl -- Kluge massively! |
|---|
| 38 | |
|---|
| 39 | no warnings 'once'; |
|---|
| 40 | our %MY_CONFIG = %Config; |
|---|
| 41 | *Config = *MY_CONFIG; |
|---|
| 42 | *Config::Config = *MY_CONFIG; |
|---|
| 43 | *ExtUtils::MM_Win32::Config = *MY_CONFIG; |
|---|
| 44 | *ExtUtils::MM_Unix::Config = *MY_CONFIG; |
|---|
| 45 | |
|---|
| 46 | $Config{ccflags} =~ s/-libpath:"?(.*?)"? //g; |
|---|
| 47 | $Config{ccdlflags} =~ s/-libpath:"?(.*?)"? //g; |
|---|
| 48 | $Config{lddlflags} =~ s/-libpath:"?(.*?)"? //g; |
|---|
| 49 | $Config{ldflags} =~ s/-libpath:"?(.*?)"? //g |
|---|
| 50 | or die "ldflags: $Config{ldflags} does not contain -libpath:"; |
|---|
| 51 | |
|---|
| 52 | my $lib = "$1/$Config{libperl}"; |
|---|
| 53 | $embed_flags .= " -optl\"$lib\" "; |
|---|
| 54 | |
|---|
| 55 | $flags = "$Config{ccflags} $Config{ccdlflags}"; |
|---|
| 56 | $flags =~ s{([\\"'])}{\\$1}g; |
|---|
| 57 | @flags = grep { length $_ } split /\s+/, $flags; |
|---|
| 58 | } |
|---|
| 59 | else { |
|---|
| 60 | warn "Unrecognized libperl shared library: $Config{libperl}, proceeding anyway...\n"; |
|---|
| 61 | } |
|---|
| 62 | |
|---|
| 63 | $ccdlflags .= (/^-[DIL]/ ? ' -optc' : ' -optl') . qq["$_" ] for @flags; |
|---|
| 64 | $embed_flags .= " -optc-Ddirent=DIRENT"; |
|---|
| 65 | } |
|---|
| 66 | else { |
|---|
| 67 | $embed_flags .= " -optc$_" for grep length, split(/\s+/, ccopts()); |
|---|
| 68 | $embed_flags .= " -optl$_" for grep length, split(/\s+/, ldopts()); |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | $embed_flags .= " $_" for grep { /-[DIL]/ } split(/\s+/, ccopts()); |
|---|
| 72 | $embed_flags .= " $_" for grep { /-[DIL]/ } split(/\s+/, ldopts()); |
|---|
| 73 | |
|---|
| 74 | if ($Config{osname} eq 'cygwin') { |
|---|
| 75 | my $cygpath = sub { |
|---|
| 76 | my $path = `cygpath -m @_`; |
|---|
| 77 | chomp $path; |
|---|
| 78 | return $path; |
|---|
| 79 | }; |
|---|
| 80 | $embed_flags =~ s{(/usr/\S+)}{$cygpath->($1)}eg; |
|---|
| 81 | $embed_flags =~ s{/cygdrive/(\w)/}{$1:/}g; |
|---|
| 82 | #warn "** Cygwin embedding flags: embed_flags\n"; |
|---|
| 83 | } |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | my @include_dirs = split(/\s+/, perl_inc()); |
|---|
| 87 | s/^-I// for @include_dirs; |
|---|
| 88 | |
|---|
| 89 | my @cc_options = map { /^-optc(.+)/ ? $1 : () } (split(/\s+/, $embed_flags), split(/\s+/, $ccdlflags)); |
|---|
| 90 | my @ld_options = grep { not /,/ } map { /^-optl(.+)/ ? $1 : () } (split(/\s+/, $embed_flags), split(/\s+/, $ccdlflags)); |
|---|
| 91 | |
|---|
| 92 | open INFO, ">Pugs.buildinfo" or die "Cannot write build info: $!"; |
|---|
| 93 | my $info = << "."; |
|---|
| 94 | executable: pugs |
|---|
| 95 | ghc-options: $embed_flags $ccdlflags $threaded |
|---|
| 96 | include-dirs: @include_dirs |
|---|
| 97 | cc-options: @cc_options |
|---|
| 98 | ld-options: @ld_options |
|---|
| 99 | . |
|---|
| 100 | $info =~ s/-arch\s+\w+\s*//g; |
|---|
| 101 | $info =~ s/-opt[lc]-arch\s+-opt[lc]\w+\s*//g; |
|---|
| 102 | print INFO $info; |
|---|
| 103 | close INFO; |
|---|
| 104 | |
|---|
| 105 | our $do_run; |
|---|
| 106 | sub try_compile_and_run { |
|---|
| 107 | local $do_run = 1; |
|---|
| 108 | try_compile(@_); |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | sub try_compile { |
|---|
| 112 | my $code = shift; |
|---|
| 113 | my $temp = "pugs-tmp-$$"; |
|---|
| 114 | my $ghc = shift or croak "try_compile called without path to ghc"; |
|---|
| 115 | |
|---|
| 116 | eval { |
|---|
| 117 | open TMP, "> $temp.hs"; |
|---|
| 118 | print TMP $code; |
|---|
| 119 | close TMP; |
|---|
| 120 | system( |
|---|
| 121 | $ghc, @_, |
|---|
| 122 | "--make", "-v0", |
|---|
| 123 | -o => "$temp.exe", |
|---|
| 124 | "$temp.hs" |
|---|
| 125 | ); |
|---|
| 126 | |
|---|
| 127 | }; |
|---|
| 128 | |
|---|
| 129 | my $ok = -s "$temp.exe"; |
|---|
| 130 | |
|---|
| 131 | if ($do_run) { |
|---|
| 132 | $ok = 0 unless system(Cwd::abs_path("$temp.exe")) == 0; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | unlink("$temp.exe"); |
|---|
| 136 | unlink("$temp.hs"); |
|---|
| 137 | unlink("$temp.hi"); |
|---|
| 138 | unlink("$temp.o"); |
|---|
| 139 | |
|---|
| 140 | return $ok; |
|---|
| 141 | } |
|---|