]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/tools/boostdep/src/boostdep.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / tools / boostdep / src / boostdep.cpp
index 7b30fef313b93a78801f73ce8a2d6d977fee01f2..f2e412db13c8c39c7839a0bf87be9a0561a4a006 100644 (file)
@@ -1,7 +1,7 @@
 
 // boostdep - a tool to generate Boost dependency reports
 //
-// Copyright 2014, 2015, 2016 Peter Dimov
+// Copyright 2014-2017 Peter Dimov
 //
 // Distributed under the Boost Software License, Version 1.0.
 // See accompanying file LICENSE_1_0.txt or copy at
@@ -46,13 +46,14 @@ static void scan_module_headers( fs::path const & path )
 
         for( ; it != last; ++it )
         {
-            fs::directory_entry const & e = *it;
+            if( it->status().type() == fs::directory_file )
+            {
+                continue;
+            }
 
-            std::string p2 = e.path().generic_string();
+            std::string p2 = it->path().generic_string();
             p2 = p2.substr( n+1 );
 
-            // std::cout << module << ": " << p2 << std::endl;
-
             s_header_map[ p2 ] = module;
             s_module_headers[ module ].insert( p2 );
         }
@@ -190,48 +191,59 @@ static fs::path module_build_path( std::string module )
     return fs::path( "libs" ) / module / "build";
 }
 
-static void scan_module_dependencies( std::string const & module, module_primary_actions & actions, bool track_sources, bool include_self )
+static fs::path module_test_path( std::string module )
 {
-    // module -> [ header, header... ]
-    std::map< std::string, std::set< std::string > > deps;
+    std::replace( module.begin(), module.end(), '~', '/' );
+    return fs::path( "libs" ) / module / "test";
+}
 
-    // header -> included from [ header, header... ]
-    std::map< std::string, std::set< std::string > > from;
+static void scan_module_path( fs::path const & dir, bool remove_prefix, std::map< std::string, std::set< std::string > > & deps, std::map< std::string, std::set< std::string > > & from )
+{
+    size_t n = dir.generic_string().size();
 
+    if( fs::exists( dir ) )
     {
-        fs::path dir = module_include_path( module );
-        size_t n = dir.generic_string().size();
-
         fs::recursive_directory_iterator it( dir ), last;
 
         for( ; it != last; ++it )
         {
-            std::string header = it->path().generic_string().substr( n+1 );
+            if( it->status().type() == fs::directory_file )
+            {
+                continue;
+            }
+
+            std::string header = it->path().generic_string();
+
+            if( remove_prefix )
+            {
+                header = header.substr( n+1 );
+            }
 
             fs::ifstream is( it->path() );
 
             scan_header_dependencies( header, is, deps, from );
         }
     }
+}
 
-    if( track_sources )
-    {
-        fs::path dir = module_source_path( module );
-        size_t n = dir.generic_string().size();
+static void scan_module_dependencies( std::string const & module, module_primary_actions & actions, bool track_sources, bool track_tests, bool include_self )
+{
+    // module -> [ header, header... ]
+    std::map< std::string, std::set< std::string > > deps;
 
-        if( fs::exists( dir ) )
-        {
-            fs::recursive_directory_iterator it( dir ), last;
+    // header -> included from [ header, header... ]
+    std::map< std::string, std::set< std::string > > from;
 
-            for( ; it != last; ++it )
-            {
-                std::string header = it->path().generic_string().substr( n+1 );
+    scan_module_path( module_include_path( module ), true, deps, from );
 
-                fs::ifstream is( it->path() );
+    if( track_sources )
+    {
+        scan_module_path( module_source_path( module ), false, deps, from );
+    }
 
-                scan_header_dependencies( header, is, deps, from );
-            }
-        }
+    if( track_tests )
+    {
+        scan_module_path( module_test_path( module ), false, deps, from );
     }
 
     actions.heading( module );
@@ -318,20 +330,20 @@ struct build_mdmap_actions: public module_primary_actions
     }
 };
 
-static void build_module_dependency_map( bool track_sources )
+static void build_module_dependency_map( bool track_sources, bool track_tests )
 {
     for( std::set< std::string >::iterator i = s_modules.begin(); i != s_modules.end(); ++i )
     {
         build_mdmap_actions actions;
-        scan_module_dependencies( *i, actions, track_sources, true );
+        scan_module_dependencies( *i, actions, track_sources, track_tests, true );
     }
 }
 
-static void output_module_primary_report( std::string const & module, module_primary_actions & actions, bool track_sources )
+static void output_module_primary_report( std::string const & module, module_primary_actions & actions, bool track_sources, bool track_tests )
 {
     try
     {
-        scan_module_dependencies( module, actions, track_sources, false );
+        scan_module_dependencies( module, actions, track_sources, track_tests, false );
     }
     catch( fs::filesystem_error const & x )
     {
@@ -357,12 +369,10 @@ static void exclude( std::set< std::string > & x, std::set< std::string > const
     }
 }
 
-static void output_module_secondary_report( std::string const & module, module_secondary_actions & actions )
+static void output_module_secondary_report( std::string const & module, std::set< std::string> deps, module_secondary_actions & actions )
 {
     actions.heading( module );
 
-    std::set< std::string > deps = s_module_deps[ module ];
-
     deps.insert( module );
 
     // build transitive closure
@@ -405,6 +415,11 @@ static void output_module_secondary_report( std::string const & module, module_s
     }
 }
 
+static void output_module_secondary_report( std::string const & module, module_secondary_actions & actions )
+{
+    output_module_secondary_report( module, s_module_deps[ module ], actions );
+}
+
 struct header_inclusion_actions
 {
     virtual void heading( std::string const & header, std::string const & module ) = 0;
@@ -512,17 +527,17 @@ struct module_primary_html_actions: public module_primary_actions
     }
 };
 
-static void output_module_primary_report( std::string const & module, bool html, bool track_sources )
+static void output_module_primary_report( std::string const & module, bool html, bool track_sources, bool track_tests )
 {
     if( html )
     {
         module_primary_html_actions actions;
-        output_module_primary_report( module, actions, track_sources );
+        output_module_primary_report( module, actions, track_sources, track_tests );
     }
     else
     {
         module_primary_txt_actions actions;
-        output_module_primary_report( module, actions, track_sources );
+        output_module_primary_report( module, actions, track_sources, track_tests );
     }
 }
 
@@ -794,7 +809,8 @@ int const unknown_level = INT_MAX / 2;
 
 struct module_level_actions
 {
-    virtual void heading() = 0;
+    virtual void begin() = 0;
+    virtual void end() = 0;
 
     virtual void level_start( int level ) = 0;
     virtual void level_end( int level ) = 0;
@@ -957,7 +973,7 @@ static void output_module_level_report( module_level_actions & actions )
 
     // output report
 
-    actions.heading();
+    actions.begin();
 
     for( std::map< int, std::set< std::string > >::iterator i = reverse_level_map.begin(); i != reverse_level_map.end(); ++i )
     {
@@ -991,17 +1007,23 @@ static void output_module_level_report( module_level_actions & actions )
 
         actions.level_end( i->first );
     }
+
+    actions.end();
 }
 
 struct module_level_txt_actions: public module_level_actions
 {
     int level_;
 
-    void heading()
+    void begin()
     {
         std::cout << "Module Levels:\n\n";
     }
 
+    void end()
+    {
+    }
+
     void level_start( int level )
     {
         if( level >= unknown_level )
@@ -1057,47 +1079,42 @@ struct module_level_html_actions: public module_level_actions
 {
     int level_;
 
-    void heading()
+    void begin()
     {
-        std::cout << "<h1>Module Levels</h1>\n";
+        std::cout << "<div id='module-levels'><h1>Module Levels</h1>\n";
     }
 
-    void level_start( int level )
+    void end()
     {
-        std::cout << "  <h2>Level ";
+        std::cout << "</div>\n";
+    }
 
+    void level_start( int level )
+    {
         if( level >= unknown_level )
         {
-            std::cout << "<em>undetermined</em>";
+            std::cout << "  <h2>Level <em>undetermined</em></h2>\n";
         }
         else
         {
-            std::cout << level;
+            std::cout << "  <h2 id='level:" << level << "'>Level " << level << "</h2>\n";
         }
 
-        std::cout << "</h2><ul>\n";
-
         level_ = level;
     }
 
     void level_end( int /*level*/ )
     {
-        std::cout << "  </ul>\n";
     }
 
     void module_start( std::string const & module )
     {
-        std::cout << "    <li><a href =\"" << module << ".html\">" << module << "</a><small>";
-
-        if( level_ > 0 )
-        {
-            std::cout << "<br />&#8674;";
-        }
+        std::cout << "    <h3 id='" << module << "'><a href=\"" << module << ".html\">" << module << "</a></h3><p class='primary-list'>";
     }
 
     void module_end( std::string const & /*module*/ )
     {
-        std::cout << "</small></li>\n";
+        std::cout << "</p>\n";
     }
 
     void module2( std::string const & module, int level )
@@ -1143,7 +1160,8 @@ static void output_module_level_report( bool html )
 
 struct module_overview_actions
 {
-    virtual void heading() = 0;
+    virtual void begin() = 0;
+    virtual void end() = 0;
 
     virtual void module_start( std::string const & module ) = 0;
     virtual void module_end( std::string const & module ) = 0;
@@ -1153,7 +1171,7 @@ struct module_overview_actions
 
 static void output_module_overview_report( module_overview_actions & actions )
 {
-    actions.heading();
+    actions.begin();
 
     for( std::set< std::string >::iterator i = s_modules.begin(); i != s_modules.end(); ++i )
     {
@@ -1168,17 +1186,23 @@ static void output_module_overview_report( module_overview_actions & actions )
 
         actions.module_end( *i );
     }
+
+    actions.end();
 }
 
 struct module_overview_txt_actions: public module_overview_actions
 {
     bool deps_;
 
-    void heading()
+    void begin()
     {
         std::cout << "Module Overview:\n\n";
     }
 
+    void end()
+    {
+    }
+
     void module_start( std::string const & module )
     {
         std::cout << module;
@@ -1204,32 +1228,28 @@ struct module_overview_txt_actions: public module_overview_actions
 
 struct module_overview_html_actions: public module_overview_actions
 {
-    bool deps_;
+    void begin()
+    {
+        std::cout << "<div id='module-overview'><h1>Module Overview</h1>\n";
+    }
 
-    void heading()
+    void end()
     {
-        std::cout << "<h1>Module Overview</h1>\n";
+        std::cout << "</div>\n";
     }
 
     void module_start( std::string const & module )
     {
-        std::cout << "  <h2><a href =\"" << module << ".html\"><em>" << module << "</em></a></h2><p><small>";
-        deps_ = false;
+        std::cout << "  <h2 id='" << module << "'><a href=\"" << module << ".html\"><em>" << module << "</em></a></h2><p class='primary-list'>";
     }
 
     void module_end( std::string const & /*module*/ )
     {
-        std::cout << "</small></p>\n";
+        std::cout << "</p>\n";
     }
 
     void module2( std::string const & module )
     {
-        if( !deps_ )
-        {
-            std::cout << "&#8674;";
-            deps_ = true;
-        }
-
         std::cout << " " << module;
     }
 };
@@ -1252,7 +1272,11 @@ static void output_module_overview_report( bool html )
 
 struct list_dependencies_actions: public module_overview_actions
 {
-    void heading()
+    void begin()
+    {
+    }
+
+    void end()
     {
     }
 
@@ -1283,30 +1307,41 @@ static void list_dependencies()
 
 //
 
-static void output_html_header( std::string const & title )
+static void output_html_header( std::string const & title, std::string const & stylesheet, std::string const & prefix )
 {
     std::cout << "<html>\n";
     std::cout << "<head>\n";
     std::cout << "<title>" << title << "</title>\n";
+
+    if( !stylesheet.empty() )
+    {
+        std::cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << stylesheet << "\" />\n";
+    }
+
     std::cout << "</head>\n";
     std::cout << "<body>\n";
+
+    if( !prefix.empty() )
+    {
+        std::cout << prefix << std::endl;
+    }
 }
 
 static void output_html_footer( std::string const & footer )
 {
     std::cout << "<hr />\n";
-    std::cout << "<p><small>" << footer << "</small></p>\n";
+    std::cout << "<p class=\"footer\">" << footer << "</p>\n";
     std::cout << "</body>\n";
     std::cout << "</html>\n";
 }
 
-static void enable_secondary( bool & secondary, bool track_sources )
+static void enable_secondary( bool & secondary, bool track_sources, bool track_tests )
 {
     if( !secondary )
     {
         try
         {
-            build_module_dependency_map( track_sources );
+            build_module_dependency_map( track_sources, track_tests );
         }
         catch( fs::filesystem_error const & x )
         {
@@ -1340,7 +1375,8 @@ static void list_buildable()
 
 struct module_weight_actions
 {
-    virtual void heading() = 0;
+    virtual void begin() = 0;
+    virtual void end() = 0;
 
     virtual void weight_start( int weight ) = 0;
     virtual void weight_end( int weight ) = 0;
@@ -1411,7 +1447,7 @@ static void output_module_weight_report( module_weight_actions & actions )
 
     // output report
 
-    actions.heading();
+    actions.begin();
 
     for( std::map< int, std::set< std::string > >::const_iterator i = modules_by_weight.begin(); i != modules_by_weight.end(); ++i )
     {
@@ -1452,15 +1488,21 @@ static void output_module_weight_report( module_weight_actions & actions )
 
         actions.weight_end( i->first );
     }
+
+    actions.end();
 }
 
 struct module_weight_txt_actions: public module_weight_actions
 {
-    void heading()
+    void begin()
     {
         std::cout << "Module Weights:\n\n";
     }
 
+    void end()
+    {
+    }
+
     void weight_start( int weight )
     {
         std::cout << "Weight " << weight << ":\n";
@@ -1514,35 +1556,39 @@ struct module_weight_html_actions: public module_weight_actions
 {
     int weight_;
 
-    void heading()
+    void begin()
     {
-        std::cout << "<h1>Module Weights</h1>\n";
+        std::cout << "<div id='module-weights'>\n<h1>Module Weights</h1>\n";
+    }
+
+    void end()
+    {
+        std::cout << "</div>\n";
     }
 
     void weight_start( int weight )
     {
-        std::cout << "  <h2>Weight " << weight << "</h2><ul>\n";
+        std::cout << "  <h2 id='weight:" << weight << "'>Weight " << weight << "</h2>\n";
         weight_ = weight;
     }
 
     void weight_end( int /*weight*/ )
     {
-        std::cout << "  </ul>\n";
     }
 
     void module_start( std::string const & module )
     {
-        std::cout << "    <li><a href =\"" << module << ".html\">" << module << "</a><small>";
+        std::cout << "    <h3 id='" << module << "'><a href=\"" << module << ".html\">" << module << "</a></h3>";
     }
 
     void module_end( std::string const & /*module*/ )
     {
-        std::cout << "</small></li>\n";
+        std::cout << "\n";
     }
 
     void module_primary_start()
     {
-        std::cout << "<br />&#8674;";
+        std::cout << "<p class='primary-list'>";
     }
 
     void module_primary( std::string const & module, int weight )
@@ -1566,11 +1612,12 @@ struct module_weight_html_actions: public module_weight_actions
 
     void module_primary_end()
     {
+        std::cout << "</p>";
     }
 
     void module_secondary_start()
     {
-        std::cout << "<br /><span style=\"padding-left: 1em;\">&#8674;";
+        std::cout << "<p class='secondary-list'>";
     }
 
     void module_secondary( std::string const & module, int /*weight*/ )
@@ -1580,7 +1627,7 @@ struct module_weight_html_actions: public module_weight_actions
 
     void module_secondary_end()
     {
-        std::cout << "</span>";
+        std::cout << "</p>";
     }
 };
 
@@ -1610,11 +1657,27 @@ struct module_subset_actions
     virtual void from_path( std::vector<std::string> const & path ) = 0;
 };
 
-static void output_module_subset_report( std::string const & module, module_subset_actions & actions )
+static void add_module_headers( fs::path const & dir, std::set<std::string> & headers )
 {
-    // build header closure
+    if( fs::exists( dir ) )
+    {
+        fs::recursive_directory_iterator it( dir ), last;
+
+        for( ; it != last; ++it )
+        {
+            if( it->status().type() == fs::directory_file )
+            {
+                continue;
+            }
+
+            headers.insert( it->path().generic_string() );
+        }
+    }
+}
 
-    std::set<std::string> const & headers = s_module_headers[ module ];
+static void output_module_subset_report_( std::string const & module, std::set<std::string> const & headers, module_subset_actions & actions )
+{
+    // build header closure
 
     // header -> (header)*
     std::map< std::string, std::set<std::string> > inc2;
@@ -1712,6 +1775,23 @@ static void output_module_subset_report( std::string const & module, module_subs
     }
 }
 
+static void output_module_subset_report( std::string const & module, bool track_sources, bool track_tests, module_subset_actions & actions )
+{
+    std::set<std::string> headers = s_module_headers[ module ];
+
+    if( track_sources )
+    {
+        add_module_headers( module_source_path( module ), headers );
+    }
+
+    if( track_tests )
+    {
+        add_module_headers( module_test_path( module ), headers );
+    }
+
+    output_module_subset_report_( module, headers, actions );
+}
+
 struct module_subset_txt_actions: public module_subset_actions
 {
     void heading( std::string const & module )
@@ -1784,18 +1864,457 @@ struct module_subset_html_actions: public module_subset_actions
     }
 };
 
-static void output_module_subset_report( std::string const & module, bool html )
+static void output_module_subset_report( std::string const & module, bool track_sources, bool track_tests, bool html )
+{
+    if( html )
+    {
+        module_subset_html_actions actions;
+        output_module_subset_report( module, track_sources, track_tests, actions );
+    }
+    else
+    {
+        module_subset_txt_actions actions;
+        output_module_subset_report( module, track_sources, track_tests, actions );
+    }
+}
+
+// --list-exceptions
+
+static void list_exceptions()
+{
+    std::string lm;
+
+    for( std::map< std::string, std::set<std::string> >::const_iterator i = s_module_headers.begin(); i != s_module_headers.end(); ++i )
+    {
+        std::string module = i->first;
+
+        std::replace( module.begin(), module.end(), '~', '/' );
+
+        std::string const prefix = "boost/" + module;
+        size_t const n = prefix.size();
+
+        for( std::set< std::string >::const_iterator j = i->second.begin(); j != i->second.end(); ++j )
+        {
+            std::string const & header = *j;
+
+            if( header.substr( 0, n+1 ) != prefix + '/' && header != prefix + ".hpp" )
+            {
+                if( lm != module )
+                {
+                    std::cout << module << ":\n";
+                    lm = module;
+                }
+
+                std::cout << "  " << header << '\n';
+            }
+        }
+    }
+}
+
+// --test
+
+struct module_test_primary_actions: public module_primary_actions
+{
+    std::set< std::string > & m_;
+
+    module_test_primary_actions( std::set< std::string > & m ): m_( m )
+    {
+    }
+
+    void heading( std::string const & module )
+    {
+        std::cout << "Test dependencies for " << module << ":\n\n";
+    }
+
+    void module_start( std::string const & module )
+    {
+        std::cout << module << "\n";
+        m_.insert( module );
+    }
+
+    void module_end( std::string const & /*module*/ )
+    {
+    }
+
+    void header_start( std::string const & /*header*/ )
+    {
+    }
+
+    void header_end( std::string const & /*header*/ )
+    {
+    }
+
+    void from_header( std::string const & /*header*/ )
+    {
+    }
+};
+
+struct module_test_secondary_actions: public module_secondary_actions
+{
+    std::set< std::string > & m_;
+    std::string m2_;
+
+    module_test_secondary_actions( std::set< std::string > & m ): m_( m )
+    {
+    }
+
+    void heading( std::string const & /*module*/ )
+    {
+    }
+
+    void module_start( std::string const & module )
+    {
+        m2_ = module;
+    }
+
+    void module_end( std::string const & /*module*/ )
+    {
+    }
+
+    void module_adds( std::string const & module )
+    {
+        if( m_.count( module ) == 0 )
+        {
+            std::cout << module << " (from " << m2_ << ")\n";
+            m_.insert( module );
+        }
+    }
+};
+
+static void output_module_test_report( std::string const & module )
+{
+    std::set< std::string > m;
+
+    module_test_primary_actions a1( m );
+    output_module_primary_report( module, a1, true, true );
+
+    std::cout << "\n";
+
+    bool secondary = false;
+    enable_secondary( secondary, true, false );
+
+    std::set< std::string > m2( m );
+    m2.insert( module );
+
+    module_test_secondary_actions a2( m2 );
+
+    output_module_secondary_report( module, m, a2 );
+}
+
+// --cmake
+
+struct collect_primary_dependencies: public module_primary_actions
+{
+    std::set< std::string > set_;
+
+    void heading( std::string const & )
+    {
+    }
+
+    void module_start( std::string const & module )
+    {
+        if( module == "(unknown)" ) return;
+
+        set_.insert( module );
+    }
+
+    void module_end( std::string const & /*module*/ )
+    {
+    }
+
+    void header_start( std::string const & /*header*/ )
+    {
+    }
+
+    void header_end( std::string const & /*header*/ )
+    {
+    }
+
+    void from_header( std::string const & /*header*/ )
+    {
+    }
+};
+
+static std::string module_cmake_package( std::string module )
+{
+    std::replace( module.begin(), module.end(), '~', '_' );
+    return "boost_" + module;
+}
+
+static std::string module_cmake_target( std::string module )
+{
+    std::replace( module.begin(), module.end(), '~', '_' );
+    return "boost::" + module;
+}
+
+static void output_module_cmake_report( std::string module )
+{
+    std::replace( module.begin(), module.end(), '/', '~' );
+
+    std::cout << "# Generated file. Do not edit.\n\n";
+
+    collect_primary_dependencies a1;
+    output_module_primary_report( module, a1, false, false );
+
+    if( !fs::exists( module_source_path( module ) ) )
+    {
+        for( std::set< std::string >::const_iterator i = a1.set_.begin(); i != a1.set_.end(); ++i )
+        {
+            std::cout << "boost_declare_dependency(" << module_cmake_package( *i ) << " INTERFACE " << module_cmake_target( *i ) << ")\n";
+        }
+    }
+    else
+    {
+        collect_primary_dependencies a2;
+        output_module_primary_report( module, a2, true, false );
+
+        for( std::set< std::string >::const_iterator i = a1.set_.begin(); i != a1.set_.end(); ++i )
+        {
+            a2.set_.erase( *i );
+            std::cout << "boost_declare_dependency(" << module_cmake_package( *i ) << " PUBLIC " << module_cmake_target( *i ) << ")\n";
+        }
+
+        std::cout << "\n";
+
+        for( std::set< std::string >::const_iterator i = a2.set_.begin(); i != a2.set_.end(); ++i )
+        {
+            std::cout << "boost_declare_dependency(" << module_cmake_package( *i ) << " PRIVATE " << module_cmake_target( *i ) << ")\n";
+        }
+    }
+}
+
+// --list-missing-headers
+
+struct missing_header_actions: public module_primary_actions
+{
+    std::string module_, module2_;
+
+    void heading( std::string const & module )
+    {
+        module_ = module;
+    }
+
+    void module_start( std::string const & module )
+    {
+        module2_ = module;
+    }
+
+    void module_end( std::string const & /*module*/ )
+    {
+    }
+
+    void header_start( std::string const & header )
+    {
+        if( module2_ == "(unknown)" )
+        {
+            if( !module_.empty() )
+            {
+                std::cout << module_ << ":\n";
+                module_.clear();
+            }
+
+            std::cout << "    <" << header << ">\n";
+        }
+    }
+
+    void header_end( std::string const & /*header*/ )
+    {
+    }
+
+    void from_header( std::string const & header )
+    {
+        if( module2_ == "(unknown)" )
+        {
+            std::cout << "        from <" << header << ">\n";
+        }
+    }
+};
+
+static void list_missing_headers( std::string const & module )
+{
+    missing_header_actions a;
+    output_module_primary_report( module, a, false, false );
+}
+
+static void list_missing_headers()
+{
+    for( std::set< std::string >::const_iterator i = s_modules.begin(); i != s_modules.end(); ++i )
+    {
+        list_missing_headers( *i );
+    }
+}
+
+// --pkgconfig
+
+struct primary_pkgconfig_actions: public module_primary_actions
+{
+    std::string version_;
+    std::string list_;
+
+    void heading( std::string const & )
+    {
+    }
+
+    void module_start( std::string const & module )
+    {
+        if( module == "(unknown)" ) return;
+
+        std::string m2( module );
+        std::replace( m2.begin(), m2.end(), '~', '_' );
+
+        if( !list_.empty() )
+        {
+            list_ += ", ";
+        }
+
+        list_ += "boost_" + m2 + " = " + version_;
+    }
+
+    void module_end( std::string const & )
+    {
+    }
+
+    void header_start( std::string const & )
+    {
+    }
+
+    void header_end( std::string const & )
+    {
+    }
+
+    void from_header( std::string const & )
+    {
+    }
+};
+
+static void output_requires( std::string const & section, std::string const & version, std::set< std::string > const & s )
+{
+    bool first = true;
+
+    for( std::set< std::string >::const_iterator i = s.begin(); i != s.end(); ++i )
+    {
+        if( first )
+        {
+            std::cout << section << ": ";
+            first = false;
+        }
+        else
+        {
+            std::cout << ", ";
+        }
+
+        std::string m2( *i );
+        std::replace( m2.begin(), m2.end(), '~', '_' );
+
+        std::cout << "boost_" << m2 << " = " << version;
+    }
+}
+
+static void output_pkgconfig( std::string const & module, std::string const & version, int argc, char const* argv[] )
 {
+    for( int i = 0; i < argc; ++i )
+    {
+        std::cout << argv[ i ] << '\n';
+    }
+
+    std::cout << '\n';
+
+    std::string m2( module );
+    std::replace( m2.begin(), m2.end(), '/', '_' );
+
+    std::string m3( module );
+    std::replace( m3.begin(), m3.end(), '/', '~' );
+
+    std::cout << "Name: boost_" << module << '\n';
+    std::cout << "Description: Boost C++ library '" << module << "'\n";
+    std::cout << "Version: " << version << '\n';
+    std::cout << "URL: http://www.boost.org/libs/" << module << '\n';
+    std::cout << "Cflags: -I${includedir}\n";
+
+    if( fs::exists( module_build_path( module ) ) && fs::exists( module_source_path( module ) ) )
+    {
+        std::cout << "Libs: -L${libdir} -lboost_" << m2 << "\n";
+    }
+
+    collect_primary_dependencies a1;
+    output_module_primary_report( m3, a1, false, false );
+
+    if( !a1.set_.empty() )
+    {
+        output_requires( "Requires", version, a1.set_ );
+        std::cout << std::endl;
+    }
+
+    collect_primary_dependencies a2;
+    output_module_primary_report( m3, a2, true, false );
+
+    for( std::set< std::string >::const_iterator i = a1.set_.begin(); i != a1.set_.end(); ++i )
+    {
+        a2.set_.erase( *i );
+    }
+
+    if( !a2.set_.empty() )
+    {
+        output_requires( "Requires.private", version, a2.set_ );
+        std::cout << std::endl;
+    }
+}
+
+// --subset-for
+
+static void output_directory_subset_report( std::string const & module, std::set<std::string> const & headers, bool html )
+{
+    for( std::set<std::string>::const_iterator i = headers.begin(); i != headers.end(); ++i )
+    {
+        std::map< std::string, std::set< std::string > > deps;
+        std::map< std::string, std::set< std::string > > from;
+
+        std::ifstream is( i->c_str() );
+        scan_header_dependencies( *i, is, deps, from );
+
+        for( std::map< std::string, std::set< std::string > >::const_iterator j = from.begin(); j != from.end(); ++j )
+        {
+            for( std::set<std::string>::const_iterator k = j->second.begin(); k != j->second.end(); ++k )
+            {
+                s_header_includes[ *k ].insert( j->first );
+            }
+        }
+    }
+
     if( html )
     {
         module_subset_html_actions actions;
-        output_module_subset_report( module, actions );
+        output_module_subset_report_( module, headers, actions );
     }
     else
     {
         module_subset_txt_actions actions;
-        output_module_subset_report( module, actions );
+        output_module_subset_report_( module, headers, actions );
+    }
+}
+
+//
+
+static bool find_boost_root()
+{
+    for( int i = 0; i < 32; ++i )
+    {
+        if( fs::exists( "Jamroot" ) )
+        {
+            return true;
+        }
+
+        fs::path p = fs::current_path();
+
+        if( p == p.root_path() )
+        {
+            return false;
+        }
+
+        fs::current_path( p.parent_path() );
     }
+
+    return false;
 }
 
 int main( int argc, char const* argv[] )
@@ -1808,7 +2327,9 @@ int main( int argc, char const* argv[] )
             "\n"
             "    boostdep --list-modules\n"
             "    boostdep --list-buildable\n"
-            "    boostdep [--track-sources] --list-dependencies\n"
+            "    boostdep [--track-sources] [--track-tests] --list-dependencies\n"
+            "    boostdep --list-exceptions\n"
+            "    boostdep --list-missing-headers\n"
             "\n"
             "    boostdep [options] --module-overview\n"
             "    boostdep [options] --module-levels\n"
@@ -1819,12 +2340,25 @@ int main( int argc, char const* argv[] )
             "    boostdep [options] --reverse <module>\n"
             "    boostdep [options] --subset <module>\n"
             "    boostdep [options] [--header] <header>\n"
+            "    boostdep --test <module>\n"
+            "    boostdep --cmake <module>\n"
+            "    boostdep --pkgconfig <module> <version> [<var>=<value>] [<var>=<value>]...\n"
+            "    boostdep [options] --subset-for <directory>\n"
             "\n"
-            "    [options]: [--track-sources] [--title <title>] [--footer <footer>] [--html]\n";
+            "    [options]: [--[no-]track-sources] [--[no-]track-tests]\n"
+            "               [--html-title <title>] [--html-footer <footer>]\n"
+            "               [--html-stylesheet <stylesheet>] [--html-prefix <prefix>]\n"
+            "               [--html]\n";
 
         return -1;
     }
 
+    if( !find_boost_root() )
+    {
+        std::cerr << "boostdep: Could not find Boost root.\n";
+        return -2;
+    }
+
     try
     {
         build_header_map();
@@ -1837,9 +2371,12 @@ int main( int argc, char const* argv[] )
     bool html = false;
     bool secondary = false;
     bool track_sources = false;
+    bool track_tests = false;
 
-    std::string title = "Boost Dependency Report";
-    std::string footer;
+    std::string html_title = "Boost Dependency Report";
+    std::string html_footer;
+    std::string html_stylesheet;
+    std::string html_prefix;
 
     for( int i = 1; i < argc; ++i )
     {
@@ -1853,18 +2390,32 @@ int main( int argc, char const* argv[] )
         {
             list_buildable();
         }
-        else if( option == "--title" )
+        else if( option == "--title" || option == "--html-title" )
+        {
+            if( i + 1 < argc )
+            {
+                html_title = argv[ ++i ];
+            }
+        }
+        else if( option == "--footer" || option == "--html-footer" )
         {
             if( i + 1 < argc )
             {
-                title = argv[ ++i ];
+                html_footer = argv[ ++i ];
             }
         }
-        else if( option == "--footer" )
+        else if( option == "--html-stylesheet" )
         {
             if( i + 1 < argc )
             {
-                footer = argv[ ++i ];
+                html_stylesheet = argv[ ++i ];
+            }
+        }
+        else if( option == "--html-prefix" )
+        {
+            if( i + 1 < argc )
+            {
+                html_prefix = argv[ ++i ];
             }
         }
         else if( option == "--html" )
@@ -1872,25 +2423,37 @@ int main( int argc, char const* argv[] )
             if( !html )
             {
                 html = true;
-                output_html_header( title );
+                output_html_header( html_title, html_stylesheet, html_prefix );
             }
         }
         else if( option == "--track-sources" )
         {
             track_sources = true;
         }
+        else if( option == "--no-track-sources" )
+        {
+            track_sources = false;
+        }
+        else if( option == "--track-tests" )
+        {
+            track_tests = true;
+        }
+        else if( option == "--no-track-tests" )
+        {
+            track_tests = false;
+        }
         else if( option == "--primary" )
         {
             if( i + 1 < argc )
             {
-                output_module_primary_report( argv[ ++i ], html, track_sources );
+                output_module_primary_report( argv[ ++i ], html, track_sources, track_tests );
             }
         }
         else if( option == "--secondary" )
         {
             if( i + 1 < argc )
             {
-                enable_secondary( secondary, track_sources );
+                enable_secondary( secondary, track_sources, track_tests );
                 output_module_secondary_report( argv[ ++i ], html );
             }
         }
@@ -1898,7 +2461,7 @@ int main( int argc, char const* argv[] )
         {
             if( i + 1 < argc )
             {
-                enable_secondary( secondary, track_sources );
+                enable_secondary( secondary, track_sources, track_tests );
                 output_module_reverse_report( argv[ ++i ], html );
             }
         }
@@ -1906,7 +2469,7 @@ int main( int argc, char const* argv[] )
         {
             if( i + 1 < argc )
             {
-                enable_secondary( secondary, track_sources );
+                enable_secondary( secondary, track_sources, track_tests );
                 output_header_report( argv[ ++i ], html );
             }
         }
@@ -1914,37 +2477,97 @@ int main( int argc, char const* argv[] )
         {
             if( i + 1 < argc )
             {
-                enable_secondary( secondary, track_sources );
-                output_module_subset_report( argv[ ++i ], html );
+                enable_secondary( secondary, track_sources, track_tests );
+                output_module_subset_report( argv[ ++i ], track_sources, track_tests, html );
+            }
+        }
+        else if( option == "--test" )
+        {
+            if( i + 1 < argc )
+            {
+                output_module_test_report( argv[ ++i ] );
+            }
+        }
+        else if( option == "--cmake" )
+        {
+            if( i + 1 < argc )
+            {
+                output_module_cmake_report( argv[ ++i ] );
             }
         }
         else if( option == "--module-levels" )
         {
-            enable_secondary( secondary, track_sources );
+            enable_secondary( secondary, track_sources, track_tests );
             output_module_level_report( html );
         }
         else if( option == "--module-overview" )
         {
-            enable_secondary( secondary, track_sources );
+            enable_secondary( secondary, track_sources, track_tests );
             output_module_overview_report( html );
         }
         else if( option == "--module-weights" )
         {
-            enable_secondary( secondary, track_sources );
+            enable_secondary( secondary, track_sources, track_tests );
             output_module_weight_report( html );
         }
         else if( option == "--list-dependencies" )
         {
-            enable_secondary( secondary, track_sources );
+            enable_secondary( secondary, track_sources, track_tests );
             list_dependencies();
         }
+        else if( option == "--list-exceptions" )
+        {
+            list_exceptions();
+        }
+        else if( option == "--list-missing-headers" )
+        {
+            list_missing_headers();
+        }
+        else if( option == "--pkgconfig" )
+        {
+            if( i + 2 < argc )
+            {
+                std::string module = argv[ ++i ];
+                std::string version = argv[ ++i ];
+
+                ++i;
+
+                output_pkgconfig( module, version, argc - i, argv + i );
+            }
+            else
+            {
+                std::cerr << "'" << option << "': missing module or version.\n";
+            }
+
+            break;
+        }
+        else if( option == "--subset-for" )
+        {
+            if( i + 1 < argc )
+            {
+                std::string module = argv[ ++i ];
+
+                enable_secondary( secondary, track_sources, track_tests );
+
+                std::set<std::string> headers;
+                add_module_headers( module, headers );
+
+                output_directory_subset_report( module, headers, html );
+            }
+            else
+            {
+                std::cerr << "'" << option << "': missing argument.\n";
+            }
+
+            break;
+        }
         else if( s_modules.count( option ) )
         {
-            output_module_primary_report( option, html, track_sources );
+            output_module_primary_report( option, html, track_sources, track_tests );
         }
         else if( s_header_map.count( option ) )
         {
-            enable_secondary( secondary, track_sources );
+            enable_secondary( secondary, track_sources, track_tests );
             output_header_report( option, html );
         }
         else
@@ -1955,6 +2578,6 @@ int main( int argc, char const* argv[] )
 
     if( html )
     {
-        output_html_footer( footer );
+        output_html_footer( html_footer );
     }
 }