ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolManager.pm
Revision: 1.11
Committed: Fri Jul 15 15:27:27 2005 UTC (19 years, 10 months ago) by sashby
Content type: text/plain
Branch: MAIN
Changes since 1.10: +30 -1 lines
Log Message:
First fully-working version.

File Contents

# Content
1 #____________________________________________________________________
2 # File: ToolManager.pm
3 #____________________________________________________________________
4 #
5 # Author: Shaun Ashby <Shaun.Ashby@cern.ch>
6 # Update: 2003-11-12 15:04:16+0100
7 # Revision: $Id: ToolManager.pm,v 1.10 2005/06/28 19:08:55 sashby Exp $
8 #
9 # Copyright: 2003 (C) Shaun Ashby
10 #
11 #--------------------------------------------------------------------
12 package BuildSystem::ToolManager;
13 require 5.004;
14
15 use Exporter;
16 use BuildSystem::ToolCache;
17 use BuildSystem::ToolParser;
18 use Utilities::AddDir;
19 use URL::URLhandler;
20 use Utilities::Verbose;
21
22 @ISA=qw(BuildSystem::ToolCache Utilities::Verbose);
23 @EXPORT_OK=qw( );
24 #
25
26 sub new
27 ###############################################################
28 # new #
29 ###############################################################
30 # modified : Wed Nov 12 10:34:10 2003 / SFA #
31 # params : #
32 # : #
33 # function : #
34 # : #
35 ###############################################################
36 {
37 my $proto=shift;
38 my $class=ref($proto) || $proto;
39 my $self=$class->SUPER::new(); # Inherit from ToolCache
40 my $projectarea=shift;
41
42 bless $self,$class;
43
44 $self->{arch}=shift;
45 $self->{topdir}=$projectarea->location();
46 $self->{configdir}=$self->{topdir}."/".$projectarea->configurationdir();
47 $self->{cache}=$projectarea->cache(); # Download tool cache
48 $self->{toolfiledir}=$self->{topdir}."/.SCRAM/InstalledTools";
49 $self->{datastore}=$self->{topdir}."/.SCRAM";
50 $self->{archstore}=$self->{topdir}."/.SCRAM/".$ENV{SCRAM_ARCH};
51
52 # Make sure our tool download dir exists:
53 AddDir::adddir($self->{toolfiledir});
54 AddDir::adddir($self->{archstore});
55
56 # Set the tool cache file to read/write:
57 $self->name($projectarea->toolcachename());
58
59 # Check for the downloaded tools cache:
60 if (exists($self->{cache}))
61 {
62 $self->{urlhandler}=URL::URLhandler->new($self->{cache});
63 }
64
65 return $self;
66 }
67
68 sub clone()
69 {
70 my $self=shift;
71 my $projectarea=shift;
72
73 # Change cache settings to reflect the new location:
74 $self->{topdir}=$projectarea->location();
75
76 $self->{configdir}=$self->{topdir}."/".$projectarea->configurationdir();
77 $self->{toolfiledir}=$self->{topdir}."/.SCRAM/InstalledTools";
78 $self->{datastore}=$self->{topdir}."/.SCRAM";
79 $self->{archstore}=$self->{topdir}."/.SCRAM/".$ENV{SCRAM_ARCH};
80
81 # Change the cache name:
82 $self->name($projectarea->toolcachename());
83 $self->cloned_tm(1);
84
85 return $self;
86 }
87
88 sub arch_change_after_copy()
89 {
90 my $self=shift;
91 my ($newarch, $cachename)=@_;
92 # Make changes to arch-specific settings when copying tool manager
93 # object to another arch during setup:
94 $self->{arch} = $newarch;
95 $self->{archstore} = $self->{topdir}."/.SCRAM/".$newarch;
96 # Change the name of the cache to reflect new (arch-specific) location:
97 $self->name($cachename);
98 }
99
100 sub interactive()
101 {
102 my $self=shift;
103 # Interactive mode on/off:
104 @_ ? $self->{interactive} = shift
105 : ((defined $self->{interactive}) ? $self->{interactive} : 0);
106 }
107
108 sub setupalltools()
109 {
110 my $self = shift;
111 my ($arealocation,$setupopt) = @_;
112 my (@localtools);
113 my $selected;
114
115 # Get the selected tool list. Handle the case where there might not be
116 # any selected tools: //FIXME: need to handle case where there are no
117 # selected tools (not very often but a possibility):
118 my $sel = $self->selected();
119
120 if (defined ($sel))
121 {
122 $selected = [ keys %{$sel} ];
123 }
124
125 # Setup option "setupopt" directs the setup: 1 is for booting from
126 # scratch, 0 is when just doing "scram setup" (in this case we don't
127 # want to pick up everything from any scram-managed projects):
128 if ($setupopt == 1) # We're booting from scratch
129 {
130 # Check to see if there are any SCRAM-managed projects in our local requirements:
131 my $scramprojects = $::scram->_loadscramdb();
132
133 # Look for a match in the scram db:
134 foreach my $S (@$selected)
135 {
136 if (exists ($scramprojects->{$S}))
137 {
138 # Now check the version required exists in
139 # list of scram projects with this name:
140 while (my ($pdata,$plocation) = each %{$scramprojects->{$S}})
141 {
142 # Split the $pdata string to get the real name and the version:
143 my ($pname,$pversion) = split(":",$pdata);
144 if ($pversion eq $self->defaultversion($S))
145 {
146 # Get the tool manager for the scram project:
147 my $sa=$::scram->scramfunctions()->scramprojectdb()->getarea($pname,$pversion);
148 # Load the tool cache:
149 if ( -r $sa->toolcachename())
150 {
151 use Cache::CacheUtilities;
152 my $satoolmanager=&Cache::CacheUtilities::read($sa->toolcachename());
153 # Copy needed content from toolmanager for scram-managed project:
154 $self->inheritcontent($satoolmanager);
155 }
156 }
157 }
158 # Also add this scram-managed project to list of tools to set up:
159 push(@localtools,$S);
160 }
161 else
162 {
163 # Store other tools in ReqDoc in separate array. We will set up these tools later:
164 push(@localtools,$S);
165 }
166 }
167
168 # Set up extra tools required in this project, in addition to
169 # any scram-managed projects
170 foreach my $localtool (@localtools)
171 {
172 # First check to see if it's already set up (i.e., was contained
173 # in list of requirements for scram project):
174 if (! $self->definedtool($localtool))
175 {
176 $self->toolsetup($arealocation,$localtool,$self->defaultversion($localtool));
177 $self->addtoselected($localtool);
178 }
179 else
180 {
181 print $localtool," already set up.","\n",if ($ENV{SCRAM_DEBUG});
182 }
183 }
184 }
185 else
186 {
187 # Just loop over all tools and setup again:
188 foreach my $localtool (@{$selected})
189 {
190 $self->toolsetup($arealocation,$localtool,$self->defaultversion($localtool));
191 }
192 }
193
194 print "\n";
195 }
196
197 sub coresetup()
198 {
199 my $self=shift;
200 my ($toolname, $toolversion, $toolfile) = @_;
201 my ($toolcheck, $toolparser);
202
203 print "\n";
204 print $::bold."Setting up ",$toolname," version ",$toolversion,": ".$::normal,"\n";
205
206 # New ToolParser object for this tool if there isn't one already.
207 # Look in array of raw tools to see if this tool has a ToolParser object:
208 $toolcheck=0;
209
210 map
211 {
212 if ($_->toolname() eq $toolname) {$toolcheck = 1; $toolparser = $_;}
213 } $self->rawtools();
214
215 # Tool not known so we create a new ToolParser object and parse it:
216 if ($toolcheck != 1)
217 {
218 $toolparser = BuildSystem::ToolParser->new();
219 # We only want to store the stuff relevant for one particular version:
220 $toolparser->parse($toolname, $toolversion, $toolfile);
221 # Store the ToolParser object in the cache:
222 $self->store($toolparser);
223 }
224
225 # Next, set up the tool:
226 my $store = $toolparser->processrawtool($self->interactive());
227 # Make sure that we have this tool in the list of selected tools (just in case this tool was
228 # set up by hand afterwards):
229 $self->addtoselected($toolname);
230
231 # Check to see if this tool is a compiler. If so, store it.
232 # Also store the language that this compiler supprots, and a
233 # compiler name (e.g. gcc323) which, in conjunction with a stem
234 # architecture name like slc3_ia32_, can be used to build a complete arch string:
235 if ($store->scram_compiler() == 1)
236 {
237 my @supported_language = $store->flags("SCRAM_LANGUAGE_TYPE");
238 my @compilername = $store->flags("SCRAM_COMPILER_NAME");
239 $self->scram_compiler($supported_language[0],$toolname,$compilername[0]);
240 }
241
242 # Store the ToolData object in the cache:
243 $self->storeincache($toolparser->toolname(),$store);
244 return $self;
245 }
246
247 sub toolsetup()
248 {
249 my $self=shift;
250 my ($arealocation, $toolname, $toolversion, $toolurl) = @_;
251 my ($urlcache, $url, $filename, $tfname);
252 my $toolfile;
253
254 $toolname =~ tr[A-Z][a-z];
255 $toolversion ||= $self->defaultversion($toolname);
256 $urlcache=URL::URLcache->new($arealocation."/.SCRAM/cache"); # Download tool cache
257
258 # Check for the downloaded tools cache:
259 if (defined($urlcache))
260 {
261 $self->{urlhandler}=URL::URLhandler->new($urlcache);
262 }
263
264 $url = $self->toolurls()->{$toolname};
265 $filename = $self->{toolfiledir}."/".$toolname;
266
267 # If .SCRAM/InstalledTools doesn't exist, create it:
268 if (! -d $self->{toolfiledir})
269 {
270 AddDir::adddir($self->{toolfiledir});
271 }
272
273 # First, check to see if there was a tool URL given. If so, we might need to read
274 # from http or from a file: type URL:
275 if (my ($proto, $urlv) = ($toolurl =~ /(.*):(.*)/))
276 {
277 # See what kind of URL (file:, http:, cvs:, svn:, .. ):
278 if ($proto eq 'file')
279 {
280 # Check to see if there is a ~ and substitute the user
281 # home directory if there is:
282 my ($urlpath) = ($urlv =~ m|^\~/(.*)$|);
283 $urlv = $ENV{HOME}."/".$urlpath;
284
285 # If the tool url is a file and the file exists,
286 # copy it to .SCRAM/InstalledTools and set the
287 # filename accordingly:
288 if ( -f $urlv)
289 {
290 use File::Copy;
291 copy($urlv, $filename);
292 my $mode = 0644; chmod $mode, $filename;
293 $toolfile=$filename;
294 }
295 else
296 {
297 $::scram->scramerror("Unable to set up $toolname from URL $toolurl-- $urlv does not exist!");
298 }
299 }
300 elsif ($proto eq 'http')
301 {
302 print "SCRAM: downloading $toolname from $toolurl","\n";
303 # Download from WWW first:
304 use LWP::Simple qw(&getstore);
305 my $http_response_val = &getstore($toolurl, $filename);
306
307 # Check the HTTP status. If doc not found, exit:
308 if ($http_response_val != 200)
309 {
310 my ($server,$doc) = ($urlv =~ m|//(.*?)/(.*)|);
311 $::scram->scramerror("Unable to set up $toolname: $doc not found on $server!");
312 }
313 else
314 {
315 $toolfile=$filename;
316 }
317 }
318 elsif ($proto eq 'cvs')
319 {
320 print "SCRAM: downloading $toolname from $urlv using protocol $proto.","\n";
321 print "[ not yet supported ]","\n";
322 exit(0);
323 }
324 elsif ($proto eq 'svn')
325 {
326 print "SCRAM: downloading $toolname from $urlv using protocol $proto.","\n";
327 print "[ not yet supported ]","\n";
328 exit(0);
329 }
330 else
331 {
332 $::scram->scramerror("Unable to download $urlv! Unknown protocol \"$proto\". Bye.");
333 }
334 }
335 else
336 {
337 # Copy the downloaded tool file to InstalledTools directory:
338 if ( ! -f $filename )
339 {
340 # If the URL is empty, the chances are that this tool was not downloaded to .SCRAM/InstalledTools.
341 # We signal an error and exit:
342 if ($url eq '')
343 {
344 $::scram->scramerror("$toolname was selected in project requirements but is not in the configuration!");
345 }
346 else
347 {
348 # Otherwise, we try to download it:
349 $self->verbose("Attempting Download of $url");
350 # Get file from download cache:
351 ($url,$filename)=$self->{urlhandler}->get($url);
352 use File::Copy;
353 $tfname=$self->{toolfiledir}."/".$toolname;
354 copy($filename, $tfname);
355 my $mode = 0644; chmod $mode, $tfname;
356 $toolfile=$tfname;
357 }
358 }
359 else
360 {
361 # File already exists in the .SCRAM/InstallTools directory:
362 $toolfile=$filename;
363 }
364 }
365
366 # Run the core setup routine:
367 $self->coresetup($toolname, $toolversion, $toolfile);
368 return $self;
369 }
370
371 sub setupself()
372 {
373 my $self=shift;
374 my ($location)=@_;
375 # Process the file "Self" in local config directory. This is used to
376 # set all the paths/runtime settings for this project:
377 my $filename=$location."/config/Self";
378
379 if ( -f $filename )
380 {
381 print "\n";
382 print $::bold."Setting up SELF:".$::normal,"\n";
383 # Self file exists so process it:
384 $selfparser = BuildSystem::ToolParser->new();
385 $selfparser->parse('self','SELF',$filename);
386
387 # Next, set up the tool:
388 $store = $selfparser->processrawtool($self->interactive());
389
390 # If we are in a developer area, also add RELEASETOP paths:
391 if (exists($ENV{RELEASETOP}))
392 {
393 print "\nAdding RELEASE area settings to self....OK","\n", if ($ENV{SCRAM_DEBUG});
394 $store->addreleasetoself();
395 }
396
397 # Store the ToolData object in the cache:
398 $self->storeincache($selfparser->toolname(),$store);
399 print "\n";
400 }
401 else
402 {
403 print "\n";
404 print "SCRAM: No file config/Self...nothing to do.";
405 print "\n";
406 return;
407 }
408 }
409
410 sub defaultversion()
411 {
412 my $self = shift;
413 my ($tool) = @_;
414 # Return default versions as taken from configuration:
415 return (%{$self->defaultversions()}->{$tool});
416 }
417
418 sub storeincache()
419 {
420 my $self=shift;
421 my ($toolname,$dataobject)=@_;
422
423 # Store ToolData object (for a set-up tool) in cache:
424 if (ref($dataobject) eq 'BuildSystem::ToolData')
425 {
426 $self->{SETUP}->{$toolname} = $dataobject;
427 }
428 else
429 {
430 $::scram->scramerror("ToolManager: BuildSystem::ToolData object reference expected.")
431 }
432 }
433
434 sub tools()
435 {
436 my $self = shift;
437 my @tools;
438
439 map
440 {
441 if ($_ ne "self")
442 {
443 push(@tools, $_);
444 }
445 } keys %{$self->{SETUP}};
446
447 # Return list of set-up tools:
448 return @tools;
449 }
450
451 sub toolsdata()
452 {
453 my $self = shift;
454 my $tooldata = [];
455 my $rawsel = $self->selected();
456
457 foreach my $tool ( sort { %{$rawsel}->{$a}
458 <=> %{$rawsel}->{$b}}
459 keys %{$rawsel} )
460 {
461 # Return tool data objects of all set-up tools, skipping the tool "self":
462 if ($_ ne "self")
463 {
464 # Keep only tools that have really been set up:
465 if (exists $self->{SETUP}->{$tool})
466 {
467 push(@tooldata,$self->{SETUP}->{$tool});
468 }
469 }
470 }
471
472 # Return the array of tools, in order that they appear in RequirementsDoc:
473 return @tooldata;
474 }
475
476 sub definedtool()
477 {
478 my $self=shift;
479 my ($tool)=@_;
480
481 # Check to see if tool X is an external tool:
482 grep ($_ eq $tool, keys %{$self->{SETUP}}) ? return 1
483 : return 0;
484 }
485
486 sub checkifsetup()
487 {
488 my $self=shift;
489 my ($tool)=@_;
490 # Return the ToolData object if the tool has been set up:
491 (exists $self->{SETUP}->{$tool}) ? return ($self->{SETUP}->{$tool})
492 : return undef;
493 }
494
495 sub cloned_tm()
496 {
497 my $self=shift;
498 # Has this area already been cloned and brought in-line with current location:
499 @_ ? $self->{CLONED} = $_[0]
500 : $self->{CLONED};
501 }
502
503 sub remove_tool()
504 {
505 my $self=shift;
506 my ($toolname)=@_;
507 my $tools = $self->{SETUP};
508 my $newtlist = {};
509
510 while (my ($tool, $tooldata) = each %$tools)
511 {
512 if ($tool ne $toolname)
513 {
514 $newtlist->{$tool} = $tooldata;
515 }
516 else
517 {
518 # Is this tool a compiler?
519 if ($tooldata->scram_compiler() == 1)
520 {
521 # Also remove this from the compiler info if there happens to be an entry:
522 while (my ($langtype, $ctool) = each %{$self->{SCRAM_COMPILER}})
523 {
524 if ($toolname eq $ctool->[0])
525 {
526 delete $self->{SCRAM_COMPILER}->{$langtype};
527 print "Deleting compiler $toolname from cache.","\n";
528 }
529 }
530 }
531 else
532 {
533 print "Deleting $toolname from cache.","\n";
534 }
535 }
536 }
537
538 $self->{SETUP} = $newtlist;
539
540 # Now remove from the RAW tool list:
541 $self->cleanup_raw($toolname);
542 print "ToolManager: Updating tool cache.","\n";
543 $self->writecache();
544 }
545
546 sub scram_projects()
547 {
548 my $self=shift;
549 my $scram_projects={};
550
551 foreach my $t ($self->tools())
552 {
553 # Get the ToolData object:
554 my $td=$self->{SETUP}->{$t};
555 $scram_projects->{$t}=$td->variable_data(uc($t)."_BASE"), if ($td->scram_project());
556 }
557
558 return $scram_projects;
559 }
560
561 sub scram_compiler()
562 {
563 my $self=shift;
564 my ($langtype, $toolname, $compilername)=@_;
565
566 if ($langtype)
567 {
568 # Store the compiler info according to supported
569 # language types.
570 #
571 # ---------------------- e.g C++ cxxcompiler gcc323
572 $self->{SCRAM_COMPILER}->{$langtype}=[ $toolname, $compilername ];
573 }
574 else
575 {
576 return $self->{SCRAM_COMPILER};
577 }
578 }
579
580 sub updatecompiler()
581 {
582 my $self=shift;
583 my ($compilername, $compilerobj) = @_;
584
585 # Replace the existing copy of the tool with the new one:
586 if (exists $self->{SETUP}->{$compilername})
587 {
588 # Check to make sure that we were really passed a compiler with
589 # the desired name:
590 if ($compilerobj->toolname() eq $compilername)
591 {
592 print "ToolManager: Updating the cached copy of ".$compilername."\n";
593 delete $self->{SETUP}->{$compilername};
594 $self->{SETUP}->{$compilername} = $compilerobj;
595 $self->writecache();
596 }
597 else
598 {
599 print "WARNING: compiler name (".$compilername.") and tool obj name (".$compilerobj->toolname().") don't match!","\n";
600 print " Not making any changes.","\n";
601 }
602 }
603 else
604 {
605 print "WARNING: No entry in cache for ".$compilername.". Not making any updates.\n";
606 }
607 }
608
609 1;