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}."/BuildReporterFile";
|
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 |
$self->{BuildDB}->checked($ClassDir,1); # Mark it as taken care of
|
259 |
|
260 |
# Do a datestamp check so that make will build files that have changed
|
261 |
# rather than just those which are older than their dependencies
|
262 |
$self->_checkdatestampindir($ClassDir);
|
263 |
|
264 |
# -- The main build here
|
265 |
$rv=system("gmake","--no-print-directory","-r","-k","-f",
|
266 |
"$ENV{DefaultMakefile}","-I$ENV{TOOL_HOME}", @Targets);
|
267 |
}
|
268 |
return $rv/256; # return the exit status of gmake
|
269 |
|
270 |
}
|
271 |
|
272 |
# TODO - work in progress - replacement for BuildDir that can handle <Build> OK
|
273 |
sub BuildIt {
|
274 |
my $self=shift;
|
275 |
my $dir=shift;
|
276 |
my @Targets=@_;
|
277 |
|
278 |
|
279 |
# -- get the top building block
|
280 |
my $topblock=$self->_gettopblock();
|
281 |
$ENV{LatestBuildFile}=$self->_gettopbf()->makefile();
|
282 |
|
283 |
# -- is there a class block associated with the directory?
|
284 |
my ($Class,$ClassDir)=getclass($dir);
|
285 |
$self->verbose("Using Class $Class");
|
286 |
my $classblock=$self->_getclassblock($Class,$topblock);
|
287 |
|
288 |
# -- If target not specified default to the class name target
|
289 |
if ( $targetnumber == -1 ) {
|
290 |
push @Targets,$Class;
|
291 |
}
|
292 |
|
293 |
# -- Create working directory
|
294 |
my $workdir=$self->{workdir}."/".$ClassDir;
|
295 |
chdir $self->{localtop};
|
296 |
AddDir::adddir($workdir);
|
297 |
$ENV{workdir}=$workdir;
|
298 |
my $fullworkdir=$self->{localtop}."/".$ENV{workdir};
|
299 |
chdir $fullworkdir || die "Unable to enter working directory $!";
|
300 |
$self->verbose("Working area setup");
|
301 |
|
302 |
# -- Search for Blocks up to tree root
|
303 |
my @dirblocks=();
|
304 |
my @dirs=split /\//, $dir;
|
305 |
my $fulldir="";
|
306 |
my $currentblock=$classblock;
|
307 |
foreach $dire ( @dirs ) {
|
308 |
($fulldir eq "")?$fulldir=$dire
|
309 |
:$fulldir=$fulldir."/".$dire;
|
310 |
$self->verbose("Searching $fulldir for Block");
|
311 |
my $block=$self->_getdirblock($fulldir,$currentblock);
|
312 |
if ( defined $block ) {
|
313 |
$currentblock=$block;
|
314 |
}
|
315 |
$ENV{LatestBuildFile}=$self->gettopbf()->makefile();
|
316 |
}
|
317 |
|
318 |
# -- Create a makefile to include both BuildFile and
|
319 |
# class makefile
|
320 |
|
321 |
my $fh=FileHandle->new();
|
322 |
my $mfile=$fullworkdir."/BuildFile.mk";
|
323 |
$self->verbose("Building makefile $mfile");
|
324 |
$fh->open(">".$mfile);
|
325 |
$fh->autoflush(1);
|
326 |
if ( -e $ENV{LatestBuildFile} ) {
|
327 |
print $fh "include $ENV{LatestBuildFile}\n";
|
328 |
}
|
329 |
|
330 |
# -- Parse the local BuildFile
|
331 |
my $dbf=$self->_getdirbf($dir);
|
332 |
if ( defined $dbf ) {
|
333 |
$dbf->Parsetofh($fh,$currentblock);
|
334 |
}
|
335 |
|
336 |
# -- Parse the class BuildFile
|
337 |
my $cbf=$self->_getclassbf($Class);
|
338 |
if ( defined $cbf ) {
|
339 |
$cbf->Parsetofh($fh,$currentblock);
|
340 |
}
|
341 |
$fh->close();
|
342 |
$ENV{DefaultMakefile}=$mfile;
|
343 |
|
344 |
# -- Hack around make by checking datestamps in local working and
|
345 |
# in _class_ working directories
|
346 |
$self->_checkdatestampindir($ClassDir);
|
347 |
opendir $fh, $ClassDir;
|
348 |
my @dfiles= grep { -d $_ } readdir $fh;
|
349 |
undef $fh;
|
350 |
foreach $dir ( @dfiles ) {
|
351 |
if ( $dir=~/^_class_/ ) {
|
352 |
$self->_checkdatestampindir($ClassDir."/".$dir);
|
353 |
}
|
354 |
}
|
355 |
|
356 |
# -- Call gmake to do the actual build
|
357 |
$rv=system("gmake","--no-print-directory","-r","-k","-f",
|
358 |
"$mfile","-I$ENV{TOOL_HOME}", @Targets);
|
359 |
return $rv/256; # return the exit status of gmake
|
360 |
}
|
361 |
|
362 |
#
|
363 |
# -- Block generation Routines
|
364 |
#
|
365 |
|
366 |
sub _getclassblock {
|
367 |
my $self=shift;
|
368 |
my $key=shift;
|
369 |
|
370 |
if ( ! defined $self->{classblocks}{$key} ) {
|
371 |
$self->verbose("Initialising Class Block $key");
|
372 |
$self->{classblocks}{$key}=BuildSystem::Block->new();
|
373 |
# -- get class buildfile
|
374 |
my $bf=$self->_getclassbf($key);
|
375 |
if ( @_ ) {
|
376 |
$self->{classblocks}{$key}->parent(shift);
|
377 |
}
|
378 |
$bf->BlockParse($self->{classblocks}{$key});
|
379 |
$self->verbose("Initialisation Complete for Class Block $key");
|
380 |
}
|
381 |
return $self->{classblocks}{$key};
|
382 |
|
383 |
}
|
384 |
|
385 |
sub _gettopblock {
|
386 |
my $self=shift;
|
387 |
|
388 |
if ( ! defined $self->{topblocks} ) {
|
389 |
$self->verbose("Initialising Top Block");
|
390 |
$self->{topblock}=BuildSystem::Block->new();
|
391 |
# -- get class buildfile
|
392 |
my $bf=$self->_gettopbf();
|
393 |
if ( @_ ) {
|
394 |
$self->{topblock}->parent(shift);
|
395 |
}
|
396 |
$bf->BlockParse($self->{topblock});
|
397 |
$self->verbose("Initialisation Complete for Top Block");
|
398 |
}
|
399 |
return $self->{topblock};
|
400 |
}
|
401 |
|
402 |
sub _getdirblock {
|
403 |
my $self=shift;
|
404 |
my $dir=shift;
|
405 |
my $block=shift;
|
406 |
|
407 |
if ( defined $dir || $dir ne "" ) {
|
408 |
if ( ! defined $self->{blocks}{$dir} ) {
|
409 |
# -- get a buildfile and do a block parse
|
410 |
$self->{blocks}{$dir}=BuildSystem::Block->new();
|
411 |
my $bf=$self->_getbuildfile($dir);
|
412 |
$self->{blocks}{$dir}->parent($block);
|
413 |
$bf->blockparse($self->{blocks}{$dir});
|
414 |
}
|
415 |
return $self->{blocks}{$dir};
|
416 |
}
|
417 |
return undef;
|
418 |
}
|
419 |
|
420 |
#
|
421 |
# -- BuildFile generation routines
|
422 |
#
|
423 |
|
424 |
sub _getclassbf {
|
425 |
my $self=shift;
|
426 |
my $class=shift;
|
427 |
|
428 |
if ( ! defined $self->{classbf}{$class} ) {
|
429 |
$self->verbose("Initialising Class BuildFile $class");
|
430 |
# -- determine BuildFile or makefile
|
431 |
my $fname=$self->{localtop}."/".$self->{projconfigdir}.
|
432 |
"/".$class."_";
|
433 |
if ( -f $fname.$self->{buildfilename} ) {
|
434 |
$fname=$fname.$self->{buildfilename};
|
435 |
}
|
436 |
elsif ( -f $fname."makefile.mk" ) {
|
437 |
$fname=$fname."makefile.mk";
|
438 |
}
|
439 |
else {
|
440 |
$self->error("$fname".$self->{buildfilename}." does not exist in ".
|
441 |
$self->{projconfigdir});
|
442 |
}
|
443 |
|
444 |
# -- create a BuildFile object
|
445 |
$self->{classbf}{$class}=BuildSystem::BuildFile->new($self->{area},$self);
|
446 |
$self->{classbf}{$class}->buildfile($fname);
|
447 |
$self->verbose("Finished Initialising Class BuildFile $class");
|
448 |
}
|
449 |
return $self->{classbf}{$class};
|
450 |
}
|
451 |
|
452 |
sub _gettopbf {
|
453 |
my $self=shift;
|
454 |
|
455 |
if ( ! defined $self->{topbf} ) {
|
456 |
$self->{topbf}=BuildSystem::BuildFile->new($self->{area},$self);
|
457 |
$self->{topbf}->buildfile($self->{localtop}."/".
|
458 |
$self->{projconfigdir}."/".$self->{buildfilename});
|
459 |
}
|
460 |
return $self->{topbf};
|
461 |
}
|
462 |
#
|
463 |
# Returns undef if BF does not exist at this dir level
|
464 |
#
|
465 |
sub _getdirbf {
|
466 |
my $self=shift;
|
467 |
my $dir=shift;
|
468 |
|
469 |
if ( ! exists $self->{dirbf}{$dir} ) {
|
470 |
$self->verbose("initialising dir BuildFile $dir");
|
471 |
# -- determine if local or releasetop
|
472 |
my $fname=$self->{path}."/".$self->{buildfilename};
|
473 |
if ( -f $self->{localtop}."/".$fname ) {
|
474 |
$fname=$self->{localtop}."/".$fname;
|
475 |
}
|
476 |
elsif ( -f $self->{releasetop}."/".$fname ) {
|
477 |
$fname=$self->{releasetop}."/".$fname;
|
478 |
}
|
479 |
else {
|
480 |
$self->{dirbf}{$dir}=undef;
|
481 |
$self->verbose("initialisation complete for dir BuildFile $dir");
|
482 |
return $self->{dirbf}{$dir};
|
483 |
}
|
484 |
|
485 |
# -- construct the bf object
|
486 |
$self->{dirbf}{$dir}=BuildSystem::BuildFile->new($self->{area},$self);
|
487 |
$self->{dirbf}{$dir}->buildfile($fname);
|
488 |
|
489 |
$self->verbose("initialisation complete for dir BuildFile $dir");
|
490 |
}
|
491 |
return $self->{dirbf}{$dir};
|
492 |
}
|
493 |
|
494 |
sub getclass2 {
|
495 |
my $self=shift;
|
496 |
my $dirname = shift;
|
497 |
my $Class="DEFAULT";
|
498 |
my $ClassDir="";
|
499 |
|
500 |
#return if $dirname eq "";
|
501 |
my @DIRA=split /\//, $dirname;
|
502 |
|
503 |
my $thispath=".";
|
504 |
# -- construct all class buildfiles in the path
|
505 |
for ( $i=0; $i<=$#DIRA; $i++ ) {
|
506 |
#$thispath=(($thispath eq "")?$DIRA[$i]:$thispath."/".$DIRA[$i]);
|
507 |
$thispath=$thispath."/".$DIRA[$i];
|
508 |
if ( ! exists $self->{pathbf}{$thispath} ) {
|
509 |
$self->verbose("Initialising BuildFile in $thispath");
|
510 |
$self->{pathbf}{$thispath}=$self->_startbuildfile($thispath);
|
511 |
}
|
512 |
# -- check class overriden by BuildFile
|
513 |
if ( defined $self->{pathbf}{$thispath}->classname() ) {
|
514 |
$Class=$self->{pathbf}{$thispath}->classname();
|
515 |
$ClassDir=$thispath;
|
516 |
}
|
517 |
else {
|
518 |
# -- sort it out from classpath directives
|
519 |
foreach $BlockClassA ( @{$self->{LoBCA}} ) {
|
520 |
next if ( $#{$BlockClassA} < $i );
|
521 |
$elem=${$BlockClassA}[$i];
|
522 |
if ( $elem=~/^$DIRA[$i]\+/ ) {
|
523 |
$elem=~s/^$DIRA[$i]//;
|
524 |
}
|
525 |
#print $elem." ".$DIRA[$i]."\n";
|
526 |
if ( $elem=~/^\+/ ) {
|
527 |
($Class=$elem)=~s/^\+//;
|
528 |
$ClassDir=$thispath;
|
529 |
}
|
530 |
#}
|
531 |
}
|
532 |
}
|
533 |
}
|
534 |
# -- default case
|
535 |
if ( $ClassDir eq "" ) {
|
536 |
if ( ! defined $self->{pathbf}{'.'}) {
|
537 |
$self->{pathbf}{'.'}=$self->_startbuildfile(".");
|
538 |
$self->verbose("DEFAULT class initialised : ".$self->{pathbf}{'.'});
|
539 |
}
|
540 |
$ClassDir=".";
|
541 |
}
|
542 |
|
543 |
# -- returns
|
544 |
($ClassDir_c=$ClassDir)=~s/^\.\///;
|
545 |
return ( $Class, $ClassDir_c, $self->{pathbf}{$ClassDir});
|
546 |
}
|
547 |
|
548 |
sub getclass {
|
549 |
my $self=shift;
|
550 |
my $dirname = shift;
|
551 |
|
552 |
my $Class="DEFAULT";
|
553 |
my $ClassDir=".";
|
554 |
|
555 |
# return if $dirname eq "";
|
556 |
my @DIRA=split /\//, $dirname;
|
557 |
|
558 |
my $thispath="";
|
559 |
for ( $i=0; $i<=$#DIRA; $i++ ) {
|
560 |
$thispath=(($thispath eq "")?$DIRA[$i]:$thispath."/".$DIRA[$i]);
|
561 |
|
562 |
# -- sort it out from classpath directives
|
563 |
foreach $BlockClassA ( @{$self->{LoBCA}} ) {
|
564 |
next if ( $#{$BlockClassA} < $i );
|
565 |
$elem=${$BlockClassA}[$i];
|
566 |
if ( $elem=~/^$DIRA[$i]\+/ ) {
|
567 |
$elem=~s/^$DIRA[$i]//;
|
568 |
}
|
569 |
#print $elem." ".$DIRA[$i]."\n";
|
570 |
if ( $elem=~/^\+/ ) {
|
571 |
($Class=$elem)=~s/^\+//;
|
572 |
$ClassDir=$thispath;
|
573 |
}
|
574 |
}
|
575 |
}
|
576 |
return ( $Class, $ClassDir );
|
577 |
}
|
578 |
|
579 |
#
|
580 |
# Check to see if the buildfile is local or in the release area and
|
581 |
# parse appropriately
|
582 |
#
|
583 |
sub _startbuildfile {
|
584 |
my $self=shift;
|
585 |
my $classdir=shift;
|
586 |
|
587 |
my $bf=BuildSystem::BuildFile->new($self->{area},$self);
|
588 |
my $thisfile="$classdir/$self->{buildfilename}";
|
589 |
|
590 |
if ( -e $self->{localtop}."/".$thisfile ) {
|
591 |
$bf->buildfile($self->{localtop}."/".$thisfile);
|
592 |
$bf->ParseBuildFile($self->{localtop}, $classdir,
|
593 |
$self->{buildfilename});
|
594 |
}
|
595 |
elsif ( -e $self->{releasetop}."/".$thisfile ) {
|
596 |
$bf->buildfile($self->{releasetop}."/".$thisfile);
|
597 |
$bf->ParseBuildFile($self->{releasetop}, $classdir,
|
598 |
$self->{buildfilename});
|
599 |
}
|
600 |
return $bf;
|
601 |
}
|
602 |
|
603 |
sub _topbuildfile {
|
604 |
my $self=shift;
|
605 |
|
606 |
$self->verbose("Generating Top Level BuildFile");
|
607 |
# -- Analyse project buildfile if it exists
|
608 |
|
609 |
my $topbf=$self->_gettopbf();
|
610 |
|
611 |
# -- generate top level makefile
|
612 |
undef $ENV{LatestBuildFile};
|
613 |
$topbf->ParseBuildFile($self->{localtop},
|
614 |
$self->{projconfigdir},$self->{buildfilename});
|
615 |
|
616 |
# -- Extract BuildStructure Information
|
617 |
my @ClassPaths=split /:/, $self->{topbf}->BlockClassPath();
|
618 |
foreach $BClassPath ( @ClassPaths ) {
|
619 |
next if ( $BClassPath eq "");
|
620 |
push @{$self->{LoBCA}}, [ split /\//, $BClassPath ];
|
621 |
}
|
622 |
$self->verbose("End top buildfile generation");
|
623 |
}
|
624 |
|
625 |
sub _checkdatestampindir {
|
626 |
my $self=shift;
|
627 |
my $dir=shift;
|
628 |
|
629 |
# -- get all local .ds files
|
630 |
my $fh=FileHandle->new();
|
631 |
my $ldir=$self->{localtop}."/".$self->{workdir}."/".$dir;
|
632 |
opendir $fh, $ldir;
|
633 |
my @dsfiles= grep /^.*\.ds$/, readdir $fh;
|
634 |
$fh->close();
|
635 |
|
636 |
# -- copy across ds files from releasetop if not existing locally
|
637 |
if ( $#dsfiles < 0 ) {
|
638 |
# -- get all releasetop .ds files
|
639 |
my $rdir=$self->{releasetop}."/".$self->{workdir}."/".$dir;
|
640 |
opendir $fh, $rdir;
|
641 |
my @releasedsfiles= grep /^.*\.ds$/, readdir $fh;
|
642 |
foreach $file ( @releasedsfiles ) {
|
643 |
use File::Copy;
|
644 |
$self->verbose("Copying $file from $rdir to $ldir");
|
645 |
copy($rdir."/".$file,$ldir."/".$file);
|
646 |
}
|
647 |
$fh->close();
|
648 |
@dsfiles=@releasedsfiles;
|
649 |
}
|
650 |
|
651 |
# -- process ds files
|
652 |
my $file;
|
653 |
foreach $datafile ( @dsfiles ) {
|
654 |
$self->verbose("Processing $ldir/$datafile\n");
|
655 |
my $ds=BuildSystem::DateStampRecord->new($ldir."/".$datafile);
|
656 |
$ds->verbosity($self->verbosity());
|
657 |
my $date;
|
658 |
my $needsupdate;
|
659 |
my $productfile=$ds->product();
|
660 |
my (%files,%moddate);
|
661 |
|
662 |
# now get dates in our dependency list
|
663 |
my @datedfiles=$ds->dated();
|
664 |
if ( $#datedfiles >= 0 ) {
|
665 |
|
666 |
$needsupdate=1;
|
667 |
$date=$datedfiles[0][1]-1;
|
668 |
}
|
669 |
else {
|
670 |
# -- extra checks for local replacement of files
|
671 |
foreach $file ( $ds->contents() ) {
|
672 |
# -- only check files
|
673 |
if ( -f $file ) {
|
674 |
$files{$file}=$ds->filedate($file);
|
675 |
# -- check to see if we have a new local copy
|
676 |
if ( ($file=~/\Q$self->{releasetop}\E/) &&
|
677 |
($self->{releasetop} ne $self->{localtop}) ) {
|
678 |
($tempfile=$file)=~s/\Q$self->{releasetop}\E/$self->{localtop}/;
|
679 |
if ( -f $tempfile ) {
|
680 |
$files{$tempfile}=$files{$file};
|
681 |
$file=$tempfile;
|
682 |
}
|
683 |
}
|
684 |
$moddate{$file}=(stat($file))[9];
|
685 |
if ( $moddate{$file} != $files{$file} ) {
|
686 |
$self->verbose($file." changed");
|
687 |
$date=$moddate{$file}-1;
|
688 |
$needsupdate=1;
|
689 |
}
|
690 |
}
|
691 |
}
|
692 |
}
|
693 |
# time stamp the product file to be older than the dependencies
|
694 |
if ( $needsupdate == 1 ) { # touch file into the past
|
695 |
my $newproductfile;
|
696 |
if ( $productfile!~/\Q$self->{localtop}\E/ ) {
|
697 |
if ( $productfile=~/\Q$self->{releasetop}\E/ ) {
|
698 |
($newproductfile=$productfile)=~
|
699 |
s/\Q$self->{releasetop}\E/$self->{localtop}/;
|
700 |
$self->verbose("Copying $productfile to $newproductfile");
|
701 |
copy($productfile,$newproductfile);
|
702 |
}
|
703 |
else { # assume no path to worry about
|
704 |
$newproductfile=$self->{localtop}."/".$ENV{workdir}.
|
705 |
"/".$productfile;
|
706 |
# -- make a local copy of the product file if not already here
|
707 |
my $oldproductfile=$self->{releasetop}."/".$ENV{workdir}.
|
708 |
"/".$productfile;
|
709 |
if ( ! -f $newproductfile ) {
|
710 |
if ( -f $oldproductfile ) {
|
711 |
$self->verbose("Copying $oldproductfile to $newproductfile");
|
712 |
copy($oldproductfile,$newproductfile);
|
713 |
}
|
714 |
}
|
715 |
}
|
716 |
}
|
717 |
else {
|
718 |
$newproductfile=$productfile;
|
719 |
}
|
720 |
if ( -f $newproductfile ) {
|
721 |
$self->verbose("Blasting $newproductfile to the past ($date)");
|
722 |
# If the (local) productfile exists - make it older
|
723 |
utime($date,$date,$newproductfile);
|
724 |
}
|
725 |
else {
|
726 |
$self->verbose("SomeThing Wrong(?) with $newproductfile\n".
|
727 |
"RELEASETOP=".$self->{releasetop}."\n".
|
728 |
"LOCALTOP=".$self->{localtop}."\n".
|
729 |
"workdir=".$ENV{workdir});
|
730 |
}
|
731 |
}
|
732 |
else {
|
733 |
$self->verbose("No need to touch $productfile");
|
734 |
}
|
735 |
}
|
736 |
undef $fh;
|
737 |
}
|