]> git.donarmstrong.com Git - debhelper.git/blob - Debian/Debhelper/Dh_Buildsystem_Bases.pm
ab24829b8eb3d6b768730f8b9b6d52fbc46455df
[debhelper.git] / Debian / Debhelper / Dh_Buildsystem_Bases.pm
1 # Defines base debhelper buildsystem class interface.
2 #
3 # Copyright: © 2008-2009 Modestas Vainius
4 # License: GPL-2+
5
6 package Debian::Debhelper::Dh_Buildsystem_Basic;
7
8 use Cwd;
9 use File::Spec;
10 use Debian::Debhelper::Dh_Lib;
11
12 # Build system name. Defaults to the last component of the package
13 # name. Do not override this method unless you know what you are
14 # doing.
15 sub NAME {
16         my $self = shift;
17         my $cls = ref($self) || $self;
18         return ($cls =~ m/^.+::([^:]+)$/) ? $1 : "[invalid package name]";
19 }
20
21 # Description of the build system to be shown to the users.
22 sub DESCRIPTION {
23         "basic debhelper build system class";
24 }
25
26 sub new {
27         my ($cls, $builddir) = @_;
28         my $self = bless({ builddir => $builddir }, $cls);
29         if (!defined($builddir) || $builddir eq ".") {
30                 $self->{builddir} = undef;
31         }
32         return $self;
33 }
34
35 # This instance method is called to check if the build system is capable
36 # to build a source package. Additional argument $action describes which
37 # operation the caller is going to perform first (either configure,
38 # build, test, install or clean). You must override this method for the
39 # build system module to be ever picked up automatically.
40 #
41 # This method is supposed to be called with source root directory being
42 # working directory. Use $self->get_buildpath($path) method to get full
43 # path to the files in the build directory.
44 sub is_buildable {
45         my $self=shift;
46         my ($action) = @_;
47         return 0;
48 }
49
50 # Derived class can call this method in its constructor
51 # to enforce in-source building even if the user
52 # requested otherwise.
53 sub enforce_in_source_building {
54         my $self=shift;
55         if ($self->{builddir}) {
56                 warning("warning: ".$self->NAME()." buildsystem does not support building outside-source. In-source build enforced.");
57                 $self->{builddir} = undef;
58         }
59 }
60
61 sub get_builddir {
62         my $self=shift;
63         return $self->{builddir};
64 }
65
66 sub get_buildpath {
67         my ($self, $path) = @_;
68         if ($self->get_builddir()) {
69                 return File::Spec->catfile($self->get_builddir(), $path);
70         }
71         else {
72                 return File::Spec->catfile('.', $path);
73         }
74 }
75
76 sub invoke_impl {
77         my $self=shift;
78         my $method=shift;
79
80         return $self->$method(@_);
81 }
82
83 # The instance methods below provide support for configuring,
84 # building, testing, install and cleaning source packages.
85 # These methods are wrappers around respective *_impl() methods
86 # which are supposed to do real buildsystem specific work. 
87
88 sub configure {
89         my $self=shift;
90         return $self->invoke_impl('configure_impl', @_);
91 }
92
93 sub build {
94         my $self=shift;
95         return $self->invoke_impl('build_impl', @_);
96 }
97
98 sub test {
99         my $self=shift;
100         return $self->invoke_impl('test_impl', @_);
101 }
102
103 sub install {
104         my $self=shift;
105         return $self->invoke_impl('install_impl', @_);
106 }
107
108 sub clean {
109         my $self=shift;
110         return $self->invoke_impl('clean_impl', @_);
111 }
112
113 # The instance methods below should be overriden by derived classes
114 # to implement buildsystem specific actions needed to build the
115 # source. Arbitary number of custom action arguments might be passed.
116 # Default implementations do nothing.
117
118 sub configure_impl {
119         my $self=shift;
120         1;
121 }
122
123 sub build_impl {
124         my $self=shift;
125         1;
126 }
127
128 sub test_impl {
129         my $self=shift;
130         1;
131 }
132
133 # destdir parameter specifies where to install files.
134 sub install_impl {
135         my $self=shift;
136         my $destdir=shift;
137         1;
138 }
139
140 sub clean_impl {
141         my $self=shift;
142         1;
143 }
144
145 package Debian::Debhelper::Dh_Buildsystem_Option;
146
147 use Debian::Debhelper::Dh_Buildsystems qw( DEFAULT_BUILD_DIRECTORY );
148 use base 'Debian::Debhelper::Dh_Buildsystem_Basic';
149
150 # Derived class can call this method in its constructor to enforce
151 # outside-source building even if the user didn't request it.
152 sub enforce_outside_source_building {
153         my ($self, $builddir) = @_;
154         if (!defined $self->{builddir}) {
155                 $self->{builddir} = ($builddir && $builddir ne ".") ? $builddir : DEFAULT_BUILD_DIRECTORY;
156         }
157 }
158
159 # Constructs option to be passed to the source package buildsystem to
160 # change build directory. Returns nothing by default.
161 sub get_builddir_option {
162         my $self=shift;
163         return;
164 }
165
166 sub invoke_impl {
167         my $self=shift;
168         my $method=shift;
169
170         if ($self->get_builddir_option()) {
171                 return $self->SUPER::invoke_impl($method, $self->get_builddir_option(), @_);
172         }
173         else {
174                 return $self->SUPER::invoke_impl($method, @_);
175         }
176 }
177
178 package Debian::Debhelper::Dh_Buildsystem_Chdir;
179
180 use Cwd;
181 use File::Spec;
182 use Debian::Debhelper::Dh_Lib;
183 use base 'Debian::Debhelper::Dh_Buildsystem_Option';
184
185 sub new {
186         my $cls=shift;
187         my $self=$cls->SUPER::new(@_);
188         $self->{topdir} = '.';
189         return $self;
190 }
191
192 sub _cd {
193         my ($cls, $dir) = @_;
194         verbose_print("cd '$dir'");
195         if (! $dh{NO_ACT}) {
196                 chdir $dir or error("error: unable to chdir to $dir");
197         }
198 }
199
200 sub _mkdir {
201         my ($cls, $dir) = @_;
202         if (-e $dir && ! -d $dir) {
203                 error("error: unable to create '$dir': object already exists and is not a directory");
204         }
205         else {
206                 verbose_print("mkdir '$dir'");
207                 if (! $dh{NO_ACT}) {
208                         mkdir($dir, 0755) or error("error: unable to create '$dir': $!");
209                 }
210                 return 1;
211         }
212         return 0;
213 }
214
215 sub get_builddir {
216         my $self=shift;
217         if (defined $self->{builddir} && $self->{topdir} ne ".") {
218                 return File::Spec->catfile($self->{topdir}, $self->{builddir});
219         }
220         return $self->SUPER::get_builddir();
221 }
222
223 sub get_topdir {
224         my $self=shift;
225         if ($self->{topdir} ne ".") {
226                 return File::Spec->abs2rel($self->{topdir});
227         }
228         return $self->{topdir};
229 }
230
231 sub get_toppath {
232         my ($self, $path) = @_;
233         return File::Spec->catfile($self->get_topdir(), $path);
234 }
235
236 sub cd {
237         my $self = shift;
238         if ($self->get_builddir() && $self->{topdir} ne ".") {
239                 $self->_cd($self->get_topdir());
240                 $self->{topdir} = ".";
241                 return 1;
242         }
243         return 0;
244 }
245
246 sub cd_to_builddir {
247         my $self = shift;
248         if ($self->get_builddir() && $self->{topdir} eq ".") {
249                 $self->{topdir} = getcwd();
250                 $self->_cd($self->get_builddir());
251                 return 1;
252         }
253         return 0;
254 }
255
256 sub exec_in_topdir {
257         my $self=shift;
258         my $sub=shift;
259         my $ret;
260
261         if ($self->get_topdir() ne ".") {
262                 $self->cd();
263                 $ret = &$sub(@_);
264                 $self->cd_to_builddir();
265         }
266         else {
267                 $ret = &$sub(@_);
268         }
269         return $ret;
270 }
271
272 # *_impl() is run with current working directory changed to the
273 # build directory if requested.
274 sub invoke_impl {
275         my $self=shift;
276         my $method=shift;
277         my $ret;
278
279         $self->cd_to_builddir();
280         $ret = $self->$method(@_);
281         $self->cd();
282         return $ret;
283 }
284
285 sub configure {
286         my $self=shift;
287         if ($self->get_builddir()) {
288                 $self->_mkdir($self->get_builddir());
289         }
290         return $self->SUPER::configure(@_);
291 }
292
293 # If outside-source tree building is done, whole build directory
294 # gets wiped out by default. Otherwise, clean_impl() is called.
295 sub clean {
296         my $self=shift;
297         if ($self->get_builddir()) {
298                 if (-d $self->get_builddir()) {
299                         $self->cd();
300                         doit("rm", "-rf", $self->get_builddir());
301                         return 1;
302                 }
303         } else {
304                 return $self->SUPER::clean(@_);
305         }
306 }
307
308 1;