]> git.tdb.fi Git - builder.git/blob - source/analyzer.cpp
7d120792591b41b7695e5de93bdbbe34a844e5b7
[builder.git] / source / analyzer.cpp
1 /* $Id$
2
3 This file is part of builder
4 Copyright © 2006-2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/fs/utils.h>
9 #include <msp/io/print.h>
10 #include "analyzer.h"
11 #include "builder.h"
12 #include "install.h"
13 #include "objectfile.h"
14 #include "package.h"
15 #include "sourcefile.h"
16 #include "target.h"
17
18 using namespace std;
19 using namespace Msp;
20
21 Analyzer::Analyzer(Builder &b):
22         builder(b),
23         mode(DEPS),
24         max_depth(0),
25         full_paths(false)
26 { }
27
28 void Analyzer::analyze()
29 {
30         TableRow row;
31         row.push_back("Name");
32         row.push_back("Package");
33         row.push_back("Type");
34         row.push_back("Rebuild");
35         table.push_back(row);
36         
37         build_depend_table(*builder.get_target("cmdline"), 0);
38
39         print_table();
40 }
41
42 void Analyzer::build_depend_table(Target &tgt, unsigned depth)
43 {
44         if(mode!=REBUILD && mode!=ALLDEPS)
45         {
46                 // Skip trivial targets
47                 if(ObjectFile *obj=dynamic_cast<ObjectFile *>(&tgt))
48                         return build_depend_table(obj->get_source(), depth);
49                 else if(Install *inst=dynamic_cast<Install *>(&tgt))
50                         return build_depend_table(inst->get_source(), depth);
51         }
52         else if(mode==REBUILD && !tgt.get_rebuild())
53                 /* All targets that depend on to-be-built targets will be rebuilt
54                 themselves, so we cn stop here. */
55                 return;
56         
57         TableRow row;
58
59         string fn;
60         if(full_paths)
61                 fn=tgt.get_name();
62         else
63                 fn=FS::basename(tgt.get_name());
64         row.push_back(string(depth*2, ' ')+fn);
65
66         const Package *pkg=tgt.get_package();
67         if(pkg)
68                 row.push_back(pkg->get_name());
69         else
70                 row.push_back("");
71         
72         row.push_back(tgt.get_type());
73         
74         if(tgt.get_rebuild())
75         {
76                 if(tgt.get_rebuild_reason().empty())
77                         row.push_back("Yes (no reason)");
78                 else
79                         row.push_back(tgt.get_rebuild_reason());
80         }
81
82         table.push_back(row);
83
84         if(!max_depth || depth<max_depth-1)
85         {
86                 const TargetList &depends=tgt.get_depends();
87                 //XXX If we want to sort the targets, we need to take the value of full_paths into account
88                 //depends.sort(target_order);
89                 for(TargetList::const_iterator i=depends.begin(); i!=depends.end(); ++i)
90                         build_depend_table(**i, depth+1);
91         }
92 }
93
94 void Analyzer::print_table() const
95 {
96         vector<unsigned> col_width;
97
98         // Determine column widths
99         for(Table::const_iterator i=table.begin(); i!=table.end(); ++i)
100         {
101                 if(col_width.size()<i->size())
102                         col_width.resize(i->size(), 0);
103                 for(unsigned j=0; j<i->size(); ++j)
104                         col_width[j]=max(col_width[j], (*i)[j].size());
105         }
106
107         for(Table::const_iterator i=table.begin(); i!=table.end(); ++i)
108         {
109                 string line;
110                 for(unsigned j=0; j<i->size(); ++j)
111                 {
112                         if(j>0)
113                                 line+="  ";
114                         line+=lexical_cast((*i)[j], Fmt("%-s").width(col_width[j]));
115                 }
116                 IO::print("%s\n", line);
117         }
118 }
119
120 bool Analyzer::target_order(Target *t1, Target *t2)
121 { return t1->get_name()<t2->get_name(); }