#!/usr/bin/perl -w # -*- perl -*- use strict; use lib qw( ./lib ); use Config; use File::Spec::Functions qw( catfile ); use Template; use ExtUtils::MakeMaker; use Cwd; select STDERR; $| = 1; select STDOUT; use vars qw( $TT_VERSION $TT_PREFIX $TT_IMAGES $TT_RUN_DBI $TT_BUILD_DOCS $TT_SPLASH_DOCS $TT_EXAMPLES $TT_EXTRAS $TT_LATEX_ENABLE $TT_LATEX_PATH $TT_PDFLATEX_PATH $TT_DVIPS_PATH $TT_XS_ENABLE $TT_XS_DEFAULT $TT_SPLASH_THEME $TT_QUIET $TT_ACCEPT $TT_YES ); # check O/S to set sensible defaults my ($WIN32, $FLAVOUR, $PREFIX, $IMAGES, $MAKE); if ($^O eq 'MSWin32') { # any others also? $WIN32 = 1; $FLAVOUR = 'Win32'; $PREFIX = 'C:/Program Files/Template Toolkit 2'; $IMAGES = '/tt2/images'; $MAKE = 'nmake'; } else { $WIN32 = 0; $FLAVOUR = 'Unix'; $PREFIX = '/usr/local/tt2'; $IMAGES = '/tt2/images'; $MAKE = 'make'; } # read command line args putting TT_* into $ttconfig and # everything else (regular Makefile.PL args, e.g. PREFIX) # goes into $config my (%config, %ttconfig); while ($_ = shift) { my ($k, $v) = split(/=/); if ($k =~ /^TT/) { $ttconfig{ $k } = $v || 0; } else { $config{ $k } = $v || 0; } }; # print help if they asked for it if (exists $ttconfig{ TT_HELP }) { print < [ 'lilac', 'mauve' ], aqua => [ 'aqua', 'marine' ], grey => [ 'grey75', 'grey50' ], blue => [ 'grey75', 'blue75' ], red => [ 'grey75', 'red75' ], green => [ 'grey75', 'green75' ], leon => [ 'red75', 'orange', 'white', 'black' ], }; # define version numbers of required modules my $TT_APPCONFIG_VERSION = '1.55'; my $TT_FILE_SPEC_VERSION = '0.8'; my $TT_FILE_TEMP_VERSION = '0.12'; #======================================================================== welcome_message(); version_check(); mandatory_modules(); optional_modules(); optional_stash_xs(); optional_latex(); optional_extras(); splash_images(); html_docs(); html_docstyle(); html_examples(); write_defaults(); print "\n"; #------------------------------------------------------------------------ # build options and write Makefile #------------------------------------------------------------------------ package MY; sub postamble { return '' unless $main::TT_PREFIX; my $amble =<<'EOF'; tt2_install :: @$(PERL) bin/tt2inst -v "$(TT_PREFIX)" tt2_splash :: @$(PERL) -I$(INST_LIB) -I$(INST_ARCHLIB) bin/gifsplash -v -i "$(TT_PREFIX)" EOF $amble .=<SUPER::install(@_); my $add = 'tt2_install tt2_splash'; $add .= ' tt2_html_docs' if $main::TT_BUILD_DOCS; $add .= ' tt2_examples' if $main::TT_EXAMPLES; $basic =~ s/^(install\s+::\s+.*)$/$1 $add/m if $main::TT_PREFIX; $basic; } sub constants { my $class = shift; my $basic = $class->SUPER::constants(@_); $basic = "TT_PREFIX = $main::TT_PREFIX\n$basic" if $main::TT_PREFIX; $basic; } package main; my %opts = ( %config, 'NAME' => 'Template', 'DISTNAME' => 'Template-Toolkit', 'VERSION_FROM' => 'lib/Template.pm', 'EXE_FILES' => [ 'bin/tpage', 'bin/ttree' ], 'PMLIBDIRS' => [ 'lib' ], 'DIR' => [ ], 'PREREQ_PM' => { 'AppConfig' => $TT_APPCONFIG_VERSION, 'File::Spec' => $TT_FILE_SPEC_VERSION, 'File::Temp' => $TT_FILE_TEMP_VERSION, }, 'dist' => { 'COMPRESS' => 'gzip', 'SUFFIX' => 'gz', }, 'clean' => { 'FILES' => join(' ', qw( docs/ttree.cfg examples/ttree.cfg t/dbi_test.cfg t/test/src/baz.ttc t/test/src/complex.org t/test/src/complex.ttc t/test/src/evalperl.ttc t/test/src/foo.ttc )), }, ); push @{ $opts{'DIR'} }, 'xs' if $TT_XS_ENABLE; if ($ExtUtils::MakeMaker::VERSION >= 5.43) { $opts{ AUTHOR } = 'Andy Wardley '; $opts{ ABSTRACT } = 'comprehensive template processing system', } WriteMakefile( %opts ); print < \&check_taf ], [ 'GD' => undef ], [ 'GD::Text' => undef ], [ 'GD::Graph' => undef ], [ 'GD::Graph3d' => undef ], [ 'Image::Info' => undef ], [ 'Image::Size' => undef ], [ 'Date::Calc' => undef ], [ 'Pod::POM' => undef ], [ 'Tie::DBI' => undef ], [ 'XML::DOM' => \&check_dom ], [ 'XML::RSS' => \&check_rss ], [ 'XML::XPath' => \&check_xpath ], [ 'DBI' => \&dbi_config ] ) { my ($module, $code) = ref $mods ? @$mods : ($mods, 0); printf(" %-16s ", $module) unless $TT_QUIET; eval "use $module"; if ($@) { nope("module not installed"); } elsif ($code) { &$code; } else { no strict qw( refs ); my $ver = ${"$module\::VERSION"}; yep("version $ver installed"); } } } #------------------------------------------------------------------------ # optional_stash_xs() # # Prompt for installation and default use of XS Stash. #------------------------------------------------------------------------ sub optional_stash_xs { # return if $TT_ACCEPT && (! $TT_XS_ENABLE || $TT_XS_ENABLE eq 'n'); message(< new Template::Stash::XS, ... }); You can also enable the XS stash (or the regular stash if you opt to use the XS stash by default) by setting the \$STASH package variable in the Template/Config.pm module. See 'perldoc Template::Config' for further details. EOF $TT_XS_ENABLE = (ttprompt('Do you want to build the XS Stash module?', $TT_XS_ENABLE) =~ /^y/i); if ($TT_XS_ENABLE) { $TT_XS_DEFAULT = (ttprompt('Do you want to use the XS Stash for all Templates?', $TT_XS_DEFAULT) =~ /^y/i); } else { # If the XS stash is disabled, we cannot use it as the default stash. $TT_XS_DEFAULT = 0; } # Actually, we would have to fix 'Config.pm' only if the XS stash is # disabled. But this way, we are sure the correct module is used. fix_file(catfile('lib','Template','Config.pm'), '$STASH', $TT_XS_DEFAULT ? 'Template::Stash::XS' : 'Template::Stash'); } #------------------------------------------------------------------------ # optional_latex() # # Prompt for installation of latex filter #------------------------------------------------------------------------ sub optional_latex { # return if $TT_ACCEPT && (! $TT_LATEX_ENABLE || $TT_LATEX_ENABLE eq 'n'); $TT_LATEX_PATH ||= find_program($ENV{PATH}, "latex") || ''; $TT_PDFLATEX_PATH ||= find_program($ENV{PATH}, "pdflatex") || ''; $TT_DVIPS_PATH ||= find_program($ENV{PATH}, "dvips") || ''; message(< $TT_PDFLATEX_PATH + latex => $TT_LATEX_PATH + dvips => $TT_DVIPS_PATH EOF if ( $TT_LATEX_PATH eq "" || $TT_PDFLATEX_PATH eq "" || $TT_DVIPS_PATH eq "" ) { $TT_LATEX_ENABLE = 'n'; } $TT_LATEX_ENABLE ||= 'y'; $TT_LATEX_ENABLE = ( ttprompt('Do you want to enable the latex filter?', $TT_LATEX_ENABLE) =~ /^y/i ); if ( $TT_LATEX_ENABLE ) { if (ttprompt('Are the pdflatex, latex and dvips paths ok?', 'y') !~ /^y/i) { $TT_PDFLATEX_PATH = ttprompt('pdflatex path', $TT_PDFLATEX_PATH); $TT_LATEX_PATH = ttprompt('latex path', $TT_LATEX_PATH); $TT_DVIPS_PATH = ttprompt('dvips path', $TT_DVIPS_PATH); } } else { # # Empty paths will cause the latex filter to throw an error # $TT_PDFLATEX_PATH = $TT_LATEX_PATH = $TT_DVIPS_PATH = ""; } fix_file(catfile('lib','Template','Config.pm'), '$PDFLATEX_PATH', $TT_PDFLATEX_PATH); fix_file(catfile('lib','Template','Config.pm'), '$LATEX_PATH', $TT_LATEX_PATH); fix_file(catfile('lib','Template','Config.pm'), '$DVIPS_PATH', $TT_DVIPS_PATH); } #------------------------------------------------------------------------ # optional_extras() # # Prompt for installation of optional libraries and other components #------------------------------------------------------------------------ sub optional_extras { message(< HTML, and PostScript * Splash! - a stylish HTML user interface template library / widget set * HTML documentation - distributed in template form for customisation * Stylesheet templates to generate docs as vanilla HTML or using Splash! * Examples - numerous examples of using the template libraries If you want to install these optional components then you'll need to specify a separate directory for them. EOF if ($TT_EXTRAS = ( ttprompt('Do you want to install these components?', $TT_EXTRAS) =~ /^y/i)) { message(<{ $t }; local $" = '/'; printf(" %-8s @$v\n", $t); } print "\n"; while (! $splash_style) { $TT_SPLASH_THEME = ttprompt("Enter name of colour scheme: ", $TT_SPLASH_THEME); message("! No such scheme\n"), $TT_SPLASH_THEME = 'default' unless ($splash_style = $SPLASH_STYLES->{ $TT_SPLASH_THEME }); } ( $TT_SPLASH_BG, $TT_SPLASH_FG, $TT_SPLASH_BT, $TT_SPLASH_FT ) = @$splash_style; # default background (unselected) text is black, fore is white $TT_SPLASH_BT ||= 'black'; $TT_SPLASH_FT ||= 'white'; $style = 'splash'; $style_cfg = < $TT_DOCS_CFG") || die "$TT_DOCS_CFG: $!\n"; print FP < $TT_EXAMPLE_CFG") || die "$TT_EXAMPLE_CFG: $!\n"; print FP < $DEFAULTS_FILE") || die "$DEFAULTS_FILE: $!\n"; my ( $ttdbi, $ttdocs, $ttsplash, $ttexamples, $ttextras, $ttlatex, $ttxs_enable, $ttxs_default ) = map { $_ ? 'y' : 'n' } ( $TT_RUN_DBI, $TT_BUILD_DOCS, $TT_SPLASH_DOCS, $TT_EXAMPLES, $TT_EXTRAS, $TT_LATEX_ENABLE, $TT_XS_ENABLE, $TT_XS_DEFAULT ); print FP <{ decimal_point }; yep("version $Text::Autoformat::VERSION installed"); if ($] <= 5.006 && $dec ne '.') { print ' ' x 6, "NOTE: tests 23 and 25 may fail under your locale, see TODO file.\n"; } } #------------------------------------------------------------------------ # check_dom() # # XML::DOM changed from HASH to ARRAY objects somewhere between versions # 1.25 and 1.27, so the latter version is an absolute necessity. #------------------------------------------------------------------------ sub check_dom { if ($XML::DOM::VERSION < 1.27) { nope("requires version 1.27 or later ($XML::DOM::VERSION installed)"); } else { yep("version $XML::DOM::VERSION installed"); } } #------------------------------------------------------------------------ # check_rss() # # Version 0.8 of XML::RSS gave warnings under Perl 5.6.0 so issue an # upgrade recommendation #------------------------------------------------------------------------ sub check_rss { if ($] >= 5.006 && $XML::RSS::VERSION < 0.9) { nope("requires version 0.9 or later ($XML::RSS::VERSION installed)"); } else { yep("version $XML::RSS::VERSION installed"); } } #------------------------------------------------------------------------ # check_xpath() # # Tests fail under some of the earlier versions (e.g. 0.55) so we issue # an upgrade recommendation. #------------------------------------------------------------------------ sub check_xpath { if ($XML::XPath::VERSION < 1.00) { nope("requires version 1.00 or later ($XML::XPath::VERSION installed)"); } else { yep("version $XML::XPath::VERSION installed"); } } #------------------------------------------------------------------------ # dbi_config() # # Quiz the user for options related to running the DBI tests. #------------------------------------------------------------------------ sub dbi_config { my ($dsn, $user, $pass) = ('') x 3; message("[X] version $DBI::VERSION installed, configuring tests\n\n"); if (ttprompt("Do you want to run the DBI tests?\n" . "It requires access to an existing test database.", $TT_RUN_DBI) =~ /y/i) { $TT_RUN_DBI = 1; my ($driver, $dbname); my @drivers = DBI->available_drivers(); local $" = ', '; my $default = (grep(/m.?sql/i, @drivers))[0] || $drivers[0] || ''; message(<$DBI_CONFIG_FILE") || die "$DBI_CONFIG_FILE: $!\n"; print CFGFILE <; close(FP); ($text =~ s/^(\s*${find}\s*=\s*)'.*?'/$1'$fix'/m) || die "$find not found in $file\n"; open(FP, "> $file") || die "$file: $!\n"; print FP $text; close(FP); } #------------------------------------------------------------------------ # find_program($path, $prog) # # Find a program, $prog, by traversing the given directory path, $path. # Returns full path if the program is found. # # Written by Craig Barratt, Richard Tietjen add fixes for Win32. # # abw changed name from studly caps findProgram() to find_program() :-) #------------------------------------------------------------------------ sub find_program { my($path, $prog) = @_; # my $sep = $WIN32 ? qr/;/ : qr/:/; # foreach my $dir ( split($sep, $path) ) { foreach my $dir ( split($Config{path_sep}, $path) ) { my $file = File::Spec->catfile($dir, $prog); if ( !$WIN32 ) { return $file if ( -x $file ); } else { # Windows executables end in .xxx, exe precedes .bat and .cmd foreach my $dx ( qw/exe bat cmd/ ) { return "$file.$dx" if ( -x "$file.$dx" ); } } } } #------------------------------------------------------------------------ # message($text) # # Print message unless quiet mode. #------------------------------------------------------------------------ sub message { return if $TT_QUIET; print @_; } #------------------------------------------------------------------------ # ttprompt($message, $default) #------------------------------------------------------------------------ sub ttprompt { my ($msg, $def)=@_; my $ISA_TTY = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ; # Pipe? my $dispdef = defined $def ? "[$def] " : " "; $def = defined $def ? $def : ""; my $ans = ''; local $|=1; print "$msg $dispdef" unless $TT_QUIET; if ($TT_ACCEPT || ! $ISA_TTY) { print "$def\n" unless $TT_QUIET; } else { chomp($ans = ); } return ($ans ne '') ? $ans : $def; } #------------------------------------------------------------------------ # yep($text) #------------------------------------------------------------------------ sub yep { return if $TT_QUIET; print '[X] ', shift, "\n"; } #------------------------------------------------------------------------ # nope($text) #------------------------------------------------------------------------ sub nope { return if $TT_QUIET; print '[ ] ', shift, "\n"; }