ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolManager.pm
Revision: 1.10
Committed: Tue Jun 28 19:08:55 2005 UTC (19 years, 10 months ago) by sashby
Content type: text/plain
Branch: MAIN
Changes since 1.9: +24 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 sashby 1.2 #____________________________________________________________________
2     # File: ToolManager.pm
3     #____________________________________________________________________
4     #
5     # Author: Shaun Ashby <Shaun.Ashby@cern.ch>
6     # Update: 2003-11-12 15:04:16+0100
7 sashby 1.10 # Revision: $Id: ToolManager.pm,v 1.9 2005/04/29 15:54:47 sashby Exp $
8 sashby 1.2 #
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 sashby 1.9
26 sashby 1.2 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 sashby 1.3
73 sashby 1.2 # 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 sashby 1.8
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 sashby 1.2 # 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 sashby 1.6
254 sashby 1.2 $toolname =~ tr[A-Z][a-z];
255     $toolversion ||= $self->defaultversion($toolname);
256     $urlcache=URL::URLcache->new($arealocation."/.SCRAM/cache"); # Download tool cache
257 sashby 1.6
258 sashby 1.2 # Check for the downloaded tools cache:
259     if (defined($urlcache))
260     {
261     $self->{urlhandler}=URL::URLhandler->new($urlcache);
262     }
263 sashby 1.6
264 sashby 1.2 $url = $self->toolurls()->{$toolname};
265     $filename = $self->{toolfiledir}."/".$toolname;
266    
267 sashby 1.4 # If .SCRAM/InstalledTools doesn't exist, create it:
268     if (! -d $self->{toolfiledir})
269     {
270     AddDir::adddir($self->{toolfiledir});
271     }
272    
273 sashby 1.2 # 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 sashby 1.10 # 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 sashby 1.2 # 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 sashby 1.5 my $mode = 0644; chmod $mode, $filename;
293 sashby 1.2 $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 sashby 1.7 # 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 sashby 1.6 if ($url eq '')
343     {
344 sashby 1.7 $::scram->scramerror("$toolname was selected in project requirements but is not in the configuration!");
345 sashby 1.6 }
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 sashby 1.2 }
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 sashby 1.10 # 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 sashby 1.2 }
536     }
537    
538     $self->{SETUP} = $newtlist;
539 sashby 1.10
540 sashby 1.2 # 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 sashby 1.8 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 sashby 1.2 1;