ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/BuildFile.pm
Revision: 1.18
Committed: Tue May 14 14:27:13 2002 UTC (23 years ago) by sashby
Content type: text/plain
Branch: MAIN
CVS Tags: SFATEST, V0_19_4, V0_19_4_pre3, V0_19_4_pre2
Branch point for: V0_19_4_B
Changes since 1.17: +181 -1 lines
Log Message:
Added module functionality

File Contents

# Content
1 # BuildFile
2 #
3 # Interface
4 # ---------
5 # new(toolbox)
6 # ParseBuildFile($base,$path,$file)
7 # ParseBuildFileExport(filename)
8 # BlockClassPath() : Return the class path
9 # ignore() : return 1 if directory should be ignored 0 otherwise
10
11 package BuildSystem::BuildFile;
12 use Utilities::Verbose;
13 use ActiveDoc::SimpleDoc;
14 use BuildSystem::ToolBox;
15 require 5.004;
16 @ISA=qw(Utilities::Verbose);
17
18 BEGIN {
19 $buildfile="BuildFile";
20 }
21
22 sub new {
23 my $class=shift;
24 my $self={};
25 bless $self, $class;
26 $self->{toolbox}=shift;
27 $self->{Arch}=1;
28 push @{$self->{ARCHBLOCK}}, $self->{Arch};
29 return $self;
30 }
31
32 sub ignore {
33 my $self=shift;
34 $self->verbose(">> ignore......<<");
35
36 return (defined $self->{ignore})?$self->{ignore}:0;
37 }
38
39 sub _initswitcher {
40 my $self=shift;
41 my $switch=ActiveDoc::SimpleDoc->new();
42 my $parse="makebuild";
43 $self->verbose(">> _initswitcher: <<");
44 $switch->newparse($parse);
45 $switch->addignoretags($parse);
46 $self->_commontags($switch,$parse);
47 $switch->addtag($parse,"Build", \&Build_start, $self);
48 $switch->addtag($parse,"none",
49 \&OutToMakefile,$self,
50 \&OutToMakefile, $self,
51 "", $self);
52 $switch->addtag($parse,"Bin",
53 \&Bin_start,$self,
54 \&OutToScreen, $self,
55 "", $self);
56 $switch->addtag($parse,"Module",
57 \&Module_start,$self,
58 \&OutToScreen, $self,
59 "", $self);
60
61 $switch->addtag($parse,"ProductStore",
62 \&Store_start,$self,
63 "", $self,
64 "", $self);
65 $switch->addtag($parse,"LibType",
66 \&LibType_Start,$self,
67 \&LibType_text, $self,
68 \&LibType_end,$self);
69 $switch->addtag($parse,"ConfigurationClass",
70 \&Class_StartTag,$self,
71 \&OutToMakefile, $self,
72 "", $self);
73 $switch->addtag($parse,"ClassPath",
74 \&setBlockClassPath,$self,
75 \&OutToMakefile, $self,
76 "", $self);
77 $switch->addtag($parse,"AssociateGroup",
78 "",$self,
79 \&AssociateGroup,$self,
80 "", $self);
81 $switch->addtag($parse,"Environment",
82 \&Environment_start,$self,
83 \&OutToMakefile, $self,
84 \&Environment_end,$self);
85 $switch->addtag($parse,"Export",
86 \&export_start,$self,
87 \&OutToMakefile, $self,
88 \&export_end,$self);
89 return $switch;
90 }
91
92 sub _commontags {
93 my $self=shift;
94 my $switch=shift;
95 my $parse=shift;
96
97 $self->verbose(">> _commontags: SW ".$switch." PARSE ".$parse." <<");
98
99 $switch->grouptag("Export",$parse);
100 $switch->addtag($parse,"Use",\&Use_start,$self,
101 \&OutToMakefile, $self,
102 "", $self);
103 $switch->addtag($parse,"Group",\&Group_start,$self,
104 \&OutToMakefile, $self,
105 "", $self);
106 $switch->grouptag("Group",$parse);
107 $switch->addtag($parse,"External",
108 \&External_StartTag,$self,
109 \&OutToMakefile, $self,
110 "", $self);
111 $switch->addtag($parse,"lib",
112 \&lib_start,$self,
113 \&OutToMakefile, $self,
114 "", $self);
115 $switch->addtag($parse,"Architecture",
116 \&Arch_Start,$self,
117 \&OutToMakefile, $self,
118 \&Arch_End,$self);
119 $switch->addtag($parse,"INCLUDE_PATH",
120 \&IncludePath_Start,$self,
121 \&OutToMakefile, $self,
122 "",$self);
123 return $switch;
124 }
125
126 sub ParseBuildFile {
127 my $self=shift;
128 my $base=shift;
129 my $path=shift;
130 my $filename=shift @_;
131 my $fullfilename;
132 if ( $filename!~/^\// ) {
133 $fullfilename="$base/$path/$filename";
134 }
135 else {
136 $fullfilename=$filename;
137 }
138
139 $self->verbose(">> ParseBuildFile: FN ".$fullfilename." <<");
140
141 $self->{path}=$path;
142 $numbins=0;
143 $self->{envnum}=0;
144 $self->{envlevel}=0;
145 $self->{currentenv}="$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/".
146 "BuildFile.mk";
147 $self->{switch}=$self->_initswitcher();
148 $self->{switch}->filetoparse($fullfilename);
149
150 # open a temporary gnumakefile to store output.
151 use Utilities::AddDir;
152 AddDir::adddir("$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}");
153 my $fh=FileHandle->new();
154 open ( $fh, ">$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/BuildFile.mk"
155 ) or die "Unable to open /$ENV{INTwork}/".$self->{path}."/BuildFile.mk $!\n";
156 @{$self->{filehandlestack}}=($fh);
157 # make an alias
158 *GNUmakefile=$fh;
159 if ( -e $ENV{LatestBuildFile} ) {
160 print GNUmakefile "include $ENV{LatestBuildFile}\n";
161 }
162
163 $ENV{LatestBuildFile}="$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/BuildFile.mk";
164 $self->{switch}->parse("makebuild"); # sort out supported tags
165 if ( $numbins > 0 ) {
166 print GNUmakefile <<ENDTEXT;
167 ifndef BINMODE
168 help::
169 \t\@echo Generic Binary targets
170 \t\@echo ----------------------
171 endif
172 ENDTEXT
173 foreach $target ( keys %$targettypes ) {
174 print GNUmakefile <<ENDTEXT;
175 ifndef BINMODE
176 help::
177 \t\@echo $target
178 endif
179 ENDTEXT
180 }
181 }
182 close GNUmakefile;
183 }
184
185 sub ParseBuildFile_Export {
186 my $self=shift;
187 my $filename=shift;
188
189 $self->verbose(">> ParseBuildFile_Export: FN ".$filename." <<");
190
191 my $bf=BuildSystem::BuildFile->new($self->{toolbox});
192 if ( defined $self->{remoteproject} ) {
193 $bf->{remoteproject}=$self->{remoteproject};
194 }
195 $bf->_parseexport($filename);
196 undef $bf;
197 }
198
199 sub _location {
200 my $self=shift;
201 use File::Basename;
202 $self->verbose(">> _location: <<");
203 return dirname($self->{switch}->filetoparse());
204 }
205
206 sub _parseexport {
207 my $self=shift;
208 my $filename=shift;
209 $self->verbose(">> _parseexport: FN ".$filename." <<");
210
211 my $switchex=ActiveDoc::SimpleDoc->new();
212 $switchex->filetoparse($filename);
213 $switchex->newparse("export");
214 $switchex->addignoretags("export");
215 $switchex->addtag("export","Export",
216 \&export_start_export,$self,
217 \&OutToMakefile, $self,
218 \&export_end_export,$self);
219 $self->_commontags($switchex,"export");
220 $switchex->allowgroup("__export","export");
221 $self->{switch}=$switchex;
222 $switchex->parse("export"); # sort out supported tags
223 }
224
225 sub _pushremoteproject {
226 my $self=shift;
227 my $path=shift;
228
229 $self->verbose(">> _pushremoteproject: PATH ".$path." <<");
230
231 if ( defined $self->{remoteproject} ) {
232 push @{$self->{rpstack}}, $self->{remoteproject};
233 }
234 $self->{remoteproject}=$path;
235 }
236
237 sub _popremoteproject {
238 my $self=shift;
239 $self->verbose(">> _popremoteproject: <<");
240
241 if ( $#{$self->{rpstack}} >=0 ) {
242 $self->{remoteproject}=pop @{$self->{rpstack}};
243 }
244 else {
245 undef $self->{remoteproject};
246 }
247 }
248
249 sub _toolmapper {
250 my $self=shift;
251
252 if ( ! defined $self->{mapper} ) {
253 require BuildSystem::ToolMapper;
254 $self->{mapper}=BuildSystem::ToolMapper->new();
255 }
256 $self->verbose(">> _toolmapper: TM ".$self->{mapper}."<<");
257 return $self->{mapper};
258 }
259
260
261 # ---- Tag routines
262
263 #-- Override a class type with the <ConfigurationClass type=xxx> tag
264 # the type tag will pick up a pre-defined class type from project space.
265
266 sub Class_StartTag {
267 my $self=shift;
268 my $name=shift;
269 my $hashref=shift;
270
271 $self->verbose(">> Classs_StartTag: NM ".$name." <<");
272
273 if ( $self->{Arch} ) {
274 if ( defined $$hashref{'type'} ) {
275 $ClassName=$$hashref{'type'};
276 }
277 }
278 }
279
280 sub IncludePath_Start
281 {
282 my $self=shift;
283 my $name=shift;
284 my $hashref=shift;
285
286 $self->verbose(">> IncludePath_Start: NM ".$name." <<");
287
288 $self->{switch}->checktag( $name, $hashref, 'path');
289 if ( $self->{Arch} )
290 {
291 print GNUmakefile "INCLUDE:=\$(filter-out ".$self->_location()."/".$$hashref{'path'}.",\$(INCLUDE))","\n";
292 print GNUmakefile "INCLUDE+=".$self->_location()."/".$$hashref{'path'}."\n";
293 }
294 }
295
296 #
297 # generic build tag
298 #
299 sub Build_start {
300 my $self=shift;
301 my $name=shift;
302 my $hashref=shift;
303
304 $self->verbose(">> Build_start: NM ".$name." <<");
305
306 $self->{switch}->checktag($name,$hashref,'class');
307 if ( $self->{Arch} ) {
308
309 # -- determine the build products name
310 my $name;
311 if ( exists $$hashref{'name'} ) {
312 $name=$$hashref{'name'};
313 }
314 else {
315 $self->{switch}->parseerror("No name specified for build product");
316 }
317
318 # -- check we have a lookup for the class type
319 my $mapper=$self->_toolmapper();
320 if ( ! $mapper->exists($$hashref{'class'}) ) {
321 $self->{switch}->parseerror("Unknown class : ".$$hashref{'class'});
322 }
323 else {
324 my @types=$self->_toolmapper()->types($$hashref{'class'});
325 my @deftypes=$self->_toolmapper()->defaulttypes($$hashref{'class'});
326
327 my $fh=$self->{filehandlestack}[0];
328 my @targets=();
329
330 # -- generate generic targets
331 print $fh "ifndef _BuildLink_\n";
332 print $fh "# -- Generic targets\n";
333 push @targets, $$hashref{'class'};
334 foreach $dtype ( @deftypes ) {
335 print $fh $$hashref{'class'}."::".$$hashref{'class'}."_".
336 $dtype."\n";
337 }
338 print $fh "\n";
339
340 # -- generate targets for each type
341 foreach $type ( @types ) {
342
343 # -- generic name for each type
344 my $pattern=$$hashref{'class'}."_".$type;
345 my $dirname=$$hashref{'class'}."_".$type."_".$name;
346 print $fh "# ------ $pattern rules ---------------\n";
347 print $fh $$hashref{'class'}."_".$type."::".$$hashref{'class'}.
348 "_".$type."_$name\n\n";
349
350 # -- create a new directory for each type
351 push @targets, $pattern;
352 my $dirname=$$hashref{'class'}."_".$type."_".$name;
353 my $here="$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/".$dirname;
354 my $makefile=$here."/BuildFile.mk";
355
356 # -- create link targets to the directory
357 push @targets, $dirname;
358 print $fh "# -- Link Targets to $type directories\n";
359 print $fh "$dirname: make_$dirname\n";
360 print $fh "\t\@cd $here; \\\n";
361 print $fh "\t\$(MAKE) LatestBuildFile=$makefile _BuildLink_=1".
362 " workdir=$here ".
363 " -f \$(TOOL_HOME)/basics.mk datestamp \$\@; \n\n";
364
365 # -- write target to make makefile for each directory
366 print $fh "# -- Build target directories\n";
367 print $fh "make_$dirname:\n";
368 print $fh "\tif [ ! -e \"$makefile\" ]; then \\\n";
369 print $fh "\t if [ ! -d \"$here\" ]; then \\\n";
370 print $fh "\t mkdir $here; \\\n";
371 print $fh "\t fi;\\\n";
372 print $fh "\t cd $dirname; \\\n";
373 print $fh "\t echo include ".$self->{currentenv}." > ".
374 "$makefile; \\\n";
375 print $fh "\t echo VPATH+=$ENV{LOCALTOP}/".$self->{path}.
376 " >> $makefile; \\\n";
377 print $fh "\t echo buildname=$name >> $makefile;\\\n";
378 print $fh "\t echo ".$dirname.":".$pattern." >> $makefile;\\\n";
379 if ( defined (my @file=$mapper->rulesfile($$hashref{'class'})) ) {
380 foreach $f ( @file ) {
381 print $fh "\t echo -include $f >> $makefile; \\\n";
382 }
383 }
384 print $fh "\tfi\n";
385 print $fh "\n";
386
387 # -- cleaning targets
388 push @targets, "clean_$dirname";
389 print $fh "# -- cleaning targets\n";
390 print $fh "clean::clean_$dirname\n";
391 print $fh "clean_".$dirname."::\n";
392 print $fh "\t\@echo cleaning $dirname\n";
393 print $fh "\t\@if [ -d $here ]; then \\\n";
394 print $fh "\tcd $here; \\\n";
395 print $fh "\t\$(MAKE) LatestBuildFile=$makefile workdir=".
396 $here." _BuildLink_=1 -f ".
397 "\$(TOOL_HOME)/basics.mk clean; \\\n";
398 print $fh "\tfi\n\n";
399
400
401 }
402 # -- help targets
403 print $fh "helpheader::\n";
404 print $fh "\t\@echo Targets available:\n";
405 print $fh "\t\@echo ------------------\n\n";
406 print $fh "help::helpheader\n";
407 foreach $target ( @targets ) {
408 print $fh "help::\n";
409 print $fh "\t\@echo $target\n"
410 }
411 print $fh "endif\n";
412 } # end else
413 }
414 }
415
416 sub Bin_start {
417 my $self=shift;
418 my $name=shift;
419 my $hashref=shift;
420
421 my $fileclass;
422 my @tools;
423 my $tool;
424 my $filename;
425 my $objectname;
426
427 $self->verbose(">> <<");
428
429 $self->{switch}->checktag($name,$hashref,'file');
430 if ( $self->{Arch} ) {
431 if ( ! defined $$hashref{name} ) {
432 ($$hashref{name}=$$hashref{file})=~s/\..*//;
433 }
434 ($filename=$$hashref{file})=~s/\..*//;
435
436 # Create a new directory for each binary target
437 my $dirname="bin_".$$hashref{name};
438 AddDir::adddir("$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/$dirname");
439 open (binGNUmakefile,
440 ">$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/$dirname/BuildFile.mk") or die "Unable to make $ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname/".
441 "BuildFile.mk $!\n";
442
443 # Create the link targets
444 $numbins++;
445 my $fh=$self->{filehandlestack}[0];
446 print $fh <<ENDTEXT;
447
448 # Link Targets to binary directories
449 ifdef BINMODE
450 # We dont want to build a library here
451 override files:=
452 endif
453 ifndef BINMODE
454
455 define stepdown_$$hashref{'name'}
456 if [ -d "$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname" ]; then \\
457 cd $ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname; \\
458 \$(MAKE) BINMODE=true LatestBuildFile=$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname/BuildFile.mk workdir=\$(workdir)/$dirname -f \$(TOOL_HOME)/basics.mk datestamp \$\@; \\
459 fi
460 endef
461
462 define stepdown2_$$hashref{'name'}
463 if [ -d "$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname" ]; then \\
464 cd $ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname; \\
465 \$(MAKE) BINMODE=true LatestBuildFile=$ENV{LOCALTOP}/$ENV{INTwork}/$self{path}/$dirname/BuildFile.mk workdir=\$(workdir)/$dirname -f \$(TOOL_HOME)/basics.mk datestamp \$\*; \\
466 fi
467
468 endef
469
470 bin_$$hashref{'name'}_%:: dummy
471 \@\$(stepdown2_$$hashref{'name'})
472
473 $$hashref{'name'}_%:: dummy
474 \@\$(stepdown_$$hashref{'name'})
475
476 help bin bin_debug bin_debug_local bin_insure bin_Insure clean $$hashref{'name'}:: dummy
477 \@\$(stepdown_$$hashref{'name'})
478
479 binfiles+=$$hashref{'file'}
480 locbinfiles+=$dirname/$$hashref{'file'}
481 endif
482
483
484 ENDTEXT
485
486
487 # the binary specifics makefile
488 print binGNUmakefile "include ".$self->{currentenv}."\n";
489 print binGNUmakefile "VPATH+=$ENV{LOCALTOP}/$self{path}\n";
490
491 # alias for bin_Insure
492 print binGNUmakefile <<ENDTEXT;
493
494 bin_insure:bin_Insure
495 ifdef MAKETARGET_bin_insure
496 MAKETARGET_$$hashref{name}_Insure=1
497 endif
498
499 # debuggging target
500 $$hashref{'name'}_echo_% :: echo_%
501
502 # help targets
503 help::
504 \t\@echo Targets For $$hashref{'name'}
505 \t\@echo -------------------------------------
506 \t\@echo $$hashref{'name'} - default build
507 \t\@echo bin_$$hashref{'name'}_clean - executable specific cleaning
508 ENDTEXT
509
510 # Make generic rules for each type
511 $targettypes={
512 "bin" => 'o',
513 "bin_debug" => 'd',
514 "bin_debug_local" => 'l_d',
515 "bin_Insure" => 'Insure'
516 };
517 #
518 foreach $target ( keys %$targettypes ) {
519 print binGNUmakefile <<ENDTEXT;
520
521 # Type $target specifics
522 ifdef MAKETARGET_$target
523 MAKETARGET_$$hashref{name}_$$targettypes{$target}=1
524 endif
525 $target ::$$hashref{name}_$$targettypes{$target}
526
527 bintargets+=$$hashref{name}_$$targettypes{$target}
528 help::
529 \t\@echo $$hashref{name}_$$targettypes{$target}
530 clean::
531 \t\@if [ -f \$(binarystore)/$$hashref{name}_$$targettypes{$target} ]; then \\
532 \techo Removing \$(binarystore)/$$hashref{name}; \\
533 \trm \$(binarystore)/$$hashref{name}_$$targettypes{$target}; \\
534 \tfi
535
536 ENDTEXT
537 ($objectname=$$hashref{file})=~s/\..*/_$$targettypes{$target}\.o/;
538 ${"objectname_$$targettypes{$target}"}=$objectname;
539 print binGNUmakefile "$objectname:$$hashref{name}.dep\n";
540 } # end loop
541
542 print binGNUmakefile "$$hashref{name}_Insure.exe:.psrc\n";
543 print binGNUmakefile "$$hashref{name}_d.exe:$objectname_d\n";
544 print binGNUmakefile "\t\$(CClinkCmdDebug)\n";
545 print binGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
546 print binGNUmakefile "$$hashref{name}_l_d.exe:$objectname_d\n";
547 print binGNUmakefile "\t\$(CClinkCmdDebugLocal)\n";
548 print binGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
549 print binGNUmakefile "$$hashref{name}_Insure.exe:$objectname_Insure\n";
550 print binGNUmakefile "\t\$(CClinkCmdInsure)\n";
551 print binGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
552 print binGNUmakefile "$$hashref{name}_o.exe:$objectname_o\n";
553 print binGNUmakefile "\t\$(CClinkCmd)\n";
554 print binGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
555 print binGNUmakefile "$$hashref{name}.dep:$$hashref{file}\n";
556 print binGNUmakefile "-include $$hashref{name}.dep\n";
557 print binGNUmakefile <<ENDTEXT;
558 clean::
559 \t\@if [ -f \$(binarystore)/$$hashref{name} ]; then \\
560 \techo Removing \$(binarystore)/$$hashref{name}; \\
561 \trm \$(binarystore)/$$hashref{name}; \\
562 \tfi
563
564 $$hashref{name}_d.exe:\$(libslocal_d)
565 $$hashref{name}_o.exe:\$(libslocal)
566 ifdef MCCABE_DATA_DIR
567 $$hashref{name}_mccabe.exe: \$(libslocal_d) \$(MCCABE_DATA_DIR)/mccabeinstr/instplus.cpp
568 endif
569 $$hashref{name}_Insure.exe:\$(libslocal_I)
570 $$hashref{name}_d:$$hashref{name}_d.exe
571 \@cp $$hashref{name}_d.exe \$(binarystore)/$$hashref{name}
572 $$hashref{name}_l_d:$$hashref{name}_l_d.exe
573 \@cp $$hashref{name}_l_d.exe \$(binarystore)/$$hashref{name}
574 $$hashref{name}_Insure:$$hashref{name}_Insure.exe
575 \@cp $$hashref{name}_Insure.exe \$(binarystore)/$$hashref{name}_Insure
576 $$hashref{name}:$$hashref{name}_d.exe
577 \@mv $$hashref{name}_d.exe \$(binarystore)/$$hashref{name}
578 $$hashref{name}_o:$$hashref{name}_o.exe
579 \@mv $$hashref{name}_o.exe \$(binarystore)/$$hashref{name}
580 binfiles+=$$hashref{file}
581 ENDTEXT
582 }
583 close binGNUmakefile;
584 }
585
586 sub Module_start {
587 my $self=shift;
588 my $name=shift;
589 my $hashref=shift;
590
591 my $fileclass;
592 my @tools;
593 my $tool;
594 my $filename;
595 my $objectname;
596
597 $self->verbose(">> In module_start: ".$name." <<");
598
599 $self->{switch}->checktag($name,$hashref,'file');
600 if ( $self->{Arch} ) {
601 if ( ! defined $$hashref{name} ) {
602 ($$hashref{name}=$$hashref{file})=~s/\..*//;
603 }
604 ($filename=$$hashref{file})=~s/\..*//;
605
606 # Create a new directory for each module target
607 my $dirname="module_".$$hashref{name};
608 AddDir::adddir("$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/$dirname");
609 open (moduleGNUmakefile,
610 ">$ENV{LOCALTOP}/$ENV{INTwork}/".$self->{path}."/$dirname/BuildFile.mk") or die "Unable to make $ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname/".
611 "BuildFile.mk $!\n";
612
613 # Create the link targets
614 $numbins++;
615 my $fh=$self->{filehandlestack}[0];
616 print $fh <<ENDTEXT;
617
618 # Link Targets to module directories
619 ifdef MODULEMODE
620 # We dont want to build a library here
621 override files:=
622 endif
623 ifndef MODULEMODE
624
625 BINMODE=true
626
627 define stepdown_$$hashref{'name'}
628 if [ -d "$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname" ]; then \\
629 cd $ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname; \\
630 \$(MAKE) MODULEMODE=true LatestBuildFile=$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname/BuildFile.mk workdir=\$(workdir)/$dirname -f \$(TOOL_HOME)/basics.mk datestamp \$\@; \\
631 fi
632 endef
633
634 define stepdown2_$$hashref{'name'}
635 if [ -d "$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname" ]; then \\
636 cd $ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/$dirname; \\
637 \$(MAKE) MODULEMODE=true LatestBuildFile=$ENV{LOCALTOP}/$ENV{INTwork}/$self{path}/$dirname/BuildFile.mk workdir=\$(workdir)/$dirname -f \$(TOOL_HOME)/basics.mk datestamp \$\*; \\
638 fi
639
640 endef
641
642 module_$$hashref{'name'}_%:: dummy
643 \@\$(stepdown2_$$hashref{'name'})
644
645 $$hashref{'name'}_%:: dummy
646 \@\$(stepdown_$$hashref{'name'})
647
648 help module module_debug module_debug_local module_insure module_Insure clean $$hashref{'name'}:: dummy
649 \@\$(stepdown_$$hashref{'name'})
650
651 modulefiles+=$$hashref{'file'}
652 locmodulefiles+=$dirname/$$hashref{'file'}
653 endif
654
655
656 ENDTEXT
657
658
659 # the module specifics makefile
660 print moduleGNUmakefile "include ".$self->{currentenv}."\n";
661 print moduleGNUmakefile "VPATH+=$ENV{LOCALTOP}/$self{path}\n";
662
663 # alias for bin_Insure
664 print moduleGNUmakefile <<ENDTEXT;
665
666 module_insure:module_Insure
667 ifdef MAKETARGET_module_insure
668 MAKETARGET_$$hashref{name}_Insure=1
669 endif
670
671 # debuggging target
672 $$hashref{'name'}_echo_% :: echo_%
673
674 # help targets
675 help::
676 \t\@echo
677 \t\@echo Targets For $$hashref{'name'}
678 \t\@echo -------------------------------------
679 \t\@echo $$hashref{'name'} - default build
680 \t\@echo module_$$hashref{'name'}_clean - executable specific cleaning
681 ENDTEXT
682
683 # Make generic rules for each type
684 $targettypes={
685 "module" => 'o',
686 "module_debug" => 'd',
687 "module_debug_local" => 'l_d',
688 "module_Insure" => 'Insure'
689 };
690 #
691 foreach $target ( keys %$targettypes ) {
692 print moduleGNUmakefile <<ENDTEXT;
693
694 # Type $target specifics
695 ifdef MAKETARGET_$target
696 MAKETARGET_$$hashref{name}_$$targettypes{$target}=1
697 endif
698 $target ::$$hashref{name}_$$targettypes{$target}
699
700 moduletargets+=$$hashref{name}_$$targettypes{$target}
701 help::
702 \t\@echo $$hashref{name}_$$targettypes{$target}
703 clean::
704 \t\@if [ -f \$(modulestore)/$$hashref{name}_$$targettypes{$target} ]; then \\
705 \techo Removing \$(modulestore)/$$hashref{name}; \\
706 \trm \$(modulestore)/$$hashref{name}_$$targettypes{$target}; \\
707 \tfi
708
709 ENDTEXT
710 ($objectname=$$hashref{file})=~s/\..*/_$$targettypes{$target}\.o/;
711 ${"objectname_$$targettypes{$target}"}=$objectname;
712 print moduleGNUmakefile "$objectname:$$hashref{name}.dep\n";
713 } # end loop
714 print moduleGNUmakefile "MDFLAGS= -shared -Wl,-soname,\$\@","\n";
715 print moduleGNUmakefile "$$hashref{name}_Insure.so:.psrc\n";
716 print moduleGNUmakefile "$$hashref{name}_d.so:$objectname_d\n";
717 print moduleGNUmakefile "\t\$(CClinkCmdDebug) \$(MDFLAGS)\n";
718 print moduleGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
719 print moduleGNUmakefile "$$hashref{name}_l_d.so:$objectname_d\n";
720 print moduleGNUmakefile "\t\$(CClinkCmdDebugLocal) \$(MDFLAGS)\n";
721 print moduleGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
722 print moduleGNUmakefile "$$hashref{name}_Insure.so:$objectname_Insure\n";
723 print moduleGNUmakefile "\t\$(CClinkCmdInsure) \$(MDFLAGS)\n";
724 print moduleGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
725 print moduleGNUmakefile "$$hashref{name}_o.so:$objectname_o\n";
726 print moduleGNUmakefile "\t\$(CClinkCmd) \$(MDFLAGS)\n";
727 print moduleGNUmakefile "\t\@\$(SCRAMPERL) \$(SCRAM_HOME)/src/scramdatestamp \$\@\.ds \$\@ \$\^\n";
728 print moduleGNUmakefile "$$hashref{name}.dep:$$hashref{file}\n";
729 print moduleGNUmakefile "-include $$hashref{name}.dep\n";
730 print moduleGNUmakefile <<ENDTEXT;
731 clean::
732 \t\@if [ -f \$(modulestore)/lib$$hashref{name} ]; then \\
733 \techo Removing \$(modulestore)/lib$$hashref{name}; \\
734 \trm \$(modulestore)/lib$$hashref{name}; \\
735 \tfi
736
737
738 $$hashref{name}_d.so:\$(libslocal_d)
739 $$hashref{name}_o.so:\$(libslocal)
740 ifdef MCCABE_DATA_DIR
741 $$hashref{name}_mccabe.so: \$(libslocal_d) \$(MCCABE_DATA_DIR)/mccabeinstr/instplus.cpp
742 endif
743 $$hashref{name}_Insure.so:\$(libslocal_I)
744 $$hashref{name}_d:$$hashref{name}_d.so
745 \@cp $$hashref{name}_d.so \$(modulestore)/lib$$hashref{name}
746 $$hashref{name}_l_d:$$hashref{name}_l_d.so
747 \@cp $$hashref{name}_l_d.so \$(modulestore)/lib$$hashref{name}
748 $$hashref{name}_Insure:$$hashref{name}_Insure.so
749 \@cp $$hashref{name}_Insure.so \$(modulestore)/lib$$hashref{name}_Insure
750 $$hashref{name}:$$hashref{name}_d.so
751 \@mv $$hashref{name}_d.so \$(modulestore)/lib$$hashref{name}
752 $$hashref{name}_o:$$hashref{name}_o.so
753 \@mv $$hashref{name}_o.so \$(modulestore)/lib$$hashref{name}.so
754 modulefiles+=$$hashref{file}
755 ENDTEXT
756 }
757 close moduleGNUmakefile;
758 }
759
760
761 sub External_StartTag {
762 my $self=shift;
763 my $name=shift;
764 my $hashref=shift;
765
766 $self->verbose(">> External_StartTag: NM ".$name." <<");
767
768 my $tool;
769 if ( $self->{Arch} ) {
770 $self->{switch}->checktag($name,$hashref,'ref');
771
772 # -- oo toolbox stuff
773 # - get the appropriate tool object
774 $$hashref{'ref'}=~tr[A-Z][a-z];
775 if ( ! exists $$hashref{'version'} ) {
776 $tool=$self->{toolbox}->gettool($$hashref{'ref'});
777 }
778 else {
779 $tool=$self->{toolbox}->gettool($$hashref{'ref'},$$hashref{'version'});
780 }
781 if ( ! defined $tool ) {
782 $self->{switch}->parseerror("Unknown Tool Specified ("
783 .$$hashref{'ref'}.")");
784 }
785
786 # -- old fashioned GNUmakefile stuff
787 print GNUmakefile $$hashref{'ref'};
788 if ( defined $$hashref{'version'} ) {
789 print GNUmakefile "_V_".$$hashref{'version'};
790 }
791 print GNUmakefile "=true\n";
792
793 # -- Sub system also specified?
794 if ( exists $$hashref{'use'} ) {
795 # -- look for a buildfile
796 my @paths=$tool->getfeature("INCLUDE");
797 my $file="";
798 my ($path,$testfile);
799 foreach $path ( @paths ) {
800 $testfile=$path."/".$$hashref{'use'}."/BuildFile" ;
801 if ( -f $testfile ) {
802 $file=$testfile;
803 $self->_pushremoteproject($path);
804 }
805 }
806 if ( $file eq "" ) {
807 $self->{switch}->parseerror("Unable to find SubSystem $testfile");
808 }
809 $self->ParseBuildFile_Export($file);
810 $self->_popremoteproject();
811 }
812 }
813 }
814
815 sub Group_start {
816 my $self=shift;
817 my $name=shift;
818 my $hashref=shift;
819
820 $self->verbose(">> Group_start: NM ".$name." <<");
821
822 $self->{switch}->checktag($name, $hashref, 'name');
823 if ( $self->{Arch} ) {
824 print GNUmakefile "GROUP_".$$hashref{'name'};
825 if ( defined $$hashref{'version'} ) {
826 print GNUmakefile "_V_".$$hashref{'version'};
827 }
828 print GNUmakefile "=true\n";
829 }
830 }
831
832 sub Use_start
833 {
834 my $self=shift;
835 my $name=shift;
836 my $hashref=shift;
837 my $filename;
838 use Utilities::SCRAMUtils;
839
840 $self->verbose(">> Use_start: NM ".$name." <<");
841
842 $self->{switch}->checktag($name, $hashref, "name");
843 if ( $self->{Arch} )
844 {
845 if ( exists $$hashref{'group'} )
846 {
847 print GNUmakefile "GROUP_".$$hashref{'group'}."=true\n";
848 }
849 if ( ! defined $self->{remoteproject} )
850 {
851 $filename=SCRAMUtils::checkfile("/$ENV{INTsrc}/$$hashref{name}/BuildFile");
852 }
853 else
854 {
855 $filename=$self->{remoteproject}."/$$hashref{name}/BuildFile";
856 print "Trying $filename\n";
857 if ( ! -f $filename ) { $filename=""; };
858 }
859 if ( $filename ne "" )
860 {
861 $self->ParseBuildFile_Export( $filename );
862 }
863 else
864 {
865 $self->{switch}->parseerror("Unable to detect Appropriate ".
866 "decription file for <$name name=".$$hashref{name}.">");
867 }
868 }
869 }
870
871 sub CheckBuildFile {
872 my $self=shift;
873 my $classdir=shift;
874 my $ClassName="";
875 my $thisfile="$classdir/$buildfile";
876
877 if ( -e $ENV{LOCALTOP}."/".$thisfile ) {
878 $DefaultBuildfile="$ENV{LOCALTOP}/$thisfile";
879 $self->ParseBuildFile($ENV{LOCALTOP}, $classdir, $buildfile);
880 }
881 elsif ( -e $ENV{RELEASETOP}."/".$thisfile ) {
882 $DefaultBuildfile="$ENV{RELEASETOP}/$thisfile";
883 $self->ParseBuildFile($ENV{RELEASETOP}, $classdir, $buildfile);
884 }
885 $self->verbose(">> CheckBuildFile: FN ".$thisfile." CN ".$ClassName." <<");
886 return $ClassName;
887 }
888
889 # List association groups between <AssociateGroup> tags
890 # seperated by newlines or spaces
891 sub AssociateGroup {
892 my $self=shift;
893 my $name=shift;
894 my $string=shift;
895 my $word;
896
897 $self->verbose(">> AssociateGroup: NM ".$name." ST ".$string." <<");
898
899 if ( $self->{Arch} ) {
900 foreach $word ( (split /\s/, $string) ){
901 chomp $word;
902 next if /^#/;
903 if ( $word=~/none/ ) {
904 $self->{ignore}=1;
905 }
906 }
907 }
908 }
909
910 sub Arch_Start {
911 my $self=shift;
912 my $name=shift;
913 my $hashref=shift;
914
915 $self->verbose(">> Arch_Start: NM ".$name." <<");
916
917 $self->{switch}->checktag($name, $hashref,'name');
918 ( ($ENV{SCRAM_ARCH}=~/$$hashref{name}.*/) )? ($self->{Arch}=1)
919 : ($self->{Arch}=0);
920 push @{$self->{ARCHBLOCK}}, $self->{Arch};
921 }
922
923 sub Arch_End {
924 my $self=shift;
925 my $name=shift;
926
927 $self->verbose(">> Arch_End: NM ".$name." <<");
928
929 pop @{$self->{ARCHBLOCK}};
930 $self->{Arch}=$self->{ARCHBLOCK}[$#{$self->{ARCHBLOCK}}];
931 }
932
933 # Split up the Class Block String into a useable array
934 sub _CutBlock {
935 my $self=shift;
936 my $string= shift @_;
937
938 $self->verbose(">> _CutBlock: ST ".$string." <<");
939
940 @BlockClassA = split /\//, $string;
941 }
942
943 sub OutToMakefile {
944 my $self=shift;
945 my $name=shift;
946 my @vars=@_;
947
948 $self->verbose(">> OutToMakefile: <<");
949
950 if ( $self->{Arch} ) {
951 $self->verbose(">> CONT: ".$#vars." lines <<");
952 print GNUmakefile @vars;
953 }
954 }
955
956 sub OutToScreen {
957 my $name=shift;
958 my @vars=@_;
959
960 if ( $self->{Arch} ) {
961 print @vars;
962 }
963 }
964 sub setBlockClassPath {
965 my $self=shift;
966 my $name=shift;
967 my $hashref=shift;
968
969 $self->verbose(">> setBlockClassPath: NM ".$name." <<");
970
971 $self->{switch}->checktag($name, $hashref, 'path');
972 $self->{BlockClassPath}=$self->{BlockClassPath}.":".$$hashref{path};
973 $self->_CutBlock($$hashref{path});
974 }
975
976 sub BlockClassPath {
977 my $self=shift;
978
979 $self->verbose(">> BlockClassPath: <<");
980
981 return $self->{BlockClassPath};
982 }
983
984 sub export_start_export {
985 my $self=shift;
986 my $name=shift;
987 my $hashref=shift;
988
989 $self->verbose(">> export_start_export: NM ".$name." <<");
990
991 $self->{switch}->opengroup("__export");
992 }
993
994 sub export_start {
995 my $self=shift;
996 my $name=shift;
997 my $hashref=shift;
998
999 $self->verbose(">> export_start: NM ".$name." <<");
1000
1001 $self->{switch}->opengroup("__export");
1002 if ( exists $$hashref{autoexport} ) {
1003 print GNUmakefile "scram_autoexport=".$$hashref{autoexport}."\n";
1004 if ( $$hashref{autoexport}=~/true/ ) {
1005 $self->{switch}->allowgroup("__export","makebuild");
1006 }
1007 else {
1008 $self->{switch}->disallowgroup("__export","makebuild");
1009 }
1010 }
1011 # -- allow default setting from other makefiles
1012 print GNUmakefile "ifeq (\$(scram_autoexport),true)\n";
1013 }
1014
1015 sub export_end_export {
1016 my $self=shift;
1017 $self->verbose(">> export_end_export: <<");
1018 $self->{switch}->closegroup("__export");
1019 }
1020
1021 sub export_end {
1022 my $self=shift;
1023 $self->verbose(">> export_end: <<");
1024 $self->{switch}->closegroup("__export");
1025 print GNUmakefile "endif\n";
1026 }
1027
1028 #
1029 # Standard lib tag
1030 #
1031 sub lib_start
1032 {
1033 my $self=shift;
1034 my $name=shift;
1035 my $hashref=shift;
1036
1037 $self->verbose(">> lib_start: NM ".$name." <<");
1038
1039 $self->{switch}->checktag($name, $hashref, 'name');
1040
1041 if ( $self->{Arch} )
1042 {
1043 print GNUmakefile "lib+=$$hashref{name}\n";
1044 }
1045 }
1046
1047 #
1048 # libtype specification
1049 #
1050 sub LibType_Start {
1051 my $self=shift;
1052 my $name=shift;
1053 my $hashref=shift;
1054
1055 $self->verbose(">> LibType_Start: NM ".$name." <<");
1056
1057 if ( $self->{Arch} ) {
1058 if ( defined $self->{libtype_conext} ) {
1059 $self->{switch}->parseerror("<$name> tag cannot be specified".
1060 " without a </$name> tag to close previous context");
1061 }
1062 else {
1063 $self->{libtype_conext}=1;
1064 $self->{switch}->checktag($name, $hashref, 'type');
1065
1066 print GNUmakefile "# Specify Library Type\n";
1067 print GNUmakefile "DefaultLibsOff=yes\n";
1068 if ( $$hashref{'type'}=~/^archive/i ) {
1069 print GNUmakefile "LibArchive=true\n";
1070 }
1071 elsif ($$hashref{'type'}=~/debug_archive/i ) {
1072 print GNUmakefile "LibDebugArchive=true\n";
1073 }
1074 elsif ($$hashref{'type'}=~/debug_shared/i ) {
1075 print GNUmakefile "LibDebugShared=true\n";
1076 }
1077 elsif ($$hashref{'type'}=~/shared/i ) {
1078 print GNUmakefile 'LibShared=true'."\n";
1079 }
1080 print GNUmakefile "\n";
1081 }
1082 }
1083 }
1084
1085 sub LibType_text {
1086 my $self=shift;
1087 my $name=shift;
1088 my $string=shift;
1089 $self->verbose(">> LibType_text: NM ".$name." <<");
1090
1091 if ( $self->{Arch} ) {
1092 $string=~s/\n/ /g;
1093 print GNUmakefile "libmsg::\n\t\@echo Library info: ";
1094 print GNUmakefile $string;
1095 print GNUmakefile "\n";
1096 }
1097 }
1098
1099 sub LibType_end {
1100 my $self=shift;
1101 my $name=shift;
1102
1103 $self->verbose(">> LibType_end: NM ".$name." <<");
1104
1105 undef $self->{libtype_conext};
1106 }
1107
1108 sub Environment_start {
1109 my $self=shift;
1110 my $name=shift;
1111 my $hashref=shift;
1112
1113 $self->verbose(">> Environment_start: NM ".$name." <<");
1114
1115 if ( $self->{Arch} ) {
1116 $self->{envnum}++;
1117
1118 # open a new Environment File
1119 my $envfile="$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/Env_".
1120 $self->{envnum}.".mk";
1121 use FileHandle;
1122 my $fh=FileHandle->new();
1123 open ($fh,">$envfile") or die "Unable to open file $envfile \n$!\n";
1124 push @{$self->{filehandlestack}}, $fh;
1125 *GNUmakefile=$fh;
1126
1127 # include the approprate environment file
1128 if ( $self->{envlevel} == 0 ) {
1129 print GNUmakefile "include $ENV{LOCALTOP}/$ENV{INTwork}/".
1130 $self->{path}."/BuildFile.mk\n";
1131 }
1132 else {
1133 print GNUmakefile "include $ENV{LOCALTOP}/$ENV{INTwork}/".
1134 $self->{path}."/Env_".$self->{Envlevels}[$self->{envlevel}].".mk\n";
1135 }
1136 $self->{envlevel}++;
1137 $self->{Envlevels}[$self->{envlevel}]=$self->{envnum};
1138 $self->{currentenv}="$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/Env_$self->{envnum}.mk";
1139 }
1140 }
1141
1142 sub Environment_end {
1143 my $self=shift;
1144 my $fd;
1145
1146 $self->verbose(">> Environment_end: NM ".$name." <<");
1147
1148 if ( $self->{Arch} ) {
1149 $self->{envlevel}--;
1150 if ( $self->{envlevel} < 0 ) {
1151 print "Too many </Environent> Tags on $self->{switch}->line()\n";
1152 exit 1;
1153 }
1154 close GNUmakefile;
1155 # restore the last filehandle
1156 $fd=pop @{$self->{filehandlestack}};
1157 close $fd;
1158 *GNUmakefile=$self->{filehandlestack}[$#{$self->{filehandlestack}}];
1159 if ( $self->{envlevel} < 1 ) {
1160 $self->{currentenv}="$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/".
1161 "BuildFile.mk";
1162 }
1163 else {
1164 $self->{currentenv}=
1165 "$ENV{LOCALTOP}/$ENV{INTwork}/$self->{path}/Env_".
1166 $self->{Envlevels}[$self->{envlevel}];
1167 }
1168 }
1169 }
1170
1171 sub Store_start {
1172 my $self=shift;
1173 my $name=shift;
1174 my $hashref=shift;
1175
1176 $self->verbose(">> Store_start: NM ".$name." <<");
1177
1178 if ( $self->{Arch} ) {
1179 $self->{switch}->checktag( $name, $hashref, 'name' );
1180
1181 # -- store creation
1182 my $dir=$$hashref{'name'};
1183 AddDir::adddir($ENV{LOCALTOP}."/".$dir);
1184 if ( exists $$hashref{'type'} ) {
1185 # -- architecture specific store
1186 if ( $$hashref{'type'}=~/^arch/i ) {
1187 $dir=$dir."/".$ENV{SCRAM_ARCH};
1188 AddDir::adddir($ENV{LOCALTOP}."/".$dir);
1189 }
1190 else {
1191 $self->parseerror("Unknown type in <$name> tag");
1192 }
1193 }
1194
1195 # -- set make variables for the store
1196 print GNUmakefile "SCRAMSTORENAME_".$$hashref{'name'}.":=".$dir."\n";
1197 print GNUmakefile "SCRAMSTORE_".$$hashref{'name'}.":=".
1198 $ENV{LOCALTOP}."/".$dir."\n";
1199 print GNUmakefile "VPATH+=".$ENV{LOCALTOP}
1200 ."/".$dir.":".$ENV{RELEASETOP}."/".$dir."\n";
1201 }
1202 }