#!/usr/bin/env perl =pod =head1 NAME Makefile.PL - Configure pugs build =head1 SYNOPSIS perl Makefile.PL [options] Options: --precompile-prelude Force prelude to be precompiled --no-precompile-prelude Force prelude not to be precompiled --help Print documentation (build system overview) =head1 DESCRIPTION Build System Overview - Makefile.PL calls get_pugs_config() in inc/Module/Install/Pugs.pm which then calls util/PugsConfig.pm to get configuration data printed with ./pugs -V - Makefile.PL calls GHC to compile Setup.hs to ./Setup.exe. - Makefile.PL writes a Makefile that will call util/build_pugs.pl upon "make". - build_pugs.pl writes a Pugs.cabal file based on the flags given in the Makefile. - build_pugs.pl calls ./Setup.exe. - Setup.exe builds dist/build/libHSPugs-6.XXX.YYY.a and returns to build_pugs.pl. - build_pugs.pl calls GHC to build ./pugs.exe (by simply linking the freshly built libHSPugs package with src/Main.hs). =cut use 5.006; use strict; use warnings; use Config; use Cwd qw(abs_path cwd); use File::Spec; use File::Copy; use File::Basename; use FindBin; use ExtUtils::Embed; BEGIN { chdir $FindBin::RealBin }; use inc::Module::Install; use lib 'inc'; use PugsBuild::Config; use Carp; use Getopt::Long; use Pod::Usage; use POSIX qw/uname/; our %options; GetOptions \%options, qw( precompile-prelude! help ) or pod2usage(2); pod2usage(-verbose => 2) if $options{'help'}; if ( $options{'precompile-prelude'} ) { $PugsBuild::Config::Conf->{precompile_prelude} = $options{'precompile-prelude'} } # Win32/CygWin GHC appears to be more memory hungry than its # *nix counterpart, causing it to bail part-way through builds. # This value will be used only if 'ghc_heap_size' in config.yml # is not defined. use constant WIN32_GHC_HEAPSIZE => "348m"; # Special case for migration - remove old version of Syck unlink 'src/Data/Yaml/Syck.hs' if -e 'src/Data/Yaml/Syck.hs'; my @warn; my $pugs = "pugs$Config{_exe}"; my ($fs) = ($Config{sitelib} =~ /([\/\\])/) or die "Can't determine file_sep"; my $thispugs = ".${fs}pugs$Config{_exe}"; my $version_h = "src/Pugs/pugs_version.h"; my $config_h = "src/Pugs/pugs_config.h"; my @srcdirs = grep {-d} glob("src"), glob("src/*"), glob("src/*/*"), glob("src/*/*/*"); # On Win32, svn may create '_svn' dirs rather than '.svn'. Hide them manually. # Details: http://svn.collab.net/repos/svn/trunk/notes/asp-dot-net-hack.txt @srcdirs = grep {! m|\b_svn\b|} @srcdirs if $ENV{SVN_ASP_DOT_NET_HACK}; my @hsfiles = map {glob "$_/[A-Z]*.hs"} @srcdirs; push @hsfiles, qw; my @hppfiles = map {my $x=$_; $x=~s/\.hs$/.hpp/; $x} @hsfiles; warn_cygwin (); for my $var (qw( PERL5LIB PERLLIB )) { if (grep { m{^(?:\.?[\\/]+)*lib$} } split(/\Q$Config{path_sep}\E/, ($ENV{$var} || next))) { die <<"EOD"; *** The "$var" environment variable contains a naked 'lib', which will disrupt the Pugs build process. Please remove it and run Makefile.PL again. EOD } last; # PERLLIB is ignored when PERL5LIB is in place } print "*** Probing configuration (please ignore any warnings)...\n\n"; name ('Perl6-Pugs'); version_from ('lib/Perl6/Pugs.pm'); abstract_from ('lib/Perl6/Pugs.pm'); author ('Audrey Tang '); license ('perl'); install_script ($pugs); install_script ('script/pugscc'); install_script ('util/prove6'); recommends ('Perl6::Bible'); recommends ('Inline'); recommends ('Filter::Simple'); recommends ('LWP::Simple'); recommends ('LWP'); build_requires ('ExtUtils::MakeMaker' => 6.15); build_requires ('FindBin'); build_requires ('File::Path'); include ('Module::Install::Makefile::Name'); include ('Module::Install::Makefile::Version'); build_subdirs (map fixpaths($_), grep { -f "$_/Makefile.PL" && not -l "$_/Makefile.PL" } glob("ext/*"), glob("docs/*") ); my $version = version(); $version .= 0 until length($version) >= length('0.123456'); $version =~ s{6\.(\d{3})(\d{3})?}{join '.', 6, int($1), int($2||0)}e; version($version); makemaker_args ( test => { TESTS => "`perl t/spec/fudgeall pugs t/*/*.t t/*/*/*.t`" }, # , "perl5/*/t/*.t" }, MAN1PODS => {}, ); if (my $prefix = PugsBuild::Config->lookup('install_dir')) { makemaker_args(PREFIX => $prefix); } clean_files (map fixpaths($_), $version_h, $config_h, (map {"$_/*.hpp"} @srcdirs), "pugs$Config{_exe}", "pil$Config{_exe}", "src/gen_prelude$Config{_exe}", "Setup$Config{_exe}", "util/ghc-pkg-wrapper$Config{_exe}", "util/runcompiler$Config{_exe}", qw( src/Pugs/pugs_config.h src/Pugs/Config.hs blib6 dist src/Pugs/Prelude.hs src/Pugs/CodeGen/PIR/Prelude.hs test.log src/Pugs/Embed/Parrot.hs src/Pugs/Embed/Parrot_hsc.* src/Pugs/*/*_stub.* util/ghc-pkg-wrapper.hs util/ghc-pkg-wrapper.hi util/ghc-pkg-wrapper.o util/runcompiler.hs util/runcompiler.hi util/runcompiler.o temp-ex* unlink-test* Prelude Pugs.cabal Setup.hi Setup.o .setup-config .installed-pkg-config temp-test.*.*-out tempfile.*.* create_this_file create_this_file2 third-party/*/*.hi third-party/*/*.o third-party/*/dist ), object_files("src/Pugs", "src/Pugs/*", "src/Pugs/*/*"), object_files("src/MO", "src/MO/*", "src/MO/*/*"), ); set_postamble (); no_index ( directory => qw< inc debian modules perl5 ext script util docs examples src > ); sign (1); WritePugs (5); print(('=' x 78), "\n\n"); print @warn; print << "."; *** Enter '$Config{make}' to build Pugs. If compilation is too slow, consider using '$Config{make} soon' instead. . ################################################################################ sub object_files { map { ("$_/*.o", "$_/*.hi") } @_; } sub try_package { my ($ghc, $ghcpkg, $code) = @_; my @packages = qw(-hide-all-packages -package base); push(@packages, "-package $ghcpkg"); if (not try_compile ($code , $ghc, @packages), ) { # We are missing mtl,network,time,whatever somehow, # likely because GHC 6.6's extra pkg is not there die <<"EOD"; *** Could not load the "$ghcpkg" package in your GHC installation. This is likely because the "extralibs" of GHC 6.6 was not built along with the base GHC distribution. To install extra libraries, extract both "-src" and "-src-extralibs" distributions from http://haskell.org/ghc/download_ghc_66.html in the same directory, then cd into ghc-6.6/ and build GHC from there. In Ubuntu Feisty/debian type "sudo aptitude install libghc6-$ghcpkg-dev" EOD } } sub set_postamble { my @srcfiles = map { glob("$_/*.*hs") } @srcdirs; push @srcfiles, map { glob("$_/*.*hs-boot") } @srcdirs; push @srcfiles, map { map { substr($_, 0, -1) } glob("$_/*.*hsc") } @srcdirs; my ($ghc, $ghc_version, $ghc_flags, $ghc_pkg) = assert_ghc(); my $hsc2hs = $ENV{HSC2HS}; my $setup = File::Spec->catfile(".", "Setup$Config{_exe}"); my $ghc_wrapper = File::Spec->catfile(".", "util", "runcompiler$Config{_exe}"); my $ghc_pkg_wrapper = File::Spec->catfile(".", "util", "ghc-pkg-wrapper$Config{_exe}"); my $config_path = File::Spec->catfile(cwd(), 'third-party', 'installed', 'packages.conf'); if (!$hsc2hs) { $hsc2hs = $ghc; $hsc2hs =~ s{(.*)ghc}{$1hsc2hs}; } preprocess( File::Spec->catfile('util', 'runcompiler.hs.in'), File::Spec->catfile('util', 'runcompiler.hs'), CONFIG_PATH => $config_path, GHC => $ghc, GHC_PKG => $ghc_pkg, ); preprocess( File::Spec->catfile('util', 'ghc-pkg-wrapper.hs.in'), File::Spec->catfile('util', 'ghc-pkg-wrapper.hs'), CONFIG_PATH => $config_path, GHC => $ghc, GHC_PKG => $ghc_pkg, ); # set up install path for third-party modules mkdir File::Spec->catdir('third-party', 'installed'); compile_hs($ghc, 'Setup', $setup); compile_hs($ghc, File::Spec->catfile('util', 'ghc-pkg-wrapper'), $ghc_pkg_wrapper); compile_hs($ghc, File::Spec->catfile('util', 'runcompiler'), $ghc_wrapper); # Add GHC to PATH local $ENV{PATH} = dirname($ghc) . $Config{path_sep} . $ENV{PATH}; try_package($ghc, 'mtl', "import Control.Monad.RWS\n" . "main = let (x, (), ()) = runRWS (return ()) () () in return x\n" ); try_package($ghc, 'network', "import Network.BSD\n" . "main = let x = defaultProtocol in return x\n" ); try_package($ghc, 'time', "import Data.Time\n" . "main = return 1\n" ); # # We probably need to promote this to a config.yml + autodetect # thing, but until it's done, put the condition here at least and # don't hardcode it into the postamble. # # Note that the -fdebugging flag only existed in GHC trunk builds # around May 2007, and would not be present either before or afterwards. # (In the newer builds it's enabled by default and supports a much more # comprehensive feature set, including single-stepping and tracing.) # my $ghci_debugging = (defined $ENV{PUGS_GHCI_DEBUGGING} ? $ENV{PUGS_GHCI_DEBUGGING} : 1) ? '-fdebugging' : ''; if ($ghc_version =~ /^(\d+\.\d+)/) { $ghci_debugging = '' if $1 <= 6.6 or $1 >= 6.8; } $ghc = $ghc_wrapper; $ghc_pkg = $ghc_pkg_wrapper; my $heap; $heap = PugsBuild::Config->lookup('ghc_heap_size') || $heap; $ghc_flags .= " +RTS -M$heap -RTS" if $heap; # $ghc_flags .= ' -dcore-lint'; # $ghc_flags .= " -keep-tmp-files"; if ($ENV{PUGS_EMBED} and $ENV{PUGS_EMBED} =~ /\bhaskell\b/i) { if (has_ghc_package('plugins') and try_compile("import System.Eval\n" ."main :: IO ()\n" .'main = (eval_ "return ()" [] [] [] [] :: IO (Either [String] (Maybe ()))) >> return ()', $ghc, '-package', 'plugins')) { $ghc_flags .= ' -package plugins -DPUGS_HAVE_HSPLUGINS '; } else { push @warn, << '.'; *** Inline Haskell support disabled. If you want dynamic loading of haskell modules, please install the hs-plugins library: http://www.cse.unsw.edu.au/~dons/hs-plugins/ Remember to "make register" after "make install" for hs-plugins! . } } if (has_ghc_package('readline') and try_compile("import System.Console.Readline\n" ."main :: IO ()\n" ."main = do\n" ." setCatchSignals False\n" ." setCatchSigwinch False\n" .' _ <- readline "" '."\n" .' return ()', $ghc)) { $ghc_flags .= ' -DPUGS_HAVE_READLINE '; # -package readline'; } else { push @warn, << '.'; *** Readline support disabled. If you want readline support, please install the GNU readline library. . } my $ghc_output = ''; # "-o pugs$Config{_exe} src/Main.hs"; my $hasktags = $ENV{HASKTAGS} || 'hasktags'; # map a bunch of .c files to a bunch of expected .o files my $o = sub { map { substr($_, 0, -1) . 'o' } @_ }; my @prereqs = (); my @derived_srcfiles = qw< src/Pugs/Embed/Parrot.hs src/Pugs/pugs_config.h src/Pugs/pugs_version.h src/Pugs/Config.hs src/Pugs/Prelude.hs src/Pugs/CodeGen/PIR/Prelude.hs >; my $embed_flags = "-I" . cwd(); my $hsc2hs_flags = ""; my $ccdlflags = ""; # [-!]perl5 does not work with the \bFLAG\b convention used in this file. # It should be removed, or the convention, and code, fixed. # Went in 2006-08-30. Depreciated 2006-09-11. if ($ENV{PUGS_EMBED} and $ENV{PUGS_EMBED} =~ /[-!]perl5\b/i) { push @warn, << '.'; *** PUGS_EMBED flags "-perl5" and "!perl5" are depreciated and buggy. Please use "noperl5" instead. . } if (!$ENV{PUGS_EMBED} or $ENV{PUGS_EMBED} !~ /(?:[-!]|\bno)perl5\b/i) { $ENV{PUGS_EMBED} .= " perl5 "; #push @prereqs, "src/perl5/p5embed.o"; # XXX # $ghc_output .= " src/perl5/p5embed.o "; $embed_flags .= " -DPUGS_HAVE_PERL5 -isrc/perl5 "; my $flags = "$Config{ccflags} $Config{ccdlflags} "; if ($flags =~ /\S/) { $flags =~ s{([\\"'])}{\\$1}g; my @flags = grep { length $_ } split /\s+/, $flags; if ($^O eq 'MSWin32') { if ($Config{libperl} =~ /lib(\w+)\.a/) { $embed_flags .= " -optl-l$1 "; } elsif (defined &Win32::BuildNumber) { # We are on ActivePerl -- Kluge massively! no warnings 'once'; our %MY_CONFIG = %Config; *Config = *MY_CONFIG; *Config::Config = *MY_CONFIG; *ExtUtils::MM_Win32::Config = *MY_CONFIG; *ExtUtils::MM_Unix::Config = *MY_CONFIG; $Config{ccflags} =~ s/-libpath:"?(.*?)"? //g; $Config{ccdlflags} =~ s/-libpath:"?(.*?)"? //g; $Config{lddlflags} =~ s/-libpath:"?(.*?)"? //g; $Config{ldflags} =~ s/-libpath:"?(.*?)"? //g or die "ldflags: $Config{ldflags} does not contain -libpath:"; my $lib = "$1/$Config{libperl}"; $embed_flags .= " -optl\"$lib\" "; $flags = "$Config{ccflags} $Config{ccdlflags}"; $flags =~ s{([\\"'])}{\\$1}g; @flags = grep { length $_ } split /\s+/, $flags; } else { warn "Unrecognized libperl shared library: $Config{libperl}, proceeding anyway...\n"; } $ccdlflags .= (/^-[DIL]/ ? ' -optc' : ' -optl') . qq["$_" ] for @flags; $embed_flags .= " -optc-Ddirent=DIRENT"; } else { $embed_flags .= " -optc$_" for grep length, split(/\s+/, ccopts()); $embed_flags .= " -optl$_" for grep length, split(/\s+/, ldopts()); } $embed_flags .= " $_" for grep { /-[DIL]/ } split(/\s+/, ccopts()); $embed_flags .= " $_" for grep { /-[DIL]/ } split(/\s+/, ldopts()); if ($Config{osname} eq 'cygwin') { my $cygpath = sub { my $path = `cygpath -m @_`; chomp $path; return $path; }; $embed_flags =~ s{(/usr/\S+)}{$cygpath->($1)}eg; $embed_flags =~ s{/cygdrive/(\w)/}{$1:/}g; #warn "** Cygwin embedding flags: embed_flags\n"; } } } else { push @warn, << '.'; *** Perl 5 embedding disabled. If you want Perl 5 support, please set the PUGS_EMBED environment variable to not contain "noperl5". . } if ($ENV{PUGS_EMBED} and $ENV{PUGS_EMBED} =~ /\bparrot\b/i and $Config{cc} eq 'cl') { push @warn, << '.'; *** Parrot linking not supported with MSVC. Parrot linking will be disabled. . $ENV{PUGS_EMBED} =~ s/\bparrot\b//g; } # Respect CC setting my $cc = $ENV{CC} || 'gcc'; $ghc_flags .= " -pgmc $cc " unless $cc eq 'gcc'; if ($Config{cf_by} eq 'Debian Project' and $ENV{PUGS_EMBED} and $ENV{PUGS_EMBED} =~ /\bperl5\b/i) { # Is it safe to remove 'Debian Project' above, to test on all platforms? my $need_path = 1; my $libperlpath = ''; my $libperl = $Config{libperl}; foreach my $path (split(/\s/, $Config{libpth} . ' ' . $Config{libsdirs})) { if (-e "$path/libperl.so") { $need_path = 0; last; } elsif (-e "$path/$libperl") { $libperlpath ||= $path; } } if ($need_path) { my $message = ''; $message .= qq[ * Symlink $libperlpath/$libperl to libperl.so\n] if ($libperlpath and $libperl); $message .= qq[ * Install libperl-dev package\n] if ($Config{cf_by} eq 'Debian Project'); die <splitpath($parrot_config))[1]; } if (!$base) { $parrot_config = which('parrot-config') || ''; $base = (File::Spec->splitpath($parrot_config))[1] if -e $parrot_config; } if (!$base and -d File::Spec->catdir(File::Spec->updir, 'parrot')) { $base = abs_path(File::Spec->catdir(File::Spec->updir, 'parrot')); } if (!$base and -d File::Spec->catdir(File::Spec->updir, 'parrot-trunk')) { $base = abs_path(File::Spec->catdir(File::Spec->updir, 'parrot-trunk')); } my $temp = File::Spec->catfile($base, 'parrot-config.imc'); if (!$parrot_config && -e $temp) { $parrot_config = $temp; } $temp = File::Spec->catfile($base, 'parrot-config.pir'); if (!$parrot_config && -e $temp) { $parrot_config = $temp; } $temp = File::Spec->catfile($base, 'parrot-config'); if (!$parrot_config && -e $temp) { $parrot_config = $temp; } $base =~ s/bin\/*$//; (-d $base and -e $parrot_config) or die "*** Please set \$ENV{PARROT_PATH} to the base path with a built parrot tree.\n"; my $ldflags = parrot_config($base, $parrot_config, 'ldflags'); my $libs = parrot_config($base, $parrot_config, 'libs'); my $icuflags = parrot_config($base, $parrot_config, 'icu_shared'); my $include_path = parrot_config($base, $parrot_config, 'prefix') . parrot_config($base, $parrot_config, 'inc'); my $rpath_blib = parrot_config($base, $parrot_config, 'rpath_blib'); my $build_dir = parrot_config($base, $parrot_config, 'top_builddir', 'build_dir'); my $is_shared = parrot_config($base, $parrot_config, 'parrot_is_shared'); my $parrot_libdir = parrot_config($base, $parrot_config, 'lib_dir'); # Convert flags to -optc-*,etc, to pass through ghc. c/ompiler l/inker $ldflags =~ s/(^|\s)-/$1-optl-/g; $libs =~ s/(^|\s)-/$1-optl-/g; $icuflags =~ s/(^|\s)-/$1-optl-/g; $include_path =~ s/(^|\s)-/$1-optc-/g; $embed_flags .= " -I$include_path" if $include_path =~ /\S/; $rpath_blib =~ s/(^|\s)-/$1-optl-/g; $embed_flags .= " -I$base/include -L$base/lib -L$base/blib/lib -DPUGS_HAVE_PARROT -L/usr/local/lib $ldflags "; $embed_flags .= " -lparrot $libs $icuflags "; my $config = $parrot_libdir."/parrot/config/install_config$Config{_o}"; $config = $parrot_libdir."/parrot/config/parrot_config$Config{_o}" unless -e $config; $config = $parrot_libdir."/parrot/config/null_config$Config{_o}" unless -e $config; $config = "$build_dir/src/install_config$Config{_o}" unless -e $config; $config = "$build_dir/src/parrot_config$Config{_o}" unless -e $config; $config = "$build_dir/src/null_config$Config{_o}" unless -e $config; die <<"EOD" unless -e $config or $is_shared; *** Could not find src/null_config.o in $build_dir. Solutions include: * Remove parrot from PUGS_EMBED * Place a built Parrot source tree under $build_dir. EOD $embed_flags .= " $config "; $embed_flags .= " $rpath_blib " if -d $build_dir; # parrot include paths for hsc2hs $hsc2hs_flags .= " -DPUGS_HAVE_PARROT -I$base/include "; push @warn, << "."; *** Embedded 'parrot' enabled. You can use it for Perl 6 regex support by setting the PUGS_REGEX_ENGINE environment variable to "PGE" at runtime. . } else { my $whichparrot = can_run('parrot'); if ($whichparrot) { push @warn, << "."; *** External 'parrot' executable found in your PATH at: $whichparrot You can use it for Perl 6 regex support by setting the PUGS_REGEX_ENGINE environment variable to "PGE" at runtime. If you want to link against Parrot, set the PUGS_EMBED environment variable to contain 'parrot', the PARROT_PATH environment variable to the path of a built parrot tree, then run Makefile.PL again. . } } my $is_win32 = ($^O =~ /MSWin|mingw|cygwin/i); my $threaded = (try_compile_and_run("main :: IO ()\nmain = return ()", $ghc, "-threaded")) ? '-threaded' : ''; if ($threaded && $ENV{PUGS_NO_THREADS}) { push @warn, << '.'; *** Thread support disabled due to explicit request in PUGS_NO_THREADS. . $threaded = ''; } my $find_ver = sub { `$_[0] $_ 2>&1` =~ /(.* (?:version|build) .*)/i && return $1 for qw{--version -v -V -? /?}; return "unknown"; }; unlink (my $build_config = 'current.build.yml'); my $config = get_pugs_config( uname => join (" ", (uname)[0,2,4] ), regex_engine => ( $ENV{PUGS_REGEX_ENGINE} ? $ENV{PUGS_REGEX_ENGINE} : 'default' ), embedded => join (" ", ( $embed_flags =~ /HAVE_PERL5/ ? $Config{perlpath} : 'noperl' ), ( $embed_flags =~ /HAVE_PARROT/ ? abs_path( File::Spec->catfile( "$ENV{PARROT_PATH}", "parrot" ) ) : 'noparrot' ), ( $ENV{PUGS_EMBED} =~ /\bhaskell\b/ ? $ghc : 'nohaskell' ) ), ghc => join (" ", [ assert_ghc() ]->[0], $ghc_version, ( $ghc_flags =~ /HAVE_READLINE/ ? 'readline' : 'noreadline' ), ( $ghc_flags =~ /HAVE_HSPLUGINS/ ? 'hsplugins' : 'nohsplugins' ), ( $threaded ? "threads" : "nothreads" ), ), cc => $find_ver->( $Config{cc} ), ); { # maybe move this to inc/PugsBuild/MiniYAML.pm ? open my $fh, '>', $build_config or die "Cannot open $build_config for writing"; print $fh "# *** NOTE ***\n"; print $fh "# This file is generated during Makefile.PL.\n"; print $fh "# Changes will not persist after running Makefile.PL\n"; for ( sort keys %$config ) { print $fh "$_: $config->{$_}\n"; } close $fh; } # As of now, Test::TAP::HTMLMatrix is the key dependency for smokes, # so we need only check for that. eval { require Test::TAP::HTMLMatrix } or push @warn, << '.'; *** You do not appear to have a Smoke Kit installed. You can still build Pugs and even run `make test', but you won't be able to run the more modern `make smoke' target to produce nice graphs and send them to the public smoke server. Installing Task::Smoke from CPAN will bring in the necessary dependencies. . # XXX - hsplugins doesn't build with profiles my $profiled_flags = $ghc_flags; $profiled_flags =~ s{-DPUGS_HAVE_HSPLUGINS}{}; $profiled_flags =~ s{-package plugins}{}; my $emit = sub { my $o = shift; my $c = substr($o, 0, -1) . 'c'; return "$o : $c\n\t$ghc $threaded $embed_flags $ghc_flags -no-link -no-hs-main -O -o $o $c\n"; }; mkdir 'dist'; mkdir 'dist/build'; mkdir 'dist/build/src'; # Using the Win32 Haskell compiler results in a setup program that # doesn't grok cygwin paths. This kludge takes any /cygdrive/ # style paths and rewrites them. This really should be factored # out to a common module. Better still, we should make a Cygwin-native # GHC. if ($Config{osname} eq 'cygwin') { # NB. We're exploiting for's aliasing of variables. foreach my $path ($ghc_pkg, $hsc2hs, $ghc) { $path = `cygpath -m $path`; chomp $path; } } my $setup_flags = "--prefix=\$(DESTDIR) --with-hc-pkg=$ghc_pkg --with-hsc2hs=$hsc2hs --ghc --with-compiler=$ghc"; my $precompile_prelude = ' --precompile-prelude '.PugsBuild::Config->lookup('precompile_prelude'); my $svn_entries = ''; my $svn_admin_dir = $ENV{SVN_ASP_DOT_NET_HACK} ? '_svn' : '.svn'; if (-d $svn_admin_dir) { $svn_entries = File::Spec->catfile($svn_admin_dir, 'entries'); } #$svn_entries = 'force_run'; # logic for Judy: # if ($Config{osname} ne 'MSWin32') { # warn "Configuring Judy...\n"; # chdir "third-party/judy/Judy-1.0.3"; # copy('src/Judy.h', '../../HsJudy'); # system("./configure") unless -e "config.status" and -e "Makefile"; # chdir "../../.."; # } # # my $judyclean; # if ($Config{osname} eq 'MSWin32') { # $judyclean = 'cd third-party\judy\Judy-1.0.3\src && '. # 'nmake /nologo /F Makefile.win32 clean'; # } else { # my $make = $Config{make}; # # # Judy at this moment wants GNU make. # $make = 'gmake' unless `$make --version` =~ /GNU/; # # $judyclean = "cd third-party/judy/Judy-1.0.3 \&\& $make clean \&\& perl cleanmore.pl"; # } my @ghci_flags = qw( -hide-all-packages -package base -package filepath -package parsec -package template-haskell -package readline -package unix -package haskell98 -package mtl -package stm -package network -package HsSyck -package pugs-hsregex ); postamble(fixpaths(<< ".")); $config_h : lib/Perl6/Pugs.pm util/config_h.pl \$(PERL) util/config_h.pl "$ghc $ghc_flags" $version_h : \$(PERL) util/version_h.pl $version_h @{[join("\n", map {$emit->($_)} grep { /\.o$/ } @prereqs)]} src/Pugs/Config.hs : util/PugsConfig.pm current.build.yml \$(PERL) -Iutil -MPugsConfig -e "PugsConfig->write_config_module" > src/Pugs/Config.hs src/gen_prelude$Config{_exe} : src/gen_prelude.hs $ghc -O0 --make -o src/gen_prelude$Config{_exe} src/gen_prelude.hs src/Pugs/CodeGen/PIR/Prelude.hs : src/gen_prelude$Config{_exe} src/perl6/Prelude/PIR.pm \@\$(PERL) -e "mkdir q-src/Pugs/CodeGen/PIR-" src/gen_prelude$Config{_exe} Pugs.CodeGen.PIR.Prelude < src/perl6/Prelude/PIR.pm > src/Pugs/CodeGen/PIR/Prelude.hs src/Pugs/Prelude.hs : src/perl6/Prelude.pm util/gen_prelude.pl \$(PERL) util/gen_prelude.pl -v --touch --inline -i src/perl6/Prelude.pm --output src/Pugs/Prelude.hs ${() = '%.hpp : %.hs @prereqs $version_h $ghc $threaded $ghc_flags -DHADDOCK -E \$< -o \$@ \$(PERL) util/munge_haddock.pl \$@'; \''} .SUFFIXES: .hs .hpp .hs.hpp : $ghc $threaded $ghc_flags -DHADDOCK -E \$< -o \$@ \$(PERL) util/munge_haddock.pl \$@ .SUFFIXES: .hsc .hs .hsc.hs : \$(PERL) -MFile::Spec -e "sub p () { File::Spec->splitpath(ARGV->[0]) }; chdir((p)[1]); system(q($hsc2hs), qw($hsc2hs_flags), (p)[2]);" \$< .SUFFIXES: .grammar .hs .grammar.hs : \$(PERL) util/file_to_hs.pl \$< \$@ .SUFFIXES: .pil .hs .pil.hs : \$(PERL) util/file_to_hs.pl \$< \$@ util/drift.pl: @{[ mk_drift_rules( qw(src/Emit/PIR src/Pugs/AST/Internals src/Pugs/PIL1 src/Pugs/PIL2) ) ]} haddock : $version_h $config_h @hppfiles dist/doc/html haddock -t Pugs-$version -h -o dist/doc/html/ @hppfiles \@\$(RM_F) @{[map "$_.pre", @hppfiles]} @hppfiles \@\$(PERL) -le "print and print q-*** API Documentation generated in @{[File::Spec->catfile('dist', 'doc', 'html', 'index.html')]}-" # make haddock one file at a time to get partial, unlinked output haddock-broken : $version_h $config_h @hppfiles dist/doc/html @{[join("\n", map {"\thaddock -t Pugs-$version -h -o dist/doc/html/ $_"} @hppfiles)]} \@\$(RM_F) @{[map "$_.pre", @hppfiles]} @hppfiles \@\$(PERL) -le "print and print q-*** Unlinked API Documentation generated in @{[File::Spec->catfile('dist', 'doc', 'html', 'index.html')]}-" dist/doc/html : \@\$(PERL) -MFile::Path -e "mkpath q-dist/doc/html-" pugs_requirements : instances src/Pugs/Config.hs src/Pugs/CodeGen/PIR/Prelude.hs @srcfiles $version_h $config_h config.yml src/perl6/Prelude.pm src/Pugs/Prelude.hs prof :: profiled soonprof :: unoptimised-profiled unoptimized-profiled :: unoptimised-profiled unoptimised-profiled :: pugs_requirements \$(PERL) util/build_pugs.pl _+SETUP $setup_flags _-SETUP _+GHC $version $ghc $ghc_pkg $ghc_version $setup --make -O0 -auto-all -prof $threaded $profiled_flags $ccdlflags $embed_flags $ghc_output _-GHC _+GEN_PRELUDE $precompile_prelude --pugs $thispugs profiled :: pugs_requirements \$(PERL) util/build_pugs.pl _+SETUP $setup_flags _-SETUP _+GHC $version $ghc $ghc_pkg $ghc_version $setup --make -O -auto-all -prof $threaded $profiled_flags $ccdlflags $embed_flags $ghc_output _-GHC _+GEN_PRELUDE $precompile_prelude --pugs $thispugs pugs.prof :: profiled find t -type f | grep -v D | grep -v R | grep -v pugsrun | ./pugs +RTS -p -RTS -e 'my sub exit {}; for =\$\$*IN -> \$\$t is copy { \$\$t .= chomp; require \$\$t }' optimised :: optimized optimized :: pugs_requirements \$(PERL) util/build_pugs.pl _+SETUP $setup_flags _-SETUP _+GHC $version $ghc $ghc_pkg $ghc_version $setup --make -O $threaded $ghc_flags $ccdlflags $embed_flags $ghc_output _-GHC _+GEN_PRELUDE $precompile_prelude --pugs $thispugs soon :: unoptimized unoptimised :: unoptimized unoptimized :: pugs_requirements \$(PERL) util/build_pugs.pl _+SETUP $setup_flags _-SETUP _+GHC $version $ghc $ghc_pkg $ghc_version $setup --make -O0 $threaded $ghc_flags $ccdlflags $embed_flags $ghc_output _-GHC _+GEN_PRELUDE $precompile_prelude --pugs $thispugs $pugs : pugs_requirements \$(PERL) util/build_pugs.pl _+SETUP $setup_flags _-SETUP _+GHC $version $ghc $ghc_pkg $ghc_version $setup --make __optimization__ $threaded $ghc_flags $ccdlflags $embed_flags $ghc_output _-GHC _+GEN_PRELUDE $precompile_prelude --pugs $thispugs pirtest : test-pir pirsmoke : smoke-pir jssmoke : smoke-js test :: blib6/lib/Test.pm.yml prelude :: blib6/lib/Prelude.pm.yml pure_all :: blib6/lib/Test.pm.yml test-all : test test-js test-pir test-perl5 test-pir : \$(PERL) -e "ENV->{HARNESS_PERL_SWITCHES}=q+-B PIR+; system qq+$Config{make}+, q+test+" test-js : \$(PERL) -e "ENV->{HARNESS_PERL_SWITCHES}=q+-B JS+; system qq+$Config{make}+, q+test+" test-perl5 : \$(PERL) -e "ENV->{HARNESS_PERL_SWITCHES}=q+-B PERL5+; system qq+$Config{make}+, q+test+" test-redsix : \$(PERL) -e "ENV->{HARNESS_PERL_SWITCHES}=q+-B REDSIX+; system qq+$Config{make}+, q+test+" blib6/lib/Test.pm.yml :: ext/Test/lib/Test.pm \$(NOECHO) \$(ECHO) "Precompiling Test.pm..." $thispugs -CParse-YAML ext/Test/lib/Test.pm > blib6/lib/Test.pm.yml blib6/lib/Prelude.pm.yml : \$(NOECHO) \$(ECHO) "Precompiling Prelude.pm..." util/gen_prelude.pl -v -i src/perl6/Prelude.pm -p $thispugs --output blib6/lib/Prelude.pm.yml upload-smoke : smoke.yml \$(PERL) util/smokeserv/smokeserv-client.pl smoke.html smoke.yml smoke-upload : upload-smoke smoke.yml : \$(PERL) util/run-smoke.pl . smoke.html smoke : smoke-pugs smoke-all : smoke-pugs smoke-js smoke-pir smoke-perl5 smoke-pugs : $pugs util/run-smoke.pl all blib6/lib/Test.pm.yml \$(PERL) util/run-smoke.pl . smoke.html smoke-pir : $pugs util/run-smoke.pl all \$(PERL) util/run-smoke.pl . smoke-pir.html -BPIR smoke-jsperl5 : $pugs util/run-smoke.pl all \$(PERL) -e "ENV->{PUGS_RUNTIME}=q+JSPERL5+; exec qw+$^X util/run-smoke.pl . smoke-jsperl5.html+" smoke-js : $pugs util/run-smoke.pl all \$(PERL) -e "ENV->{PUGS_RUNTIME}=q+JS+; exec qw+$^X util/run-smoke.pl . smoke-js.html+" smoke-perl5 : $pugs util/run-smoke.pl all \$(PERL) -e "ENV->{PUGS_RUNTIME}=q+PERL5+; exec qw+$^X util/run-smoke.pl . smoke-perl5.html -BPERL5+" smoke-redsix : $pugs util/run-smoke.pl all \$(PERL) -e "ENV->{PUGS_RUNTIME}=q+REDSIX+; exec qw+$^X util/run-smoke.pl . smoke-redsix.html -BREDSIX+" ghci : @prereqs @derived_srcfiles $ghc @{[ dethread_flags($ghc_flags) ]} $ghc_output -DPUGS_UNDER_GHCI -no-link --make -O0 -fglasgow-exts -L. -idist/build -Ldist/build -idist/build/src -Ldist/build/src -isrc src/Prereqs.hs @prereqs \@\$(RM_RF) src/Pugs/*/*_stub.* $ghc @{[ dethread_flags($ghc_flags) ]} @ghci_flags $ghc_output -DPUGS_UNDER_GHCI --interactive -fglasgow-exts $ghci_debugging -L. -idist/build -Ldist/build -idist/build/src -Ldist/build/src -isrc src/Main.hs @prereqs ctags : @prereqs @derived_srcfiles echo ":ctags" | $ghc $ghc_flags @ghci_flags $ghc_output --interactive -osuf moose -hisuf miise -fglasgow-exts -L. -idist/build -Ldist/build -idist/build/src -Ldist/build/src -isrc src/Main.hs @prereqs etags : @prereqs @derived_srcfiles echo ":etags" | $ghc $ghc_flags @ghci_flags $ghc_output --interactive -osuf moose -hisuf miise -fglasgow-exts -L. -idist/build -Ldist/build -idist/build/src -Ldist/build/src -isrc src/Main.hs @prereqs pil$Config{_exe} : $config_h @srcfiles src/PIL/Native/Bootstrap.hs src/PIL/Native/Syntax.hs $ghc $ghc_flags --make -fglasgow-exts -H0 -isrc -Isrc -L. -fno-warn-name-shadowing -o pil$Config{_exe} -main-is PIL.main src/PIL.hs pili : pil$Config{_exe} $ghc --interactive -fglasgow-exts -isrc -Isrc -L. -static -fno-warn-name-shadowing src/PIL.hs tags : @srcfiles $hasktags -c @{[ grep { !/PIL/ } @srcfiles ]} sort tags > tags.tmp mv tags.tmp tags config.yml: src/perl6/Prelude.pm: INST6_ARCHLIB = blib6/arch INST6_SCRIPT = blib6/script INST6_BIN = blib6/bin INST6_LIB = blib6/lib INST6_MAN1DIR = blib6/man1 INST6_MAN3DIR = blib6/man3 INSTPUGS_LIB = blib6/pugs build_perl5 :: @{[for_perl5(" cd __DIR__ && $^X Makefile.PL && \$(MAKE) ")]} clean :: \@\$(RM_RF) third-party/installed @{[for_perl5(" -cd __DIR__ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) clean ")]} realclean :: \@\$(RM_RF) third-party/installed @{[for_perl5(" -cd __DIR__ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) realclean ")]} pure_all :: build_perl5 \$(PERLRUN) util/src_to_blib.pl register :: \$(PERLRUN) util/ghc_setup.pl copy --copy-prefix=\$(DESTDIR) \$(PERLRUN) util/ghc_setup.pl register --prefix=\$(DESTDIR) pure_site_install :: \$(NOECHO) \$(MOD_INSTALL) \\ \$(INST6_LIB) \$(DESTDIR)$config->{sitelib} \\ \$(INST6_ARCHLIB) \$(DESTDIR)$config->{sitearch} \\ \$(INST6_BIN) \$(DESTDIR)$config->{sitebin} \\ \$(INST6_SCRIPT) \$(DESTDIR)$config->{sitescript} \\ \$(INST6_MAN1DIR) \$(DESTDIR)$config->{installsiteman1dir} \\ \$(INST6_MAN3DIR) \$(DESTDIR)$config->{installsiteman3dir} \\ \$(INSTPUGS_LIB) \$(DESTDIR)$config->{sitelib}/auto/pugs # \$(PERLRUN) util/ghc_setup.pl copy --copy-prefix=\$(DESTDIR) pure_vendor_install :: \$(NOECHO) \$(MOD_INSTALL) \\ \$(INST6_LIB) \$(DESTDIR)$config->{privlib} \\ \$(INST6_ARCHLIB) \$(DESTDIR)$config->{archlib} \\ \$(INST6_BIN) \$(DESTDIR)$config->{installbin} \\ \$(INST6_SCRIPT) \$(DESTDIR)$config->{installscript} \\ \$(INST6_MAN1DIR) \$(DESTDIR)$config->{installman1dir} \\ \$(INST6_MAN3DIR) \$(DESTDIR)$config->{installman3dir} \\ \$(INSTPUGS_LIB) \$(DESTDIR)$config->{privlib}/auto/pugs # \$(PERLRUN) util/ghc_setup.pl copy --copy-prefix=\$(DESTDIR) . } sub for_perl5 { my $cmd = shift; $cmd =~ s{\n}{}g; my @cmds; foreach my $dir (grep { -d } glob('perl5/*')) { -e "$dir/Makefile.PL" or next; # Skip XS modules for now next if glob("$dir/*.xs") or glob("$dir/*.i") or $dir =~ /-\d+/; my $this = $cmd; $this =~ s{__DIR__}{$dir}g; push @cmds, $this; } return join("\n", @cmds); } our $do_run; sub try_compile_and_run { local $do_run = 1; try_compile(@_); } sub try_compile { my $code = shift; my $temp = "pugs-tmp-$$"; my $ghc = shift or croak "try_compile called without path to ghc"; eval { open TMP, "> $temp.hs"; print TMP $code; close TMP; system( $ghc, @_, "--make", "-v0", -o => "$temp.exe", "$temp.hs" ); }; my $ok = -s "$temp.exe"; if ($do_run) { $ok = 0 unless system(abs_path("$temp.exe")) == 0; } unlink("$temp.exe"); unlink("$temp.hs"); unlink("$temp.hi"); unlink("$temp.o"); return $ok; } sub parrot_config { my $base = shift; my $parrot_config = shift; my $ac_path = abs_path(); my $sp_base = $base; $sp_base =~ s{\\}{\/}g; chdir( $sp_base ) or die "Can't change dir to '$sp_base'"; my $parrot = "parrot$Config{_exe}"; $parrot = "bin/$parrot" if not -e $parrot; my $value; while (@_) { my $config = shift; $value = `./$parrot $parrot_config $config`; $value =~ /no such key:/ or last; } die $value if $value =~ /no such key:/; chomp($value); chdir( $ac_path ) or die "Can't change dir to '$ac_path'"; return $value; } sub which { my $file = shift; for ( File::Spec->path() ) { my $full_name = File::Spec->catfile($_, $file); return $full_name if -e $full_name; } return undef; } sub preprocess { my ($infile, $outfile, %substitutions) = @_; open IN, '<', $infile or die "failed to open $infile ($!)"; open OUT, '>', $outfile or die "failed to open $outfile ($!)"; if ($Config{osname} eq 'cygwin') { for my $path (values %substitutions){ $path = `cygpath -m $path`; chomp $path; } } while () { while (my ($pat, $subst) = each(%substitutions)) { $subst =~ s{\\}{\\\\}g; s/__${pat}__/$subst/g } print OUT $_; } close OUT; close IN; } sub compile_hs { my ($ghc, $prefix, $out) = @_; unlink($prefix . $_) for ( $Config{_exe}, '.o', '.hi', ); my $rv = system($ghc, '--make', '-o' => $out, (-e $prefix. '.hs') ? $prefix.'.hs' : $prefix.'.lhs' ); unless (-s $out) { die << "."; *** Building Setup$Config{_exe} failed (exit code $rv) Please check your GHC and Cabal installation. . } } sub mk_drift_rules { join "\n\n", ("instances: " . join " ", map { "$_/Instances.hs" } @_), (map { "$_.hs:" } @_), map { <<"." } @_; $_/Instances.hs: $_.hs util/drift.pl \t\$(PERL) util/drift.pl $_.hs . } __END__