ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolManager.pm
Revision: 1.14
Committed: Wed May 17 12:21:57 2006 UTC (18 years, 11 months ago) by sashby
Content type: text/plain
Branch: MAIN
Changes since 1.13: +40 -3 lines
Log Message:
Compatibility fixes when reading caches from other scram projects.

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.14 # Revision: $Id: ToolManager.pm,v 1.13 2005/10/07 16:05:44 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 sashby 1.14 # Copy needed content from toolmanager for scram-managed project only
154     # if the projects have compatible configurations (compare first set of
155     # digits):
156     if ($self->check_compatibility($satoolmanager))
157     {
158     print "DEBUG: $pname and current project have compatible configurations.\n";
159     $self->inheritcontent($satoolmanager);
160     }
161     else
162     {
163     print "DEBUG: $pname and current project do NOT have compatible configurations. Skipping...\n";
164     }
165 sashby 1.2 }
166     }
167     }
168     # Also add this scram-managed project to list of tools to set up:
169     push(@localtools,$S);
170     }
171     else
172     {
173     # Store other tools in ReqDoc in separate array. We will set up these tools later:
174     push(@localtools,$S);
175     }
176     }
177    
178     # Set up extra tools required in this project, in addition to
179     # any scram-managed projects
180     foreach my $localtool (@localtools)
181     {
182     # First check to see if it's already set up (i.e., was contained
183     # in list of requirements for scram project):
184     if (! $self->definedtool($localtool))
185     {
186     $self->toolsetup($arealocation,$localtool,$self->defaultversion($localtool));
187     $self->addtoselected($localtool);
188     }
189     else
190     {
191     print $localtool," already set up.","\n",if ($ENV{SCRAM_DEBUG});
192     }
193     }
194     }
195     else
196     {
197     # Just loop over all tools and setup again:
198     foreach my $localtool (@{$selected})
199     {
200     $self->toolsetup($arealocation,$localtool,$self->defaultversion($localtool));
201     }
202     }
203    
204     print "\n";
205     }
206    
207     sub coresetup()
208     {
209     my $self=shift;
210 sashby 1.13 my ($toolname, $toolversion, $toolfile, $force) = @_;
211 sashby 1.2 my ($toolcheck, $toolparser);
212    
213     print "\n";
214     print $::bold."Setting up ",$toolname," version ",$toolversion,": ".$::normal,"\n";
215    
216     # New ToolParser object for this tool if there isn't one already.
217     # Look in array of raw tools to see if this tool has a ToolParser object:
218     $toolcheck=0;
219    
220     map
221     {
222     if ($_->toolname() eq $toolname) {$toolcheck = 1; $toolparser = $_;}
223     } $self->rawtools();
224    
225     # Tool not known so we create a new ToolParser object and parse it:
226 sashby 1.13 if ($toolcheck != 1 || $force == 1)
227 sashby 1.2 {
228     $toolparser = BuildSystem::ToolParser->new();
229     # We only want to store the stuff relevant for one particular version:
230     $toolparser->parse($toolname, $toolversion, $toolfile);
231     # Store the ToolParser object in the cache:
232     $self->store($toolparser);
233 sashby 1.13 print "\nFile $toolfile reparsed (modified)","\n",if ($ENV{SCRAM_DEBUG});
234 sashby 1.2 }
235    
236     # Next, set up the tool:
237     my $store = $toolparser->processrawtool($self->interactive());
238     # Make sure that we have this tool in the list of selected tools (just in case this tool was
239     # set up by hand afterwards):
240     $self->addtoselected($toolname);
241 sashby 1.8
242     # Check to see if this tool is a compiler. If so, store it.
243     # Also store the language that this compiler supprots, and a
244     # compiler name (e.g. gcc323) which, in conjunction with a stem
245     # architecture name like slc3_ia32_, can be used to build a complete arch string:
246     if ($store->scram_compiler() == 1)
247     {
248     my @supported_language = $store->flags("SCRAM_LANGUAGE_TYPE");
249     my @compilername = $store->flags("SCRAM_COMPILER_NAME");
250     $self->scram_compiler($supported_language[0],$toolname,$compilername[0]);
251     }
252    
253 sashby 1.2 # Store the ToolData object in the cache:
254     $self->storeincache($toolparser->toolname(),$store);
255     return $self;
256     }
257    
258     sub toolsetup()
259     {
260     my $self=shift;
261     my ($arealocation, $toolname, $toolversion, $toolurl) = @_;
262     my ($urlcache, $url, $filename, $tfname);
263     my $toolfile;
264 sashby 1.13 my $force = 0; # we may have to force a reparse of a tool file
265 sashby 1.6
266 sashby 1.2 $toolname =~ tr[A-Z][a-z];
267     $toolversion ||= $self->defaultversion($toolname);
268     $urlcache=URL::URLcache->new($arealocation."/.SCRAM/cache"); # Download tool cache
269 sashby 1.6
270 sashby 1.2 # Check for the downloaded tools cache:
271     if (defined($urlcache))
272     {
273     $self->{urlhandler}=URL::URLhandler->new($urlcache);
274     }
275 sashby 1.6
276 sashby 1.2 $url = $self->toolurls()->{$toolname};
277     $filename = $self->{toolfiledir}."/".$toolname;
278    
279 sashby 1.4 # If .SCRAM/InstalledTools doesn't exist, create it:
280     if (! -d $self->{toolfiledir})
281     {
282     AddDir::adddir($self->{toolfiledir});
283     }
284    
285 sashby 1.2 # First, check to see if there was a tool URL given. If so, we might need to read
286     # from http or from a file: type URL:
287     if (my ($proto, $urlv) = ($toolurl =~ /(.*):(.*)/))
288     {
289     # See what kind of URL (file:, http:, cvs:, svn:, .. ):
290     if ($proto eq 'file')
291     {
292 sashby 1.10 # Check to see if there is a ~ and substitute the user
293 sashby 1.13 # home directory if there is (file:~/xyz):
294     if (my ($urlpath) = ($urlv =~ m|^\~/(.*)$|))
295     {
296     $urlv = $ENV{HOME}."/".$urlpath;
297     }
298     elsif (my ($urlpath) = ($urlv =~ m|^\./(.*)$|))
299     {
300     # Relative to current directory (file:./xyz):
301     use Cwd qw(&cwd);
302     $urlv = cwd()."/".$urlpath;
303     }
304    
305 sashby 1.2 # If the tool url is a file and the file exists,
306     # copy it to .SCRAM/InstalledTools and set the
307     # filename accordingly:
308     if ( -f $urlv)
309     {
310     use File::Copy;
311     copy($urlv, $filename);
312 sashby 1.5 my $mode = 0644; chmod $mode, $filename;
313 sashby 1.2 $toolfile=$filename;
314 sashby 1.13 # Here we must account for the fact that the file tool doc may be
315     # a modified version of an existing tool in the current config. we
316     # make sure that this file is reparsed, even if there is already a
317     # ToolParser object for the tool:
318     $force = 1;
319 sashby 1.2 }
320     else
321     {
322 sashby 1.13 $::scram->scramerror("Unable to set up $toolname from URL \"$toolurl\" - $urlv does not exist!");
323 sashby 1.2 }
324     }
325     elsif ($proto eq 'http')
326     {
327     print "SCRAM: downloading $toolname from $toolurl","\n";
328     # Download from WWW first:
329     use LWP::Simple qw(&getstore);
330     my $http_response_val = &getstore($toolurl, $filename);
331 sashby 1.13
332 sashby 1.2 # Check the HTTP status. If doc not found, exit:
333     if ($http_response_val != 200)
334     {
335     my ($server,$doc) = ($urlv =~ m|//(.*?)/(.*)|);
336     $::scram->scramerror("Unable to set up $toolname: $doc not found on $server!");
337     }
338     else
339     {
340     $toolfile=$filename;
341     }
342     }
343     elsif ($proto eq 'cvs')
344     {
345     print "SCRAM: downloading $toolname from $urlv using protocol $proto.","\n";
346     print "[ not yet supported ]","\n";
347     exit(0);
348     }
349     elsif ($proto eq 'svn')
350     {
351     print "SCRAM: downloading $toolname from $urlv using protocol $proto.","\n";
352     print "[ not yet supported ]","\n";
353     exit(0);
354     }
355     else
356     {
357     $::scram->scramerror("Unable to download $urlv! Unknown protocol \"$proto\". Bye.");
358     }
359     }
360     else
361     {
362     # Copy the downloaded tool file to InstalledTools directory:
363     if ( ! -f $filename )
364     {
365 sashby 1.7 # If the URL is empty, the chances are that this tool was not downloaded to .SCRAM/InstalledTools.
366     # We signal an error and exit:
367 sashby 1.6 if ($url eq '')
368     {
369 sashby 1.7 $::scram->scramerror("$toolname was selected in project requirements but is not in the configuration!");
370 sashby 1.6 }
371     else
372     {
373     # Otherwise, we try to download it:
374     $self->verbose("Attempting Download of $url");
375     # Get file from download cache:
376     ($url,$filename)=$self->{urlhandler}->get($url);
377     use File::Copy;
378     $tfname=$self->{toolfiledir}."/".$toolname;
379     copy($filename, $tfname);
380     my $mode = 0644; chmod $mode, $tfname;
381     $toolfile=$tfname;
382     }
383 sashby 1.2 }
384     else
385     {
386     # File already exists in the .SCRAM/InstallTools directory:
387     $toolfile=$filename;
388     }
389     }
390    
391     # Run the core setup routine:
392 sashby 1.13 $self->coresetup($toolname, $toolversion, $toolfile,$force);
393 sashby 1.2 return $self;
394     }
395    
396     sub setupself()
397     {
398     my $self=shift;
399     my ($location)=@_;
400     # Process the file "Self" in local config directory. This is used to
401     # set all the paths/runtime settings for this project:
402     my $filename=$location."/config/Self";
403    
404     if ( -f $filename )
405     {
406     print "\n";
407     print $::bold."Setting up SELF:".$::normal,"\n";
408     # Self file exists so process it:
409     $selfparser = BuildSystem::ToolParser->new();
410     $selfparser->parse('self','SELF',$filename);
411    
412     # Next, set up the tool:
413     $store = $selfparser->processrawtool($self->interactive());
414    
415     # If we are in a developer area, also add RELEASETOP paths:
416     if (exists($ENV{RELEASETOP}))
417     {
418     print "\nAdding RELEASE area settings to self....OK","\n", if ($ENV{SCRAM_DEBUG});
419     $store->addreleasetoself();
420     }
421    
422     # Store the ToolData object in the cache:
423     $self->storeincache($selfparser->toolname(),$store);
424     print "\n";
425     }
426     else
427     {
428     print "\n";
429     print "SCRAM: No file config/Self...nothing to do.";
430     print "\n";
431     return;
432     }
433     }
434    
435     sub defaultversion()
436     {
437     my $self = shift;
438     my ($tool) = @_;
439     # Return default versions as taken from configuration:
440     return (%{$self->defaultversions()}->{$tool});
441     }
442    
443     sub storeincache()
444     {
445     my $self=shift;
446     my ($toolname,$dataobject)=@_;
447    
448     # Store ToolData object (for a set-up tool) in cache:
449     if (ref($dataobject) eq 'BuildSystem::ToolData')
450     {
451     $self->{SETUP}->{$toolname} = $dataobject;
452     }
453     else
454     {
455     $::scram->scramerror("ToolManager: BuildSystem::ToolData object reference expected.")
456     }
457     }
458    
459     sub tools()
460     {
461     my $self = shift;
462     my @tools;
463    
464     map
465     {
466     if ($_ ne "self")
467     {
468     push(@tools, $_);
469     }
470     } keys %{$self->{SETUP}};
471    
472     # Return list of set-up tools:
473     return @tools;
474     }
475    
476     sub toolsdata()
477     {
478     my $self = shift;
479     my $tooldata = [];
480     my $rawsel = $self->selected();
481    
482     foreach my $tool ( sort { %{$rawsel}->{$a}
483     <=> %{$rawsel}->{$b}}
484     keys %{$rawsel} )
485     {
486     # Return tool data objects of all set-up tools, skipping the tool "self":
487     if ($_ ne "self")
488     {
489     # Keep only tools that have really been set up:
490     if (exists $self->{SETUP}->{$tool})
491     {
492     push(@tooldata,$self->{SETUP}->{$tool});
493     }
494     }
495     }
496    
497     # Return the array of tools, in order that they appear in RequirementsDoc:
498     return @tooldata;
499     }
500    
501     sub definedtool()
502     {
503     my $self=shift;
504     my ($tool)=@_;
505    
506     # Check to see if tool X is an external tool:
507     grep ($_ eq $tool, keys %{$self->{SETUP}}) ? return 1
508     : return 0;
509     }
510    
511     sub checkifsetup()
512     {
513     my $self=shift;
514     my ($tool)=@_;
515     # Return the ToolData object if the tool has been set up:
516     (exists $self->{SETUP}->{$tool}) ? return ($self->{SETUP}->{$tool})
517     : return undef;
518     }
519    
520     sub cloned_tm()
521     {
522     my $self=shift;
523     # Has this area already been cloned and brought in-line with current location:
524     @_ ? $self->{CLONED} = $_[0]
525     : $self->{CLONED};
526     }
527    
528     sub remove_tool()
529     {
530     my $self=shift;
531     my ($toolname)=@_;
532     my $tools = $self->{SETUP};
533     my $newtlist = {};
534    
535     while (my ($tool, $tooldata) = each %$tools)
536     {
537     if ($tool ne $toolname)
538     {
539     $newtlist->{$tool} = $tooldata;
540     }
541     else
542     {
543 sashby 1.10 # Is this tool a compiler?
544     if ($tooldata->scram_compiler() == 1)
545     {
546     # Also remove this from the compiler info if there happens to be an entry:
547     while (my ($langtype, $ctool) = each %{$self->{SCRAM_COMPILER}})
548     {
549     if ($toolname eq $ctool->[0])
550     {
551     delete $self->{SCRAM_COMPILER}->{$langtype};
552     print "Deleting compiler $toolname from cache.","\n";
553     }
554     }
555     }
556     else
557     {
558     print "Deleting $toolname from cache.","\n";
559     }
560 sashby 1.2 }
561     }
562    
563     $self->{SETUP} = $newtlist;
564 sashby 1.10
565 sashby 1.2 # Now remove from the RAW tool list:
566     $self->cleanup_raw($toolname);
567     print "ToolManager: Updating tool cache.","\n";
568     $self->writecache();
569     }
570    
571     sub scram_projects()
572     {
573     my $self=shift;
574     my $scram_projects={};
575    
576     foreach my $t ($self->tools())
577     {
578     # Get the ToolData object:
579     my $td=$self->{SETUP}->{$t};
580     $scram_projects->{$t}=$td->variable_data(uc($t)."_BASE"), if ($td->scram_project());
581     }
582    
583     return $scram_projects;
584     }
585    
586 sashby 1.8 sub scram_compiler()
587     {
588     my $self=shift;
589     my ($langtype, $toolname, $compilername)=@_;
590    
591     if ($langtype)
592     {
593     # Store the compiler info according to supported
594     # language types.
595     #
596     # ---------------------- e.g C++ cxxcompiler gcc323
597     $self->{SCRAM_COMPILER}->{$langtype}=[ $toolname, $compilername ];
598     }
599     else
600     {
601     return $self->{SCRAM_COMPILER};
602     }
603     }
604    
605 sashby 1.12 sub updatetool()
606 sashby 1.11 {
607     my $self=shift;
608 sashby 1.12 my ($name, $obj) = @_;
609 sashby 1.11
610     # Replace the existing copy of the tool with the new one:
611 sashby 1.12 if (exists $self->{SETUP}->{$name})
612 sashby 1.11 {
613     # Check to make sure that we were really passed a compiler with
614     # the desired name:
615 sashby 1.12 if ($obj->toolname() eq $name)
616 sashby 1.11 {
617 sashby 1.12 print "ToolManager: Updating the cached copy of ".$name."\n";
618     delete $self->{SETUP}->{$name};
619     $self->{SETUP}->{$name} = $obj;
620 sashby 1.11 $self->writecache();
621     }
622     else
623     {
624 sashby 1.12 print "WARNING: Tool name (".$name.") and tool obj name (".$obj->toolname().") don't match!","\n";
625 sashby 1.11 print " Not making any changes.","\n";
626     }
627     }
628     else
629     {
630 sashby 1.12 print "WARNING: No entry in cache for ".$name.". Not making any updates.\n";
631 sashby 1.11 }
632     }
633    
634 sashby 1.14 sub check_compatibility()
635     {
636     my $self=shift;
637     my ($itoolmgr)=@_;
638     # Get the version of the toolmanager. If the project fails to return a version
639     # string we return 0 for no compatibility (in which case, all tools will be set
640     # up in the traditional way):
641     my $itm_configversion = $itoolmgr->configversion();
642     if ($itm_configversion)
643     {
644     # The configurations won't be identical. We must compare the digits:
645     my ($numeric_version) = ($itm_configversion =~ /[a-zA-Z]*\_([0-9a-z]*).*?/);
646     my $current_configversion = $self->configversion();
647     my ($current_numeric_version) = ($current_configversion =~ /[a-zA-Z]*\_([0-9a-z]*).*?/);
648     ($current_numeric_version == $numeric_version) && return 1; # OK, compatible;
649     }
650     # Project does not define configuration version so just return:
651     return 0;
652     }
653    
654     sub configversion()
655     {
656     my $self=shift;
657     @_ ? $self->{CONFIGVERSION} = shift
658     : $self->{CONFIGVERSION};
659     }
660    
661 sashby 1.2 1;