X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Debian%2FDebhelper%2FDh_Buildsystems.pm;h=0a51a4d228ea6fa81cf5df75d8640d8e82f358a1;hb=e7f5f747e04176bda1d0e353eee3e0b5445b70f8;hp=6774511c058e6cc49481124b953162cb660a4bea;hpb=dee85c67c6730518bc8f7dc29e1d557a9f2718af;p=debhelper.git diff --git a/Debian/Debhelper/Dh_Buildsystems.pm b/Debian/Debhelper/Dh_Buildsystems.pm index 6774511..0a51a4d 100644 --- a/Debian/Debhelper/Dh_Buildsystems.pm +++ b/Debian/Debhelper/Dh_Buildsystems.pm @@ -1,5 +1,5 @@ -# A module for loading and managing debhelper buildsystem plugins. -# This module is intended to be used by all dh_auto_* helper commands. +# A module for loading and managing debhelper build system classes. +# This module is intended to be used by all dh_auto_* programs. # # Copyright: © 2009 Modestas Vainius # License: GPL-2+ @@ -9,37 +9,34 @@ package Debian::Debhelper::Dh_Buildsystems; use strict; use warnings; use Debian::Debhelper::Dh_Lib; +use File::Spec; use base 'Exporter'; -our @EXPORT=qw(&buildsystems_init &buildsystems_do &load_buildsystem); - -# XXX JEH as noted, this has to match historical order for back-compat -# XXX MDX Current dh_auto_* look like: -# configure: autotools, perl_makemaker, perl_build -# build: makefile, python_distutils, perl_build -# test: makefile, perl_build -# install: makefile (with perl_makermaker) hack, python_distutils, perl_build -# clean: makefile, python_distutils, perl_build -# So historical @BUILDSYSTEMS order (as per autodetection, see -# is_auto_buildable() of the respective classes): -# autotools (+configure; the rest - next class) -# python_distutils (+build +install +clean; the rest - next class) -# perl_makemaker (+configure +install (special hack); the rest - next class) -# makefile (+build +test +install +clean; configure - next class) -# perl_build (handles everything) -# XXX JEH I think that makes sense.. +our @EXPORT=qw(&buildsystems_init &buildsystems_do &load_buildsystem &load_all_buildsystems); + +use constant BUILD_STEPS => qw(configure build test install clean); # Historical order must be kept for backwards compatibility. New -# buildsystems MUST be added to the END of the list. +# build systems MUST be added to the END of the list. our @BUILDSYSTEMS = ( - "autotools", - "python_distutils", - "perl_makemaker", - "makefile", - "perl_build", - "cmake", + "autoconf", + (! compat(7) ? "perl_build" : ()), + "perl_makemaker", + "makefile", + "python_distutils", + (compat(7) ? "perl_build" : ()), + "cmake", + "ant", + "qmake", + "qmake_qt4", ); +my $opt_buildsys; +my $opt_sourcedir; +my $opt_builddir; +my $opt_list; +my $opt_parallel; + sub create_buildsystem_instance { my $system=shift; my %bsopts=@_; @@ -47,96 +44,185 @@ sub create_buildsystem_instance { eval "use $module"; if ($@) { - error("unable to load buildsystem class '$system': $@"); + error("unable to load build system class '$system': $@"); } - if (!exists $bsopts{builddir} && exists $dh{BUILDDIR}) { - $bsopts{builddir} = $dh{BUILDDIR}; + if (!exists $bsopts{builddir} && defined $opt_builddir) { + $bsopts{builddir} = ($opt_builddir eq "") ? undef : $opt_builddir; + } + if (!exists $bsopts{sourcedir} && defined $opt_sourcedir) { + $bsopts{sourcedir} = ($opt_sourcedir eq "") ? undef : $opt_sourcedir; + } + if (!exists $bsopts{parallel}) { + $bsopts{parallel} = $opt_parallel; } return $module->new(%bsopts); } +# Autoselect a build system from the list of instances +sub autoselect_buildsystem { + my $step=shift; + my $selected; + my $selected_level = 0; + + foreach my $inst (@_) { + # Only derived (i.e. more specific) build system can be + # considered beyond the currently selected one. + next if defined $selected && !$inst->isa(ref $selected); + + # If the build system says it is auto-buildable at the current + # step and it can provide more specific information about its + # status than its parent (if any), auto-select it. + my $level = $inst->check_auto_buildable($step); + if ($level > $selected_level) { + $selected = $inst; + $selected_level = $level; + } + } + return $selected; +} + +# Similar to create_build system_instance(), but it attempts to autoselect +# a build system if none was specified. In case autoselection fails, undef +# is returned. sub load_buildsystem { - my ($action, $system)=@_; + my $system=shift; + my $step=shift; if (defined $system) { - my $inst = create_buildsystem_instance($system); - verbose_print("Selected buildsystem (specified): ".$inst->NAME()); + my $inst = create_buildsystem_instance($system, @_); return $inst; } else { # Try to determine build system automatically - for $system (@BUILDSYSTEMS) { - my $inst = create_buildsystem_instance($system, is_auto=>1); - if ($inst->is_auto_buildable($action)) { - verbose_print("Selected buildsystem (auto): ". $inst->NAME()); - return $inst; - } + my @buildsystems; + foreach $system (@BUILDSYSTEMS) { + push @buildsystems, create_buildsystem_instance($system, @_); } + return autoselect_buildsystem($step, @buildsystems); } - return; } -sub list_buildsystems { - for my $system (@BUILDSYSTEMS) { - my $inst = create_buildsystem_instance($system); - printf("%s - %s.\n", $inst->NAME(), $inst->DESCRIPTION()); +sub load_all_buildsystems { + my $incs=shift || \@INC; + my (%buildsystems, @buildsystems); + + foreach my $inc (@$incs) { + my $path = File::Spec->catdir($inc, "Debian/Debhelper/Buildsystem"); + if (-d $path) { + foreach my $module_path (glob "$path/*.pm") { + my $name = basename($module_path); + $name =~ s/\.pm$//; + next if exists $buildsystems{$name}; + $buildsystems{$name} = create_buildsystem_instance($name, @_); + } + } + } + + # Standard debhelper build systems first + foreach my $name (@BUILDSYSTEMS) { + error("standard debhelper build system '$name' could not be found/loaded") + if not exists $buildsystems{$name}; + push @buildsystems, $buildsystems{$name}; + delete $buildsystems{$name}; + } + + # The rest are 3rd party build systems + foreach my $name (keys %buildsystems) { + my $inst = $buildsystems{$name}; + $inst->{thirdparty} = 1; + push @buildsystems, $inst; } + + return @buildsystems; } sub buildsystems_init { my %args=@_; - # TODO: Not documented in the manual pages yet. - # Initialize options from environment variables - # XXX JEH I think these should be my variables, they are only used - # inside this one file so putting them in the global %dh hash seems - # unnecessary. - if (exists $ENV{DH_AUTO_BUILDDIRECTORY}) { - $dh{BUILDDIR} = $ENV{DH_AUTO_BUILDDIRECTORY}; - } - if (exists $ENV{DH_AUTO_BUILDSYSTEM}) { - $dh{BUILDSYS} = $ENV{DH_AUTO_BUILDSYSTEM}; - } + my $max_parallel=1; # Available command line options - my $list_bs = sub { list_buildsystems(); exit 0 }; - my $set_builddir = sub { $dh{BUILDDIR} = $_[1] }; my %options = ( - "b:s" => $set_builddir, - "build-directory:s" => $set_builddir, - "builddirectory:s" => $set_builddir, + "D=s" => \$opt_sourcedir, + "sourcedirectory=s" => \$opt_sourcedir, + + "B:s" => \$opt_builddir, + "builddirectory:s" => \$opt_builddir, - "m=s" => \$dh{BUILDSYS}, - # XXX JEH Let's only keep one spelling of this. - "build-system=s" => \$dh{BUILDSYS}, - "buildsystem=s" => \$dh{BUILDSYS}, + "S=s" => \$opt_buildsys, + "buildsystem=s" => \$opt_buildsys, - "l" => $list_bs, - "--list" => $list_bs, + "l" => \$opt_list, + "list" => \$opt_list, + + "parallel" => sub { $max_parallel = -1 }, + "max-parallel=i" => \$max_parallel, ); - map { $args{options}{$_} = $options{$_} } keys(%options); + $args{options}{$_} = $options{$_} foreach keys(%options); Debian::Debhelper::Dh_Lib::init(%args); + Debian::Debhelper::Dh_Lib::set_buildflags(); + set_parallel($max_parallel); +} + +sub set_parallel { + my $max=shift; + + # Get number of processes from parallel=n option, limiting it + # with $max if needed + $opt_parallel=get_buildoption("parallel") || 1; + + if ($max > 0 && $opt_parallel > $max) { + $opt_parallel = $max; + } +} + +sub buildsystems_list { + my $step=shift; + + my @buildsystems = load_all_buildsystems(); + my $auto = autoselect_buildsystem($step, grep { ! $_->{thirdparty} } @buildsystems); + my $specified; + + # List build systems (including auto and specified status) + foreach my $inst (@buildsystems) { + if (! defined $specified && defined $opt_buildsys && $opt_buildsys eq $inst->NAME()) { + $specified = $inst; + } + printf("%-20s %s", $inst->NAME(), $inst->DESCRIPTION()); + print " [3rd party]" if $inst->{thirdparty}; + print "\n"; + } + print "\n"; + print "Auto-selected: ", $auto->NAME(), "\n" if defined $auto; + print "Specified: ", $specified->NAME(), "\n" if defined $specified; + print "No system auto-selected or specified\n" + if ! defined $auto && ! defined $specified; } sub buildsystems_do { - my $action=shift; + my $step=shift; + + if (!defined $step) { + $step = basename($0); + $step =~ s/^dh_auto_//; + } - if (!defined $action) { - $action = basename($0); - $action =~ s/^dh_auto_//; + if (grep(/^\Q$step\E$/, BUILD_STEPS) == 0) { + error("unrecognized build step: " . $step); } - if (grep(/^\Q$action\E$/, qw{configure build test install clean}) == 0) { - error("unrecognized auto action: ".basename($0)); + if ($opt_list) { + buildsystems_list($step); + exit 0; } - my $buildsystem = load_buildsystem($action, $dh{BUILDSYS}); + my $buildsystem = load_buildsystem($opt_buildsys, $step); if (defined $buildsystem) { - $buildsystem->pre_action($action); - $buildsystem->$action(@_, @{$dh{U_PARAMS}}); - $buildsystem->post_action($action); + $buildsystem->pre_building_step($step); + $buildsystem->$step(@_, @{$dh{U_PARAMS}}); + $buildsystem->post_building_step($step); } return 0; } -1; +1