File Coverage

blib/lib/KIF/Build.pm
Criterion Covered Total %
statement 21 176 11.9
branch 0 84 0.0
condition 0 3 0.0
subroutine 7 30 23.3
pod 0 20 0.0
total 28 313 8.9


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             #
3             # Revision History:
4             #
5             # 26-Nov-2002 Dick Munroe (munroe@csworks.com)
6             # Initial version created.
7             # Save and restore the configuration files around the
8             # running of doClean.
9             # Make doClean issue a distclean to guarantee that things
10             # will get built properly.
11             #
12             # 03-Dec-2002 Dick Munroe (munroe@csworks.com)
13             # Copy autoconf.h as well as .config when saving configuration
14             # files.
15             #
16             # 18-May-2003 Dick Munroe (munroe@csworks.com)
17             # Make sure package variables don't leak.
18             #
19             # 19-May-2003 Dick Munroe (munroe@csworks.com)
20             # Use Carp.
21             # oldconfig needs to be run after distclean all the time.
22             # Isolate kif related classes in a KIF namespace.
23             # Change variable names to elminate warnings.
24             #
25             # 20-May-2003 Dick Munroe (munroe@csworks.com)
26             # If a initrd file exists in the boot configuration,
27             # then get it out of the way running mkinitrd.
28             #
29              
30             package KIF::Build ;
31              
32 1     1   562 use vars qw($VERSION @ISA) ;
  1         2  
  1         60  
33              
34             our $VERSION = "1.04" ;
35             our @ISA = qw(
36             ) ;
37              
38 1     1   4 use strict ;
  1         1  
  1         23  
39              
40 1     1   4 use Carp ;
  1         3  
  1         54  
41 1     1   5 use File::Basename ;
  1         1  
  1         44  
42 1     1   5 use File::Copy ;
  1         16  
  1         82  
43 1     1   748 use File::stat ;
  1         7853  
  1         7  
44 1     1   75 use FileHandle ;
  1         2  
  1         8  
45              
46             our $theBuildDirectory = undef ;
47             our $theLogFile = undef ;
48             our $theReleaseTag = undef ;
49             our $theTestFlag = undef ;
50             our $theVerboseFlag = undef ;
51              
52             sub new
53             {
54 0     0 0   my $thePackage = shift ;
55 0           my %theArguments = @_ ;
56              
57 0           my $theObject = bless
58             {
59             bootloader=>undef,
60             logFileHandle=>undef,
61             space=>undef
62             }, $thePackage ;
63              
64 0 0         if (defined($theArguments{'directory'}))
65             {
66 0 0         chdir $theArguments{'directory'} or croak "Can't change to directory $theArguments{'directory'}: $!" ;
67             } ;
68              
69 0           $theObject->logFile($theArguments{'log'}) ;
70              
71 0           $theObject->verboseFlag($theArguments{'verbose'}) ;
72              
73 0           $theObject->testFlag($theArguments{'test'}) ;
74              
75 0           $theObject->buildDirectory(`pwd`) ;
76              
77 0           $theObject->_buildReleaseTag() ;
78              
79 0           $theObject->space($theObject->_calculateSpace()) ;
80              
81 0           return $theObject ;
82             } ;
83              
84             sub bootloader
85             {
86 0     0 0   my $theObject = shift ;
87              
88 0 0         $theObject->{'bootloader'} = $_[0] if (@_) ;
89              
90 0           return $theObject->{'bootloader'} ;
91             } ;
92              
93             sub buildDirectory
94             {
95 0     0 0   my $theObject = shift ;
96              
97 0 0         $theBuildDirectory = $_[0] if (@_) ;
98              
99 0           chomp($theBuildDirectory) ;
100              
101 0           return $theBuildDirectory ;
102             } ;
103              
104             sub logFile
105             {
106 0     0 0   my $theObject = shift ;
107              
108 0 0         if (@_)
109             {
110 0           $theLogFile = $_[0] ;
111 0 0         if (defined($theLogFile))
112             {
113 0 0         $theObject->{'logFileHandle'} = new FileHandle "> $theLogFile" or croak "Can't open log file: $theLogFile" ;
114             } ;
115             } ;
116              
117 0           return $theLogFile ;
118             } ;
119              
120             sub releaseTag
121             {
122 0     0 0   my $theObject = shift ;
123              
124 0 0         $theReleaseTag = $_[0] if (@_) ;
125              
126 0           return $theReleaseTag ;
127             } ;
128              
129             sub space
130             {
131 0     0 0   my $theObject = shift ;
132              
133 0 0         $theObject->{'space'} = $_[0] if (@_) ;
134              
135 0           return $theObject->{'space'} ;
136             } ;
137              
138             sub testFlag
139             {
140 0     0 0   my $theObject = shift ;
141              
142 0 0         $theTestFlag = $_[0] if (@_) ;
143              
144 0           return $theTestFlag ;
145             } ;
146              
147             sub verboseFlag
148             {
149 0     0 0   my $theObject = shift ;
150              
151 0 0         $theVerboseFlag = $_[0] if (@_) ;
152              
153 0           return $theVerboseFlag ;
154             } ;
155              
156             sub _buildReleaseTag
157             {
158 0     0     my $theObject = shift ;
159              
160 0           my $theFileHandle = new FileHandle "< Makefile" ;
161              
162 0 0         croak "Can't open $theBuildDirectory/Makefile" if (!defined($theFileHandle)) ;
163              
164 0           my $theMakefile = eval { my @theFile = $theFileHandle->getlines() ; join '',@theFile ; } ;
  0            
  0            
165              
166 0 0         croak "No VERSION in $theBuildDirectory/Makefile" if ($theMakefile !~ m/^[ \t]*VERSION[ \t]*=[ \t]*([^ \t\n]*)/m) ;
167              
168 0           my $theVersion = $1 ;
169              
170 0 0         croak "No PATCHLEVEL in $theBuildDirectory/Makefile" if ($theMakefile !~ m/^[ \t]*PATCHLEVEL[ \t]*=[ \t]*([^ \t\n]*)/m) ;
171              
172 0           my $thePatch = $1 ;
173              
174 0 0         croak "No SUBLEVEL in $theBuildDirectory/Makefile" if ($theMakefile !~ m/^[ \t]*SUBLEVEL[ \t]*=[ \t]*([^ \t\n]*)/m) ;
175              
176 0           my $theSublevel = $1 ;
177              
178 0 0         croak "No EXTRAVERSION in $theBuildDirectory/Makefile" if ($theMakefile !~ m/^[ \t]*EXTRAVERSION[ \t]*=[ \t]*([^ \t\n]*)/m) ;
179              
180 0           my $theKernelRelease = $1 ;
181            
182 0           undef $theFileHandle ;
183              
184 0           $theObject->releaseTag("$theVersion.$thePatch.$theSublevel$theKernelRelease") ;
185             } ;
186              
187             sub _calculateSpace
188             {
189 0     0     my ($theObject, $theDirectory) = @_ ;
190              
191 0 0         $theDirectory = '.' if (!$theDirectory) ;
192              
193 0           my $theSpace = (split /\s+/,(split /\n/,`df -mP $theDirectory`)[1])[3] ;
194              
195 0           $theObject->_print("Space: $theDirectory => $theSpace\n", 3) ;
196              
197 0           return $theSpace ;
198             } ;
199              
200             sub _print
201             {
202 0     0     my ($theObject, $theString, $theLevel) = @_ ;
203              
204 0 0         print $theString if ($theObject->verboseFlag() >= $theLevel) ;
205              
206 0 0         $theObject->{'logFileHandle'}->print($theString) if (defined($theObject->{'logFileHandle'})) ;
207             } ;
208              
209             sub run
210             {
211 0     0 0   my ($theObject, $theCommand) = @_ ;
212              
213 0           $theObject->_print("$theCommand\n", 1) ;
214              
215 0 0         return if ($theObject->testFlag()) ;
216              
217 0 0         open theReadHandle, $theCommand . " 2>&1 |" or croak "Can't fork: $!" ;
218              
219 0           while ()
220             {
221 0           $theObject->_print($_, 2) ;
222             } ;
223              
224 0 0         close theReadHandle or croak "Can't run $theCommand: $!" ;
225             } ;
226              
227             #
228             # Check all the miscellaneous bits and pieces of the build environment
229             # to make sure they're sane before beginning.
230             #
231              
232             sub validate
233             {
234 0     0 0   my $theObject = shift ;
235              
236 0 0 0       croak "/boot/vmlinux must be a link" if ((-e "/boot/vmlinux") && (!-l "/boot/vmlinux")) ;
237             } ;
238              
239             sub doDependencies
240             {
241 0     0 0   my $theObject = shift ;
242              
243 0           $theObject->run("make dep") ;
244              
245 0           $theObject->space($theObject->_calculateSpace()) ;
246             } ;
247              
248             sub doClean
249             {
250 0     0 0   my $theObject = shift ;
251              
252 0           my $theBuildDirectory ;
253             my $theReleaseTag ;
254              
255 0           my @theFileList = (".config") ;
256 0           my $theIndex ;
257              
258 0           my $theBuildDirectoryXXX = $theObject->buildDirectory() ;
259 0           my $theReleaseTagXXX = $theObject->releaseTag() ;
260              
261 0           for ($theIndex = 0; $theIndex < scalar(@theFileList); $theIndex++)
262             {
263 0           $_ = $theBuildDirectoryXXX . '/' . $theFileList[$theIndex] ;
264              
265 0 0         if (-e $_)
266             {
267             #
268             # Save the current configuration, if any.
269             #
270              
271 0 0         move($_, '/tmp/' . basename($_) . "-$theReleaseTagXXX") if (!$theObject->testFlag()) ;
272              
273 0           $theObject->_print("Moved $_ => /tmp/" . basename($_) . "-$theReleaseTagXXX\n", 1) ;
274             } ;
275             } ;
276              
277 0           $theObject->run("make distclean") ;
278              
279 0           for ($theIndex = 0; $theIndex < scalar(@theFileList); $theIndex++)
280             {
281 0           $_ = '/tmp/' . basename($theFileList[$theIndex]) . "-$theReleaseTagXXX" ;
282              
283 0 0         if (-e $_)
284             {
285             #
286             # Restore the current configuration, if any.
287             #
288              
289 0 0         move($_, $theBuildDirectoryXXX . '/' . $theFileList[$theIndex]) if (!$theObject->testFlag()) ;
290              
291 0           $theObject->_print("Moved $_ => " . $theBuildDirectoryXXX . '/' . $theFileList[$theIndex] . "\n", 1) ;
292             } ;
293             } ;
294              
295             #
296             # Once distclean has been run, it's necessary to recreate all the files
297             # associated with the configuration process. This is most easily done
298             # by simply running oldconfig rather that attempting to save all of them.
299             #
300              
301 0 0         if (-e "$theBuildDirectoryXXX/.config")
302             {
303 0           $theObject->run("make oldconfig") ;
304             } ;
305              
306 0           $theObject->space($theObject->_calculateSpace()) ;
307             } ;
308              
309             sub doKernel
310             {
311 0     0 0   my $theObject = shift ;
312              
313 0 0         croak "Need at least 30MB to build a kernel" if ($theObject->space() < 30) ;
314              
315 0           $theObject->run("make kernel") ;
316              
317 0           $theObject->space($theObject->_calculateSpace()) ;
318             } ;
319              
320             sub doModules
321             {
322 0     0 0   my $theObject = shift ;
323              
324 0 0         croak "Need at least 40MB in " . $theObject->buildDirectory() . " to build modules." if ($theObject->space() < 40) ;
325              
326 0           $theObject->run("make modules") ;
327              
328 0           $theObject->space($theObject->_calculateSpace()) ;
329             } ;
330              
331             sub doModules_install
332             {
333 0     0 0   my $theObject = shift ;
334              
335 0 0         croak "Need at least 20MB in /lib/modules/ to install modules" if ($theObject->_calculateSpace("/lib/modules/") < 20) ;
336              
337 0           $theObject->run("make modules_install") ;
338              
339 0           $theObject->_calculateSpace("/lib/modules/") ;
340              
341 0           $theObject->space($theObject->_calculateSpace()) ;
342             } ;
343              
344             sub doMovefiles
345             {
346 0     0 0   my $theObject = shift ;
347              
348 0           my $theBuildDirectoryXXX = $theObject->buildDirectory() ;
349 0           my $theReleaseTagXXX = $theObject->releaseTag() ;
350              
351 0           my %theFiles =
352             (
353             "$theBuildDirectoryXXX/.config" => "/boot/config-$theReleaseTagXXX",
354             "$theBuildDirectoryXXX/include/linux/autoconf.h" => "/boot/autoconf.h-$theReleaseTagXXX",
355             "$theBuildDirectoryXXX/System.map" => "/boot/System.map-$theReleaseTagXXX",
356             "$theBuildDirectoryXXX/vmlinux" => "/boot/vmlinux-$theReleaseTagXXX"
357             ) ;
358 0           my %theMode =
359             (
360             "/boot/vmlinux-$theReleaseTagXXX" => 0755
361             ) ;
362              
363 0           foreach (keys %theFiles)
364             {
365 0 0         if (-e $_)
366             {
367 0           copy($_, $theFiles{$_}) ;
368 0           $theObject->_print("Moved $_ => " . $theFiles{$_} . "\n", 1) ;
369             } ;
370              
371 0 0         if (defined($theMode{$theFiles{$_}}))
372             {
373 0           chmod($theMode{$theFiles{$_}}, $theFiles{$_}) ;
374             } ;
375             } ;
376              
377 0           return $theObject ;
378             } ;
379              
380             sub doBootloader
381             {
382 0     0 0   my $theObject = shift ;
383              
384 0           $theObject->bootloader->modify($theObject) ;
385             } ;
386              
387             sub doLinks
388             {
389 0     0 0   my $theObject = shift ;
390              
391 0 0         if (!@_)
392             {
393 0           $theObject->doLinks('vmlinuz') ;
394 0           $theObject->doLinks('vmlinux') ;
395 0           return ;
396             } ;
397              
398 0           my $theKernel = shift ;
399              
400             #
401             # Make all the soft links that might be needed for the default
402             # boot case.
403             #
404              
405 0 0         chdir('/boot') or croak "Can't chdir to /boot: $!" ;
406              
407 0           $theObject->_print("chdir('/boot')\n",3) ;
408              
409 0 0         if (-e "$theKernel-" . $theObject->releaseTag())
410             {
411 0 0         if (-e "$theKernel")
412             {
413 0 0         if (-l "$theKernel")
414             {
415 0           unlink("$theKernel") ;
416 0           symlink("$theKernel-" . $theObject->releaseTag(), "$theKernel") ;
417 0           $theObject->_print("Making symbolic link from $theKernel to $theKernel-" . $theObject->releaseTag() . "\n",1) ;
418             }
419             else
420             {
421 0           croak "/boot/$theKernel isn't a symbolic link." ;
422             } ;
423             }
424             else
425             {
426 0           symlink("$theKernel-" . $theObject->releaseTag(), "$theKernel") ;
427 0           $theObject->_print("Making symbolic link from $theKernel to $theKernel-" . $theObject->releaseTag() . "\n", 1) ;
428             } ;
429             } ;
430            
431 0           chdir($theObject->buildDirectory()) ;
432              
433 0           $theObject->_print("chdir('" . $theObject->buildDirectory() . "')\n",3) ;
434             } ;
435              
436             sub doInitrd
437             {
438 0     0 0   my $theObject = shift ;
439              
440             #
441             # The default action is to rebuild initrd files if they already
442             # exist for this kernel.
443             #
444              
445 0           my $theInitrdFile ;
446 0           my $theReleaseTagXXX = $theObject->releaseTag() ;
447              
448 0 0         if (-e ($theInitrdFile = '/boot/initrd-' . $theReleaseTagXXX . '.img'))
    0          
449             {
450 0           $theObject->run("mv -vf $theInitrdFile $theInitrdFile.old") ;
451 0           $theObject->run("mkinitrd -v $theInitrdFile $theReleaseTagXXX") ;
452 0 0         if (-e $theInitrdFile)
453             {
454 0           unlink($theInitrdFile) ;
455 0           $theObject->_print("Deleting the old rdinit file: $theInitrdFile.old\n",1) ;
456             }
457             else
458             {
459 0           $theObject->run("mv -vf $theInitrdFile.old $theInitrdFile") ;
460 0           croak "mkrdinit failed to create: $theInitrdFile" ;
461             }
462             }
463             elsif (defined($theInitrdFile = $theObject->bootloader()->initrdFile()))
464             {
465 0           $theObject->run("mkinitrd -v /boot/$theInitrdFile $theReleaseTagXXX") ;
466 0 0         if (! -e "/boot/$theInitrdFile")
467             {
468 0           croak "mkrdinit failed to create: $theInitrdFile" ;
469             }
470             } ;
471             } ;
472              
473             sub doDepmod
474             {
475 0     0 0   my $theObject = shift ;
476              
477 0           $theObject->run('depmod -a -F /boot/System.map-' . $theObject->releaseTag() . " " . $theObject->releaseTag()) ;
478             } ;
479              
480             1;