file_dependencies.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 190 行

CPP
190
字号
//=======================================================================// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek//// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//=======================================================================// Some small modifications are done by Alexander Holler/*  Paul Moore's request:  As an example of a practical problem which is not restricted to graph  "experts", consider file dependencies. It's basically graph construction,  plus topological sort, but it might make a nice "tutorial" example. Build a  dependency graph of files, then use the algorithms to do things like  1. Produce a full recompilation order (topological sort, by modified date)  2. Produce a "parallel" recompilation order (same as above, but group files  which can be built in parallel)  3. Change analysis (if I change file x, which others need recompiling)  4. Dependency changes (if I add a dependency between file x and file y, what  are the effects)*/#include <boost/config.hpp> // put this first to suppress some VC++ warnings#include <iostream>#include <iterator>#include <algorithm>#include <time.h>#include <boost/utility.hpp>#include <boost/graph/adjacency_list.hpp>#include <boost/graph/topological_sort.hpp>#include <boost/graph/depth_first_search.hpp>#include <boost/graph/dijkstra_shortest_paths.hpp>#include <boost/graph/visitors.hpp>using namespace std;using namespace boost;enum files_e { dax_h, yow_h, boz_h, zow_h, foo_cpp,                foo_o, bar_cpp, bar_o, libfoobar_a,               zig_cpp, zig_o, zag_cpp, zag_o,                  libzigzag_a, killerapp, N };const char* name[] = { "dax.h", "yow.h", "boz.h", "zow.h", "foo.cpp",                       "foo.o", "bar.cpp", "bar.o", "libfoobar.a",                       "zig.cpp", "zig.o", "zag.cpp", "zag.o",                       "libzigzag.a", "killerapp" };struct print_visitor : public bfs_visitor<> {  template <class Vertex, class Graph>  void discover_vertex(Vertex v, Graph&) {    cout << name[v] << " ";  }};struct cycle_detector : public dfs_visitor<>{  cycle_detector(bool& has_cycle)     : m_has_cycle(has_cycle) { }  template <class Edge, class Graph>  void back_edge(Edge, Graph&) { m_has_cycle = true; }protected:  bool& m_has_cycle;};int main(int,char*[]){  typedef pair<int,int> Edge;  Edge used_by[] = {    Edge(dax_h, foo_cpp), Edge(dax_h, bar_cpp), Edge(dax_h, yow_h),    Edge(yow_h, bar_cpp), Edge(yow_h, zag_cpp),    Edge(boz_h, bar_cpp), Edge(boz_h, zig_cpp), Edge(boz_h, zag_cpp),    Edge(zow_h, foo_cpp),     Edge(foo_cpp, foo_o),    Edge(foo_o, libfoobar_a),    Edge(bar_cpp, bar_o),    Edge(bar_o, libfoobar_a),    Edge(libfoobar_a, libzigzag_a),    Edge(zig_cpp, zig_o),    Edge(zig_o, libzigzag_a),    Edge(zag_cpp, zag_o),    Edge(zag_o, libzigzag_a),    Edge(libzigzag_a, killerapp)  };  const std::size_t nedges = sizeof(used_by)/sizeof(Edge);  typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300  // VC++ can't handle the iterator constructor  Graph g(N);  for (std::size_t j = 0; j < nedges; ++j) {    graph_traits<Graph>::edge_descriptor e; bool inserted;    tie(e, inserted) = add_edge(used_by[j].first, used_by[j].second, g);  }#else  Graph g(used_by, used_by + nedges, N);#endif  typedef graph_traits<Graph>::vertex_descriptor Vertex;  // Determine ordering for a full recompilation  // and the order with files that can be compiled in parallel  {    typedef list<Vertex> MakeOrder;    MakeOrder::iterator i;    MakeOrder make_order;    topological_sort(g, std::front_inserter(make_order));    cout << "make ordering: ";    for (i = make_order.begin();         i != make_order.end(); ++i)       cout << name[*i] << " ";      cout << endl << endl;    // Parallel compilation ordering    std::vector<int> time(N, 0);    for (i = make_order.begin(); i != make_order.end(); ++i) {          // Walk through the in_edges an calculate the maximum time.      if (in_degree (*i, g) > 0) {        Graph::in_edge_iterator j, j_end;        int maxdist=0;        // Through the order from topological sort, we are sure that every         // time we are using here is already initialized.        for (tie(j, j_end) = in_edges(*i, g); j != j_end; ++j)          maxdist=std::max(time[source(*j, g)], maxdist);        time[*i]=maxdist+1;      }    }    cout << "parallel make ordering, " << endl         << "vertices with same group number can be made in parallel" << endl;    {      graph_traits<Graph>::vertex_iterator i, iend;      for (tie(i,iend) = vertices(g); i != iend; ++i)        cout << "time_slot[" << name[*i] << "] = " << time[*i] << endl;    }  }  cout << endl;  // if I change yow.h what files need to be re-made?  {    cout << "A change to yow.h will cause what to be re-made?" << endl;    print_visitor vis;    breadth_first_search(g, vertex(yow_h, g), visitor(vis));    cout << endl;  }  cout << endl;  // are there any cycles in the graph?  {    bool has_cycle = false;    cycle_detector vis(has_cycle);    depth_first_search(g, visitor(vis));    cout << "The graph has a cycle? " << has_cycle << endl;  }  cout << endl;  // add a dependency going from bar.cpp to dax.h  {    cout << "adding edge bar_cpp -> dax_h" << endl;    add_edge(bar_cpp, dax_h, g);  }  cout << endl;  // are there any cycles in the graph?  {    bool has_cycle = false;    cycle_detector vis(has_cycle);    depth_first_search(g, visitor(vis));    cout << "The graph has a cycle now? " << has_cycle << endl;  }  return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?