X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Debian%2FDebhelper%2FBuildsystem.pm;h=7f7465a42840171f1b73c34754da47d0a5376196;hb=758ce0bb1fbb505aa05f2dd3ac85d7d084b94312;hp=c63f8153b5358457f7d59c7dfea7965e3933d39e;hpb=b4a1bdaa371033df1f0c1755652e8e472982ff0d;p=debhelper.git diff --git a/Debian/Debhelper/Buildsystem.pm b/Debian/Debhelper/Buildsystem.pm index c63f815..7f7465a 100644 --- a/Debian/Debhelper/Buildsystem.pm +++ b/Debian/Debhelper/Buildsystem.pm @@ -47,7 +47,9 @@ sub DEFAULT_BUILD_DIRECTORY { # specified or empty, defaults to the current directory. # - builddir - specifies build directory to use. Path is relative to the # current (top) directory. If undef or empty, -# DEFAULT_BUILD_DIRECTORY directory will be used. +# DEFAULT_BUILD_DIRECTORY directory will be used. +# - parallel - max number of parallel processes to be spawned for building +# sources (-1 = unlimited; 1 = no parallel) # Derived class can override the constructor to initialize common object # parameters. Do NOT use constructor to execute commands or otherwise # configure/setup build environment. There is absolutely no guarantee the @@ -57,20 +59,24 @@ sub new { my ($class, %opts)=@_; my $this = bless({ sourcedir => '.', - builddir => undef, }, $class); + builddir => undef, + parallel => undef, + cwd => Cwd::getcwd() }, $class); if (exists $opts{sourcedir}) { # Get relative sourcedir abs_path (without symlinks) - my $curdir = Cwd::getcwd(); my $abspath = Cwd::abs_path($opts{sourcedir}); - if (! -d $abspath || $abspath !~ /^\Q$curdir\E/) { + if (! -d $abspath || $abspath !~ /^\Q$this->{cwd}\E/) { error("invalid or non-existing path to the source directory: ".$opts{sourcedir}); } - $this->{sourcedir} = File::Spec->abs2rel($abspath, $curdir); + $this->{sourcedir} = File::Spec->abs2rel($abspath, $this->{cwd}); } if (exists $opts{builddir}) { $this->_set_builddir($opts{builddir}); } + if (defined $opts{parallel}) { + $this->{parallel} = $opts{parallel}; + } return $this; } @@ -79,31 +85,51 @@ sub new { # unset the build directory. sub _set_builddir { my $this=shift; - my $builddir=shift; - $this->{builddir} = ($builddir) ? $builddir : $this->DEFAULT_BUILD_DIRECTORY; - - # Canonicalize. If build directory ends up the same as source directory, drop it - if (defined $this->{builddir}) { - $this->{builddir} = $this->_canonpath($this->{builddir}); - if ($this->{builddir} eq $this->get_sourcedir()) { - $this->{builddir} = undef; + my $builddir=shift || $this->DEFAULT_BUILD_DIRECTORY; + + if (defined $builddir) { + $builddir = $this->canonpath($builddir); # Canonicalize + + # Sanitize $builddir + if ($builddir =~ m#^\.\./#) { + # We can't handle those as relative. Make them absolute + $builddir = File::Spec->catdir($this->{cwd}, $builddir); + } + elsif ($builddir =~ /\Q$this->{cwd}\E/) { + $builddir = File::Spec::abs2rel($builddir, $this->{cwd}); + } + + # If build directory ends up the same as source directory, drop it + if ($builddir eq $this->get_sourcedir()) { + $builddir = undef; } } + $this->{builddir} = $builddir; + return $builddir; } # This instance method is called to check if the build system is able -# to auto build a source package. Additional argument $step describes -# which operation the caller is going to perform (either configure, -# build, test, install or clean). You must override this method for the -# build system module to be ever picked up automatically. This method is -# used in conjuction with @Dh_Buildsystems::BUILDSYSTEMS. +# to build a source package. It will be called during build +# system auto-selection process inside the root directory of the debian +# source package. Current build step will be passed as an additional +# argument. The value returned must be 0 if the source is not buildable +# or a positive integer otherwise. # -# This method is supposed to be called inside the source root directory. -# Use $this->get_buildpath($path) method to get full path to the files -# in the build directory. +# Generally, it is enough to look for invariant unique build system +# files shipped with clean source to determine if the source might +# be buildable or not. However, if the build system enhances (i.e. +# derives) from the other auto-buildable build system, this method +# may also check if the source has already been built with this build +# system partitially by looking for temporary files or other common +# results the build system produces during the build process. The +# latter checks must be unique to the current build system and must +# be very unlikely to be true for either its parent or other build +# systems. If it is determined that the source has already built +# partitially with this build system, the value returned must be +# greater than the one of the SUPER call. sub check_auto_buildable { my $this=shift; - my ($step) = @_; + my ($step)=@_; return 0; } @@ -117,17 +143,17 @@ sub enforce_in_source_building { } } -# Derived class can call this method in its constructor to enforce -# out of source building even if the user didn't request it. However, -# if 'builddir' named parameter is passed, accept its value as the -# build directory even if it matches the source directory (meaning out -# of source is only prefered to in source, not enforced). -sub enforce_out_of_source_building { +# Derived class can call this method in its constructor to *prefer* +# out of source building. Unless build directory has already been +# specified building will proceed in the DEFAULT_BUILD_DIRECTORY or +# the one specified in the 'builddir' named parameter (which may +# match the source directory). Typically you should pass @_ from +# the constructor to this call. +sub prefer_out_of_source_building { my $this=shift; my %args=@_; if (!defined $this->get_builddir()) { - $this->_set_builddir($args{builddir}); - if (!defined $this->get_builddir() && !$args{builddir}) { + if (!$this->_set_builddir($args{builddir}) && !$args{builddir}) { # If we are here, DEFAULT_BUILD_DIRECTORY matches # the source directory, building might fail. error("default build directory is the same as the source directory." . @@ -139,7 +165,7 @@ sub enforce_out_of_source_building { # Enhanced version of File::Spec::canonpath. It collapses .. # too so it may return invalid path if symlinks are involved. # On the other hand, it does not need for the path to exist. -sub _canonpath { +sub canonpath { my ($this, $path)=@_; my @canon; my $back=0; @@ -157,16 +183,25 @@ sub _canonpath { return (@canon + $back > 0) ? join('/', ('..')x$back, @canon) : '.'; } -# Given both $path and $base are relative to the same directory, -# converts and returns path of $path being relative the $base. +# Given both $path and $base are relative to the $root, converts and +# returns path of $path being relative to the $base. If either $path or +# $base is absolute, returns another $path (converted to) absolute. sub _rel2rel { my ($this, $path, $base, $root)=@_; - $root = "/tmp" if !defined $root; - - return File::Spec->abs2rel( - File::Spec->rel2abs($path, $root), - File::Spec->rel2abs($base, $root) - ); + $root = $this->{cwd} unless defined $root; + + if (File::Spec->file_name_is_absolute($path)) { + return $path; + } + elsif (File::Spec->file_name_is_absolute($base)) { + return File::Spec->rel2abs($path, $root); + } + else { + return File::Spec->abs2rel( + File::Spec->rel2abs($path, $root), + File::Spec->rel2abs($base, $root) + ); + } } # Get path to the source directory @@ -223,6 +258,11 @@ sub get_source_rel2builddir { return $dir; } +sub get_parallel { + my $this=shift; + return $this->{parallel}; +} + # When given a relative path to the build directory, converts it # to the path that is relative to the source directory. If $path is # not given, returns a path to the build directory that is relative @@ -264,10 +304,9 @@ sub doit_in_sourcedir { my $this=shift; if ($this->get_sourcedir() ne '.') { my $sourcedir = $this->get_sourcedir(); - my $curdir = Cwd::getcwd(); $this->_cd($sourcedir); doit(@_); - $this->_cd($this->_rel2rel($curdir, $sourcedir, $curdir)); + $this->_cd($this->_rel2rel($this->{cwd}, $sourcedir)); } else { doit(@_); @@ -282,10 +321,9 @@ sub doit_in_builddir { my $this=shift; if ($this->get_buildpath() ne '.') { my $buildpath = $this->get_buildpath(); - my $curdir = Cwd::getcwd(); $this->_cd($buildpath); doit(@_); - $this->_cd($this->_rel2rel($curdir, $buildpath, $curdir)); + $this->_cd($this->_rel2rel($this->{cwd}, $buildpath)); } else { doit(@_); @@ -302,17 +340,21 @@ sub rmdir_builddir { my $only_empty=shift; if ($this->get_builddir()) { my $buildpath = $this->get_buildpath(); - if (-d $buildpath && ! $dh{NO_ACT}) { - my @spdir = File::Spec->splitdir($this->get_build_rel2sourcedir()); + if (-d $buildpath) { + my @dir = File::Spec->splitdir($this->get_build_rel2sourcedir()); my $peek; - if (!$only_empty) { + if (not $only_empty) { doit("rm", "-rf", $buildpath); - pop @spdir; + pop @dir; } - # If build directory had 2 or more levels, delete empty - # parent directories until the source directory level. - while (($peek=pop(@spdir)) && $peek ne '.' && $peek ne '..') { - last if ! rmdir($this->get_sourcepath(File::Spec->catdir(@spdir, $peek))); + # If build directory is relative and had 2 or more levels, delete + # empty parent directories until the source or top directory level. + if (not File::Spec->file_name_is_absolute($buildpath)) { + while (($peek=pop @dir) && $peek ne '.' && $peek ne '..') { + my $dir = $this->get_sourcepath(File::Spec->catdir(@dir, $peek)); + doit("rmdir", "--ignore-fail-on-non-empty", $dir); + last if -d $dir; + } } } return 1;