Distribution::Guess::BuildSystem - This is the description


Distribution-Guess-BuildSystem documentation Contained in the Distribution-Guess-BuildSystem distribution.

Index


Code Index:

NAME

Top

Distribution::Guess::BuildSystem - This is the description

SYNOPSIS

Top

	use Distribution::Guess::BuildSystem;

	chdir $dist_dir;

	my $guesser = Distribution::Guess::BuildSystem->new(
		dist_dir => $dir
		);

	my $build_files   = $guesser->build_files; # Hash ref

	my $build_pl      = $guesser->has_build_pl;
	my $makefile_pl   = $guesser->has_makefile_pl;

	my $both          = $guesser->has_build_and_makefile;

	my $build_command = $guesser->build_commands; # Hash ref

	if( $guesser->uses_module_install ) 
		{
		my $version = $guesser->module_install_version;
		my $pita    = $guesser->uses_auto_install;
		}

	if( $guesser->uses_makemaker )   
		{
		my $version = $guesser->makemaker_version;
		my $make    = $guesser->make_command;
		}

DESCRIPTION

Top

There are three major build system for Perl distributions:

* ExtUtils::MakeMaker

Uses Makefile.PL and make.

* Module::Build

Uses Build.PL and perl, although it might have a Makefile.PL that is a wrapper.

* Module::Install

Uses Makefile.PL and calls to an embedded Module::Install. It might use auto_install to call CPAN.pm at build time.

The trick is to figure out which one you are supposed to use. This module has several methods to look at a distribution and guess what its build system is. The main object is simply some settings. Every time you want to ask a question about the distribution, the object looks at the distribution. That is, it doesn't capture the information when you create the object.

Methods

new

Creates a new guesser object. You can set:

	dist_dir            - the distribution directory (where the build file is)
	perl_binary         - the path to the perl you want to use
	prefer_module_build - some methods will return the preferred builder
	prefer_makemaker    - some methods will return the preferred builder

If you prefer The defaults are:

	dist_dir            - current working directory
	perl_binary         - $^X (may be relative and no longer in path!)
	prefer_module_build - true
	prefer_makemaker    - false

dist_dir( [ DIR ] )

Returns or sets the distribution directory.

perl_binary( [PERL] )

Returns or sets the perl binary path. This is either the one that you set or the value of $^X. There's no check to verify that this is actually a perl binary.

prefer_makemaker( [TRUE|FALSE] )

Returns or sets the Module::Build preference. If this is true, some of the methods preferentially return answers for Module::Build over MakeMaker when a distribution can use both systems. If both prefer_makemaker and prefer_module_build are true, then MakeMaker wins. =cut

prefer_module_build( [TRUE|FALSE] )

Returns or sets the Module::Build preference. If this is true, some of the methods preferentially return answers for Module::Build over MakeMaker when a distribution can use both systems. If both prefer_makemaker and prefer_module_build are true, then MakeMaker wins.

Questions about the distribution

build_files

Returns an hash reference of build files found in the distribution. The keys are the filenames of the build files. The values

preferred_build_file

Returns the build file that you should use, even if there is more than one. Right now this is simple:

1. In the single build file distributions, return that build file

2. If you've specified a preference with prefer_module_build or prefer_makemaker, use that.

3. If there is no preference (both are false), prefer Module::Build.

4. If no of those work, return nothing.

preferred_build_command

Returns the build command that you should use. This uses the logic of preferred_build_file. It returns the result of either perl_command or make_command.

build_file_paths

Returns an anonymous hash to the paths to the build files, based on the dist_dir argument to new and the return value of build_files. The keys are the file names and the values are the paths.

makefile_pl_path
build_pl_path
has_build_pl

Has the file name returned by build_pl.

has_makefile_pl

Has the file name returned by makefile_pl.

has_build_and_makefile

Has both the files returned by makefile_pl and build_pl.

make_command

Looks in %Config to see what perl discovered when someone built it if you can use a make variant to build the distribution.

build_command

Returns ./Build, the script that Build.PL should have created, if the distribution has a Build.PL. Otherwise it returns nothing.

perl_command

Returns the perl currently running. This is the perl that you would use to run the Makefile.PL or Build.PL.

build_commands

Returns a hash reference of the commands you can use to build the distribution. The keys are the commands, such as make or perl Build.PL.

uses_makemaker

Returns true if the distro uses ExtUtils::Makemaker.

uses_makemaker_only

Returns true if MakeMaker is the only build system. Knowing that can cut down on the logic quite a bit since you don't have to choose between possibilities or preferences.

makemaker_version

Returns the version of Makemaker installed for the perl running this code.

uses_module_build

Returns true if this distribution uses Module::Build. This means that it has a Build.PL and that the Build.PL actually uses Module::Build.

uses_module_build_only

Returns true if Module::Build is the only build system. Knowing that can cut down on the logic quite a bit since you don't have to choose between possibilities or preferences.

module_build_version

Returns the version of Module::Build install for perl running this code.

uses_module_install

Returns true if this distribution uses Module::Install.

uses_auto_install

Returns true if this distribution uses Module::Install and will use the auto_install feature.

This is a very simple test right now. If it finds the string auto_install in the build file, it returns true.

module_install_version

Returns the version of Module::Install.

uses_module_build_compat

Returns true if this distribution uses Module::Install::Compat and will use the create_makefile_pl feature.

This is a very simple test right now. If it finds the string create_makefile_pl in the build file, it returns true.

build_pl_wraps_makefile_pl

Returns true if Build.PL is a wrapper around Makefile.PL.

just_give_me_a_hash

Methods for strings

You may want to override or extend these, so they are methods.

makefile_pl

Returns the string used for the Makefile.PL filename. Seems stupid until you want to change it in a subclass, which you can do now that it's a method. :)

build_pl

Returns the string used for the Build.PL filename. Seems stupid until you want to change it in a subclass, which you can do now that it's a method. :)

makemaker_name

Returns the module name of Makemaker, which is ExtUtils::MakeMaker.

module_build_name

Return the string representing the name for Module::Build.

module_install_name

Return the string representing the name for Module::Install. By default this is inc::Module::Install.

module_install_dir

Returns the directory that contains Module::Install. This is the distribution directory because the module name is actually inc::Module::Install.

module_extractor_class

The name of the module that can get a list of used modules from a Perl file. By default this is Module::Extract::Use.

TO DO

Top

SEE ALSO

Top

SOURCE AVAILABILITY

Top

This source is in Github:

	git://github.com/briandfoy/distribution-guess-buildsystem.git

AUTHOR

Top

brian d foy, <bdfoy@cpan.org>

COPYRIGHT AND LICENSE

Top


Distribution-Guess-BuildSystem documentation Contained in the Distribution-Guess-BuildSystem distribution.
# $Id$
package Distribution::Guess::BuildSystem;
use strict;

use warnings;
no warnings;

use subs qw();
use vars qw($VERSION);

use Carp                  qw(carp);
use Config                qw(%Config);
use Cwd                   qw(cwd);
use File::Spec::Functions qw(catfile);

use Module::Extract::VERSION;

$VERSION = '0.12';

sub new
	{
	my %defaults = ( 
		dist_dir            => cwd(),
		prefer_module_build => 1,
		prefer_makemaker    => 0,		
		perl_binary         => $^X,
		);
	
	my( $class, %args ) = @_;
	
	bless { %defaults, %args }, $class;
	}

sub dist_dir
	{
	my( $self ) = shift;
	$self->_setting( 'dist_dir', @_ );
	}

sub perl_binary
	{
	my( $self ) = shift;
	$self->_setting( 'perl_binary', @_ );
	}

sub prefer_makemaker
	{
	my( $self ) = shift;
	$self->_setting( 'prefer_makemaker', @_ );
	}

sub prefer_module_build
	{
	my( $self ) = shift;
	$self->_setting( 'prefer_module_build', @_ );
	}

sub _setting
	{
	my( $self, $key, $value ) = @_;
	
	if( @_ == 3 ) {
		$self->{$key} = $value;
		}

	return $self->{$key};
	}
	
{
my @files = (
	[ qw( has_makefile_pl makefile_pl ) ],
	[ qw( has_build_pl    build_pl ) ],

	);
	
sub build_files
	{
	my %found;
	
	foreach my $pairs ( @files )
		{
		my( $check, $file ) = @$pairs;
		$found{ $_[0]->$file() } = $_[0]->$file() if $_[0]->$check()
		}
		
	return \%found;
	}

}

sub preferred_build_file
	{
	# preference doesn't matter in single build system cases
	return $_[0]->makefile_pl if $_[0]->uses_makemaker_only;
	return $_[0]->build_pl    if $_[0]->uses_module_build_only;

	# preference now matter
	return $_[0]->build_pl if( 
		$_[0]->prefer_module_build and $_[0]->uses_module_build );
	return $_[0]->makefile_pl if( 
		$_[0]->prefer_makemaker and $_[0]->uses_makemaker );

	# absence of preference
	return $_[0]->build_pl    if $_[0]->uses_module_build;
	return $_[0]->makefile_pl if $_[0]->uses_makemaker;
	
	# no build system?
	return;
	}

sub preferred_build_command
	{
	return $_[0]->build_command if $_[0]->preferred_build_file eq $_[0]->build_pl;
	return $_[0]->make_command if $_[0]->preferred_build_file eq $_[0]->makefile_pl;
	return;
	}
	
sub build_file_paths
	{
	my %paths;
	
	foreach my $file ( keys %{ $_[0]->build_files } )
		{
		$paths{$file} = File::Spec->catfile( $_[0]->dist_dir, $file );	
		}
		
	return \%paths;
	}

sub makefile_pl_path
	{
	return unless $_[0]->has_makefile_pl;
	
	File::Spec->catfile( $_[0]->dist_dir, $_[0]->makefile_pl );
	}

sub build_pl_path
	{
	return unless $_[0]->has_build_pl;
	
	File::Spec->catfile( $_[0]->dist_dir, $_[0]->build_pl );
	}
	
sub _has_file
	{
	my( $self, $file ) = @_;
	
	my $path = File::Spec->catfile(
		$self->dist_dir, $file
		);
	
	$self->{has}{$file} = $path if -e $path;
	$self->{has}{$file};
	}

sub has_build_pl { $_[0]->_has_file( $_[0]->build_pl )  }

sub has_makefile_pl { $_[0]->_has_file( $_[0]->makefile_pl )  }

sub has_build_and_makefile
	{
	$_[0]->has_build_pl 
		&& 
	$_[0]->has_makefile_pl
	}

sub make_command { $_[0]->has_makefile_pl ? $Config{make} : () }

sub build_command { $_[0]->has_build_pl ? './Build' : () }

sub perl_command { $_[0]->has_build_pl ? $_[0]->perl_binary : () }


sub build_commands
	{
	my %commands;
	
	$commands{ $_[0]->make_command } = 1 
		if $_[0]->has_makefile_pl;

	$commands{ $_[0]->perl_command . " " . $_[0]->build_pl } = 1 
		if $_[0]->has_build_pl;

	return \%commands;
	}

sub _get_modules
	{
	my( $self, $path ) = @_;
	my $extractor = $self->module_extractor_class->new;
	$extractor->get_modules( $path );	
	}
	
sub uses_makemaker
	{
	return unless $_[0]->has_makefile_pl;
	
	scalar grep { $_ eq $_[0]->makemaker_name } 
		$_[0]->_get_modules( $_[0]->makefile_pl_path )
	}

sub uses_makemaker_only
	{
	return unless $_[0]->has_makefile_pl;
	return if     $_[0]->has_build_pl;

	return 1;	
	}

sub makemaker_version
	{
	return unless $_[0]->uses_makemaker;
	
	my $version = $_[0]->_get_version( $_[0]->makemaker_name );
	}

sub _get_version
	{
	require Module::Extract::VERSION;
	
	my( $self, $module, @dirs ) = @_;
	
	@dirs = @INC unless @dirs;
	
	my $file = catfile( split /::/, $module ) . ".pm";
	
	foreach my $dir ( @dirs )
		{
		my $module = catfile( $dir, $file );
		next unless -e $module;
		
		return Module::Extract::VERSION->parse_version_safely( $module );
		}
		
	}
	
sub uses_module_build
	{
	return unless $_[0]->has_build_pl;

	scalar grep { $_ eq $_[0]->module_build_name } 
		$_[0]->_get_modules( $_[0]->build_pl_path );
	}

sub uses_module_build_only
	{
	return unless $_[0]->has_build_pl;
	return if     $_[0]->has_makefile_pl;

	return 1;	
	}

sub module_build_version
	{
	return unless $_[0]->uses_module_build;

	my $version = $_[0]->_get_version( $_[0]->module_build_name );
	}

sub uses_module_install
	{		
	return unless $_[0]->has_makefile_pl;

	scalar grep { $_ eq $_[0]->module_install_name } 
		$_[0]->_get_modules( $_[0]->makefile_pl_path )
	}

sub uses_auto_install
	{
	return unless $_[0]->has_makefile_pl && $_[0]->uses_module_install;
	
	$_[0]->_file_has_string( $_[0]->makefile_pl_path, 'auto_install' );
 	}

sub module_install_version
	{
	return unless $_[0]->uses_module_install;

	my $version = $_[0]->_get_version( 
		 $_[0]->module_install_name,  $_[0]->module_install_dir
		);
	}

sub uses_module_build_compat
	{
	return unless $_[0]->has_build_pl && $_[0]->uses_module_build;
	
	$_[0]->_file_has_string( $_[0]->build_pl_path, 'create_makefile_pl' );
	}

sub build_pl_wraps_makefile_pl
	{
	return unless $_[0]->has_build_pl && $_[0]->has_makefile_pl;
	
	$_[0]->_file_has_string( $_[0]->build_pl_path, 
		"Makefile.PL" );	
	}
	
sub _file_has_string
	{
	my $fh;
	unless( open $fh, "<", $_[1] )
		{
		carp "Could not open $_[1]: $!";
		return;
		}
		
	while( <$fh> ) { return 1 if /\Q$_[2]/ }
		
	return;
	}

{
my @methods = qw(
	dist_dir
	build_files
	build_file_paths
	makefile_pl_path
	build_pl_path
	has_build_pl
	has_makefile_pl
	has_build_and_makefile
	make_command
	perl_command
	build_commands
	uses_makemaker
	makemaker_version
	uses_module_build
	module_build_version
	uses_module_install
	uses_auto_install
	module_install_version
	uses_module_build_compat
	build_pl_wraps_makefile_pl
	);

sub just_give_me_a_hash
	{
	my %hash = ();
		
	foreach my $method ( @methods )
		{
		$hash{ $method } = $_[0]->$method();
		}
	
	return \%hash;
	}
}

sub makefile_pl { 'Makefile.PL' }

sub build_pl  { 'Build.PL' }

sub makemaker_name { 'ExtUtils::MakeMaker' }

sub module_build_name { 'Module::Build' }

sub module_install_name { 'inc::Module::Install' }

sub module_install_dir  { $_[0]->dist_dir }

sub module_extractor_class { 'Module::Extract::Use' }
BEGIN { require Module::Extract::Use }

1;