void Analyzer::analyze()
{
+ if(mode==RDEPS)
+ {
+ rdepends.clear();
+ const TargetMap &targets = builder.get_targets();
+ for(TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
+ {
+ const TargetList &depends = i->second->get_depends();
+ for(TargetList::const_iterator j=depends.begin(); j!=depends.end(); ++j)
+ rdepends[*j].insert(i->second);
+ }
+ }
+
table.clear();
TableRow row;
row.push_back("Rebuild");
table.push_back(row);
- build_depend_table(*builder.get_target("cmdline"), 0);
+ const Target &cmdline = *builder.get_target("cmdline");
+ if(mode==RDEPS)
+ {
+ const TargetList &deps = cmdline.get_depends();
+ for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+ build_depend_table(**i, 0);
+ }
+ else
+ build_depend_table(cmdline, 0);
print_table();
}
-void Analyzer::build_depend_table(Target &tgt, unsigned depth)
+void Analyzer::build_depend_table(const Target &tgt, unsigned depth)
{
- if(mode!=REBUILD && mode!=ALLDEPS)
+ if(mode==DEPS)
{
// Skip trivial targets
- if(ObjectFile *obj = dynamic_cast<ObjectFile *>(&tgt))
+ if(const ObjectFile *obj = dynamic_cast<const ObjectFile *>(&tgt))
return build_depend_table(obj->get_source(), depth);
- else if(Install *inst = dynamic_cast<Install *>(&tgt))
+ else if(const Install *inst = dynamic_cast<const Install *>(&tgt))
return build_depend_table(inst->get_source(), depth);
}
else if(mode==REBUILD && !tgt.get_rebuild())
TableRow row;
string name;
- FileTarget *ft = dynamic_cast<FileTarget *>(&tgt);
+ const FileTarget *ft = dynamic_cast<const FileTarget *>(&tgt);
if(full_paths && ft)
name = ft->get_path().str();
else
if(!max_depth || depth<max_depth-1)
{
- const TargetList &depends = tgt.get_depends();
- //XXX If we want to sort the targets, we need to take the value of full_paths into account
- //depends.sort(target_order);
+ TargetList depends;
+ if(mode==RDEPS)
+ {
+ const set<Target *> &rdeps = rdepends[&tgt];
+ depends.assign(rdeps.begin(), rdeps.end());
+ }
+ else
+ depends = tgt.get_depends();
+
+ depends.sort(full_paths ? target_order_full : target_order);
+
for(TargetList::const_iterator i=depends.begin(); i!=depends.end(); ++i)
build_depend_table(**i, depth+1);
}
}
}
-bool Analyzer::target_order(Target *t1, Target *t2)
-{ return t1->get_name()<t2->get_name(); }
+bool Analyzer::target_order(const Target *t1, const Target *t2)
+{
+ return t1->get_name()<t2->get_name();
+}
+
+bool Analyzer::target_order_full(const Target *t1, const Target *t2)
+{
+ const FileTarget *ft1 = dynamic_cast<const FileTarget *>(t1);
+ const FileTarget *ft2 = dynamic_cast<const FileTarget *>(t2);
+ if(!ft1)
+ {
+ if(ft2)
+ return true;
+ return target_order(t1, t2);
+ }
+ else if(!ft2)
+ return false;
+ return ft1->get_path().str()<ft2->get_path().str();
+}
#define ANALYZER_H_
#include <list>
+#include <set>
#include <string>
#include <vector>
DEPS, //< Skip over "trivial" targets such as Install and Compile
ALLDEPS, //< Print out absolutely every target
REBUILD, //< Print targets that are going to be rebuilt
- RDEPS //< Print targets that depend on the given targets (NYI)
+ RDEPS //< Print targets that depend on the given targets
};
private:
Table table;
unsigned max_depth;
bool full_paths;
+ std::map<const Target *, std::set<Target *> > rdepends;
public:
Analyzer(Builder &);
/**
Adds rows to the table for the given target and its dependencies.
*/
- void build_depend_table(Target &, unsigned);
+ void build_depend_table(const Target &, unsigned);
/**
Prints out the table that resulted from the analysis.
*/
void print_table() const;
- static bool target_order(Target *, Target *);
+ static bool target_order(const Target *, const Target *);
+ static bool target_order_full(const Target *, const Target *);
};
#endif