]> git.tdb.fi Git - builder.git/blob - source/analyzer.cpp
Make the name of a FileTarget be its basename instead of full path
[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 name;
62         FileTarget *ft = dynamic_cast<FileTarget *>(&tgt);
63         if(full_paths && ft)
64                 name = ft->get_path().str();
65         else
66                 name = tgt.get_name();
67         row.push_back(string(depth*2, ' ')+name);
68
69         const Package *pkg = tgt.get_package();
70         if(pkg)
71                 row.push_back(pkg->get_name());
72         else
73                 row.push_back("");
74         
75         row.push_back(tgt.get_type());
76         
77         if(tgt.get_rebuild())
78         {
79                 if(tgt.get_rebuild_reason().empty())
80                         row.push_back("Yes (no reason)");
81                 else
82                         row.push_back(tgt.get_rebuild_reason());
83         }
84
85         table.push_back(row);
86
87         if(!max_depth || depth<max_depth-1)
88         {
89                 const TargetList &depends = tgt.get_depends();
90                 //XXX If we want to sort the targets, we need to take the value of full_paths into account
91                 //depends.sort(target_order);
92                 for(TargetList::const_iterator i=depends.begin(); i!=depends.end(); ++i)
93                         build_depend_table(**i, depth+1);
94         }
95 }
96
97 void Analyzer::print_table() const
98 {
99         vector<string::size_type> col_width;
100
101         // Determine column widths
102         for(Table::const_iterator i=table.begin(); i!=table.end(); ++i)
103         {
104                 if(col_width.size()<i->size())
105                         col_width.resize(i->size(), 0);
106                 for(unsigned j=0; j<i->size(); ++j)
107                         col_width[j] = max(col_width[j], (*i)[j].size());
108         }
109
110         for(Table::const_iterator i=table.begin(); i!=table.end(); ++i)
111         {
112                 string line;
113                 for(unsigned j=0; j<i->size(); ++j)
114                 {
115                         if(j>0)
116                                 line += "  ";
117                         line += lexical_cast((*i)[j], Fmt("%-s").width(col_width[j]));
118                 }
119                 IO::print("%s\n", line);
120         }
121 }
122
123 bool Analyzer::target_order(Target *t1, Target *t2)
124 { return t1->get_name()<t2->get_name(); }