2 // boostdep - a tool to generate Boost dependency reports
4 // Copyright 2014-2017 Peter Dimov
6 // Distributed under the Boost Software License, Version 1.0.
7 // See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt
11 #include <boost/filesystem.hpp>
12 #include <boost/filesystem/fstream.hpp>
22 namespace fs
= boost::filesystem
;
25 static std::map
< std::string
, std::string
> s_header_map
;
28 static std::map
< std::string
, std::set
<std::string
> > s_module_headers
;
30 static std::set
< std::string
> s_modules
;
32 static void scan_module_headers( fs::path
const & path
)
36 std::string module
= path
.generic_string().substr( 5 ); // strip "libs/"
38 std::replace( module
.begin(), module
.end(), '/', '~' );
40 s_modules
.insert( module
);
42 fs::path dir
= path
/ "include";
43 size_t n
= dir
.generic_string().size();
45 fs::recursive_directory_iterator
it( dir
), last
;
47 for( ; it
!= last
; ++it
)
49 if( it
->status().type() == fs::directory_file
)
54 std::string p2
= it
->path().generic_string();
55 p2
= p2
.substr( n
+1 );
57 s_header_map
[ p2
] = module
;
58 s_module_headers
[ module
].insert( p2
);
61 catch( fs::filesystem_error
const & x
)
63 std::cout
<< x
.what() << std::endl
;
67 static void scan_submodules( fs::path
const & path
)
69 fs::directory_iterator
it( path
), last
;
71 for( ; it
!= last
; ++it
)
73 fs::directory_entry
const & e
= *it
;
75 if( e
.status().type() != fs::directory_file
)
80 fs::path path
= e
.path();
82 if( fs::exists( path
/ "include" ) )
84 scan_module_headers( path
);
87 if( fs::exists( path
/ "sublibs" ) )
89 scan_submodules( path
);
94 static void build_header_map()
96 scan_submodules( "libs" );
99 static void scan_header_dependencies( std::string
const & header
, std::istream
& is
, std::map
< std::string
, std::set
< std::string
> > & deps
, std::map
< std::string
, std::set
< std::string
> > & from
)
103 while( std::getline( is
, line
) )
105 while( !line
.empty() && ( line
[0] == ' ' || line
[0] == '\t' ) )
110 if( line
.empty() || line
[0] != '#' ) continue;
114 while( !line
.empty() && ( line
[0] == ' ' || line
[0] == '\t' ) )
119 if( line
.substr( 0, 7 ) != "include" ) continue;
123 while( !line
.empty() && ( line
[0] == ' ' || line
[0] == '\t' ) )
128 if( line
.size() < 2 ) continue;
132 if( ch
!= '<' && ch
!= '"' ) continue;
141 std::string::size_type k
= line
.find_first_of( ch
);
143 if( k
!= std::string::npos
)
148 std::map
< std::string
, std::string
>::const_iterator i
= s_header_map
.find( line
);
150 if( i
!= s_header_map
.end() )
152 deps
[ i
->second
].insert( line
);
153 from
[ line
].insert( header
);
155 else if( line
.substr( 0, 6 ) == "boost/" )
157 deps
[ "(unknown)" ].insert( line
);
158 from
[ line
].insert( header
);
163 struct module_primary_actions
165 virtual void heading( std::string
const & module
) = 0;
167 virtual void module_start( std::string
const & module
) = 0;
168 virtual void module_end( std::string
const & module
) = 0;
170 virtual void header_start( std::string
const & header
) = 0;
171 virtual void header_end( std::string
const & header
) = 0;
173 virtual void from_header( std::string
const & header
) = 0;
176 static fs::path
module_include_path( std::string module
)
178 std::replace( module
.begin(), module
.end(), '~', '/' );
179 return fs::path( "libs" ) / module
/ "include";
182 static fs::path
module_source_path( std::string module
)
184 std::replace( module
.begin(), module
.end(), '~', '/' );
185 return fs::path( "libs" ) / module
/ "src";
188 static fs::path
module_build_path( std::string module
)
190 std::replace( module
.begin(), module
.end(), '~', '/' );
191 return fs::path( "libs" ) / module
/ "build";
194 static fs::path
module_test_path( std::string module
)
196 std::replace( module
.begin(), module
.end(), '~', '/' );
197 return fs::path( "libs" ) / module
/ "test";
200 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
)
202 size_t n
= dir
.generic_string().size();
204 if( fs::exists( dir
) )
206 fs::recursive_directory_iterator
it( dir
), last
;
208 for( ; it
!= last
; ++it
)
210 if( it
->status().type() == fs::directory_file
)
215 std::string header
= it
->path().generic_string();
219 header
= header
.substr( n
+1 );
222 fs::ifstream
is( it
->path() );
224 scan_header_dependencies( header
, is
, deps
, from
);
229 static void scan_module_dependencies( std::string
const & module
, module_primary_actions
& actions
, bool track_sources
, bool track_tests
, bool include_self
)
231 // module -> [ header, header... ]
232 std::map
< std::string
, std::set
< std::string
> > deps
;
234 // header -> included from [ header, header... ]
235 std::map
< std::string
, std::set
< std::string
> > from
;
237 scan_module_path( module_include_path( module
), true, deps
, from
);
241 scan_module_path( module_source_path( module
), false, deps
, from
);
246 scan_module_path( module_test_path( module
), false, deps
, from
);
249 actions
.heading( module
);
251 for( std::map
< std::string
, std::set
< std::string
> >::iterator i
= deps
.begin(); i
!= deps
.end(); ++i
)
253 if( i
->first
== module
&& !include_self
) continue;
255 actions
.module_start( i
->first
);
257 for( std::set
< std::string
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
259 actions
.header_start( *j
);
261 std::set
< std::string
> const & f
= from
[ *j
];
263 for( std::set
< std::string
>::const_iterator k
= f
.begin(); k
!= f
.end(); ++k
)
265 actions
.from_header( *k
);
268 actions
.header_end( *j
);
271 actions
.module_end( i
->first
);
275 // module depends on [ module, module... ]
276 static std::map
< std::string
, std::set
< std::string
> > s_module_deps
;
278 // header is included by [header, header...]
279 static std::map
< std::string
, std::set
< std::string
> > s_header_deps
;
281 // [ module, module... ] depend on module
282 static std::map
< std::string
, std::set
< std::string
> > s_reverse_deps
;
284 // header includes [header, header...]
285 static std::map
< std::string
, std::set
< std::string
> > s_header_includes
;
287 struct build_mdmap_actions
: public module_primary_actions
290 std::string module2_
;
293 void heading( std::string
const & module
)
298 void module_start( std::string
const & module
)
300 if( module
!= module_
)
302 s_module_deps
[ module_
].insert( module
);
303 s_reverse_deps
[ module
].insert( module_
);
309 void module_end( std::string
const & /*module*/ )
313 void header_start( std::string
const & header
)
318 void header_end( std::string
const & /*header*/ )
322 void from_header( std::string
const & header
)
324 if( module_
!= module2_
)
326 s_header_deps
[ header_
].insert( header
);
329 s_header_includes
[ header
].insert( header_
);
333 static void build_module_dependency_map( bool track_sources
, bool track_tests
)
335 for( std::set
< std::string
>::iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
337 build_mdmap_actions actions
;
338 scan_module_dependencies( *i
, actions
, track_sources
, track_tests
, true );
342 static void output_module_primary_report( std::string
const & module
, module_primary_actions
& actions
, bool track_sources
, bool track_tests
)
346 scan_module_dependencies( module
, actions
, track_sources
, track_tests
, false );
348 catch( fs::filesystem_error
const & x
)
350 std::cout
<< x
.what() << std::endl
;
354 struct module_secondary_actions
356 virtual void heading( std::string
const & module
) = 0;
358 virtual void module_start( std::string
const & module
) = 0;
359 virtual void module_end( std::string
const & module
) = 0;
361 virtual void module_adds( std::string
const & module
) = 0;
364 static void exclude( std::set
< std::string
> & x
, std::set
< std::string
> const & y
)
366 for( std::set
< std::string
>::const_iterator i
= y
.begin(); i
!= y
.end(); ++i
)
372 static void output_module_secondary_report( std::string
const & module
, std::set
< std::string
> deps
, module_secondary_actions
& actions
)
374 actions
.heading( module
);
376 deps
.insert( module
);
378 // build transitive closure
382 std::set
< std::string
> deps2( deps
);
384 for( std::set
< std::string
>::iterator i
= deps
.begin(); i
!= deps
.end(); ++i
)
386 std::set
< std::string
> deps3
= s_module_deps
[ *i
];
388 exclude( deps3
, deps
);
395 actions
.module_start( *i
);
397 for( std::set
< std::string
>::iterator j
= deps3
.begin(); j
!= deps3
.end(); ++j
)
399 actions
.module_adds( *j
);
402 actions
.module_end( *i
);
404 deps2
.insert( deps3
.begin(), deps3
.end() );
418 static void output_module_secondary_report( std::string
const & module
, module_secondary_actions
& actions
)
420 output_module_secondary_report( module
, s_module_deps
[ module
], actions
);
423 struct header_inclusion_actions
425 virtual void heading( std::string
const & header
, std::string
const & module
) = 0;
427 virtual void module_start( std::string
const & module
) = 0;
428 virtual void module_end( std::string
const & module
) = 0;
430 virtual void header( std::string
const & header
) = 0;
433 static void output_header_inclusion_report( std::string
const & header
, header_inclusion_actions
& actions
)
435 std::string module
= s_header_map
[ header
];
437 actions
.heading( header
, module
);
439 std::set
< std::string
> from
= s_header_deps
[ header
];
441 // classify 'from' dependencies by module
443 // module -> [header, header...]
444 std::map
< std::string
, std::set
< std::string
> > from2
;
446 for( std::set
< std::string
>::iterator i
= from
.begin(); i
!= from
.end(); ++i
)
448 from2
[ s_header_map
[ *i
] ].insert( *i
);
451 for( std::map
< std::string
, std::set
< std::string
> >::iterator i
= from2
.begin(); i
!= from2
.end(); ++i
)
453 actions
.module_start( i
->first
);
455 for( std::set
< std::string
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
457 actions
.header( *j
);
460 actions
.module_end( i
->first
);
464 // output_module_primary_report
466 struct module_primary_txt_actions
: public module_primary_actions
468 void heading( std::string
const & module
)
470 std::cout
<< "Primary dependencies for " << module
<< ":\n\n";
473 void module_start( std::string
const & module
)
475 std::cout
<< module
<< ":\n";
478 void module_end( std::string
const & /*module*/ )
483 void header_start( std::string
const & header
)
485 std::cout
<< " <" << header
<< ">\n";
488 void header_end( std::string
const & /*header*/ )
492 void from_header( std::string
const & header
)
494 std::cout
<< " from <" << header
<< ">\n";
498 struct module_primary_html_actions
: public module_primary_actions
500 void heading( std::string
const & module
)
502 std::cout
<< "\n\n<h1 id=\"primary-dependencies\">Primary dependencies for <em>" << module
<< "</em></h1>\n";
505 void module_start( std::string
const & module
)
507 std::cout
<< " <h2 id=\"" << module
<< "\"><a href=\"" << module
<< ".html\"><em>" << module
<< "</em></a></h2>\n";
510 void module_end( std::string
const & /*module*/ )
514 void header_start( std::string
const & header
)
516 std::cout
<< " <h3><code><" << header
<< "></code></h3><ul>\n";
519 void header_end( std::string
const & /*header*/ )
521 std::cout
<< " </ul>\n";
524 void from_header( std::string
const & header
)
526 std::cout
<< " <li>from <code><" << header
<< "></code></li>\n";
530 static void output_module_primary_report( std::string
const & module
, bool html
, bool track_sources
, bool track_tests
)
534 module_primary_html_actions actions
;
535 output_module_primary_report( module
, actions
, track_sources
, track_tests
);
539 module_primary_txt_actions actions
;
540 output_module_primary_report( module
, actions
, track_sources
, track_tests
);
544 // output_module_secondary_report
546 struct module_secondary_txt_actions
: public module_secondary_actions
548 void heading( std::string
const & module
)
550 std::cout
<< "Secondary dependencies for " << module
<< ":\n\n";
553 void module_start( std::string
const & module
)
555 std::cout
<< module
<< ":\n";
558 void module_end( std::string
const & /*module*/ )
563 void module_adds( std::string
const & module
)
565 std::cout
<< " adds " << module
<< "\n";
569 struct module_secondary_html_actions
: public module_secondary_actions
573 void heading( std::string
const & module
)
575 std::cout
<< "\n\n<h1 id=\"secondary-dependencies\">Secondary dependencies for <em>" << module
<< "</em></h1>\n";
578 void module_start( std::string
const & module
)
580 std::cout
<< " <h2><a href=\"" << module
<< ".html\"><em>" << module
<< "</em></a></h2><ul>\n";
584 void module_end( std::string
const & /*module*/ )
586 std::cout
<< " </ul>\n";
589 void module_adds( std::string
const & module
)
591 std::cout
<< " <li><a href=\"" << m2_
<< ".html#" << module
<< "\">adds <em>" << module
<< "</em></a></li>\n";
595 static void output_module_secondary_report( std::string
const & module
, bool html
)
599 module_secondary_html_actions actions
;
600 output_module_secondary_report( module
, actions
);
604 module_secondary_txt_actions actions
;
605 output_module_secondary_report( module
, actions
);
609 // output_header_report
611 struct header_inclusion_txt_actions
: public header_inclusion_actions
613 void heading( std::string
const & header
, std::string
const & module
)
615 std::cout
<< "Inclusion report for <" << header
<< "> (in module " << module
<< "):\n\n";
618 void module_start( std::string
const & module
)
620 std::cout
<< " from " << module
<< ":\n";
623 void module_end( std::string
const & /*module*/ )
628 void header( std::string
const & header
)
630 std::cout
<< " <" << header
<< ">\n";
634 struct header_inclusion_html_actions
: public header_inclusion_actions
636 void heading( std::string
const & header
, std::string
const & module
)
638 std::cout
<< "<h1>Inclusion report for <code><" << header
<< "></code> (in module <em>" << module
<< "</em>)</h1>\n";
641 void module_start( std::string
const & module
)
643 std::cout
<< " <h2>From <a href=\"" << module
<< ".html\"><em>" << module
<< "</em></a></h2><ul>\n";
646 void module_end( std::string
const & /*module*/ )
648 std::cout
<< " </ul>\n";
651 void header( std::string
const & header
)
653 std::cout
<< " <li><code><" << header
<< "></code></li>\n";
657 static void output_header_report( std::string
const & header
, bool html
)
661 header_inclusion_html_actions actions
;
662 output_header_inclusion_report( header
, actions
);
666 header_inclusion_txt_actions actions
;
667 output_header_inclusion_report( header
, actions
);
671 // output_module_reverse_report
673 struct module_reverse_actions
675 virtual void heading( std::string
const & module
) = 0;
677 virtual void module_start( std::string
const & module
) = 0;
678 virtual void module_end( std::string
const & module
) = 0;
680 virtual void header_start( std::string
const & header
) = 0;
681 virtual void header_end( std::string
const & header
) = 0;
683 virtual void from_header( std::string
const & header
) = 0;
686 static void output_module_reverse_report( std::string
const & module
, module_reverse_actions
& actions
)
688 actions
.heading( module
);
690 std::set
< std::string
> const from
= s_reverse_deps
[ module
];
692 for( std::set
< std::string
>::const_iterator i
= from
.begin(); i
!= from
.end(); ++i
)
694 actions
.module_start( *i
);
696 for( std::map
< std::string
, std::set
< std::string
> >::iterator j
= s_header_deps
.begin(); j
!= s_header_deps
.end(); ++j
)
698 if( s_header_map
[ j
->first
] == module
)
700 bool header_started
= false;
702 for( std::set
< std::string
>::iterator k
= j
->second
.begin(); k
!= j
->second
.end(); ++k
)
704 if( s_header_map
[ *k
] == *i
)
706 if( !header_started
)
708 actions
.header_start( j
->first
);
710 header_started
= true;
713 actions
.from_header( *k
);
719 actions
.header_end( j
->first
);
724 actions
.module_end( *i
);
728 struct module_reverse_txt_actions
: public module_reverse_actions
730 void heading( std::string
const & module
)
732 std::cout
<< "Reverse dependencies for " << module
<< ":\n\n";
735 void module_start( std::string
const & module
)
737 std::cout
<< module
<< ":\n";
740 void module_end( std::string
const & /*module*/ )
745 void header_start( std::string
const & header
)
747 std::cout
<< " <" << header
<< ">\n";
750 void header_end( std::string
const & /*header*/ )
754 void from_header( std::string
const & header
)
756 std::cout
<< " from <" << header
<< ">\n";
760 struct module_reverse_html_actions
: public module_reverse_actions
762 void heading( std::string
const & module
)
764 std::cout
<< "\n\n<h1 id=\"reverse-dependencies\">Reverse dependencies for <em>" << module
<< "</em></h1>\n";
767 void module_start( std::string
const & module
)
769 std::cout
<< " <h2 id=\"reverse-" << module
<< "\"><a href=\"" << module
<< ".html\"><em>" << module
<< "</em></a></h2>\n";
772 void module_end( std::string
const & /*module*/ )
776 void header_start( std::string
const & header
)
778 std::cout
<< " <h3><code><" << header
<< "></code></h3><ul>\n";
781 void header_end( std::string
const & /*header*/ )
783 std::cout
<< " </ul>\n";
786 void from_header( std::string
const & header
)
788 std::cout
<< " <li>from <code><" << header
<< "></code></li>\n";
792 static void output_module_reverse_report( std::string
const & module
, bool html
)
796 module_reverse_html_actions actions
;
797 output_module_reverse_report( module
, actions
);
801 module_reverse_txt_actions actions
;
802 output_module_reverse_report( module
, actions
);
806 // module_level_report
808 int const unknown_level
= INT_MAX
/ 2;
810 struct module_level_actions
812 virtual void begin() = 0;
813 virtual void end() = 0;
815 virtual void level_start( int level
) = 0;
816 virtual void level_end( int level
) = 0;
818 virtual void module_start( std::string
const & module
) = 0;
819 virtual void module_end( std::string
const & module
) = 0;
821 virtual void module2( std::string
const & module
, int level
) = 0;
824 static void output_module_level_report( module_level_actions
& actions
)
826 // build module level map
828 std::map
< std::string
, int > level_map
;
830 for( std::set
< std::string
>::iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
832 if( s_module_deps
[ *i
].empty() )
835 // std::cerr << *i << ": " << 0 << std::endl;
839 level_map
[ *i
] = unknown_level
;
843 // build transitive closure to see through cycles
845 std::map
< std::string
, std::set
< std::string
> > deps2
= s_module_deps
;
854 for( std::map
< std::string
, std::set
< std::string
> >::iterator i
= deps2
.begin(); i
!= deps2
.end(); ++i
)
856 std::set
< std::string
> tmp
= i
->second
;
858 for( std::set
< std::string
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
860 std::set
< std::string
> tmp2
= deps2
[ *j
];
861 tmp
.insert( tmp2
.begin(), tmp2
.end() );
864 if( tmp
.size() != i
->second
.size() )
874 // compute acyclic levels
876 for( int k
= 1, n
= s_modules
.size(); k
< n
; ++k
)
878 for( std::map
< std::string
, std::set
< std::string
> >::iterator i
= s_module_deps
.begin(); i
!= s_module_deps
.end(); ++i
)
880 // i->first depends on i->second
882 if( level_map
[ i
->first
] >= unknown_level
)
886 for( std::set
< std::string
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
888 level
= std::max( level
, level_map
[ *j
] + 1 );
893 level_map
[ i
->first
] = level
;
894 // std::cerr << i->first << ": " << level << std::endl;
900 // min_level_map[ M ] == L means the level is unknown, but at least L
901 std::map
< std::string
, int > min_level_map
;
903 // initialize min_level_map for acyclic dependencies
905 for( std::map
< std::string
, int >::iterator i
= level_map
.begin(); i
!= level_map
.end(); ++i
)
907 if( i
->second
< unknown_level
)
909 min_level_map
[ i
->first
] = i
->second
;
913 // compute levels for cyclic modules
915 for( int k
= 1, n
= s_modules
.size(); k
< n
; ++k
)
917 for( std::map
< std::string
, std::set
< std::string
> >::iterator i
= s_module_deps
.begin(); i
!= s_module_deps
.end(); ++i
)
919 if( level_map
[ i
->first
] >= unknown_level
)
923 for( std::set
< std::string
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
925 int jl
= level_map
[ *j
];
927 if( jl
< unknown_level
)
929 level
= std::max( level
, jl
+ 1 );
933 int ml
= min_level_map
[ *j
];
935 if( deps2
[ *j
].count( i
->first
) == 0 )
937 // *j does not depend on i->first, so
938 // the level of i->first is at least
939 // 1 + the minimum level of *j
944 level
= std::max( level
, ml
);
948 min_level_map
[ i
->first
] = level
;
955 std::map
< int, std::set
< std::string
> > reverse_level_map
;
957 for( std::map
< std::string
, int >::iterator i
= level_map
.begin(); i
!= level_map
.end(); ++i
)
959 int level
= i
->second
;
961 if( level
>= unknown_level
)
963 int min_level
= min_level_map
[ i
->first
];
971 reverse_level_map
[ level
].insert( i
->first
);
978 for( std::map
< int, std::set
< std::string
> >::iterator i
= reverse_level_map
.begin(); i
!= reverse_level_map
.end(); ++i
)
980 actions
.level_start( i
->first
);
982 for( std::set
< std::string
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
984 actions
.module_start( *j
);
986 std::set
< std::string
> mdeps
= s_module_deps
[ *j
];
988 for( std::set
< std::string
>::iterator k
= mdeps
.begin(); k
!= mdeps
.end(); ++k
)
990 int level
= level_map
[ *k
];
992 if( level
>= unknown_level
)
994 int min_level
= min_level_map
[ *k
];
1002 actions
.module2( *k
, level
);
1005 actions
.module_end( *j
);
1008 actions
.level_end( i
->first
);
1014 struct module_level_txt_actions
: public module_level_actions
1020 std::cout
<< "Module Levels:\n\n";
1027 void level_start( int level
)
1029 if( level
>= unknown_level
)
1031 std::cout
<< "Level (undetermined):\n";
1035 std::cout
<< "Level " << level
<< ":\n";
1041 void level_end( int /*level*/ )
1046 void module_start( std::string
const & module
)
1048 std::cout
<< " " << module
;
1056 void module_end( std::string
const & /*module*/ )
1061 void module2( std::string
const & module
, int level
)
1063 std::cout
<< " " << module
<< "(";
1065 if( level
>= unknown_level
)
1078 struct module_level_html_actions
: public module_level_actions
1084 std::cout
<< "<div id='module-levels'><h1>Module Levels</h1>\n";
1089 std::cout
<< "</div>\n";
1092 void level_start( int level
)
1094 if( level
>= unknown_level
)
1096 std::cout
<< " <h2>Level <em>undetermined</em></h2>\n";
1100 std::cout
<< " <h2 id='level:" << level
<< "'>Level " << level
<< "</h2>\n";
1106 void level_end( int /*level*/ )
1110 void module_start( std::string
const & module
)
1112 std::cout
<< " <h3 id='" << module
<< "'><a href=\"" << module
<< ".html\">" << module
<< "</a></h3><p class='primary-list'>";
1115 void module_end( std::string
const & /*module*/ )
1117 std::cout
<< "</p>\n";
1120 void module2( std::string
const & module
, int level
)
1124 bool important
= level
< unknown_level
&& level
> 1 && level
>= level_
- 1;
1128 std::cout
<< "<strong>";
1131 std::cout
<< module
;
1133 if( level
< unknown_level
)
1135 std::cout
<< "<sup>" << level
<< "</sup>";
1140 std::cout
<< "</strong>";
1145 static void output_module_level_report( bool html
)
1149 module_level_html_actions actions
;
1150 output_module_level_report( actions
);
1154 module_level_txt_actions actions
;
1155 output_module_level_report( actions
);
1159 // module_overview_report
1161 struct module_overview_actions
1163 virtual void begin() = 0;
1164 virtual void end() = 0;
1166 virtual void module_start( std::string
const & module
) = 0;
1167 virtual void module_end( std::string
const & module
) = 0;
1169 virtual void module2( std::string
const & module
) = 0;
1172 static void output_module_overview_report( module_overview_actions
& actions
)
1176 for( std::set
< std::string
>::iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
1178 actions
.module_start( *i
);
1180 std::set
< std::string
> const mdeps
= s_module_deps
[ *i
];
1182 for( std::set
< std::string
>::const_iterator j
= mdeps
.begin(); j
!= mdeps
.end(); ++j
)
1184 actions
.module2( *j
);
1187 actions
.module_end( *i
);
1193 struct module_overview_txt_actions
: public module_overview_actions
1199 std::cout
<< "Module Overview:\n\n";
1206 void module_start( std::string
const & module
)
1208 std::cout
<< module
;
1212 void module_end( std::string
const & /*module*/ )
1217 void module2( std::string
const & module
)
1225 std::cout
<< " " << module
;
1229 struct module_overview_html_actions
: public module_overview_actions
1233 std::cout
<< "<div id='module-overview'><h1>Module Overview</h1>\n";
1238 std::cout
<< "</div>\n";
1241 void module_start( std::string
const & module
)
1243 std::cout
<< " <h2 id='" << module
<< "'><a href=\"" << module
<< ".html\"><em>" << module
<< "</em></a></h2><p class='primary-list'>";
1246 void module_end( std::string
const & /*module*/ )
1248 std::cout
<< "</p>\n";
1251 void module2( std::string
const & module
)
1253 std::cout
<< " " << module
;
1257 static void output_module_overview_report( bool html
)
1261 module_overview_html_actions actions
;
1262 output_module_overview_report( actions
);
1266 module_overview_txt_actions actions
;
1267 output_module_overview_report( actions
);
1271 // list_dependencies
1273 struct list_dependencies_actions
: public module_overview_actions
1283 void module_start( std::string
const & module
)
1285 std::cout
<< module
<< " ->";
1288 void module_end( std::string
const & /*module*/ )
1293 void module2( std::string
const & module
)
1295 if( module
!= "(unknown)" )
1297 std::cout
<< " " << module
;
1302 static void list_dependencies()
1304 list_dependencies_actions actions
;
1305 output_module_overview_report( actions
);
1310 static void output_html_header( std::string
const & title
, std::string
const & stylesheet
, std::string
const & prefix
)
1312 std::cout
<< "<html>\n";
1313 std::cout
<< "<head>\n";
1314 std::cout
<< "<title>" << title
<< "</title>\n";
1316 if( !stylesheet
.empty() )
1318 std::cout
<< "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << stylesheet
<< "\" />\n";
1321 std::cout
<< "</head>\n";
1322 std::cout
<< "<body>\n";
1324 if( !prefix
.empty() )
1326 std::cout
<< prefix
<< std::endl
;
1330 static void output_html_footer( std::string
const & footer
)
1332 std::cout
<< "<hr />\n";
1333 std::cout
<< "<p class=\"footer\">" << footer
<< "</p>\n";
1334 std::cout
<< "</body>\n";
1335 std::cout
<< "</html>\n";
1338 static void enable_secondary( bool & secondary
, bool track_sources
, bool track_tests
)
1344 build_module_dependency_map( track_sources
, track_tests
);
1346 catch( fs::filesystem_error
const & x
)
1348 std::cout
<< x
.what() << std::endl
;
1355 static void list_modules()
1357 for( std::set
< std::string
>::iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
1359 std::cout
<< *i
<< "\n";
1363 static void list_buildable()
1365 for( std::set
< std::string
>::iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
1367 if( fs::exists( module_build_path( *i
) ) && fs::exists( module_source_path( *i
) ) )
1369 std::cout
<< *i
<< "\n";
1374 // module_weight_report
1376 struct module_weight_actions
1378 virtual void begin() = 0;
1379 virtual void end() = 0;
1381 virtual void weight_start( int weight
) = 0;
1382 virtual void weight_end( int weight
) = 0;
1384 virtual void module_start( std::string
const & module
) = 0;
1385 virtual void module_end( std::string
const & module
) = 0;
1387 virtual void module_primary_start() = 0;
1388 virtual void module_primary( std::string
const & module
, int weight
) = 0;
1389 virtual void module_primary_end() = 0;
1391 virtual void module_secondary_start() = 0;
1392 virtual void module_secondary( std::string
const & module
, int weight
) = 0;
1393 virtual void module_secondary_end() = 0;
1396 static void output_module_weight_report( module_weight_actions
& actions
)
1398 // gather secondary dependencies
1400 struct build_secondary_deps
: public module_secondary_actions
1402 std::map
< std::string
, std::set
< std::string
> > * pm_
;
1404 build_secondary_deps( std::map
< std::string
, std::set
< std::string
> > * pm
): pm_( pm
)
1408 std::string module_
;
1410 void heading( std::string
const & module
)
1415 void module_start( std::string
const & /*module*/ )
1419 void module_end( std::string
const & /*module*/ )
1423 void module_adds( std::string
const & module
)
1425 (*pm_
)[ module_
].insert( module
);
1429 std::map
< std::string
, std::set
< std::string
> > secondary_deps
;
1431 build_secondary_deps
bsd( &secondary_deps
);
1433 for( std::set
< std::string
>::const_iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
1435 output_module_secondary_report( *i
, bsd
);
1440 std::map
< int, std::set
< std::string
> > modules_by_weight
;
1442 for( std::set
< std::string
>::const_iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
1444 int w
= s_module_deps
[ *i
].size() + secondary_deps
[ *i
].size();
1445 modules_by_weight
[ w
].insert( *i
);
1452 for( std::map
< int, std::set
< std::string
> >::const_iterator i
= modules_by_weight
.begin(); i
!= modules_by_weight
.end(); ++i
)
1454 actions
.weight_start( i
->first
);
1456 for( std::set
< std::string
>::const_iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
1458 actions
.module_start( *j
);
1460 if( !s_module_deps
[ *j
].empty() )
1462 actions
.module_primary_start();
1464 for( std::set
< std::string
>::const_iterator k
= s_module_deps
[ *j
].begin(); k
!= s_module_deps
[ *j
].end(); ++k
)
1466 int w
= s_module_deps
[ *k
].size() + secondary_deps
[ *k
].size();
1467 actions
.module_primary( *k
, w
);
1470 actions
.module_primary_end();
1473 if( !secondary_deps
[ *j
].empty() )
1475 actions
.module_secondary_start();
1477 for( std::set
< std::string
>::const_iterator k
= secondary_deps
[ *j
].begin(); k
!= secondary_deps
[ *j
].end(); ++k
)
1479 int w
= s_module_deps
[ *k
].size() + secondary_deps
[ *k
].size();
1480 actions
.module_secondary( *k
, w
);
1483 actions
.module_secondary_end();
1486 actions
.module_end( *j
);
1489 actions
.weight_end( i
->first
);
1495 struct module_weight_txt_actions
: public module_weight_actions
1499 std::cout
<< "Module Weights:\n\n";
1506 void weight_start( int weight
)
1508 std::cout
<< "Weight " << weight
<< ":\n";
1511 void weight_end( int /*weight*/ )
1516 void module_start( std::string
const & module
)
1518 std::cout
<< " " << module
;
1521 void module_end( std::string
const & /*module*/ )
1526 void module_primary_start()
1531 void module_primary( std::string
const & module
, int weight
)
1533 std::cout
<< " " << module
<< "(" << weight
<< ")";
1536 void module_primary_end()
1540 void module_secondary_start()
1545 void module_secondary( std::string
const & module
, int /*weight*/ )
1547 std::cout
<< " " << module
;
1550 void module_secondary_end()
1555 struct module_weight_html_actions
: public module_weight_actions
1561 std::cout
<< "<div id='module-weights'>\n<h1>Module Weights</h1>\n";
1566 std::cout
<< "</div>\n";
1569 void weight_start( int weight
)
1571 std::cout
<< " <h2 id='weight:" << weight
<< "'>Weight " << weight
<< "</h2>\n";
1575 void weight_end( int /*weight*/ )
1579 void module_start( std::string
const & module
)
1581 std::cout
<< " <h3 id='" << module
<< "'><a href=\"" << module
<< ".html\">" << module
<< "</a></h3>";
1584 void module_end( std::string
const & /*module*/ )
1589 void module_primary_start()
1591 std::cout
<< "<p class='primary-list'>";
1594 void module_primary( std::string
const & module
, int weight
)
1598 bool heavy
= weight
>= 0.8 * weight_
;
1602 std::cout
<< "<strong>";
1605 std::cout
<< module
<< "<sup>" << weight
<< "</sup>";
1609 std::cout
<< "</strong>";
1613 void module_primary_end()
1615 std::cout
<< "</p>";
1618 void module_secondary_start()
1620 std::cout
<< "<p class='secondary-list'>";
1623 void module_secondary( std::string
const & module
, int /*weight*/ )
1625 std::cout
<< " " << module
;
1628 void module_secondary_end()
1630 std::cout
<< "</p>";
1634 static void output_module_weight_report( bool html
)
1638 module_weight_html_actions actions
;
1639 output_module_weight_report( actions
);
1643 module_weight_txt_actions actions
;
1644 output_module_weight_report( actions
);
1648 // output_module_subset_report
1650 struct module_subset_actions
1652 virtual void heading( std::string
const & module
) = 0;
1654 virtual void module_start( std::string
const & module
) = 0;
1655 virtual void module_end( std::string
const & module
) = 0;
1657 virtual void from_path( std::vector
<std::string
> const & path
) = 0;
1660 static void add_module_headers( fs::path
const & dir
, std::set
<std::string
> & headers
)
1662 if( fs::exists( dir
) )
1664 fs::recursive_directory_iterator
it( dir
), last
;
1666 for( ; it
!= last
; ++it
)
1668 if( it
->status().type() == fs::directory_file
)
1673 headers
.insert( it
->path().generic_string() );
1678 static void output_module_subset_report_( std::string
const & module
, std::set
<std::string
> const & headers
, module_subset_actions
& actions
)
1680 // build header closure
1682 // header -> (header)*
1683 std::map
< std::string
, std::set
<std::string
> > inc2
;
1685 // (header, header) -> path
1686 std::map
< std::pair
<std::string
, std::string
>, std::vector
<std::string
> > paths
;
1688 for( std::set
<std::string
>::const_iterator i
= headers
.begin(); i
!= headers
.end(); ++i
)
1690 std::set
<std::string
> & s
= inc2
[ *i
];
1692 s
= s_header_includes
[ *i
];
1694 for( std::set
<std::string
>::const_iterator j
= s
.begin(); j
!= s
.end(); ++j
)
1696 std::vector
<std::string
> & v
= paths
[ std::make_pair( *i
, *j
) ];
1708 for( std::map
< std::string
, std::set
<std::string
> >::iterator i
= inc2
.begin(); i
!= inc2
.end(); ++i
)
1710 std::set
<std::string
> & s2
= i
->second
;
1712 for( std::set
<std::string
>::const_iterator j
= s2
.begin(); j
!= s2
.end(); ++j
)
1714 std::set
<std::string
> const & s
= s_header_includes
[ *j
];
1716 for( std::set
<std::string
>::const_iterator k
= s
.begin(); k
!= s
.end(); ++k
)
1718 if( s2
.count( *k
) == 0 )
1722 std::vector
<std::string
> const & v1
= paths
[ std::make_pair( i
->first
, *j
) ];
1723 std::vector
<std::string
> & v2
= paths
[ std::make_pair( i
->first
, *k
) ];
1737 // module -> header -> path [header -> header -> header]
1738 std::map
< std::string
, std::map
< std::string
, std::vector
<std::string
> > > subset
;
1740 for( std::set
<std::string
>::const_iterator i
= headers
.begin(); i
!= headers
.end(); ++i
)
1742 std::set
<std::string
> const & s
= inc2
[ *i
];
1744 for( std::set
<std::string
>::const_iterator j
= s
.begin(); j
!= s
.end(); ++j
)
1746 std::string
const & m
= s_header_map
[ *j
];
1748 if( m
.empty() ) continue;
1750 std::vector
<std::string
> const & path
= paths
[ std::make_pair( *i
, *j
) ];
1752 if( subset
.count( m
) == 0 || subset
[ m
].count( *i
) == 0 || subset
[ m
][ *i
].size() > path
.size() )
1754 subset
[ m
][ *i
] = path
;
1759 actions
.heading( module
);
1761 for( std::map
< std::string
, std::map
< std::string
, std::vector
<std::string
> > >::const_iterator i
= subset
.begin(); i
!= subset
.end(); ++i
)
1763 if( i
->first
== module
) continue;
1765 actions
.module_start( i
->first
);
1769 for( std::map
< std::string
, std::vector
<std::string
> >::const_iterator j
= i
->second
.begin(); j
!= i
->second
.end() && k
< 4; ++j
, ++k
)
1771 actions
.from_path( j
->second
);
1774 actions
.module_end( i
->first
);
1778 static void output_module_subset_report( std::string
const & module
, bool track_sources
, bool track_tests
, module_subset_actions
& actions
)
1780 std::set
<std::string
> headers
= s_module_headers
[ module
];
1784 add_module_headers( module_source_path( module
), headers
);
1789 add_module_headers( module_test_path( module
), headers
);
1792 output_module_subset_report_( module
, headers
, actions
);
1795 struct module_subset_txt_actions
: public module_subset_actions
1797 void heading( std::string
const & module
)
1799 std::cout
<< "Subset dependencies for " << module
<< ":\n\n";
1802 void module_start( std::string
const & module
)
1804 std::cout
<< module
<< ":\n";
1807 void module_end( std::string
const & /*module*/ )
1812 void from_path( std::vector
<std::string
> const & path
)
1814 for( std::vector
<std::string
>::const_iterator i
= path
.begin(); i
!= path
.end(); ++i
)
1816 if( i
== path
.begin() )
1822 std::cout
<< " -> ";
1832 struct module_subset_html_actions
: public module_subset_actions
1834 void heading( std::string
const & module
)
1836 std::cout
<< "\n\n<h1 id=\"subset-dependencies\">Subset dependencies for <em>" << module
<< "</em></h1>\n";
1839 void module_start( std::string
const & module
)
1841 std::cout
<< " <h2 id=\"subset-" << module
<< "\"><a href=\"" << module
<< ".html\"><em>" << module
<< "</em></a></h2><ul>\n";
1844 void module_end( std::string
const & /*module*/ )
1846 std::cout
<< "</ul>\n";
1849 void from_path( std::vector
<std::string
> const & path
)
1851 std::cout
<< " <li>";
1853 for( std::vector
<std::string
>::const_iterator i
= path
.begin(); i
!= path
.end(); ++i
)
1855 if( i
!= path
.begin() )
1857 std::cout
<< " ⇢ ";
1860 std::cout
<< "<code>" << *i
<< "</code>";
1863 std::cout
<< "</li>\n";
1867 static void output_module_subset_report( std::string
const & module
, bool track_sources
, bool track_tests
, bool html
)
1871 module_subset_html_actions actions
;
1872 output_module_subset_report( module
, track_sources
, track_tests
, actions
);
1876 module_subset_txt_actions actions
;
1877 output_module_subset_report( module
, track_sources
, track_tests
, actions
);
1881 // --list-exceptions
1883 static void list_exceptions()
1887 for( std::map
< std::string
, std::set
<std::string
> >::const_iterator i
= s_module_headers
.begin(); i
!= s_module_headers
.end(); ++i
)
1889 std::string module
= i
->first
;
1891 std::replace( module
.begin(), module
.end(), '~', '/' );
1893 std::string
const prefix
= "boost/" + module
;
1894 size_t const n
= prefix
.size();
1896 for( std::set
< std::string
>::const_iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
1898 std::string
const & header
= *j
;
1900 if( header
.substr( 0, n
+1 ) != prefix
+ '/' && header
!= prefix
+ ".hpp" )
1904 std::cout
<< module
<< ":\n";
1908 std::cout
<< " " << header
<< '\n';
1916 struct module_test_primary_actions
: public module_primary_actions
1918 std::set
< std::string
> & m_
;
1920 module_test_primary_actions( std::set
< std::string
> & m
): m_( m
)
1924 void heading( std::string
const & module
)
1926 std::cout
<< "Test dependencies for " << module
<< ":\n\n";
1929 void module_start( std::string
const & module
)
1931 std::cout
<< module
<< "\n";
1932 m_
.insert( module
);
1935 void module_end( std::string
const & /*module*/ )
1939 void header_start( std::string
const & /*header*/ )
1943 void header_end( std::string
const & /*header*/ )
1947 void from_header( std::string
const & /*header*/ )
1952 struct module_test_secondary_actions
: public module_secondary_actions
1954 std::set
< std::string
> & m_
;
1957 module_test_secondary_actions( std::set
< std::string
> & m
): m_( m
)
1961 void heading( std::string
const & /*module*/ )
1965 void module_start( std::string
const & module
)
1970 void module_end( std::string
const & /*module*/ )
1974 void module_adds( std::string
const & module
)
1976 if( m_
.count( module
) == 0 )
1978 std::cout
<< module
<< " (from " << m2_
<< ")\n";
1979 m_
.insert( module
);
1984 static void output_module_test_report( std::string
const & module
)
1986 std::set
< std::string
> m
;
1988 module_test_primary_actions
a1( m
);
1989 output_module_primary_report( module
, a1
, true, true );
1993 bool secondary
= false;
1994 enable_secondary( secondary
, true, false );
1996 std::set
< std::string
> m2( m
);
1997 m2
.insert( module
);
1999 module_test_secondary_actions
a2( m2
);
2001 output_module_secondary_report( module
, m
, a2
);
2006 struct collect_primary_dependencies
: public module_primary_actions
2008 std::set
< std::string
> set_
;
2010 void heading( std::string
const & )
2014 void module_start( std::string
const & module
)
2016 if( module
== "(unknown)" ) return;
2018 set_
.insert( module
);
2021 void module_end( std::string
const & /*module*/ )
2025 void header_start( std::string
const & /*header*/ )
2029 void header_end( std::string
const & /*header*/ )
2033 void from_header( std::string
const & /*header*/ )
2038 static std::string
module_cmake_package( std::string module
)
2040 std::replace( module
.begin(), module
.end(), '~', '_' );
2041 return "boost_" + module
;
2044 static std::string
module_cmake_target( std::string module
)
2046 std::replace( module
.begin(), module
.end(), '~', '_' );
2047 return "boost::" + module
;
2050 static void output_module_cmake_report( std::string module
)
2052 std::replace( module
.begin(), module
.end(), '/', '~' );
2054 std::cout
<< "# Generated file. Do not edit.\n\n";
2056 collect_primary_dependencies a1
;
2057 output_module_primary_report( module
, a1
, false, false );
2059 if( !fs::exists( module_source_path( module
) ) )
2061 for( std::set
< std::string
>::const_iterator i
= a1
.set_
.begin(); i
!= a1
.set_
.end(); ++i
)
2063 std::cout
<< "boost_declare_dependency(" << module_cmake_package( *i
) << " INTERFACE " << module_cmake_target( *i
) << ")\n";
2068 collect_primary_dependencies a2
;
2069 output_module_primary_report( module
, a2
, true, false );
2071 for( std::set
< std::string
>::const_iterator i
= a1
.set_
.begin(); i
!= a1
.set_
.end(); ++i
)
2073 a2
.set_
.erase( *i
);
2074 std::cout
<< "boost_declare_dependency(" << module_cmake_package( *i
) << " PUBLIC " << module_cmake_target( *i
) << ")\n";
2079 for( std::set
< std::string
>::const_iterator i
= a2
.set_
.begin(); i
!= a2
.set_
.end(); ++i
)
2081 std::cout
<< "boost_declare_dependency(" << module_cmake_package( *i
) << " PRIVATE " << module_cmake_target( *i
) << ")\n";
2086 // --list-missing-headers
2088 struct missing_header_actions
: public module_primary_actions
2090 std::string module_
, module2_
;
2092 void heading( std::string
const & module
)
2097 void module_start( std::string
const & module
)
2102 void module_end( std::string
const & /*module*/ )
2106 void header_start( std::string
const & header
)
2108 if( module2_
== "(unknown)" )
2110 if( !module_
.empty() )
2112 std::cout
<< module_
<< ":\n";
2116 std::cout
<< " <" << header
<< ">\n";
2120 void header_end( std::string
const & /*header*/ )
2124 void from_header( std::string
const & header
)
2126 if( module2_
== "(unknown)" )
2128 std::cout
<< " from <" << header
<< ">\n";
2133 static void list_missing_headers( std::string
const & module
)
2135 missing_header_actions a
;
2136 output_module_primary_report( module
, a
, false, false );
2139 static void list_missing_headers()
2141 for( std::set
< std::string
>::const_iterator i
= s_modules
.begin(); i
!= s_modules
.end(); ++i
)
2143 list_missing_headers( *i
);
2149 struct primary_pkgconfig_actions
: public module_primary_actions
2151 std::string version_
;
2154 void heading( std::string
const & )
2158 void module_start( std::string
const & module
)
2160 if( module
== "(unknown)" ) return;
2162 std::string
m2( module
);
2163 std::replace( m2
.begin(), m2
.end(), '~', '_' );
2165 if( !list_
.empty() )
2170 list_
+= "boost_" + m2
+ " = " + version_
;
2173 void module_end( std::string
const & )
2177 void header_start( std::string
const & )
2181 void header_end( std::string
const & )
2185 void from_header( std::string
const & )
2190 static void output_requires( std::string
const & section
, std::string
const & version
, std::set
< std::string
> const & s
)
2194 for( std::set
< std::string
>::const_iterator i
= s
.begin(); i
!= s
.end(); ++i
)
2198 std::cout
<< section
<< ": ";
2206 std::string
m2( *i
);
2207 std::replace( m2
.begin(), m2
.end(), '~', '_' );
2209 std::cout
<< "boost_" << m2
<< " = " << version
;
2213 static void output_pkgconfig( std::string
const & module
, std::string
const & version
, int argc
, char const* argv
[] )
2215 for( int i
= 0; i
< argc
; ++i
)
2217 std::cout
<< argv
[ i
] << '\n';
2222 std::string
m2( module
);
2223 std::replace( m2
.begin(), m2
.end(), '/', '_' );
2225 std::string
m3( module
);
2226 std::replace( m3
.begin(), m3
.end(), '/', '~' );
2228 std::cout
<< "Name: boost_" << module
<< '\n';
2229 std::cout
<< "Description: Boost C++ library '" << module
<< "'\n";
2230 std::cout
<< "Version: " << version
<< '\n';
2231 std::cout
<< "URL: http://www.boost.org/libs/" << module
<< '\n';
2232 std::cout
<< "Cflags: -I${includedir}\n";
2234 if( fs::exists( module_build_path( module
) ) && fs::exists( module_source_path( module
) ) )
2236 std::cout
<< "Libs: -L${libdir} -lboost_" << m2
<< "\n";
2239 collect_primary_dependencies a1
;
2240 output_module_primary_report( m3
, a1
, false, false );
2242 if( !a1
.set_
.empty() )
2244 output_requires( "Requires", version
, a1
.set_
);
2245 std::cout
<< std::endl
;
2248 collect_primary_dependencies a2
;
2249 output_module_primary_report( m3
, a2
, true, false );
2251 for( std::set
< std::string
>::const_iterator i
= a1
.set_
.begin(); i
!= a1
.set_
.end(); ++i
)
2253 a2
.set_
.erase( *i
);
2256 if( !a2
.set_
.empty() )
2258 output_requires( "Requires.private", version
, a2
.set_
);
2259 std::cout
<< std::endl
;
2265 static void output_directory_subset_report( std::string
const & module
, std::set
<std::string
> const & headers
, bool html
)
2267 for( std::set
<std::string
>::const_iterator i
= headers
.begin(); i
!= headers
.end(); ++i
)
2269 std::map
< std::string
, std::set
< std::string
> > deps
;
2270 std::map
< std::string
, std::set
< std::string
> > from
;
2272 std::ifstream
is( i
->c_str() );
2273 scan_header_dependencies( *i
, is
, deps
, from
);
2275 for( std::map
< std::string
, std::set
< std::string
> >::const_iterator j
= from
.begin(); j
!= from
.end(); ++j
)
2277 for( std::set
<std::string
>::const_iterator k
= j
->second
.begin(); k
!= j
->second
.end(); ++k
)
2279 s_header_includes
[ *k
].insert( j
->first
);
2286 module_subset_html_actions actions
;
2287 output_module_subset_report_( module
, headers
, actions
);
2291 module_subset_txt_actions actions
;
2292 output_module_subset_report_( module
, headers
, actions
);
2298 static bool find_boost_root()
2300 for( int i
= 0; i
< 32; ++i
)
2302 if( fs::exists( "Jamroot" ) )
2307 fs::path p
= fs::current_path();
2309 if( p
== p
.root_path() )
2314 fs::current_path( p
.parent_path() );
2320 int main( int argc
, char const* argv
[] )
2328 " boostdep --list-modules\n"
2329 " boostdep --list-buildable\n"
2330 " boostdep [--track-sources] [--track-tests] --list-dependencies\n"
2331 " boostdep --list-exceptions\n"
2332 " boostdep --list-missing-headers\n"
2334 " boostdep [options] --module-overview\n"
2335 " boostdep [options] --module-levels\n"
2336 " boostdep [options] --module-weights\n"
2338 " boostdep [options] [--primary] <module>\n"
2339 " boostdep [options] --secondary <module>\n"
2340 " boostdep [options] --reverse <module>\n"
2341 " boostdep [options] --subset <module>\n"
2342 " boostdep [options] [--header] <header>\n"
2343 " boostdep --test <module>\n"
2344 " boostdep --cmake <module>\n"
2345 " boostdep --pkgconfig <module> <version> [<var>=<value>] [<var>=<value>]...\n"
2346 " boostdep [options] --subset-for <directory>\n"
2348 " [options]: [--[no-]track-sources] [--[no-]track-tests]\n"
2349 " [--html-title <title>] [--html-footer <footer>]\n"
2350 " [--html-stylesheet <stylesheet>] [--html-prefix <prefix>]\n"
2356 if( !find_boost_root() )
2358 std::cerr
<< "boostdep: Could not find Boost root.\n";
2366 catch( fs::filesystem_error
const & x
)
2368 std::cout
<< x
.what() << std::endl
;
2372 bool secondary
= false;
2373 bool track_sources
= false;
2374 bool track_tests
= false;
2376 std::string html_title
= "Boost Dependency Report";
2377 std::string html_footer
;
2378 std::string html_stylesheet
;
2379 std::string html_prefix
;
2381 for( int i
= 1; i
< argc
; ++i
)
2383 std::string option
= argv
[ i
];
2385 if( option
== "--list-modules" )
2389 else if( option
== "--list-buildable" )
2393 else if( option
== "--title" || option
== "--html-title" )
2397 html_title
= argv
[ ++i
];
2400 else if( option
== "--footer" || option
== "--html-footer" )
2404 html_footer
= argv
[ ++i
];
2407 else if( option
== "--html-stylesheet" )
2411 html_stylesheet
= argv
[ ++i
];
2414 else if( option
== "--html-prefix" )
2418 html_prefix
= argv
[ ++i
];
2421 else if( option
== "--html" )
2426 output_html_header( html_title
, html_stylesheet
, html_prefix
);
2429 else if( option
== "--track-sources" )
2431 track_sources
= true;
2433 else if( option
== "--no-track-sources" )
2435 track_sources
= false;
2437 else if( option
== "--track-tests" )
2441 else if( option
== "--no-track-tests" )
2443 track_tests
= false;
2445 else if( option
== "--primary" )
2449 output_module_primary_report( argv
[ ++i
], html
, track_sources
, track_tests
);
2452 else if( option
== "--secondary" )
2456 enable_secondary( secondary
, track_sources
, track_tests
);
2457 output_module_secondary_report( argv
[ ++i
], html
);
2460 else if( option
== "--reverse" )
2464 enable_secondary( secondary
, track_sources
, track_tests
);
2465 output_module_reverse_report( argv
[ ++i
], html
);
2468 else if( option
== "--header" )
2472 enable_secondary( secondary
, track_sources
, track_tests
);
2473 output_header_report( argv
[ ++i
], html
);
2476 else if( option
== "--subset" )
2480 enable_secondary( secondary
, track_sources
, track_tests
);
2481 output_module_subset_report( argv
[ ++i
], track_sources
, track_tests
, html
);
2484 else if( option
== "--test" )
2488 output_module_test_report( argv
[ ++i
] );
2491 else if( option
== "--cmake" )
2495 output_module_cmake_report( argv
[ ++i
] );
2498 else if( option
== "--module-levels" )
2500 enable_secondary( secondary
, track_sources
, track_tests
);
2501 output_module_level_report( html
);
2503 else if( option
== "--module-overview" )
2505 enable_secondary( secondary
, track_sources
, track_tests
);
2506 output_module_overview_report( html
);
2508 else if( option
== "--module-weights" )
2510 enable_secondary( secondary
, track_sources
, track_tests
);
2511 output_module_weight_report( html
);
2513 else if( option
== "--list-dependencies" )
2515 enable_secondary( secondary
, track_sources
, track_tests
);
2516 list_dependencies();
2518 else if( option
== "--list-exceptions" )
2522 else if( option
== "--list-missing-headers" )
2524 list_missing_headers();
2526 else if( option
== "--pkgconfig" )
2530 std::string module
= argv
[ ++i
];
2531 std::string version
= argv
[ ++i
];
2535 output_pkgconfig( module
, version
, argc
- i
, argv
+ i
);
2539 std::cerr
<< "'" << option
<< "': missing module or version.\n";
2544 else if( option
== "--subset-for" )
2548 std::string module
= argv
[ ++i
];
2550 enable_secondary( secondary
, track_sources
, track_tests
);
2552 std::set
<std::string
> headers
;
2553 add_module_headers( module
, headers
);
2555 output_directory_subset_report( module
, headers
, html
);
2559 std::cerr
<< "'" << option
<< "': missing argument.\n";
2564 else if( s_modules
.count( option
) )
2566 output_module_primary_report( option
, html
, track_sources
, track_tests
);
2568 else if( s_header_map
.count( option
) )
2570 enable_secondary( secondary
, track_sources
, track_tests
);
2571 output_header_report( option
, html
);
2575 std::cerr
<< "'" << option
<< "': not an option, module or header.\n";
2581 output_html_footer( html_footer
);