@@ -125,6 +125,8 @@ struct NinjaMain : public BuildLogUser {
125
125
int ToolBrowse (const Options* options, int argc, char * argv[]);
126
126
int ToolMSVC (const Options* options, int argc, char * argv[]);
127
127
int ToolTargets (const Options* options, int argc, char * argv[]);
128
+ int ToolDynOuts (const Options* options, int argc, char * argv[]);
129
+ int ToolOutputs (const Options* options, int argc, char * argv[]);
128
130
int ToolCommands (const Options* options, int argc, char * argv[]);
129
131
int ToolInputs (const Options* options, int argc, char * argv[]);
130
132
int ToolClean (const Options* options, int argc, char * argv[]);
@@ -570,10 +572,11 @@ int NinjaMain::ToolDeps(const Options* options, int argc, char** argv) {
570
572
TimeStamp mtime = disk_interface.Stat ((*it)->path (), &err);
571
573
if (mtime == -1 )
572
574
Error (" %s" , err.c_str ()); // Log and ignore Stat() errors;
575
+ int deps_count = deps->node_count - deps->outputs_count ;
573
576
printf (" %s: #deps %d, deps mtime %" PRId64 " (%s)\n " ,
574
- (*it)->path ().c_str (), deps-> node_count , deps->mtime ,
577
+ (*it)->path ().c_str (), deps_count , deps->mtime ,
575
578
(!mtime || mtime > deps->mtime ? " STALE" :" VALID" ));
576
- for (int i = 0 ; i < deps-> node_count ; ++i)
579
+ for (int i = 0 ; i < deps_count ; ++i)
577
580
printf (" %s\n " , deps->nodes [i]->path ().c_str ());
578
581
printf (" \n " );
579
582
}
@@ -601,6 +604,84 @@ int NinjaMain::ToolMissingDeps(const Options* options, int argc, char** argv) {
601
604
return 0 ;
602
605
}
603
606
607
+ int NinjaMain::ToolDynOuts (const Options*, int argc, char ** argv) {
608
+ vector<Node*> nodes;
609
+ if (argc == 0 ) {
610
+ for (vector<Node*>::const_iterator ni = deps_log_.nodes ().begin ();
611
+ ni != deps_log_.nodes ().end (); ++ni) {
612
+ if (deps_log_.IsDepsEntryLiveFor (*ni))
613
+ nodes.push_back (*ni);
614
+ }
615
+ } else {
616
+ string err;
617
+ if (!CollectTargetsFromArgs (argc, argv, &nodes, &err)) {
618
+ Error (" %s" , err.c_str ());
619
+ return 1 ;
620
+ }
621
+ }
622
+
623
+ RealDiskInterface disk_interface;
624
+ for (vector<Node*>::iterator it = nodes.begin (), end = nodes.end ();
625
+ it != end; ++it) {
626
+ DepsLog::Deps* deps = deps_log_.GetDeps (*it);
627
+ if (!deps) {
628
+ printf (" %s: deps not found\n " , (*it)->path ().c_str ());
629
+ continue ;
630
+ }
631
+
632
+ string err;
633
+ TimeStamp mtime = disk_interface.Stat ((*it)->path (), &err);
634
+ if (mtime == -1 )
635
+ Error (" %s" , err.c_str ()); // Log and ignore Stat() errors;
636
+ int deps_count = deps->node_count - deps->outputs_count ;
637
+ printf (" %s: #dynouts %d, deps mtime %" PRId64 " (%s)\n " ,
638
+ (*it)->path ().c_str (), deps->outputs_count , deps->mtime ,
639
+ (!mtime || mtime > deps->mtime ? " STALE" :" VALID" ));
640
+ for (int i = deps_count; i < deps->node_count ; ++i)
641
+ printf (" %s\n " , deps->nodes [i]->path ().c_str ());
642
+ printf (" \n " );
643
+ }
644
+
645
+ return 0 ;
646
+ }
647
+
648
+ int NinjaMain::ToolOutputs (const Options*, int , char *[]) {
649
+ // Load dyndep files that exist, in order to load dynamic outputs
650
+ DyndepLoader dyndep_loader (&state_, &disk_interface_);
651
+ for (vector<Edge*>::iterator e = state_.edges_ .begin ();
652
+ e != state_.edges_ .end (); ++e) {
653
+ if (Node* dyndep = (*e)->dyndep_ ) {
654
+ std::string err;
655
+ dyndep_loader.LoadDyndeps (dyndep, &err);
656
+ }
657
+ }
658
+
659
+ std::string err;
660
+ // Load dynamic outputs which may exist in the deps log
661
+ DepfileParserOptions depfileOptions;
662
+ ImplicitDepLoader implicit_dep_loader (&state_, &deps_log_, &disk_interface_,
663
+ &depfileOptions);
664
+ for (vector<Edge*>::iterator e = state_.edges_ .begin ();
665
+ e != state_.edges_ .end (); ++e) {
666
+ string dynout = (*e)->GetUnescapedDynout ();
667
+
668
+ if (!dynout.empty ()) {
669
+ implicit_dep_loader.LoadImplicitOutputs (*e, &err);
670
+ }
671
+ }
672
+
673
+ for (vector<Edge*>::iterator e = state_.edges_ .begin ();
674
+ e != state_.edges_ .end (); ++e) {
675
+ for (vector<Node*>::iterator out_node = (*e)->outputs_ .begin ();
676
+ out_node != (*e)->outputs_ .end (); ++out_node) {
677
+ printf (" %s: %s\n " , (*out_node)->path ().c_str (),
678
+ (*e)->rule_ ->name ().c_str ());
679
+ }
680
+ }
681
+
682
+ return 0 ;
683
+ }
684
+
604
685
int NinjaMain::ToolTargets (const Options* options, int argc, char * argv[]) {
605
686
int depth = 1 ;
606
687
if (argc >= 1 ) {
@@ -1118,6 +1199,8 @@ const Tool* ChooseTool(const string& tool_name) {
1118
1199
Tool::RUN_AFTER_LOAD, &NinjaMain::ToolInputs},
1119
1200
{ " deps" , " show dependencies stored in the deps log" ,
1120
1201
Tool::RUN_AFTER_LOGS, &NinjaMain::ToolDeps },
1202
+ { " dynouts" , " shows dynamic outputs stored in the deps log" ,
1203
+ Tool::RUN_AFTER_LOGS, &NinjaMain::ToolDynOuts },
1121
1204
{ " missingdeps" , " check deps log dependencies on generated files" ,
1122
1205
Tool::RUN_AFTER_LOGS, &NinjaMain::ToolMissingDeps },
1123
1206
{ " graph" , " output graphviz dot file for targets" ,
@@ -1126,6 +1209,8 @@ const Tool* ChooseTool(const string& tool_name) {
1126
1209
Tool::RUN_AFTER_LOGS, &NinjaMain::ToolQuery },
1127
1210
{ " targets" , " list targets by their rule or depth in the DAG" ,
1128
1211
Tool::RUN_AFTER_LOAD, &NinjaMain::ToolTargets },
1212
+ { " outputs" , " list all outputs of the build graph, including dynamic outputs stored in the deps log" ,
1213
+ Tool::RUN_AFTER_LOGS, &NinjaMain::ToolOutputs },
1129
1214
{ " compdb" , " dump JSON compilation database to stdout" ,
1130
1215
Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCompilationDatabase },
1131
1216
{ " recompact" , " recompacts ninja-internal data structures" ,
0 commit comments