]> git.tdb.fi Git - builder.git/blob - source/analyzer.cpp
Miscellaneous minor code cleanups
[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         table.clear();
31
32         TableRow row;
33         row.push_back("Name");
34         row.push_back("Package");
35         row.push_back("Type");
36         row.push_back("Rebuild");
37         table.push_back(row);
38         
39         build_depend_table(*builder.get_target("cmdline"), 0);
40
41         print_table();
42 }
43
44 void Analyzer::build_depend_table(Target &tgt, unsigned depth)
45 {
46         if(mode!=REBUILD && mode!=ALLDEPS)
47         {
48                 // Skip trivial targets
49                 if(ObjectFile *obj=dynamic_cast<ObjectFile *>(&tgt))
50                         return build_depend_table(obj->get_source(), depth);
51                 else if(Install *inst=dynamic_cast<Install *>(&tgt))
52                         return build_depend_table(inst->get_source(), depth);
53         }
54         else if(mode==REBUILD && !tgt.get_rebuild())
55                 /* All targets that depend on to-be-built targets will be rebuilt
56                 themselves, so we cn stop here. */
57                 return;
58         
59         TableRow row;
60
61         string fn;
62         if(full_paths)
63                 fn=tgt.get_name();
64         else
65                 fn=FS::basename(tgt.get_name());
66         row.push_back(string(depth*2, ' ')+fn);
67
68         const Package *pkg=tgt.get_package();
69         if(pkg)
70                 row.push_back(pkg->get_name());
71         else
72                 row.push_back("");
73         
74         row.push_back(tgt.get_type());
75         
76         if(tgt.get_rebuild())
77         {
78                 if(tgt.get_rebuild_reason().empty())
79                         row.push_back("Yes (no reason)");
80                 else
81                         row.push_back(tgt.get_rebuild_reason());
82         }
83
84         table.push_back(row);
85
86         if(!max_depth || depth<max_depth-1)
87         {
88                 const TargetList &depends=tgt.get_depends();
89                 //XXX If we want to sort the targets, we need to take the value of full_paths into account
90                 //depends.sort(target_order);
91                 for(TargetList::const_iterator i=depends.begin(); i!=depends.end(); ++i)
92                         build_depend_table(**i, depth+1);
93         }
94 }
95
96 void Analyzer::print_table() const
97 {
98         vector<unsigned> col_width;
99
100         // Determine column widths
101         for(Table::const_iterator i=table.begin(); i!=table.end(); ++i)
102         {
103                 if(col_width.size()<i->size())
104                         col_width.resize(i->size(), 0);
105                 for(unsigned j=0; j<i->size(); ++j)
106                         col_width[j]=max(col_width[j], (*i)[j].size());
107         }
108
109         for(Table::const_iterator i=table.begin(); i!=table.end(); ++i)
110         {
111                 string line;
112                 for(unsigned j=0; j<i->size(); ++j)
113                 {
114                         if(j>0)
115                                 line+="  ";
116                         line+=lexical_cast((*i)[j], Fmt("%-s").width(col_width[j]));
117                 }
118                 IO::print("%s\n", line);
119         }
120 }
121
122 bool Analyzer::target_order(Target *t1, Target *t2)
123 { return t1->get_name()<t2->get_name(); }