| 1 | #!/usr/bin/env perl |
|---|
| 2 | |
|---|
| 3 | use 5.006; |
|---|
| 4 | use strict; |
|---|
| 5 | use warnings; |
|---|
| 6 | use FindBin; |
|---|
| 7 | BEGIN { chdir $FindBin::RealBin }; |
|---|
| 8 | use inc::Module::Install; |
|---|
| 9 | use lib 'inc'; |
|---|
| 10 | use Config; |
|---|
| 11 | use File::Spec; |
|---|
| 12 | use POSIX qw/uname/; |
|---|
| 13 | |
|---|
| 14 | # Hack to prevent recursive calls |
|---|
| 15 | exit if @ARGV and $ARGV[0] =~ /^--with/; |
|---|
| 16 | |
|---|
| 17 | my ($ghc, $ghc_version, $ghc_flags, $ghc_pkg) = assert_ghc(); |
|---|
| 18 | |
|---|
| 19 | my $setup_exe = File::Spec->catfile('.', "Setup$Config{_exe}"); |
|---|
| 20 | |
|---|
| 21 | rebuild_setup(); |
|---|
| 22 | my $app_dir = `$setup_exe -d`; |
|---|
| 23 | chomp $app_dir; |
|---|
| 24 | |
|---|
| 25 | die "Cannot find application directory '$app_dir'; check to see if Setup.lhs compiles?\n" |
|---|
| 26 | unless $app_dir; |
|---|
| 27 | |
|---|
| 28 | my $bin_dir = File::Spec->catdir($app_dir, 'bin'); |
|---|
| 29 | my $cabal = File::Spec->catfile($bin_dir, "cabal$Config{_exe}"); |
|---|
| 30 | my $cabal_config = File::Spec->catfile($app_dir, 'config'); |
|---|
| 31 | |
|---|
| 32 | $ENV{PATH} = $bin_dir . $Config{path_sep} . $ENV{PATH}; |
|---|
| 33 | |
|---|
| 34 | # First let's see if Cabal is there. |
|---|
| 35 | print "*** Checking for Haskell dependencies...\n"; |
|---|
| 36 | print "[Automatic Installation]\n"; |
|---|
| 37 | |
|---|
| 38 | my $rebuilt = 0; |
|---|
| 39 | $rebuilt += bootstrap_with(Cabal => qr/1\.4\./, '1.4.0'); |
|---|
| 40 | $rebuilt += bootstrap_with(parsec => qr/2\./, '2.0'); |
|---|
| 41 | $rebuilt += bootstrap_with(network => qr/[12]\./, '1.0'); |
|---|
| 42 | $rebuilt += bootstrap_with(HTTP => qr/300[01]\./, '3000.0'); |
|---|
| 43 | $rebuilt += bootstrap_with(zlib => qr/0\.(?:[4-9]|[1-9]\d)\./, '0.4'); |
|---|
| 44 | $rebuilt += bootstrap_with('cabal-install' => qr/0\.(?:[5-9]|[1-9]\d)\..*9999/, '0.5.2.0.9999'); |
|---|
| 45 | |
|---|
| 46 | if ($rebuilt) { |
|---|
| 47 | rebuild_setup(); |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | print "[Pugs Dependencies]\n"; |
|---|
| 51 | |
|---|
| 52 | my @deps = qw( |
|---|
| 53 | stm mtl time utf8-string binary haskeline FindBin MetaObject HsParrot |
|---|
| 54 | pugs-compat pugs-DrIFT stringtable-atom HsSyck control-timeout |
|---|
| 55 | ); |
|---|
| 56 | |
|---|
| 57 | # This line is here simply to trick Cabal into creating a default config file. |
|---|
| 58 | delete $ENV{CABAL_CONFIG_FILE}; |
|---|
| 59 | my $rv = `$cabal list -v0 --installed --simple-output`; |
|---|
| 60 | |
|---|
| 61 | my $cabal_local_config = "$FindBin::RealBin/third-party/packages/config"; |
|---|
| 62 | |
|---|
| 63 | # Ok, now we copy the config file to our tree. |
|---|
| 64 | open IN, '<', $cabal_config or die "Impossible: $cabal_config not found?"; |
|---|
| 65 | open OUT, '>', $cabal_local_config; |
|---|
| 66 | print OUT << "."; |
|---|
| 67 | local-repos: "$FindBin::RealBin/third-party/packages/hackage.haskell.org" |
|---|
| 68 | . |
|---|
| 69 | while (<IN>) { |
|---|
| 70 | next if /^(?:local-)?repos:/; |
|---|
| 71 | print OUT $_; |
|---|
| 72 | } |
|---|
| 73 | close IN; |
|---|
| 74 | close OUT; |
|---|
| 75 | |
|---|
| 76 | $ENV{CABAL_CONFIG_FILE} = $cabal_local_config; |
|---|
| 77 | system($cabal => 'install', '--user', @deps); |
|---|
| 78 | |
|---|
| 79 | do "Configure.PL"; |
|---|
| 80 | print "==> Pugs configuration finished.\n"; |
|---|
| 81 | |
|---|
| 82 | name ('Perl6-Pugs'); |
|---|
| 83 | version_from ('lib/Perl6/Pugs.pm'); |
|---|
| 84 | abstract_from ('lib/Perl6/Pugs.pm'); |
|---|
| 85 | author ('Audrey Tang <cpan@audreyt.org>'); |
|---|
| 86 | license ('perl'); |
|---|
| 87 | install_script ("pugs$Config{_exe}"); |
|---|
| 88 | install_script ('script/pugscc'); |
|---|
| 89 | install_script ('util/prove6'); |
|---|
| 90 | build_subdirs (map fixpaths($_), grep { |
|---|
| 91 | -f "$_/Makefile.PL" && not -l "$_/Makefile.PL" |
|---|
| 92 | } glob("ext/*"), glob("docs/*") |
|---|
| 93 | ); |
|---|
| 94 | my $version = version(); |
|---|
| 95 | $version .= 0 until length($version) >= length('0.123456'); |
|---|
| 96 | $version =~ s{6\.(\d{3})(\d{3})?}{join '.', 6, int($1), int($2||0)}e; |
|---|
| 97 | version($version); |
|---|
| 98 | makemaker_args ( |
|---|
| 99 | test => { TESTS => "`perl t/spec/fudgeall pugs t/*/*.t t/*/*/*.t`" }, # , "perl5/*/t/*.t" }, |
|---|
| 100 | MAN1PODS => {}, |
|---|
| 101 | ); |
|---|
| 102 | set_postamble (); |
|---|
| 103 | no_index ( |
|---|
| 104 | directory => |
|---|
| 105 | qw< inc debian modules perl5 ext script util docs examples src > |
|---|
| 106 | ); |
|---|
| 107 | sign (1); |
|---|
| 108 | WritePugs (5); |
|---|
| 109 | |
|---|
| 110 | sub set_postamble { |
|---|
| 111 | unlink (my $build_config = 'current.build.yml'); |
|---|
| 112 | |
|---|
| 113 | my $find_ver = sub { |
|---|
| 114 | `$_[0] $_ 2>&1` =~ /(.* (?:version|build) .*)/i && return $1 |
|---|
| 115 | for qw{--version -v -V -? /?}; |
|---|
| 116 | return "unknown"; |
|---|
| 117 | }; |
|---|
| 118 | my $config = get_pugs_config( |
|---|
| 119 | uname => join (" ", (uname)[0,2,4] ), |
|---|
| 120 | regex_engine => ( $ENV{PUGS_REGEX_ENGINE} ? $ENV{PUGS_REGEX_ENGINE} : 'default' ), |
|---|
| 121 | embed_flags => 'noparrot nohaskell', |
|---|
| 122 | # embedded => join (" ", ( $embed_flags =~ /HAVE_PERL5/ ? $Config{perlpath} : 'noperl' ), |
|---|
| 123 | # ( $embed_flags =~ /HAVE_PARROT/ |
|---|
| 124 | # ? abs_path( File::Spec->catfile( "$ENV{PARROT_PATH}", "parrot" ) ) |
|---|
| 125 | # : 'noparrot' ), |
|---|
| 126 | # ( $ENV{PUGS_EMBED} =~ /\bhaskell\b/ ? $ghc : 'nohaskell' ) |
|---|
| 127 | # ), |
|---|
| 128 | # ghc => join (" ", [ assert_ghc() ]->[0], $ghc_version, |
|---|
| 129 | # ( $ghc_flags =~ /HAVE_READLINE/ ? 'readline' : 'noreadline' ), |
|---|
| 130 | # ( $ghc_flags =~ /HAVE_HSPLUGINS/ ? 'hsplugins' : 'nohsplugins' ), |
|---|
| 131 | # ( $threaded ? "threads" : "nothreads" ), |
|---|
| 132 | # ), |
|---|
| 133 | ghc => 'noreadline nohsplugins nothreads', |
|---|
| 134 | cc => $find_ver->( $Config{cc} ), |
|---|
| 135 | ); |
|---|
| 136 | |
|---|
| 137 | { |
|---|
| 138 | # maybe move this to inc/PugsBuild/MiniYAML.pm ? |
|---|
| 139 | open my $fh, '>', $build_config or die "Cannot open $build_config for writing"; |
|---|
| 140 | print $fh "# *** NOTE ***\n"; |
|---|
| 141 | print $fh "# This file is generated during Makefile.PL.\n"; |
|---|
| 142 | print $fh "# Changes will not persist after running Makefile.PL\n"; |
|---|
| 143 | for ( sort keys %$config ) { |
|---|
| 144 | print $fh "$_: $config->{$_}\n"; |
|---|
| 145 | } |
|---|
| 146 | close $fh; |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | my @srcdirs = grep {-d} glob("src"), glob("src/*"), glob("src/*/*"), glob("src/*/*/*"); |
|---|
| 150 | my @srcfiles = map { glob("$_/*.*hs") } @srcdirs; |
|---|
| 151 | push @srcfiles, map { glob("$_/*.*hs-boot") } @srcdirs; |
|---|
| 152 | push @srcfiles, map { map { substr($_, 0, -1) } glob("$_/*.*hsc") } @srcdirs; |
|---|
| 153 | |
|---|
| 154 | my $version_h = "src/Pugs/pugs_version.h"; |
|---|
| 155 | my $config_h = "src/Pugs/pugs_config.h"; |
|---|
| 156 | |
|---|
| 157 | my $EMBED_SMOP = ($ENV{PUGS_EMBED} // '') ? '--flags=SMOP' : ''; |
|---|
| 158 | # Ok, now we have Cabal-Install and all the deps. Let's be lazy and write a simple makefile. |
|---|
| 159 | postamble(<<"."); |
|---|
| 160 | pugs_requirements : @srcfiles $version_h $config_h src/Pugs/Config.hs src/Pugs/Prelude.hs |
|---|
| 161 | |
|---|
| 162 | $config_h : lib/Perl6/Pugs.pm util/config_h.pl |
|---|
| 163 | \$(PERL) util/config_h.pl "$ghc $ghc_flags" |
|---|
| 164 | |
|---|
| 165 | $version_h : |
|---|
| 166 | \$(PERL) util/version_h.pl $version_h |
|---|
| 167 | |
|---|
| 168 | pugs$Config{_exe} :: pugs_requirements build_perl5 |
|---|
| 169 | ./Configure.PL |
|---|
| 170 | \$(RM_F) dist/build/pugs/pugs$Config{_exe} |
|---|
| 171 | \$(RM_F) Pugs.cabal |
|---|
| 172 | \$(CP) Pugs.cabal.in Pugs.cabal |
|---|
| 173 | ./Setup$Config{_exe} configure --user $EMBED_SMOP |
|---|
| 174 | ./Setup$Config{_exe} build |
|---|
| 175 | \$(CP) dist/build/pugs/pugs$Config{_exe} . |
|---|
| 176 | |
|---|
| 177 | prof :: pugs-prof$Config{_exe} |
|---|
| 178 | |
|---|
| 179 | pugs-prof$Config{_exe} :: pugs_requirements build_perl5 |
|---|
| 180 | $cabal install --user -p @deps |
|---|
| 181 | PUGS_NO_THREADS=true ./Configure.PL |
|---|
| 182 | \$(RM_F) dist/build/pugs/pugs$Config{_exe} |
|---|
| 183 | \$(RM_F) Pugs.cabal |
|---|
| 184 | \$(CP) Pugs.cabal.in Pugs.cabal |
|---|
| 185 | ./Setup$Config{_exe} configure --user -p --enable-executable-profiling |
|---|
| 186 | ./Setup$Config{_exe} build |
|---|
| 187 | \$(CP) dist/build/pugs/pugs$Config{_exe} ./pugs-prof$Config{_exe} |
|---|
| 188 | |
|---|
| 189 | install :: |
|---|
| 190 | \t./Setup$Config{_exe} install --user |
|---|
| 191 | |
|---|
| 192 | INST6_ARCHLIB = blib6/arch |
|---|
| 193 | INST6_SCRIPT = blib6/script |
|---|
| 194 | INST6_BIN = blib6/bin |
|---|
| 195 | INST6_LIB = blib6/lib |
|---|
| 196 | INST6_MAN1DIR = blib6/man1 |
|---|
| 197 | INST6_MAN3DIR = blib6/man3 |
|---|
| 198 | INSTPUGS_LIB = blib6/pugs |
|---|
| 199 | |
|---|
| 200 | clean :: |
|---|
| 201 | \t./Setup$Config{_exe} clean |
|---|
| 202 | |
|---|
| 203 | src/Pugs/Config.hs : util/PugsConfig.pm current.build.yml |
|---|
| 204 | \t\$(PERL) -Iutil -MPugsConfig -e "PugsConfig->write_config_module" > src/Pugs/Config.hs |
|---|
| 205 | |
|---|
| 206 | smoke : pugs$Config{_exe} util/run-smoke.pl |
|---|
| 207 | \t\$(PERL) util/run-smoke.pl . smoke.html |
|---|
| 208 | |
|---|
| 209 | upload-smoke : smoke.yml |
|---|
| 210 | \t\$(PERL) util/smokeserv/smokeserv-client.pl smoke.html smoke.yml |
|---|
| 211 | |
|---|
| 212 | smoke-upload : upload-smoke |
|---|
| 213 | |
|---|
| 214 | src/Pugs/Prelude.hs : src/perl6/Prelude.pm util/gen_prelude.pl |
|---|
| 215 | \t\$(PERL) util/gen_prelude.pl -v --touch --inline -i src/perl6/Prelude.pm --output src/Pugs/Prelude.hs |
|---|
| 216 | |
|---|
| 217 | build_perl5 :: |
|---|
| 218 | @{[for_perl5(" |
|---|
| 219 | cd __DIR__ && $^X Makefile.PL && \$(MAKE) |
|---|
| 220 | ")]} |
|---|
| 221 | |
|---|
| 222 | clean :: |
|---|
| 223 | @{[for_perl5(" |
|---|
| 224 | -cd __DIR__ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) clean |
|---|
| 225 | ")]} |
|---|
| 226 | |
|---|
| 227 | realclean :: |
|---|
| 228 | @{[for_perl5(" |
|---|
| 229 | -cd __DIR__ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) realclean |
|---|
| 230 | ")]} |
|---|
| 231 | |
|---|
| 232 | . |
|---|
| 233 | |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | sub bootstrap_with { |
|---|
| 237 | my ($package, $pattern, $version) = @_; |
|---|
| 238 | my @has_version; |
|---|
| 239 | if ($package eq 'cabal-install') { |
|---|
| 240 | @has_version = sort map { /^cabal-install version ($pattern.*)/ ? $1 : () } `$cabal --version`; |
|---|
| 241 | } |
|---|
| 242 | else { |
|---|
| 243 | @has_version = sort map { /^version: ($pattern.*)/ ? $1 : () } `$ghc_pkg describe $package`; |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | printf "- %-20s ", $package; |
|---|
| 247 | if (@has_version) { |
|---|
| 248 | print "...loaded. ($has_version[0] >= $version)\n"; |
|---|
| 249 | return 0; |
|---|
| 250 | } |
|---|
| 251 | |
|---|
| 252 | print "...missing. (would need $version)\n"; |
|---|
| 253 | print "==> Installing $package. This may take a minute or two...\n"; |
|---|
| 254 | sleep 1; |
|---|
| 255 | |
|---|
| 256 | chdir "third-party/$package"; |
|---|
| 257 | |
|---|
| 258 | my ($setup_hs) = glob('Setup.*hs'); |
|---|
| 259 | die "Impossible: No Setup?" unless $setup_hs; |
|---|
| 260 | |
|---|
| 261 | use File::Path; |
|---|
| 262 | File::Path::rmtree(['dist']); |
|---|
| 263 | |
|---|
| 264 | system($ghc, qw(--make -O0), -o => $setup_exe, $setup_hs) |
|---|
| 265 | || system($setup_exe, qw(configure --user)) |
|---|
| 266 | || system($setup_exe, qw(build)) |
|---|
| 267 | || system($setup_exe, qw(install --user)) |
|---|
| 268 | || system($setup_exe, qw(clean)) |
|---|
| 269 | and die << "."; |
|---|
| 270 | Cannot install $package: $? |
|---|
| 271 | Please enter the third-party/Cabal directory and install it manually |
|---|
| 272 | following the instructions of README there. |
|---|
| 273 | . |
|---|
| 274 | |
|---|
| 275 | chdir $FindBin::RealBin; |
|---|
| 276 | return 1; |
|---|
| 277 | } |
|---|
| 278 | |
|---|
| 279 | sub for_perl5 { |
|---|
| 280 | my $cmd = shift; |
|---|
| 281 | $cmd =~ s{\n}{}g; |
|---|
| 282 | my @cmds; |
|---|
| 283 | foreach my $dir (grep { -d } glob('perl5/*')) { |
|---|
| 284 | -e "$dir/Makefile.PL" or next; |
|---|
| 285 | |
|---|
| 286 | # Skip XS modules for now |
|---|
| 287 | next if glob("$dir/*.xs") or glob("$dir/*.i") or $dir =~ /-\d+/; |
|---|
| 288 | |
|---|
| 289 | next unless $dir =~ /Pugs-Compiler-Rule/; |
|---|
| 290 | |
|---|
| 291 | my $this = $cmd; |
|---|
| 292 | $this =~ s{__DIR__}{$dir}g; |
|---|
| 293 | push @cmds, $this; |
|---|
| 294 | } |
|---|
| 295 | return join("\n", @cmds); |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | sub rebuild_setup { |
|---|
| 299 | unlink $_ for qw(Setup.hi Setup.o); |
|---|
| 300 | unlink $setup_exe; |
|---|
| 301 | system($ghc, qw(--make -O0), -o => $setup_exe, 'Setup.lhs'); |
|---|
| 302 | } |
|---|