File indexing completed on 2024-04-06 12:31:48
0001
0002 use File::Basename;
0003 use lib dirname($0);
0004 use SCRAMGenUtils;
0005 use Getopt::Long;
0006
0007 my $pwd=`/bin/pwd`; chomp $pwd; $pwd=&SCRAMGenUtils::fixPath($pwd);
0008 my $scriptDir=dirname($0);
0009 if ($scriptDir!~/^\//){$scriptDir="${pwd}/${scriptDir}";}
0010
0011
0012 if(&GetOptions(
0013 "--release=s",\$dir,
0014 "--tool=s",\@itools,
0015 "--product=s",\@iproducts,
0016 "--detail",\$detail,
0017 "--dependency=s",\$dependency,
0018 "--clean",\$clean,
0019 "--recursive",\$full,
0020 "--cppfilt",\$cppfilt,
0021 "--graph",\$graph,
0022 "--help",\$help,
0023 ) eq ""){print STDERR "#Wrong arguments.\n"; &usage_msg();}
0024
0025 my %systemsym=();
0026 $systemsym{"__cxa_.+"}=1;
0027 $systemsym{"__gxx_.+"}=1;
0028 $systemsym{_fini}=1;
0029 $systemsym{_init}=1;
0030 $systemsym{fclose}=1;
0031 $systemsym{fopen}=1;
0032 $systemsym{"pthread_cond_.+"}=1;
0033 $systemsym{regexec}=1;
0034 $systemsym{".+\@\@GLIBCXX.*"}=1;
0035 $systemsym{".+\@\@GCC.*"}=1;
0036 $systemsym{".+\@\@CXXABI.*"}=1;
0037 $systemsym{__fxstat64}=1;
0038 $systemsym{__lxstat64}=1;
0039 $systemsym{__xstat64}=1;
0040 $systemsym{_dl_argv}=1;
0041 $systemsym{_r_debug}=1;
0042 $systemsym{getrlimit64}=1;
0043 $systemsym{pthread_create}=1;
0044 $systemsym{readdir64}=1;
0045
0046 my $symDefine="T|R|V|W|B|D";
0047 my $symUnDefine="U";
0048
0049 if(defined $help){&usage_msg();}
0050
0051 if(defined $detail){$detail=1;}
0052 else{$detail=0;}
0053
0054 if(defined $cppfilt){$cppfilt=1;}
0055 else{$cppfilt=0;}
0056
0057 if(defined $full){$full=1;}
0058 else{$full=0;}
0059
0060 if(defined $graph){$graph=1;}
0061 else{$graph=0;}
0062
0063 if (!defined $dir){$dir=$pwd;}
0064 my $release=&SCRAMGenUtils::scramReleaseTop($dir);
0065 if($release eq ""){print STDERR "ERROR: Please run this script from a SCRAM-based area.\n"; exit 1;}
0066 &SCRAMGenUtils::init ($release);
0067 my $releaseTop=&SCRAMGenUtils::getFromEnvironmentFile("RELEASETOP",$release);
0068 $SCRAMGenUtils::CacheType=0;
0069
0070 my $scramarch=&SCRAMGenUtils::getScramArch();
0071 my $cachedir="${pwd}/Cache";
0072 my $symboldir="${cachedir}/Symbols";
0073 my $data={};
0074 my $xjobs=10;
0075
0076 my %utools=();
0077 if ($dependency eq "")
0078 {
0079 foreach my $t (@itools)
0080 {
0081 my $lt=lc($t);
0082 if (-f "${release}/.SCRAM/${scramarch}/timestamps/${lt}"){$utools{TOOLS}{$lt}=1;}
0083 else{$utools{TOOLS}{$t}=1;}
0084 }
0085 foreach my $t (@iproducts){$utools{SELF}{$t}=1;}
0086 if (scalar(keys %utools)==0){print STDERR "Missing tool/product name.\n"; &usage_msg();}
0087 }
0088
0089 if (defined $clean){system("rm -rf $symboldir");}
0090 system("mkdir -p $symboldir ${cachedir}/Dot");
0091
0092 print "Reading external tools symbols info ....";
0093 system("mkdir -p ${symboldir}/TOOLS ${symboldir}/SYSTEM");
0094 my $cf="${release}/.SCRAM/${scramarch}/ToolCache.db.gz";
0095 if (-f $cf){&addToolDep(&SCRAMGenUtils::readCache($cf),"TOOLS");}
0096 &SCRAMGenUtils::waitForChild();
0097 print STDERR "\n";
0098 $data->{SYSTEM_SYMBOLS_DEF}=&SCRAMGenUtils::mergeSymbols("${symboldir}/SYSTEM","",$symDefine);
0099
0100 $data->{paths}{0}="lib/${scramarch}";
0101 $data->{paths}{1}="bin/${scramarch}";
0102 $data->{paths}{2}="test/${scramarch}";
0103
0104 my $prodfile="${release}/src/ReleaseProducts.list";
0105 if (!-f $prodfile)
0106 {
0107 my $rdir=$release;
0108 if ($releaseTop ne "")
0109 {
0110 $prodfile="${release}/src/ReleaseProducts.list";
0111 $rdir=$releaseTop;
0112 }
0113 if (!-f $prodfile)
0114 {
0115 $prodfile="${cachedir}/ReleaseProducts.list";
0116 if (!-f $prodfile){system("${scriptDir}/RelProducts.pl $rdir > $prodfile");}
0117 }
0118 }
0119
0120 foreach my $line (`cat $prodfile`)
0121 {
0122 chomp $line;
0123 my ($pack,$prods)=split(":",$line,2);
0124 $data->{pack}{$pack}={};
0125 my @types=split('\\|',$prods,4);
0126 for(my $i=0;$i<1;$i++)
0127 {
0128 foreach my $prod (split(",",$types[$i]))
0129 {
0130 if ($prod eq ""){next;}
0131 $data->{pack}{$pack}{$prod}=1;
0132 $data->{prod}{$prod}{pack}=$pack;
0133 $data->{prod}{$prod}{path}=$i;
0134 }
0135 }
0136 }
0137
0138 print "Reading local libraries symbols info ....";
0139 system("mkdir -p ${symboldir}/SELF");
0140 foreach my $prod (keys %{$data->{prod}})
0141 {
0142 my $p=$data->{paths}{$data->{prod}{$prod}{path}};
0143 my $f="${release}/${p}/${prod}";
0144 if ((!-f $f) && ($releaseTop ne "")){$f="${releaseTop}/${p}/${prod}";}
0145 if ($prod=~/^lib.+\.so$/){$data->{PRODUCT_MAP}{$prod}=$data->{prod}{$prod}{pack};}
0146 if (-f $f)
0147 {
0148 &SCRAMGenUtils::symbolCacheFork($f,"cmssw","${symboldir}/SELF",$xjobs);
0149 print STDERR ".";
0150 }
0151 else{print STDERR "ERROR: Missing file: $f\n";}
0152 }
0153 &SCRAMGenUtils::waitForChild();
0154 print STDERR "\n";
0155 &SCRAMGenUtils::writeHashCache($data->{PRODUCT_MAP},"${symboldir}/Lib2Package.db");
0156 &SCRAMGenUtils::writeHashCache($data->{TOOL_TYPE},"${symboldir}/LibTypes.db");
0157
0158 if ($dependency ne "")
0159 {
0160 $data->{PRODUCT_MAP} = &SCRAMGenUtils::readHashCache("${symboldir}/Lib2Package.db");
0161 $data->{TOOL_TYPE} = &SCRAMGenUtils::readHashCache("${symboldir}/LibTypes.db");
0162 $data->{SELF_SYMBOLS_DEF}=&SCRAMGenUtils::mergeSymbols("${symboldir}/SELF","",$symDefine);
0163 $data->{TOOLS_SYMBOLS_DEF}=&SCRAMGenUtils::mergeSymbols("${symboldir}/TOOLS","",$symDefine);
0164 &doDependency($dependency);
0165 exit 0;
0166 }
0167 else
0168 {
0169 delete $data->{SELF_SYMBOLS_DEF};
0170 delete $data->{TOOLS_SYMBOLS_DEF};
0171 delete $data->{PRODUCT_MAP};
0172 delete $data->{TOOL_TYPE};
0173 }
0174
0175 $data->{SELF_SYMBOLS_UNDEF}=&SCRAMGenUtils::mergeSymbols("${symboldir}/SELF","",$symUnDefine);
0176
0177 my $toolsym={};
0178 &findDefinedSyms(\%utools,$symDefine,$toolsym);
0179
0180 my %deps=();
0181 $deps{direct}=&findSymbolDependency($toolsym);
0182 if($detail){&detailDepInfo("direct",\%deps);}
0183 if($full){&processSelfDependency("direct",\%deps);}
0184
0185 my %packs=();
0186 foreach my $lib (keys %deps)
0187 {
0188 if (exists $data->{prod}{$lib}){$packs{$data->{prod}{$lib}{pack}}{$lib}=1;}
0189 foreach my $dep (keys %{$deps{$lib}})
0190 {
0191 if(exists $data->{prod}{$dep}){$packs{$data->{prod}{$dep}{pack}}{$dep}=1;}
0192 }
0193 }
0194
0195 print "\n##################################\nALL DEPS\n";
0196 foreach my $pk (sort keys %packs)
0197 {
0198 my $direct="";
0199 foreach my $x (keys %{$packs{$pk}})
0200 {if(exists $deps{direct}{$x}){$direct="*"; last;}}
0201 print "${direct}${pk}:\n";
0202 foreach my $p (sort keys %{$packs{$pk}}){print " $p\n";}
0203 print "\n";
0204 }
0205
0206 sub usage_msg()
0207 {
0208 my $s=basename($0);
0209 print "Usage: \n$s --release <path> --tool <tool>|--product <product>|--dependnecy <library>\n",
0210 " [--recursive] [--cppfilt] [--clean] [--detail] [--help]\n\n",
0211 " Script can find out actual binary dependency of a cmssw products\n",
0212 " (lib/exe/plugin) OR it can be used to find out which cmssw packages/products\n",
0213 " are dependening on an external tool or cmssw product e.g.\n",
0214 " * To find out the actual binary dependency of sub-system/package/individual\n";
0215 " products(lib/exe/plugin)\n",
0216 " $s --rel <path> --dependnecy FWCore\n",
0217 " $s --rel <path> --dependnecy FWCore/Framework\n",
0218 " $s --rel <path> --dependnecy pluginFWCorePrescaleServicePlugin.so\n",
0219 " $s --rel <path> --dependnecy libFWCoreFramework.so\n\n",
0220 " * To find out which product(s) of CMSSW actually need a tool/product\n",
0221 " $s --rel <path> --tool oracle --tool oracleocci --tool oracle\n",
0222 " $s --rel <path> --tool xdaq --full\n",
0223 " $s --rel <path> --product libFWCoreFramework.so [--recursive]\n",
0224 " when --recursive option is specified then it will show all the products which\n",
0225 " directly/in-directly depending on this tool/product\n";
0226 exit 0;
0227 }
0228
0229
0230
0231 sub findDefinedSyms()
0232 {
0233 my ($c,$type,$syms)=@_;
0234 foreach my $x (keys %$c)
0235 {
0236 foreach my $t (keys %{$c->{$x}})
0237 {
0238 my $fil="lib*.$t";
0239 if ($x eq "SELF"){$fil="$t.cmssw";}
0240 foreach my $f (`find ${symboldir}/${x} -name '$fil' -type f`)
0241 {
0242 chomp $f;
0243 &accSymbolsFromFile($f,$syms,$type);
0244 }
0245 }
0246 }
0247 foreach my $s (keys %$syms){if (&isSystemSymbol($s)==1){delete $syms->{$s};}}
0248 }
0249
0250 sub accSymbolsFromFile()
0251 {
0252 my ($file,$syms,$type,$system)=@_;
0253 print "Reading File: $file\n";
0254 my $s=&SCRAMGenUtils::readHashCache($file);
0255 foreach my $x (keys %$s)
0256 {
0257 foreach my $l (keys %{$s->{$x}})
0258 {
0259 foreach my $ty (keys %{$s->{$x}{$l}})
0260 {
0261 if ($ty=~/^$type$/){foreach my $s (keys %{$s->{$x}{$l}{$ty}}){$syms->{$s}=1;}}
0262 }
0263 }
0264 }
0265 if (defined $system){foreach my $s (keys %$syms){if (&isSystemSymbol($s)==1){delete $syms->{$s};}}}
0266 }
0267
0268 sub detailDepInfo()
0269 {
0270 my $prod=shift;
0271 my $cache=shift;
0272 print "DEPS:$prod\n";
0273 foreach my $x (sort keys %{$cache->{$prod}})
0274 {
0275 print " $x\n";
0276 foreach my $s (sort keys %{$cache->{$prod}{$x}})
0277 {
0278 if ($cppfilt){$s=&SCRAMGenUtils::cppFilt($s);}
0279 print " $s\n";
0280 }
0281 }
0282 print "\n";
0283 }
0284
0285 sub processSelfDependency()
0286 {
0287 my $prod=shift;
0288 my $cache=shift;
0289 foreach my $d (keys %{$cache->{$prod}})
0290 {
0291 if (exists $cache->{$d}){next;}
0292 $cache->{$d}={};
0293 if ($d!~/^lib.+\.so$/){next;}
0294 my $c="${symboldir}/SELF/${d}.cmssw";
0295 if (!-f $c){print STDERR "ERROR: Missing symbol cache file: $c\n";}
0296 else
0297 {
0298 my $syms={};
0299 &accSymbolsFromFile($c,$syms,$symDefine,1);
0300 $cache->{$d}=&findSymbolDependency($syms);
0301 if ($detail){&detailDepInfo($d,$cache);}
0302 &processSelfDependency($d,$cache);
0303 }
0304 }
0305 }
0306
0307 sub findSymbolDependency()
0308 {
0309 my ($syms)=@_;
0310 my $d={};
0311 foreach my $sym (keys %$syms)
0312 {
0313 if (exists $data->{SELF_SYMBOLS_UNDEF}{$sym})
0314 {
0315 foreach my $l (keys %{$data->{SELF_SYMBOLS_UNDEF}{$sym}{cmssw}}){$d->{$l}{$sym}=1;}
0316 }
0317 }
0318 return $d;
0319 }
0320
0321 sub getLibMap()
0322 {
0323 my $cache=shift;
0324 my $map={};
0325 foreach my $dir (keys %{$cache->{BUILDTREE}})
0326 {
0327 my $c=$cache->{BUILDTREE}{$dir};
0328 my $suffix=$c->{SUFFIX};
0329 if($suffix ne ""){next;}
0330 my $class=$c->{CLASS};
0331 my $name=$c->{NAME};
0332 if($class=~/^(LIBRARY|CLASSLIB|SEAL_PLATFORM)$/){$map->{$c->{PARENT}}=$c->{NAME};}
0333 }
0334 return $map;
0335 }
0336
0337 sub addToolDep ()
0338 {
0339 my ($tools,$symdir,$t)=@_;
0340 if (!defined $t)
0341 {
0342 foreach $t (&SCRAMGenUtils::getOrderedTools($tools)){&addToolDep($tools,$symdir,$t);}
0343 return;
0344 }
0345 if (exists $tools->{TOOLSDONE}{$t}{deps}){return;}
0346 $tools->{TOOLSDONE}{$t}{deps}={};
0347 my $c=$tools->{TOOLSDONE}{$t}{deps};
0348 if ($t ne "self")
0349 {
0350 if ($tools->{SETUP}{$t}{SCRAM_PROJECT} == 1)
0351 {
0352 my $bv=uc($t)."_BASE";
0353 my $sbase=$tools->{SETUP}{$t}{$bv};
0354 my $spfile="${sbase}/.SCRAM/${scramarch}/ProjectCache.db.gz";
0355 if (-f $spfile)
0356 {
0357 my $libmap=&getLibMap(&SCRAMGenUtils::readCache($spfile));
0358 &SCRAMGenUtils::scramToolSymbolCache($tools,$t,"${symboldir}/${symdir}",$xjobs,$libmap);
0359 foreach my $p (keys %$libmap)
0360 {
0361 my $l=$libmap->{$p};
0362 $data->{PRODUCT_MAP}{"lib${l}.so"}=$p;
0363 $data->{TOOL_TYPE}{"lib${l}.so"}="TOOLS";
0364 }
0365 }
0366 next;
0367 }
0368 elsif ($t eq "cxxcompiler")
0369 {
0370 my $sbase=$tools->{SETUP}{$t}{GCC_BASE};
0371 if (-d "${sbase}/lib")
0372 {
0373 foreach my $l ("stdc++","gcc_s","gfortran","ssp")
0374 {
0375 my $lib="${sbase}/lib/lib${l}.so";
0376 if(-f $lib)
0377 {
0378 $data->{PRODUCT_MAP}{"lib${l}.so"}="system";
0379 &SCRAMGenUtils::symbolCacheFork($lib,"cxxcompiler","${symboldir}/SYSTEM",$xjobs);
0380 }
0381 else{print STDERR "No such file: $lib\n";}
0382 }
0383 }
0384 foreach my $l ("m","util","rt")
0385 {
0386 my $f=0;
0387 foreach my $d ("/lib","/usr/lib")
0388 {
0389 my $lib="${d}/lib${l}.so";
0390 if(-f $lib)
0391 {
0392 &SCRAMGenUtils::symbolCacheFork($lib,"system","${symboldir}/SYSTEM",$xjobs);
0393 $data->{PRODUCT_MAP}{"lib${l}.so"}="system";
0394 $f=1;
0395 last;
0396 }
0397 }
0398 if (!$f){print STDERR "No such file: lib$l.so\n";}
0399 }
0400 foreach my $lib ("/lib/libpthread.so.0","/lib/libc.so.6")
0401 {
0402 if(-f $lib)
0403 {
0404 &SCRAMGenUtils::symbolCacheFork($lib,"system","${symboldir}/SYSTEM",$xjobs);
0405 my $l=basename($lib);
0406 $data->{PRODUCT_MAP}{"lib${l}.so"}="system";
0407 }
0408 else{print STDERR "No such file: $lib\n";}
0409 }
0410 }
0411 else
0412 {
0413 &SCRAMGenUtils::toolSymbolCache($tools,$t,"${symboldir}/TOOLS",$xjobs);
0414 if (exists $tools->{SETUP}{$t}{LIB})
0415 {
0416 foreach my $l (@{$tools->{SETUP}{$t}{LIB}})
0417 {
0418 $data->{PRODUCT_MAP}{"lib${l}.so"}=$t;
0419 $data->{TOOL_TYPE}{"lib${l}.so"}="TOOLS";
0420 }
0421 }
0422 }
0423 if (!exists $tools->{SETUP}{$t}{USE}){return;}
0424 foreach my $u (@{$tools->{SETUP}{$t}{USE}})
0425 {
0426 $u=lc($u);
0427 if(exists $tools->{SETUP}{$u})
0428 {
0429 &addToolDep($tools,$u);
0430 $c->{$u}=1;
0431 foreach my $k (keys %{$tools->{TOOLSDONE}{$t}{deps}}){$c->{$k}=1;}
0432 }
0433 }
0434 }
0435 }
0436
0437 sub isSystemSymbol()
0438 {
0439 my $sym=shift;
0440 if (exists $data->{SYSTEM_SYMBOLS_DEF}{$sym}){return 1;}
0441 foreach my $r (keys %systemsym){if($sym=~/^$r$/){return 1;}}
0442 return 0;
0443 }
0444
0445
0446
0447
0448 sub readSyms()
0449 {
0450 my ($lib,$type)=@_;
0451 my $sfile="${symboldir}/${type}";
0452 my $tool="cmssw";
0453 if (($type ne "SELF") && (exists $data->{PRODUCT_MAP}{$lib})){$tool=$data->{PRODUCT_MAP}{$lib};}
0454 my $sfile="${symboldir}/${type}/${lib}.${tool}";
0455 if (-f $sfile)
0456 {
0457 my $c=&SCRAMGenUtils::readHashCache($sfile);
0458 if (exists $c->{$tool}{$lib}){return $c->{$tool}{$lib};}
0459 }
0460 print STDERR "ERROR: Symbols not found for library: $lib\n";
0461 return {};
0462 }
0463
0464 sub sym2Lib()
0465 {
0466 my $lib=shift;
0467 my $graph=shift;
0468 my $cache=shift || {};
0469 my $tab=shift || "";
0470 my $parent=shift || "";
0471 my $depth=1+(length($tab)/2);
0472 if (exists $cache->{$lib}){return;}
0473 $cache->{$lib}=1;
0474 my $ltype="SELF";
0475 if (exists $data->{TOOL_TYPE}{$lib}){$ltype=$data->{TOOL_TYPE}{$lib};}
0476 my %syms=();
0477 my $deps={};
0478 if (!exists $data->{LIBDEPS}{$lib})
0479 {
0480 my $xsyms=&readSyms($lib,$ltype);
0481 foreach my $sym (keys %{$xsyms->{U}})
0482 {
0483 if (&isSystemSymbol($sym)==1){next;}
0484 $syms{$sym}=1;
0485 }
0486 foreach my $sym (keys %syms)
0487 {
0488 my $c=undef;
0489 if ($ltype eq "SELF")
0490 {
0491 if (exists $data->{SELF_SYMBOLS_DEF}{$sym}){$c=$data->{SELF_SYMBOLS_DEF}{$sym};}
0492 elsif(exists $data->{TOOLS_SYMBOLS_DEF}{$sym}){$c=$data->{TOOLS_SYMBOLS_DEF}{$sym};}
0493 }
0494 elsif(exists $data->{TOOLS_SYMBOLS_DEF}{$sym}){$c=$data->{TOOLS_SYMBOLS_DEF}{$sym};}
0495 if (defined $c)
0496 {
0497 foreach my $t (keys %{$c})
0498 {
0499 foreach my $l (keys %{$c->{$t}})
0500 {
0501 my $p=$l;
0502 if (exists $data->{PRODUCT_MAP}{$l}){$p=$data->{PRODUCT_MAP}{$l};}
0503 if (!exists $deps->{$p}){$deps->{$p}{c}=0;}
0504 $deps->{$p}{c}+=1;
0505 $deps->{$p}{l}{$l}=1;
0506 }
0507 }
0508 }
0509 elsif ($ltype eq "SELF"){$data->{UNKNOWN_SYM}{$sym}=1;}
0510 }
0511 $data->{LIBDEPS}{$lib}=$deps;
0512 if ($full)
0513 {
0514 foreach my $p (sort keys %$deps)
0515 {
0516 foreach my $l (keys %{$deps->{$p}{l}}){if (!exists $data->{LIBDEPS}{$l}){&sym2Lib($l,$graph);}}
0517 }
0518 }
0519 }
0520 else{$deps=$data->{LIBDEPS}{$lib};}
0521 my $mp=$lib;
0522 if ($depth>1){$mp=$data->{PRODUCT_MAP}{$lib};}
0523 if (($detail) && ($depth==1)){print "#######################################\n$lib:\n";}
0524 if ($depth<10){$depth="0$depth";}
0525 foreach my $p (sort keys %$deps)
0526 {
0527 if ($graph){$cache->{GRAPH}{DEPS}{$mp}{$p}=1;}
0528 if ($p eq "system"){next;}
0529 if (($detail) && ($p ne $parent))
0530 {
0531 my $ls=join(",",sort keys %{$deps->{$p}{l}});
0532 print "$depth.${tab} $p (",$deps->{$p}{c},": $ls)\n";
0533 }
0534 foreach my $l (keys %{$deps->{$p}{l}}){&sym2Lib($l,$graph,$cache,"$tab ",$p);}
0535 }
0536 if ($depth==1)
0537 {
0538 if (!$detail){print "\n###########################\n$lib:\n";}
0539 my %p=();
0540 my $pk="";
0541 foreach my $l (keys %$cache)
0542 {
0543 if (exists $data->{PRODUCT_MAP}{$l})
0544 {
0545 $pk=$data->{PRODUCT_MAP}{$l};
0546 if ($pk ne "system"){$p{$pk}=1;}
0547 }
0548 }
0549 if (exists $data->{PRODUCT_MAP}{$lib}){delete $p{$data->{PRODUCT_MAP}{$lib}};}
0550 my @ds=sort keys %p;
0551 if ($graph)
0552 {
0553 $cache->{GRAPH}{NODES}{$lib}=1;
0554 foreach my $x (@ds){$cache->{GRAPH}{NODES}{$x}=1;}
0555 &generateGraph($lib,$cache->{GRAPH});
0556 }
0557 print " * Direct dependencies:\n";
0558 foreach my $x (@ds){if (exists $deps->{$x}){print " $x\n";}}
0559 print " * Indirect dependencies:\n";
0560 foreach my $x (@ds){if (!exists $deps->{$x}){print " $x\n";}}
0561 }
0562 }
0563
0564 sub generateGraph()
0565 {
0566 my $l=shift;
0567 my $data=shift;
0568 my $ref;
0569 if (open($ref,">${cachedir}/Dot/${l}.dot"))
0570 {
0571 print $ref "digraph Dependencies {\n",
0572 ' fontname="Helvetica"; fontsize=12; center=true; ratio=auto;concentrate=true;',"\n",
0573 ' label="\n',$l,'\n"',"\n",
0574 ' node [shape=ellipse, fontname="Helvetica-Bold", fontsize=12, style=filled, color="0.9 1.0 1.0", fontcolor="0 0 1" ]',"\n",
0575 ' edge [fontname="Helvetica", fontsize=12 ]',"\n\n";
0576 foreach my $n (keys %{$data->{NODES}}){print $ref " \"$n\" []\n";}
0577 foreach my $n (keys %{$data->{DEPS}})
0578 {
0579 foreach my $d (keys %{$data->{DEPS}{$n}}) {print $ref " \"$n\" -> \"$d\" []\n";}
0580 }
0581 print $ref "}\n";
0582 close($ref);
0583 }
0584 else{print STDERR "ERROR: Can not open file for writing: ${l}.dot\n";}
0585 }
0586
0587 sub doDependency()
0588 {
0589 my $dependency=shift;
0590 my @prods=();
0591 if (exists $data->{prod}{$dependency}){$prods[0]=$dependency;}
0592 else
0593 {
0594 foreach my $pk (sort keys %{$data->{pack}})
0595 {
0596 if ($pk=~/^$dependency(\/.+|)$/o){foreach my $p (keys %{$data->{pack}{$pk}}){push @prods,$p;}}
0597 }
0598 }
0599 foreach my $lib (@prods){&sym2Lib($lib,$graph);}
0600 if ($detail && (exists $data->{UNKNOWN_SYM}))
0601 {
0602 print "SYMBOLS UNKNOWN:\n";
0603 foreach my $s (sort keys %{$data->{UNKNOWN_SYM}})
0604 {
0605 if ($cppfilt){$s=&SCRAMGenUtils::cppFilt($s);}
0606 print "$s\n";
0607 }
0608 }
0609 }