1 |
#
|
2 |
#
|
3 |
# Interface
|
4 |
# ---------
|
5 |
# new(ConfigArea) : A new BuildSetup
|
6 |
# BuildDir(directory,targets) : prepare the ground for a build and build
|
7 |
# getclass(directory) : return (Class, ClassDir, BuildFileobject)
|
8 |
# associated with directory
|
9 |
# setup(dir)
|
10 |
|
11 |
package BuildSystem::BuildSetup;
|
12 |
require 5.004;
|
13 |
use Utilities::Verbose;
|
14 |
use Utilities::SCRAMUtils;
|
15 |
use BuildSystem::BuildFile;
|
16 |
use BuildSystem::BuildRecorder;
|
17 |
use BuildSystem::DateStampRecord;
|
18 |
use BuildSystem::Block;
|
19 |
use Utilities::AddDir;
|
20 |
@ISA=qw(Utilities::Verbose);
|
21 |
|
22 |
sub new {
|
23 |
my $class=shift;
|
24 |
my $self={};
|
25 |
bless $self,$class;
|
26 |
$self->{area}=shift;
|
27 |
$self->{toolbox}=$self->{area}->toolbox();
|
28 |
$self->{projconfigdir}=$self->{area}->configurationdir();
|
29 |
$self->{localtop}=$self->{area}->location();
|
30 |
$self->{releasearea}=$self->{area}->linkarea();
|
31 |
if ( ! defined $self->{releasearea} ) {
|
32 |
$self->{releasearea}=$self->{area};
|
33 |
}
|
34 |
$self->{releasetop}=$self->{releasearea}->location();
|
35 |
$self->{buildfilename}="BuildFile";
|
36 |
$self->verbosity(1);
|
37 |
$self->_configurationsetup();
|
38 |
# -- clean up from any previous builds
|
39 |
$self->{BuildDBfile}=$self->{localtop}."/".
|
40 |
$self->{workdir}."/BuildRecorderFile";
|
41 |
if ( -f $self->{BuildDBfile} ) {
|
42 |
unlink $self->{BuildDBfile};
|
43 |
}
|
44 |
return $self;
|
45 |
}
|
46 |
|
47 |
sub _generateexternals {
|
48 |
my $self=shift;
|
49 |
my $outfile=shift;
|
50 |
|
51 |
# -- specify these files for dependency information
|
52 |
my $depfile=$self->{projconfigdir}."/External_Dependencies";
|
53 |
|
54 |
# -- get list of dependent files
|
55 |
my $datadir=$self->{localtop}."/.SCRAM/".$ENV{SCRAM_ARCH};
|
56 |
$fdir=FileHandle->new();
|
57 |
opendir $fdir, $datadir;
|
58 |
my @depfiles=grep !/^\.\.?$/, readdir $fdir;
|
59 |
undef $fdir;
|
60 |
for (my $i=0; $i<=$#depfiles; $i++ ) {
|
61 |
$depfiles[$i]=$datadir."/".$depfiles[$i];
|
62 |
}
|
63 |
|
64 |
# -- do we need to rebuild?
|
65 |
if ( SCRAMUtils::dated($outfile,@depfiles) ) {
|
66 |
print "Configuring Local Area\n";
|
67 |
# -- open output file
|
68 |
my $fout=FileHandle->new();
|
69 |
$fout->open(">".$outfile) or die "Unable to open $outfile for output".
|
70 |
$!."\n";
|
71 |
|
72 |
# -- print out tool/ version info
|
73 |
my ($tool,$toolobj,$f,$val,$version);
|
74 |
foreach $tool ( $self->{toolbox}->tools() ) {
|
75 |
$version=$self->{toolbox}->defaultversion($tool);
|
76 |
# default versions
|
77 |
print $fout "ifdef $tool\n".$tool."_V_".$version."=true\nendif\n";
|
78 |
# -- set up the different version -- externals
|
79 |
foreach $version ( $self->{toolbox}->versions($tool) ) {
|
80 |
$toolobj=$self->{toolbox}->gettool($tool,$version);
|
81 |
@deps=$toolobj->getfeature("_externals");
|
82 |
foreach $d ( @deps ) {
|
83 |
$d=~tr[A-Z][a-z];
|
84 |
print $fout "ifdef ".$tool."_V_".$version."\n $d=true\nendif\n";
|
85 |
}
|
86 |
# -- tool info
|
87 |
print $fout "ifdef ".$tool."_V_".$version."\n";
|
88 |
foreach $f ( $toolobj->features() ) {
|
89 |
foreach $val ( $toolobj->getfeature($f) ) {
|
90 |
print $fout "\t".$f." += ".$val."\n";
|
91 |
}
|
92 |
}
|
93 |
print $fout "endif\n";
|
94 |
}
|
95 |
}
|
96 |
# -- some addittional processing of specific vars
|
97 |
print $fout 'INCLUDEPATH+=$(addprefix -I,$(INCLUDE))'."\n";
|
98 |
print $fout 'LDFLAGS+=$(addprefix -L,$(LIBDIR))'."\n";
|
99 |
print $fout 'CPPFLAGS+=$(addprefix -D,$(CPPDEFINES))'."\n";
|
100 |
print $fout 'lib+=$(extralib)'."\n";
|
101 |
print $fout 'LDLIBS+=$(addprefix -l,$(lib))'."\n";
|
102 |
print $fout 'LDLIBS+=$(addprefix -l,$(REQUIRES))'."\n";
|
103 |
print $fout 'LD_LIBRARY_PATH:=$(subst $(space),:,$(LD_LIBRARY_PATH))'."\n";
|
104 |
|
105 |
undef $fout;
|
106 |
$self->verbose("End Externals Configuration Setup");
|
107 |
}
|
108 |
}
|
109 |
|
110 |
sub classsetup {
|
111 |
my $self=shift;
|
112 |
my $THISDIR=shift;
|
113 |
|
114 |
my $classmakefile;
|
115 |
|
116 |
my ($Class, $ClassDir, $bf)=$self->getclass2($THISDIR);
|
117 |
$self->verbose("Class = $Class : ClassDir = $ClassDir for directory ".
|
118 |
$THISDIR);
|
119 |
|
120 |
# -- should we ignore?
|
121 |
if ( $bf->ignore() ) {
|
122 |
print "Nothing to be done - empty group\n";
|
123 |
exit;
|
124 |
}
|
125 |
|
126 |
|
127 |
# -- Create a makefile from the class BuildFile
|
128 |
my $classbuildfile=$self->{localtop}."/".
|
129 |
$self->{projconfigdir}."/".$Class."_BuildFile";
|
130 |
if ( -f $classbuildfile ) {
|
131 |
$classmakefile=$self->{localtop}."/".$ENV{INTwork}.
|
132 |
"/".$Class."_makefile.mk";
|
133 |
if ( SCRAMUtils::dated($classmakefile, $classbuildfile) ) {
|
134 |
# -- generate the new makefile if out of date
|
135 |
$self->verbose("Generating $classmakefile from".
|
136 |
" $classbuildfile");
|
137 |
my $classbf=BuildSystem::BuildFile->new($self->{area},$self);
|
138 |
undef $ENV{LatestBuildFile}; # gets set by BuildFile
|
139 |
$classbf->GenerateMakefile($classbuildfile, $classmakefile);
|
140 |
undef $ENV{LatestBuildFile}; # gets set by BuildFile
|
141 |
}
|
142 |
}
|
143 |
else {
|
144 |
# -- No BuildFile - maybe its old style makefile
|
145 |
$classmakefile=$self->{localtop}."/".
|
146 |
$self->{projconfigdir}."/".$Class."_makefile.mk";
|
147 |
if ( ! -f $classmakefile ) {
|
148 |
$self->error("Unable to find matching ".$Class.
|
149 |
"_BuildFile or ".$Class."_makefile.mk");
|
150 |
}
|
151 |
}
|
152 |
# -- set LatestBuildFile
|
153 |
if ( $bf->buildfile() ne "" ) {
|
154 |
$ENV{LatestBuildFile}=$bf->makefile();
|
155 |
}
|
156 |
else {
|
157 |
$ENV{LatestBuildFile}=$self->{topbf}->makefile();
|
158 |
}
|
159 |
|
160 |
return ($Class,$ClassDir,$classmakefile);
|
161 |
}
|
162 |
|
163 |
sub _configurationsetup {
|
164 |
my $self=shift;
|
165 |
|
166 |
# -- set working directory
|
167 |
$self->{workdir}=$ENV{INTwork};
|
168 |
$self->{fullworkdir}=$self->{localtop}."/".$self->{workdir};
|
169 |
|
170 |
# -- make working directory
|
171 |
chdir $self->{localtop};
|
172 |
AddDir::adddir($self->{workdir});
|
173 |
|
174 |
# -- generate tool info
|
175 |
$self->_generateexternals($self->{fullworkdir}."/clientmakefile");
|
176 |
|
177 |
# -- process project BuildFile
|
178 |
$self->_topbuildfile();
|
179 |
}
|
180 |
|
181 |
sub BuildDir {
|
182 |
my $self=shift;
|
183 |
my $THISDIR=shift;
|
184 |
my @Targets=@_;
|
185 |
my $DefaultBuildFile="";
|
186 |
|
187 |
# -- Setup Class specifics
|
188 |
($Class,$ClassDir,$classmakefile)=$self->classsetup($THISDIR);
|
189 |
$ENV{classmakefile}=$classmakefile;
|
190 |
$ENV{Class}=$Class;
|
191 |
$ENV{ClassDir}=$ClassDir;
|
192 |
$DefaultBuildFile=$ENV{classmakefile};
|
193 |
$ENV{DefaultBuildFile}=$DefaultBuildFile;
|
194 |
|
195 |
# -- Create working directory
|
196 |
my $workdir=$self->{workdir}."/".$ClassDir;
|
197 |
chdir $self->{localtop};
|
198 |
AddDir::adddir($workdir);
|
199 |
$ENV{workdir}=$workdir;
|
200 |
my $fullworkdir=$self->{localtop}."/".$ENV{workdir};
|
201 |
chdir $fullworkdir || die "Unable to enter working directory $!";
|
202 |
|
203 |
# -- Set up some other useful variables for the Build
|
204 |
# set variables listing directories/files available
|
205 |
my $fh=FileHandle->new();
|
206 |
opendir $fh, "$self->{localtop}/$ClassDir";
|
207 |
my @allfiles= grep !/^\.\.?$/, readdir $fh;
|
208 |
undef $fh;
|
209 |
foreach $file ( @allfiles ) {
|
210 |
if ( -d "$self->{localtop}/$ClassDir/$file" ) {
|
211 |
$ENV{SCRAM_AVAILDIRS}=$ENV{SCRAM_AVAILDIRS}." ".$file;
|
212 |
}
|
213 |
else {
|
214 |
$ENV{SCRAM_AVAILFILES}=$ENV{SCRAM_AVAILFILES}." ".$file;
|
215 |
}
|
216 |
}
|
217 |
my $targetnumber=$#Targets;
|
218 |
$ENV{"MAKETARGETS"}="";
|
219 |
foreach $word ( @Targets ) {
|
220 |
if ( $word=~/.*=.*/ ) { # if we have an assignment it cant be a target
|
221 |
$targetnumber--;
|
222 |
}
|
223 |
else {
|
224 |
# set some variables for use in makefiles
|
225 |
$ENV{"MAKETARGET_".$word}=$word;
|
226 |
if ( $ENV{"MAKETARGETS"} ne "" ) {
|
227 |
$ENV{"MAKETARGETS"}=$ENV{"MAKETARGETS"}." ".$word;
|
228 |
}
|
229 |
else {
|
230 |
$ENV{"MAKETARGETS"}=$word;
|
231 |
}
|
232 |
}
|
233 |
}
|
234 |
|
235 |
# -- If target not specified default to the class name target
|
236 |
if ( $targetnumber == -1 ) {
|
237 |
push @Targets,$Class;
|
238 |
}
|
239 |
|
240 |
$ENV{DefaultMakefile}="$ENV{TOOL_HOME}/basics.mk";
|
241 |
|
242 |
|
243 |
$SCRAM_GROUPSDIR=$self->{localtop}."/".$self->{projconfigdir}."/groups.mk";
|
244 |
if ( -f $SCRAM_GROUPSDIR ) {
|
245 |
$ENV{SCRAM_GROUPSDIR}=$SCRAM_GROUPSDIR;
|
246 |
}
|
247 |
|
248 |
|
249 |
#
|
250 |
# Keep a track of what we have built this run
|
251 |
#
|
252 |
if ( ! defined $self->{BuildDB} ) {
|
253 |
my $file=$self->{BuildDBfile};
|
254 |
$self->{BuildDB}=BuildSystem::BuildRecorder->new($file);
|
255 |
}
|
256 |
my $rv=0;
|
257 |
if ( ! $self->{BuildDB}->checked($ClassDir) ) {
|
258 |
if ( $Targets[0] eq $Class ) {
|
259 |
$self->{BuildDB}->checked($ClassDir,1); # Mark it as taken care of
|
260 |
}
|
261 |
|
262 |
# Do a datestamp check so that make will build files that have changed
|
263 |
# rather than just those which are older than their dependencies
|
264 |
$self->_checkdatestampindir($ClassDir);
|
265 |
|
266 |
# -- The main build here
|
267 |
$rv=system("gmake","--no-print-directory","-r","-k","-f",
|
268 |
"$ENV{DefaultMakefile}","-I$ENV{TOOL_HOME}", @Targets);
|
269 |
}
|
270 |
return $rv/256; # return the exit status of gmake
|
271 |
|
272 |
}
|
273 |
|
274 |
# TODO - work in progress - replacement for BuildDir that can handle <Build> OK
|
275 |
sub BuildIt {
|
276 |
my $self=shift;
|
277 |
my $dir=shift;
|
278 |
my @Targets=@_;
|
279 |
|
280 |
|
281 |
# -- get the top building block
|
282 |
my $topblock=$self->_gettopblock();
|
283 |
$ENV{LatestBuildFile}=$self->_gettopbf()->makefile();
|
284 |
|
285 |
# -- is there a class block associated with the directory?
|
286 |
my ($Class,$ClassDir)=getclass($dir);
|
287 |
$self->verbose("Using Class $Class");
|
288 |
my $classblock=$self->_getclassblock($Class,$topblock);
|
289 |
|
290 |
# -- If target not specified default to the class name target
|
291 |
if ( $targetnumber == -1 ) {
|
292 |
push @Targets,$Class;
|
293 |
}
|
294 |
|
295 |
# -- Create working directory
|
296 |
my $workdir=$self->{workdir}."/".$ClassDir;
|
297 |
chdir $self->{localtop};
|
298 |
AddDir::adddir($workdir);
|
299 |
$ENV{workdir}=$workdir;
|
300 |
my $fullworkdir=$self->{localtop}."/".$ENV{workdir};
|
301 |
chdir $fullworkdir || die "Unable to enter working directory $!";
|
302 |
$self->verbose("Working area setup");
|
303 |
|
304 |
# -- Search for Blocks up to tree root
|
305 |
my @dirblocks=();
|
306 |
my @dirs=split /\//, $dir;
|
307 |
my $fulldir="";
|
308 |
my $currentblock=$classblock;
|
309 |
foreach $dire ( @dirs ) {
|
310 |
($fulldir eq "")?$fulldir=$dire
|
311 |
:$fulldir=$fulldir."/".$dire;
|
312 |
$self->verbose("Searching $fulldir for Block");
|
313 |
my $block=$self->_getdirblock($fulldir,$currentblock);
|
314 |
if ( defined $block ) {
|
315 |
$currentblock=$block;
|
316 |
}
|
317 |
$ENV{LatestBuildFile}=$self->gettopbf()->makefile();
|
318 |
}
|
319 |
|
320 |
# -- Create a makefile to include both BuildFile and
|
321 |
# class makefile
|
322 |
|
323 |
my $fh=FileHandle->new();
|
324 |
my $mfile=$fullworkdir."/BuildFile.mk";
|
325 |
$self->verbose("Building makefile $mfile");
|
326 |
$fh->open(">".$mfile);
|
327 |
$fh->autoflush(1);
|
328 |
if ( -e $ENV{LatestBuildFile} ) {
|
329 |
print $fh "include $ENV{LatestBuildFile}\n";
|
330 |
}
|
331 |
|
332 |
# -- Parse the local BuildFile
|
333 |
my $dbf=$self->_getdirbf($dir);
|
334 |
if ( defined $dbf ) {
|
335 |
$dbf->Parsetofh($fh,$currentblock);
|
336 |
}
|
337 |
|
338 |
# -- Parse the class BuildFile
|
339 |
my $cbf=$self->_getclassbf($Class);
|
340 |
if ( defined $cbf ) {
|
341 |
$cbf->Parsetofh($fh,$currentblock);
|
342 |
}
|
343 |
$fh->close();
|
344 |
$ENV{DefaultMakefile}=$mfile;
|
345 |
|
346 |
# -- Hack around make by checking datestamps in local working and
|
347 |
# in _class_ working directories
|
348 |
$self->_checkdatestampindir($ClassDir);
|
349 |
opendir $fh, $ClassDir;
|
350 |
my @dfiles= grep { -d $_ } readdir $fh;
|
351 |
undef $fh;
|
352 |
foreach $dir ( @dfiles ) {
|
353 |
if ( $dir=~/^_class_/ ) {
|
354 |
$self->_checkdatestampindir($ClassDir."/".$dir);
|
355 |
}
|
356 |
}
|
357 |
|
358 |
# -- Call gmake to do the actual build
|
359 |
$rv=system("gmake","--no-print-directory","-r","-k","-f",
|
360 |
"$mfile","-I$ENV{TOOL_HOME}", @Targets);
|
361 |
return $rv/256; # return the exit status of gmake
|
362 |
}
|
363 |
|
364 |
#
|
365 |
# -- Block generation Routines
|
366 |
#
|
367 |
|
368 |
sub _getclassblock {
|
369 |
my $self=shift;
|
370 |
my $key=shift;
|
371 |
|
372 |
if ( ! defined $self->{classblocks}{$key} ) {
|
373 |
$self->verbose("Initialising Class Block $key");
|
374 |
$self->{classblocks}{$key}=BuildSystem::Block->new();
|
375 |
# -- get class buildfile
|
376 |
my $bf=$self->_getclassbf($key);
|
377 |
if ( @_ ) {
|
378 |
$self->{classblocks}{$key}->parent(shift);
|
379 |
}
|
380 |
$bf->BlockParse($self->{classblocks}{$key});
|
381 |
$self->verbose("Initialisation Complete for Class Block $key");
|
382 |
}
|
383 |
return $self->{classblocks}{$key};
|
384 |
|
385 |
}
|
386 |
|
387 |
sub _gettopblock {
|
388 |
my $self=shift;
|
389 |
|
390 |
if ( ! defined $self->{topblocks} ) {
|
391 |
$self->verbose("Initialising Top Block");
|
392 |
$self->{topblock}=BuildSystem::Block->new();
|
393 |
# -- get class buildfile
|
394 |
my $bf=$self->_gettopbf();
|
395 |
if ( @_ ) {
|
396 |
$self->{topblock}->parent(shift);
|
397 |
}
|
398 |
$bf->BlockParse($self->{topblock});
|
399 |
$self->verbose("Initialisation Complete for Top Block");
|
400 |
}
|
401 |
return $self->{topblock};
|
402 |
}
|
403 |
|
404 |
sub _getdirblock {
|
405 |
my $self=shift;
|
406 |
my $dir=shift;
|
407 |
my $block=shift;
|
408 |
|
409 |
if ( defined $dir || $dir ne "" ) {
|
410 |
if ( ! defined $self->{blocks}{$dir} ) {
|
411 |
# -- get a buildfile and do a block parse
|
412 |
$self->{blocks}{$dir}=BuildSystem::Block->new();
|
413 |
my $bf=$self->_getbuildfile($dir);
|
414 |
$self->{blocks}{$dir}->parent($block);
|
415 |
$bf->blockparse($self->{blocks}{$dir});
|
416 |
}
|
417 |
return $self->{blocks}{$dir};
|
418 |
}
|
419 |
return undef;
|
420 |
}
|
421 |
|
422 |
#
|
423 |
# -- BuildFile generation routines
|
424 |
#
|
425 |
|
426 |
sub _getclassbf {
|
427 |
my $self=shift;
|
428 |
my $class=shift;
|
429 |
|
430 |
if ( ! defined $self->{classbf}{$class} ) {
|
431 |
$self->verbose("Initialising Class BuildFile $class");
|
432 |
# -- determine BuildFile or makefile
|
433 |
my $fname=$self->{localtop}."/".$self->{projconfigdir}.
|
434 |
"/".$class."_";
|
435 |
if ( -f $fname.$self->{buildfilename} ) {
|
436 |
$fname=$fname.$self->{buildfilename};
|
437 |
}
|
438 |
elsif ( -f $fname."makefile.mk" ) {
|
439 |
$fname=$fname."makefile.mk";
|
440 |
}
|
441 |
else {
|
442 |
$self->error("$fname".$self->{buildfilename}." does not exist in ".
|
443 |
$self->{projconfigdir});
|
444 |
}
|
445 |
|
446 |
# -- create a BuildFile object
|
447 |
$self->{classbf}{$class}=BuildSystem::BuildFile->new($self->{area},$self);
|
448 |
$self->{classbf}{$class}->buildfile($fname);
|
449 |
$self->verbose("Finished Initialising Class BuildFile $class");
|
450 |
}
|
451 |
return $self->{classbf}{$class};
|
452 |
}
|
453 |
|
454 |
sub _gettopbf {
|
455 |
my $self=shift;
|
456 |
|
457 |
if ( ! defined $self->{topbf} ) {
|
458 |
$self->{topbf}=BuildSystem::BuildFile->new($self->{area},$self);
|
459 |
$self->{topbf}->buildfile($self->{localtop}."/".
|
460 |
$self->{projconfigdir}."/".$self->{buildfilename});
|
461 |
}
|
462 |
return $self->{topbf};
|
463 |
}
|
464 |
#
|
465 |
# Returns undef if BF does not exist at this dir level
|
466 |
#
|
467 |
sub _getdirbf {
|
468 |
my $self=shift;
|
469 |
my $dir=shift;
|
470 |
|
471 |
if ( ! exists $self->{dirbf}{$dir} ) {
|
472 |
$self->verbose("initialising dir BuildFile $dir");
|
473 |
# -- determine if local or releasetop
|
474 |
my $fname=$self->{path}."/".$self->{buildfilename};
|
475 |
if ( -f $self->{localtop}."/".$fname ) {
|
476 |
$fname=$self->{localtop}."/".$fname;
|
477 |
}
|
478 |
elsif ( -f $self->{releasetop}."/".$fname ) {
|
479 |
$fname=$self->{releasetop}."/".$fname;
|
480 |
}
|
481 |
else {
|
482 |
$self->{dirbf}{$dir}=undef;
|
483 |
$self->verbose("initialisation complete for dir BuildFile $dir");
|
484 |
return $self->{dirbf}{$dir};
|
485 |
}
|
486 |
|
487 |
# -- construct the bf object
|
488 |
$self->{dirbf}{$dir}=BuildSystem::BuildFile->new($self->{area},$self);
|
489 |
$self->{dirbf}{$dir}->buildfile($fname);
|
490 |
|
491 |
$self->verbose("initialisation complete for dir BuildFile $dir");
|
492 |
}
|
493 |
return $self->{dirbf}{$dir};
|
494 |
}
|
495 |
|
496 |
sub getclass2 {
|
497 |
my $self=shift;
|
498 |
my $dirname = shift;
|
499 |
my $Class="DEFAULT";
|
500 |
my $ClassDir="";
|
501 |
|
502 |
#return if $dirname eq "";
|
503 |
my @DIRA=split /\//, $dirname;
|
504 |
|
505 |
my $thispath=".";
|
506 |
# -- construct all class buildfiles in the path
|
507 |
for ( $i=0; $i<=$#DIRA; $i++ ) {
|
508 |
#$thispath=(($thispath eq "")?$DIRA[$i]:$thispath."/".$DIRA[$i]);
|
509 |
$thispath=$thispath."/".$DIRA[$i];
|
510 |
if ( ! exists $self->{pathbf}{$thispath} ) {
|
511 |
$self->verbose("Initialising BuildFile in $thispath");
|
512 |
$self->{pathbf}{$thispath}=$self->_startbuildfile($thispath);
|
513 |
}
|
514 |
# -- check class overriden by BuildFile
|
515 |
if ( defined $self->{pathbf}{$thispath}->classname() ) {
|
516 |
$Class=$self->{pathbf}{$thispath}->classname();
|
517 |
$ClassDir=$thispath;
|
518 |
}
|
519 |
else {
|
520 |
# -- sort it out from classpath directives
|
521 |
foreach $BlockClassA ( @{$self->{LoBCA}} ) {
|
522 |
next if ( $#{$BlockClassA} < $i );
|
523 |
$elem=${$BlockClassA}[$i];
|
524 |
if ( $elem=~/^$DIRA[$i]\+/ ) {
|
525 |
$elem=~s/^$DIRA[$i]//;
|
526 |
}
|
527 |
#print $elem." ".$DIRA[$i]."\n";
|
528 |
if ( $elem=~/^\+/ ) {
|
529 |
($Class=$elem)=~s/^\+//;
|
530 |
$ClassDir=$thispath;
|
531 |
}
|
532 |
#}
|
533 |
}
|
534 |
}
|
535 |
}
|
536 |
# -- default case
|
537 |
if ( $ClassDir eq "" ) {
|
538 |
if ( ! defined $self->{pathbf}{'.'}) {
|
539 |
$self->{pathbf}{'.'}=$self->_startbuildfile(".");
|
540 |
$self->verbose("DEFAULT class initialised : ".$self->{pathbf}{'.'});
|
541 |
}
|
542 |
$ClassDir=".";
|
543 |
}
|
544 |
|
545 |
# -- returns
|
546 |
($ClassDir_c=$ClassDir)=~s/^\.\///;
|
547 |
return ( $Class, $ClassDir_c, $self->{pathbf}{$ClassDir});
|
548 |
}
|
549 |
|
550 |
sub getclass {
|
551 |
my $self=shift;
|
552 |
my $dirname = shift;
|
553 |
|
554 |
my $Class="DEFAULT";
|
555 |
my $ClassDir=".";
|
556 |
|
557 |
# return if $dirname eq "";
|
558 |
my @DIRA=split /\//, $dirname;
|
559 |
|
560 |
my $thispath="";
|
561 |
for ( $i=0; $i<=$#DIRA; $i++ ) {
|
562 |
$thispath=(($thispath eq "")?$DIRA[$i]:$thispath."/".$DIRA[$i]);
|
563 |
|
564 |
# -- sort it out from classpath directives
|
565 |
foreach $BlockClassA ( @{$self->{LoBCA}} ) {
|
566 |
next if ( $#{$BlockClassA} < $i );
|
567 |
$elem=${$BlockClassA}[$i];
|
568 |
if ( $elem=~/^$DIRA[$i]\+/ ) {
|
569 |
$elem=~s/^$DIRA[$i]//;
|
570 |
}
|
571 |
#print $elem." ".$DIRA[$i]."\n";
|
572 |
if ( $elem=~/^\+/ ) {
|
573 |
($Class=$elem)=~s/^\+//;
|
574 |
$ClassDir=$thispath;
|
575 |
}
|
576 |
}
|
577 |
}
|
578 |
return ( $Class, $ClassDir );
|
579 |
}
|
580 |
|
581 |
#
|
582 |
# Check to see if the buildfile is local or in the release area and
|
583 |
# parse appropriately
|
584 |
#
|
585 |
sub _startbuildfile {
|
586 |
my $self=shift;
|
587 |
my $classdir=shift;
|
588 |
|
589 |
my $bf=BuildSystem::BuildFile->new($self->{area},$self);
|
590 |
my $thisfile="$classdir/$self->{buildfilename}";
|
591 |
|
592 |
if ( -e $self->{localtop}."/".$thisfile ) {
|
593 |
$bf->buildfile($self->{localtop}."/".$thisfile);
|
594 |
$bf->ParseBuildFile($self->{localtop}, $classdir,
|
595 |
$self->{buildfilename});
|
596 |
}
|
597 |
elsif ( -e $self->{releasetop}."/".$thisfile ) {
|
598 |
$bf->buildfile($self->{releasetop}."/".$thisfile);
|
599 |
$bf->ParseBuildFile($self->{releasetop}, $classdir,
|
600 |
$self->{buildfilename});
|
601 |
}
|
602 |
return $bf;
|
603 |
}
|
604 |
|
605 |
sub _topbuildfile {
|
606 |
my $self=shift;
|
607 |
|
608 |
$self->verbose("Generating Top Level BuildFile");
|
609 |
# -- Analyse project buildfile if it exists
|
610 |
|
611 |
my $topbf=$self->_gettopbf();
|
612 |
|
613 |
# -- generate top level makefile
|
614 |
undef $ENV{LatestBuildFile};
|
615 |
$topbf->ParseBuildFile($self->{localtop},
|
616 |
$self->{projconfigdir},$self->{buildfilename});
|
617 |
|
618 |
# -- Extract BuildStructure Information
|
619 |
my @ClassPaths=split /:/, $self->{topbf}->BlockClassPath();
|
620 |
foreach $BClassPath ( @ClassPaths ) {
|
621 |
next if ( $BClassPath eq "");
|
622 |
push @{$self->{LoBCA}}, [ split /\//, $BClassPath ];
|
623 |
}
|
624 |
$self->verbose("End top buildfile generation");
|
625 |
}
|
626 |
|
627 |
sub _checkdatestampindir {
|
628 |
my $self=shift;
|
629 |
my $dir=shift;
|
630 |
|
631 |
# -- get all local .ds files
|
632 |
my $fh=FileHandle->new();
|
633 |
my $ldir=$self->{localtop}."/".$self->{workdir}."/".$dir;
|
634 |
opendir $fh, $ldir;
|
635 |
my @dsfiles= grep /^.*\.ds$/, readdir $fh;
|
636 |
$fh->close();
|
637 |
|
638 |
# -- copy across ds files from releasetop if not existing locally
|
639 |
if ( $#dsfiles < 0 ) {
|
640 |
# -- get all releasetop .ds files
|
641 |
my $rdir=$self->{releasetop}."/".$self->{workdir}."/".$dir;
|
642 |
opendir $fh, $rdir;
|
643 |
my @releasedsfiles= grep /^.*\.ds$/, readdir $fh;
|
644 |
foreach $file ( @releasedsfiles ) {
|
645 |
use File::Copy;
|
646 |
$self->verbose("Copying $file from $rdir to $ldir");
|
647 |
copy($rdir."/".$file,$ldir."/".$file);
|
648 |
}
|
649 |
$fh->close();
|
650 |
@dsfiles=@releasedsfiles;
|
651 |
}
|
652 |
|
653 |
# -- process ds files
|
654 |
my $file;
|
655 |
foreach $datafile ( @dsfiles ) {
|
656 |
$self->verbose("Processing $ldir/$datafile\n");
|
657 |
my $ds=BuildSystem::DateStampRecord->new($ldir."/".$datafile);
|
658 |
$ds->verbosity($self->verbosity());
|
659 |
my $date;
|
660 |
my $needsupdate;
|
661 |
my $productfile=$ds->product();
|
662 |
my (%files,%moddate);
|
663 |
|
664 |
# now get dates in our dependency list
|
665 |
my @datedfiles=$ds->dated();
|
666 |
if ( $#datedfiles >= 0 ) {
|
667 |
|
668 |
$needsupdate=1;
|
669 |
$date=$datedfiles[0][1]-1;
|
670 |
}
|
671 |
else {
|
672 |
# -- extra checks for local replacement of files
|
673 |
foreach $file ( $ds->contents() ) {
|
674 |
# -- only check files
|
675 |
if ( -f $file ) {
|
676 |
$files{$file}=$ds->filedate($file);
|
677 |
# -- check to see if we have a new local copy
|
678 |
if ( ($file=~/\Q$self->{releasetop}\E/) &&
|
679 |
($self->{releasetop} ne $self->{localtop}) ) {
|
680 |
($tempfile=$file)=~s/\Q$self->{releasetop}\E/$self->{localtop}/;
|
681 |
if ( -f $tempfile ) {
|
682 |
$files{$tempfile}=$files{$file};
|
683 |
$file=$tempfile;
|
684 |
}
|
685 |
}
|
686 |
$moddate{$file}=(stat($file))[9];
|
687 |
if ( $moddate{$file} != $files{$file} ) {
|
688 |
$self->verbose($file." changed");
|
689 |
$date=$moddate{$file}-1;
|
690 |
$needsupdate=1;
|
691 |
}
|
692 |
}
|
693 |
}
|
694 |
}
|
695 |
# time stamp the product file to be older than the dependencies
|
696 |
if ( $needsupdate == 1 ) { # touch file into the past
|
697 |
my $newproductfile;
|
698 |
if ( $productfile!~/\Q$self->{localtop}\E/ ) {
|
699 |
if ( $productfile=~/\Q$self->{releasetop}\E/ ) {
|
700 |
($newproductfile=$productfile)=~
|
701 |
s/\Q$self->{releasetop}\E/$self->{localtop}/;
|
702 |
$self->verbose("Copying $productfile to $newproductfile");
|
703 |
copy($productfile,$newproductfile);
|
704 |
}
|
705 |
else { # assume no path to worry about
|
706 |
$newproductfile=$self->{localtop}."/".$ENV{workdir}.
|
707 |
"/".$productfile;
|
708 |
# -- make a local copy of the product file if not already here
|
709 |
my $oldproductfile=$self->{releasetop}."/".$ENV{workdir}.
|
710 |
"/".$productfile;
|
711 |
if ( ! -f $newproductfile ) {
|
712 |
if ( -f $oldproductfile ) {
|
713 |
$self->verbose("Copying $oldproductfile to $newproductfile");
|
714 |
copy($oldproductfile,$newproductfile);
|
715 |
}
|
716 |
}
|
717 |
}
|
718 |
}
|
719 |
else {
|
720 |
$newproductfile=$productfile;
|
721 |
}
|
722 |
if ( -f $newproductfile ) {
|
723 |
$self->verbose("Blasting $newproductfile to the past ($date)");
|
724 |
# If the (local) productfile exists - make it older
|
725 |
utime($date,$date,$newproductfile);
|
726 |
}
|
727 |
else {
|
728 |
$self->verbose("SomeThing Wrong(?) with $newproductfile\n".
|
729 |
"RELEASETOP=".$self->{releasetop}."\n".
|
730 |
"LOCALTOP=".$self->{localtop}."\n".
|
731 |
"workdir=".$ENV{workdir});
|
732 |
}
|
733 |
}
|
734 |
else {
|
735 |
$self->verbose("No need to touch $productfile");
|
736 |
}
|
737 |
}
|
738 |
undef $fh;
|
739 |
}
|