ninja_build/
build.rs

1// Copyright 2011 Google Inc. All Rights Reserved.
2// Copyright 2017 The Ninja-rs Project Developers. All Rights Reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::cell::{Cell, RefCell};
17use std::collections::{BTreeMap, BTreeSet, btree_map};
18
19use super::state::State;
20use super::deps_log::DepsLog;
21use super::build_log::BuildLog;
22use super::disk_interface::DiskInterface;
23use super::graph::{NodeIndex, EdgeIndex, DependencyScan};
24use super::exit_status::ExitStatus;
25use super::metrics::Stopwatch;
26use super::metrics::get_time_millis;
27use super::debug_flags::KEEP_RSP;
28use super::timestamp::TimeStamp;
29use super::subprocess::SubprocessSet;
30use super::utils::{get_load_average, pathbuf_from_bytes};
31use super::line_printer::{LinePrinter, LinePrinterLineType};
32
33pub enum EdgeResult {
34    EdgeFailed,
35    EdgeSucceeded,
36}
37
38/// Plan stores the state of a build plan: what we intend to build,
39/// which steps we're ready to execute.
40pub struct Plan {
41    wanted_edges: usize,
42    command_edges: usize,
43
44    /// Keep track of which edges we want to build in this plan.  If this map does
45    /// not contain an entry for an edge, we do not want to build the entry or its
46    /// dependents.  If an entry maps to false, we do not want to build it, but we
47    /// might want to build one of its dependents.  If the entry maps to true, we
48    /// want to build it.
49    want: BTreeMap<EdgeIndex, bool>,
50    ready: BTreeSet<EdgeIndex>,
51}
52
53trait IsVacant {
54    fn is_vacant(&self) -> bool;
55}
56
57impl<'a, K, V> IsVacant for btree_map::Entry<'a, K, V> {
58    fn is_vacant(&self) -> bool {
59        match self {
60            &btree_map::Entry::Vacant(_) => true,
61            _ => false,
62        }
63    }
64}
65
66
67impl Plan {
68    pub fn new() -> Self {
69        Plan {
70            wanted_edges: 0usize,
71            command_edges: 0usize,
72            want: BTreeMap::new(),
73            ready: BTreeSet::new(),
74        }
75    }
76
77    /// Add a target to our plan (including all its dependencies).
78    /// Returns false if we don't need to build this target; may
79    /// fill in |err| with an error message if there's a problem.
80    pub fn add_target(&mut self, state: &State, node: NodeIndex) -> Result<bool, String> {
81        self.add_sub_target(state, node, None)
82    }
83
84    pub fn add_sub_target(
85        &mut self,
86        state: &State,
87        node_idx: NodeIndex,
88        dependent: Option<NodeIndex>,
89    ) -> Result<bool, String> {
90        let node = state.node_state.get_node(node_idx);
91        let edge_idx = node.in_edge();
92        if edge_idx.is_none() {
93            if node.is_dirty() {
94                let mut err = format!("'{}'", String::from_utf8_lossy(node.path()));
95                if let Some(dependent) = dependent {
96                    err += &format!(
97                        ", needed by '{}',",
98                        String::from_utf8_lossy(state.node_state.get_node(dependent).path())
99                    );
100                }
101                err += " missing and no known rule to make it";
102                return Err(err);
103            }
104            return Ok(false);
105        }
106        let edge_idx = edge_idx.unwrap();
107        let edge = state.edge_state.get_edge(edge_idx);
108        if edge.outputs_ready() {
109            return Ok(false); // Don't need to do anything.
110        }
111
112        // If an entry in want_ does not already exist for edge, create an entry which
113        // maps to false, indicating that we do not want to build this entry itself.
114        let want = self.want.get(&edge_idx).cloned();
115        let vacant = want.is_none();
116
117        if node.is_dirty() && want.unwrap_or(false) == false {
118            self.want.insert(edge_idx, true);
119            self.wanted_edges += 1;
120            if edge.all_inputs_ready(state) {
121                self.schedule_work(state, edge_idx);
122            }
123            if !edge.is_phony() {
124                self.command_edges += 1;
125            }
126        }
127
128        if vacant {
129            for input_node_idx in edge.inputs.iter() {
130                self.add_sub_target(state, *input_node_idx, Some(node_idx))?;
131            }
132        }
133
134        return Ok(true);
135    }
136
137    /// Number of edges with commands to run.
138    fn command_edge_count(&self) -> usize {
139        return self.command_edges;
140    }
141
142    /// Reset state.  Clears want and ready sets.
143    fn reset(&mut self) {
144        self.command_edges = 0;
145        self.wanted_edges = 0;
146        self.ready.clear();
147        self.want.clear();
148    }
149
150    /// Returns true if there's more work to be done.
151    pub fn more_to_do(&self) -> bool {
152        self.wanted_edges > 0 && self.command_edges > 0
153    }
154
155    /// Submits a ready edge as a candidate for execution.
156    /// The edge may be delayed from running, for example if it's a member of a
157    /// currently-full pool.
158    pub fn schedule_work(&mut self, state: &State, edge_idx: EdgeIndex) {
159        if self.ready.get(&edge_idx).is_some() {
160            // This edge has already been scheduled.  We can get here again if an edge
161            // and one of its dependencies share an order-only input, or if a node
162            // duplicates an out edge (see https://github.com/ninja-build/ninja/pull/519).
163            // Avoid scheduling the work again.
164            return;
165        }
166
167        let edge = state.edge_state.get_edge(edge_idx);
168        let mut pool = edge.pool.borrow_mut();
169        if pool.should_delay_edge() {
170            pool.delay_edge(state, edge_idx);
171            pool.retrieve_ready_edges(state, &mut self.ready);
172        } else {
173            pool.edge_scheduled(state, edge_idx);
174            self.ready.insert(edge_idx);
175        }
176    }
177
178    // Pop a ready edge off the queue of edges to build.
179    // Returns NULL if there's no work to do.
180    pub fn find_work(&mut self) -> Option<EdgeIndex> {
181        match self.ready.iter().next().cloned() {
182            Some(idx) => {
183                self.ready.remove(&idx);
184                Some(idx)
185            }
186            None => None,
187        }
188    }
189
190    /// Mark an edge as done building (whether it succeeded or failed).
191    pub fn edge_finished(&mut self, state: &mut State, edge_idx: EdgeIndex, result: EdgeResult) {
192        let directly_wanted = self.want.get(&edge_idx).unwrap().clone();
193
194        {
195            let edge = state.edge_state.get_edge(edge_idx);
196
197            // See if this job frees up any delayed jobs.
198            if directly_wanted {
199                edge.pool.borrow_mut().edge_finished(state, edge_idx);
200            }
201
202            edge.pool.borrow_mut().retrieve_ready_edges(
203                state,
204                &mut self.ready,
205            );
206        }
207
208
209        match result {
210            EdgeResult::EdgeSucceeded => {
211                if directly_wanted {
212                    self.wanted_edges -= 1;
213                }
214                self.want.remove(&edge_idx);
215
216                state.edge_state.get_edge_mut(edge_idx).outputs_ready = true;
217
218                // Check off any nodes we were waiting for with this edge.
219                for output_node_idx in state
220                    .edge_state
221                    .get_edge_mut(edge_idx)
222                    .outputs
223                    .clone()
224                    .into_iter()
225                {
226                    self.node_finished(state, output_node_idx);
227                }
228            }
229            _ => {}
230        };
231    }
232
233    pub fn node_finished(&mut self, state: &mut State, node_idx: NodeIndex) {
234        // See if we we want any edges from this node.
235        for out_edge_idx in state
236            .node_state
237            .get_node(node_idx)
238            .out_edges()
239            .to_owned()
240            .into_iter()
241        {
242            let want_e = self.want.get(&out_edge_idx).cloned();
243            if want_e.is_none() {
244                continue;
245            }
246
247            {
248                let oe = state.edge_state.get_edge(out_edge_idx);
249                if !oe.all_inputs_ready(state) {
250                    continue;
251                }
252            }
253
254            if want_e.unwrap() {
255                self.schedule_work(state, out_edge_idx);
256            } else {
257                // We do not need to build this edge, but we might need to build one of
258                // its dependents.
259                self.edge_finished(state, out_edge_idx, EdgeResult::EdgeSucceeded);
260            }
261        }
262    }
263
264    /// Clean the given node during the build.
265    /// Return false on error.
266    pub fn clean_node(
267        &mut self,
268        scan: &DependencyScan,
269        State: &State,
270        node_idx: NodeIndex,
271    ) -> Result<(), String> {
272        unimplemented!()
273    }
274}
275
276/*
277
278struct Plan {
279  Plan();
280
281  /// Dumps the current state of the plan.
282  void Dump();
283
284  enum EdgeResult {
285    kEdgeFailed,
286    kEdgeSucceeded
287  };
288
289
290  /// Clean the given node during the build.
291  /// Return false on error.
292  bool CleanNode(DependencyScan* scan, Node* node, string* err);
293
294
295  /// Reset state.  Clears want and ready sets.
296  void Reset();
297
298private:
299  bool AddSubTarget(Node* node, Node* dependent, string* err);
300  void NodeFinished(Node* node);
301
302  set<Edge*> ready_;
303
304  /// Total number of edges that have commands (not phony).
305  int command_edges_;
306
307  /// Total remaining number of wanted edges.
308  int wanted_edges_;
309};
310*/
311
312/// CommandRunner is an interface that wraps running the build
313/// subcommands.  This allows tests to abstract out running commands.
314/// RealCommandRunner is an implementation that actually runs commands.
315
316/// The result of waiting for a command.
317pub struct CommandRunnerResult {
318    pub edge: EdgeIndex,
319    pub status: ExitStatus,
320    pub output: Vec<u8>,
321}
322
323impl CommandRunnerResult {
324    fn is_success(&self) -> bool {
325        match self.status {
326            ExitStatus::ExitSuccess => true,
327            _ => false,
328        }
329    }
330}
331
332pub trait CommandRunner {
333    fn can_run_more(&self) -> bool;
334    fn start_command(&mut self, state: &State, edge: EdgeIndex) -> bool;
335    /// Wait for a command to complete, or return false if interrupted.
336    fn wait_for_command(&mut self) -> Option<CommandRunnerResult>;
337    fn get_active_edges(&self) -> Vec<EdgeIndex>;
338    fn abort(&mut self);
339}
340
341pub enum BuildConfigVerbosity {
342    NORMAL,
343    QUIET, // No output -- used when testing.
344    VERBOSE,
345}
346
347/// Options (e.g. verbosity, parallelism) passed to a build.
348pub struct BuildConfig {
349    pub verbosity: BuildConfigVerbosity,
350    pub dry_run: bool,
351    pub parallelism: usize,
352    pub failures_allowed: usize,
353    pub max_load_average: f64,
354}
355
356impl BuildConfig {
357    pub fn new() -> Self {
358        BuildConfig {
359            verbosity: BuildConfigVerbosity::NORMAL,
360            dry_run: false,
361            parallelism: 1,
362            failures_allowed: 1,
363            max_load_average: -0.0f64,
364        }
365    }
366}
367
368/*
369struct BuildConfig {
370  BuildConfig() : verbosity(NORMAL), dry_run(false), parallelism(1),
371                  failures_allowed(1), max_load_average(-0.0f) {}
372
373  enum Verbosity {
374    NORMAL,
375    QUIET,  // No output -- used when testing.
376    VERBOSE
377  };
378  Verbosity verbosity;
379  bool dry_run;
380  int parallelism;
381  int failures_allowed;
382  /// The maximum load average we must not exceed. A negative value
383  /// means that we do not have any limit.
384  double max_load_average;
385};
386*/
387
388/// Builder wraps the build process: starting commands, updating status.
389pub struct Builder<'s, 'p, 'a, 'b, 'c>
390where
391    's: 'a,
392{
393    state: &'s mut State,
394    config: &'p BuildConfig,
395    plan: Plan,
396    command_runner: Option<Box<CommandRunner + 'p>>,
397    disk_interface: &'c DiskInterface,
398    scan: DependencyScan<'s, 'a, 'b, 'c>,
399    status: BuildStatus<'p>,
400}
401
402impl<'s, 'p, 'a, 'b, 'c> Builder<'s, 'p, 'a, 'b, 'c>
403where
404    's: 'a,
405{
406    pub fn new(
407        state: &'s mut State,
408        config: &'p BuildConfig,
409        build_log: &'a BuildLog<'s>,
410        deps_log: &'b DepsLog,
411        disk_interface: &'c DiskInterface,
412    ) -> Self {
413        Builder {
414            state,
415            config,
416            plan: Plan::new(),
417            command_runner: None,
418            disk_interface,
419            scan: DependencyScan::new(build_log, deps_log, disk_interface),
420            status: BuildStatus::new(config),
421        }
422    }
423
424    /// Add a target to the build, scanning dependencies.
425    /// @return false on error.
426    pub fn add_target(&mut self, node_idx: NodeIndex) -> Result<(), String> {
427        self.scan.recompute_dirty(self.state, node_idx)?;
428
429        if let Some(in_edge) = self.state.node_state.get_node(node_idx).in_edge() {
430            if self.state.edge_state.get_edge(in_edge).outputs_ready() {
431                return Ok(()); // Nothing to do.
432            }
433        }
434
435        self.plan.add_target(self.state, node_idx)?;
436
437        Ok(())
438    }
439
440    /// Returns true if the build targets are already up to date.
441    pub fn is_already_up_to_date(&mut self) -> bool {
442        !self.plan.more_to_do()
443    }
444
445    /// Run the build.  Returns false on error.
446    /// It is an error to call this function when AlreadyUpToDate() is true.
447    pub fn build(&mut self) -> Result<(), String> {
448        assert!(!self.is_already_up_to_date());
449
450        self.status.plan_has_total_edges(
451            self.plan.command_edge_count(),
452        );
453
454        let mut pending_commands = 0;
455        let mut failures_allowed = self.config.failures_allowed;
456
457        // Set up the command runner if we haven't done so already.
458        let config = self.config;
459        if self.command_runner.is_none() {
460            self.command_runner = Some(if config.dry_run {
461                Box::new(DryRunCommandRunner::new())
462            } else {
463                Box::new(RealCommandRunner::new(config))
464            });
465        }
466
467        // We are about to start the build process.
468        self.status.build_started();
469
470        // This main loop runs the entire build process.
471        // It is structured like this:
472        // First, we attempt to start as many commands as allowed by the
473        // command runner.
474        // Second, we attempt to wait for / reap the next finished command.
475
476        while self.plan.more_to_do() {
477            // See if we can start any more commands.
478            if failures_allowed > 0 && self.command_runner.as_ref().unwrap().can_run_more() {
479                if let Some(edge_idx) = self.plan.find_work() {
480                    if let Err(e) = self.start_edge(edge_idx) {
481                        self.cleanup();
482                        self.status.build_finished();
483                        return Err(e);
484                    };
485
486                    if self.state.edge_state.get_edge(edge_idx).is_phony() {
487                        self.plan.edge_finished(
488                            self.state,
489                            edge_idx,
490                            EdgeResult::EdgeSucceeded,
491                        );
492                    } else {
493                        pending_commands += 1;
494                    }
495
496                    // We made some progress; go back to the main loop.
497                    continue;
498                }
499            }
500
501            // See if we can reap any finished commands.
502            if pending_commands > 0 {
503                let result = self.command_runner.as_mut().unwrap().wait_for_command();
504
505                if result.is_none() ||
506                    result.as_ref().unwrap().status == ExitStatus::ExitInterrupted
507                {
508                    self.cleanup();
509                    self.status.build_finished();
510                    return Err("interrupted by user".to_owned());
511                }
512
513                pending_commands -= 1;
514                let result = self.finish_command(result.unwrap());
515                if let Err(e) = result {
516                    self.cleanup();
517                    self.status.build_finished();
518                    return Err(e);
519                }
520
521                let result = result.unwrap();
522                if !result.is_success() {
523                    if failures_allowed > 0 {
524                        failures_allowed -= 1;
525                    }
526                }
527
528                // We made some progress; start the main loop over.
529                continue;
530            }
531
532            // If we get here, we cannot make any more progress.
533            self.status.build_finished();
534            return match failures_allowed {
535                0 if config.failures_allowed > 1 => Err("subcommands failed".to_owned()),
536                0 => Err("subcommand failed".to_owned()),
537                _ if failures_allowed < self.config.failures_allowed => Err(
538                    "cannot make progress due to previous errors"
539                        .to_owned(),
540                ),
541                _ => Err("stuck [this is a bug]".to_owned()),
542            };
543        }
544
545        self.status.build_finished();
546        return Ok(());
547    }
548
549    fn start_edge(&mut self, edge_idx: EdgeIndex) -> Result<(), String> {
550        metric_record!("StartEdge");
551        let edge = self.state.edge_state.get_edge(edge_idx);
552        if edge.is_phony() {
553            return Ok(());
554        }
555
556        self.status.build_edge_started(self.state, edge_idx);
557
558        // Create directories necessary for outputs.
559        // XXX: this will block; do we care?
560        for out_idx in edge.outputs.iter() {
561            let path = pathbuf_from_bytes(
562                self.state.node_state.get_node(*out_idx).path().to_owned(),
563            ).map_err(|e| {
564                format!("invalid utf-8 filename: {}", String::from_utf8_lossy(&e))
565            })?;
566            if let Some(parent) = path.parent() {
567                self.disk_interface.make_dirs(parent).map_err(
568                    |e| format!("{}", e),
569                )?;
570            }
571        }
572
573        // Create response file, if needed
574        // XXX: this may also block; do we care?
575        let rspfile = edge.get_unescaped_rspfile(&self.state.node_state);
576        if !rspfile.as_ref().is_empty() {
577            let content = edge.get_binding(&self.state.node_state, b"rspfile_content");
578            let rspfile_path = pathbuf_from_bytes(rspfile.into_owned()).map_err(|e| {
579                format!("invalid utf-8 filename: {}", String::from_utf8_lossy(&e))
580            })?;
581            self.disk_interface
582                .write_file(&rspfile_path, content.as_ref())
583                .map_err(|_| String::new())?;
584        }
585
586        // start command computing and run it
587        if !self.command_runner.as_mut().unwrap().start_command(
588            self.state,
589            edge_idx,
590        )
591        {
592            return Err(format!(
593                "command '{}' failed.",
594                String::from_utf8_lossy(
595                    &edge.evaluate_command(&self.state.node_state),
596                )
597            ));
598        }
599
600        Ok(())
601    }
602
603    /// Update status ninja logs following a command termination.
604    /// @return false if the build can not proceed further due to a fatal error.
605    fn finish_command(
606        &mut self,
607        mut result: CommandRunnerResult,
608    ) -> Result<CommandRunnerResult, String> {
609        use errno;
610
611        metric_record!("FinishCommand");
612
613        let edge_idx = result.edge;
614
615        // First try to extract dependencies from the result, if any.
616        // This must happen first as it filters the command output (we want
617        // to filter /showIncludes output, even on compile failure) and
618        // extraction itself can fail, which makes the command fail from a
619        // build perspective.
620        let mut deps_nodes = Vec::new();
621
622        let (deps_type, deps_prefix) = {
623            let edge = self.state.edge_state.get_edge(edge_idx);
624            let deps_type = edge.get_binding(&self.state.node_state, b"deps");
625            let deps_prefix = edge.get_binding(&self.state.node_state, b"msvc_deps_prefix");
626            (deps_type.into_owned(), deps_prefix.into_owned())
627        };
628        if !deps_type.is_empty() {
629            match self.extract_deps(&mut result, deps_type.as_ref(), deps_prefix.as_ref()) {
630                Ok(n) => {
631                    deps_nodes = n;
632                }
633                Err(e) => {
634                    if result.is_success() {
635                        if !result.output.is_empty() {
636                            result.output.extend_from_slice(b"\n".as_ref());
637                        }
638                        result.output.extend_from_slice(e.as_bytes());
639                        result.status = ExitStatus::ExitFailure;
640                    }
641                }
642            }
643        }
644
645        let (start_time, end_time) = self.status.build_edge_finished(
646            self.state,
647            edge_idx,
648            result.is_success(),
649            &result.output,
650        );
651
652        if !result.is_success() {
653            self.plan.edge_finished(
654                self.state,
655                edge_idx,
656                EdgeResult::EdgeFailed,
657            );
658            return Ok(result);
659        }
660
661        // The rest of this function only applies to successful commands.
662
663        // Restat the edge outputs
664        let mut output_mtime = TimeStamp(0);
665        let restat = self.state.edge_state.get_edge(edge_idx).get_binding_bool(
666            &self.state
667                .node_state,
668            b"restat",
669        );
670        if !self.config.dry_run {
671            let edge = self.state.edge_state.get_edge(edge_idx);
672            let mut node_cleaned = false;
673            for o_node_idx in edge.outputs.iter() {
674                let o_node = self.state.node_state.get_node(*o_node_idx);
675                let path = pathbuf_from_bytes(o_node.path().to_owned()).map_err(|e| {
676                    format!("Invalid utf-8 pathname {}", String::from_utf8_lossy(&e))
677                })?;
678                let new_mtime = self.disk_interface.stat(&path)?;
679                if new_mtime > output_mtime {
680                    output_mtime = new_mtime;
681                }
682                if o_node.mtime() == new_mtime && restat {
683                    // The rule command did not change the output.  Propagate the clean
684                    // state through the build graph.
685                    // Note that this also applies to nonexistent outputs (mtime == 0).
686                    self.plan.clean_node(&self.scan, self.state, *o_node_idx)?;
687                    node_cleaned = true;
688                }
689            }
690
691            if node_cleaned {
692                let mut restat_mtime = TimeStamp(0);
693                // If any output was cleaned, find the most recent mtime of any
694                // (existing) non-order-only input or the depfile.
695                for i_idx in edge.inputs[edge.non_order_only_deps_range()].iter() {
696                    let path = pathbuf_from_bytes(
697                        self.state.node_state.get_node(*i_idx).path().to_owned(),
698                    ).map_err(|e| {
699                        format!("invalid utf-8 filename: {}", String::from_utf8_lossy(&e))
700                    })?;
701                    let input_mtime = self.disk_interface.stat(&path)?;
702                    if input_mtime > restat_mtime {
703                        restat_mtime = input_mtime;
704                    }
705                }
706
707                let depfile = edge.get_unescaped_depfile(&self.state.node_state);
708                if restat_mtime.0 != 0 && deps_type.is_empty() && !depfile.is_empty() {
709                    let path = pathbuf_from_bytes(depfile.into_owned()).map_err(|e| {
710                        format!("invalid utf-8 filename: {}", String::from_utf8_lossy(&e))
711                    })?;
712                    let depfile_mtime = self.disk_interface.stat(&path)?;
713                    if depfile_mtime > restat_mtime {
714                        restat_mtime = depfile_mtime;
715                    }
716                }
717
718                // The total number of edges in the plan may have changed as a result
719                // of a restat.
720                self.status.plan_has_total_edges(
721                    self.plan.command_edge_count(),
722                );
723                output_mtime = restat_mtime;
724            }
725        }
726
727        self.plan.edge_finished(
728            self.state,
729            edge_idx,
730            EdgeResult::EdgeSucceeded,
731        );
732
733        let edge = self.state.edge_state.get_edge(edge_idx);
734        let rspfile = edge.get_unescaped_rspfile(&self.state.node_state);
735        if !rspfile.is_empty() && !KEEP_RSP {
736            if let Ok(path) = pathbuf_from_bytes(rspfile.into_owned()) {
737                let _ = self.disk_interface.remove_file(&path);
738            };
739        }
740
741        if let Some(build_log) = self.scan.build_log() {
742            build_log
743                .record_command(self.state, edge_idx, start_time, end_time, output_mtime)
744                .map_err(|e| {
745                    format!("Error writing to build log: {}", errno::errno())
746                })?;
747        }
748
749        if !deps_type.is_empty() && !self.config.dry_run {
750            assert!(edge.outputs.len() == 1);
751            //or it should have been rejected by parser.
752            let out_idx = edge.outputs[0];
753            let out = self.state.node_state.get_node(out_idx);
754            let path = pathbuf_from_bytes(out.path().to_owned()).map_err(|e| {
755                format!("Invalid utf-8 pathname {}", String::from_utf8_lossy(&e))
756            })?;
757
758            let deps_mtime = self.disk_interface.stat(&path)?;
759
760            self.scan
761                .deps_log()
762                .record_deps(self.state, out_idx, deps_mtime, &deps_nodes)
763                .map_err(|e| format!("Error writing to deps log: {}", errno::errno()))?;
764        }
765
766        Ok(result)
767    }
768
769    /// Clean up after interrupted commands by deleting output files.
770    pub fn cleanup(&mut self) {
771        if self.command_runner.is_none() {
772            return;
773        }
774        let command_runner = self.command_runner.as_mut().unwrap();
775
776        let active_edges = command_runner.get_active_edges();
777        command_runner.abort();
778        for edge_idx in active_edges.into_iter() {
779            let edge = self.state.edge_state.get_edge(edge_idx);
780            let depfile = edge.get_unescaped_depfile(&self.state.node_state)
781                .into_owned();
782            for out_idx in edge.outputs.iter() {
783                // Only delete this output if it was actually modified.  This is
784                // important for things like the generator where we don't want to
785                // delete the manifest file if we can avoid it.  But if the rule
786                // uses a depfile, always delete.  (Consider the case where we
787                // need to rebuild an output because of a modified header file
788                // mentioned in a depfile, and the command touches its depfile
789                // but is interrupted before it touches its output file.)
790                let out_node = self.state.node_state.get_node(*out_idx);
791                match pathbuf_from_bytes(out_node.path().to_owned()) {
792                    Err(e) => {
793                        error!("invalid utf-8 filename: {}", String::from_utf8_lossy(&e));
794                    }
795                    Ok(path) => {
796                        match self.disk_interface.stat(&path) {
797                            Err(e) => {
798                                error!("{}", e);
799                            }
800                            Ok(new_mtime) => {
801                                if !depfile.is_empty() || out_node.mtime() != new_mtime {
802                                    let _ = self.disk_interface.remove_file(&path);
803                                }
804                            }
805                        }
806                    }
807                }
808            }
809            if !depfile.is_empty() {
810                match pathbuf_from_bytes(depfile) {
811                    Err(e) => {
812                        error!("invalid utf-8 filename: {}", String::from_utf8_lossy(&e));
813                    }
814                    Ok(path) => {
815                        let _ = self.disk_interface.remove_file(&path);
816                    }
817                };
818            }
819        }
820    }
821
822    fn extract_deps(
823        &self,
824        result: &mut CommandRunnerResult,
825        deps_type: &[u8],
826        deps_prefix: &[u8],
827    ) -> Result<Vec<NodeIndex>, String> {
828        if deps_type == b"msvc" {
829            /*
830    CLParser parser;
831    string output;
832    if (!parser.Parse(result->output, deps_prefix, &output, err))
833      return false;
834    result->output = output;
835    for (set<string>::iterator i = parser.includes_.begin();
836         i != parser.includes_.end(); ++i) {
837      // ~0 is assuming that with MSVC-parsed headers, it's ok to always make
838      // all backslashes (as some of the slashes will certainly be backslashes
839      // anyway). This could be fixed if necessary with some additional
840      // complexity in IncludesNormalize::Relativize.
841      deps_nodes->push_back(state_->GetNode(*i, ~0u));
842    }
843*/
844            return Ok(Vec::new());
845            unimplemented!{}
846        } else if deps_type == b"gcc" {
847            /*
848    string depfile = result->edge->GetUnescapedDepfile();
849    if (depfile.empty()) {
850      *err = string("edge with deps=gcc but no depfile makes no sense");
851      return false;
852    }
853
854    // Read depfile content.  Treat a missing depfile as empty.
855    string content;
856    switch (disk_interface_->ReadFile(depfile, &content, err)) {
857    case DiskInterface::Okay:
858      break;
859    case DiskInterface::NotFound:
860      err->clear();
861      break;
862    case DiskInterface::OtherError:
863      return false;
864    }
865    if (content.empty())
866      return true;
867
868    DepfileParser deps;
869    if (!deps.Parse(&content, err))
870      return false;
871
872    // XXX check depfile matches expected output.
873    deps_nodes->reserve(deps.ins_.size());
874    for (vector<StringPiece>::iterator i = deps.ins_.begin();
875         i != deps.ins_.end(); ++i) {
876      uint64_t slash_bits;
877      if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, &slash_bits,
878                            err))
879        return false;
880      deps_nodes->push_back(state_->GetNode(*i, slash_bits));
881    }
882
883    if (!g_keep_depfile) {
884      if (disk_interface_->RemoveFile(depfile) < 0) {
885        *err = string("deleting depfile: ") + strerror(errno) + string("\n");
886        return false;
887      }
888    }
889*/
890            return Ok(Vec::new());
891            unimplemented!{}
892        } else {
893            fatal!("unknown deps type '{}'", String::from_utf8_lossy(deps_type));
894            unreachable!();
895        }
896    }
897}
898
899impl<'s, 'p, 'a, 'b, 'c> Drop for Builder<'s, 'p, 'a, 'b, 'c> {
900    fn drop(&mut self) {
901        self.cleanup();
902    }
903}
904
905/*
906struct Builder {
907  Builder(State* state, const BuildConfig& config,
908          BuildLog* build_log, DepsLog* deps_log,
909          DiskInterface* disk_interface);
910  ~Builder();
911
912  /// Clean up after interrupted commands by deleting output files.
913  void Cleanup();
914
915  Node* AddTarget(const string& name, string* err);
916
917
918
919
920  /// Used for tests.
921  void SetBuildLog(BuildLog* log) {
922    scan_.set_build_log(log);
923  }
924
925  State* state_;
926  const BuildConfig& config_;
927  Plan plan_;
928  auto_ptr<CommandRunner> command_runner_;
929  BuildStatus* status_;
930
931 private:
932   bool ExtractDeps(CommandRunner::Result* result, const string& deps_type,
933                    const string& deps_prefix, vector<Node*>* deps_nodes,
934                    string* err);
935
936  DiskInterface* disk_interface_;
937  DependencyScan scan_;
938
939  // Unimplemented copy ctor and operator= ensure we don't copy the auto_ptr.
940  Builder(const Builder &other);        // DO NOT IMPLEMENT
941  void operator=(const Builder &other); // DO NOT IMPLEMENT
942};
943*/
944
945enum BuildStatusEdgeStatus {
946    EdgeStarted,
947    EdgeFinished,
948}
949
950/// Tracks the status of a build: completion fraction, printing updates.
951struct BuildStatus<'a> {
952    config: &'a BuildConfig,
953
954    /// Time the build started.
955    start_time_millis: u64,
956
957    started_edges: usize,
958    running_edges: BTreeMap<EdgeIndex, u64>,
959    /// Map of running edge to time the edge started running.
960    finished_edges: usize,
961    total_edges: usize,
962
963    /// The custom progress status format to use.
964    progress_status_format: Vec<u8>,
965
966    /// Prints progress output.
967    printer: LinePrinter,
968
969    overall_rate: RefCell<RateInfo>,
970    current_rate: RefCell<SlidingRateInfo>,
971}
972
973impl<'a> BuildStatus<'a> {
974    pub fn new(config: &'a BuildConfig) -> Self {
975        let v = BuildStatus {
976            config,
977
978            start_time_millis: get_time_millis(),
979
980            started_edges: 0,
981            running_edges: BTreeMap::new(),
982            finished_edges: 0,
983            total_edges: 0,
984
985            progress_status_format: Vec::new(), // TODO
986            printer: LinePrinter::new(),
987
988            overall_rate: RefCell::new(RateInfo::new()),
989            current_rate: RefCell::new(SlidingRateInfo::new(config.parallelism)),
990        };
991        return v;
992        unimplemented!{}
993    }
994
995    pub fn plan_has_total_edges(&mut self, total: usize) {
996        self.total_edges = total;
997    }
998
999    pub fn build_started(&mut self) {
1000        self.overall_rate.borrow_mut().restart();
1001        self.current_rate.borrow_mut().restart();
1002    }
1003
1004    pub fn build_finished(&mut self) {
1005        self.printer.set_console_locked(false);
1006        self.printer.print_on_new_line(b"");
1007    }
1008
1009    pub fn build_edge_started(&mut self, state: &State, edge_idx: EdgeIndex) {
1010        let start_time = get_time_millis() - self.start_time_millis;
1011        self.running_edges.insert(edge_idx, start_time);
1012        self.started_edges += 1;
1013
1014        let edge_use_console = state.edge_state.get_edge(edge_idx).use_console();
1015        if edge_use_console || self.printer.is_smart_terminal() {
1016            self.print_status(state, edge_idx, BuildStatusEdgeStatus::EdgeStarted);
1017        }
1018
1019        if edge_use_console {
1020            self.printer.set_console_locked(true);
1021        }
1022    }
1023
1024    pub fn build_edge_finished(
1025        &mut self,
1026        state: &State,
1027        edge_idx: EdgeIndex,
1028        success: bool,
1029        output: &[u8],
1030    ) -> (u64, u64) {
1031        let now = get_time_millis();
1032        self.finished_edges += 1;
1033
1034        let start_time = self.running_edges.remove(&edge_idx).unwrap();
1035        let end_time = now - self.start_time_millis;
1036
1037        if state.edge_state.get_edge(edge_idx).use_console() {
1038            self.printer.set_console_locked(false);
1039        }
1040
1041        match self.config.verbosity {
1042            BuildConfigVerbosity::QUIET => {
1043                return (start_time, end_time);
1044            }
1045            _ => {}
1046        };
1047
1048        /*
1049  if (!edge->use_console())
1050    PrintStatus(edge, kEdgeFinished);
1051
1052  // Print the command that is spewing before printing its output.
1053  if (!success) {
1054    string outputs;
1055    for (vector<Node*>::const_iterator o = edge->outputs_.begin();
1056         o != edge->outputs_.end(); ++o)
1057      outputs += (*o)->path() + " ";
1058
1059    printer_.PrintOnNewLine("FAILED: " + outputs + "\n");
1060    printer_.PrintOnNewLine(edge->EvaluateCommand() + "\n");
1061  }
1062
1063  if (!output.empty()) {
1064    // ninja sets stdout and stderr of subprocesses to a pipe, to be able to
1065    // check if the output is empty. Some compilers, e.g. clang, check
1066    // isatty(stderr) to decide if they should print colored output.
1067    // To make it possible to use colored output with ninja, subprocesses should
1068    // be run with a flag that forces them to always print color escape codes.
1069    // To make sure these escape codes don't show up in a file if ninja's output
1070    // is piped to a file, ninja strips ansi escape codes again if it's not
1071    // writing to a |smart_terminal_|.
1072    // (Launching subprocesses in pseudo ttys doesn't work because there are
1073    // only a few hundred available on some systems, and ninja can launch
1074    // thousands of parallel compile commands.)
1075    // TODO: There should be a flag to disable escape code stripping.
1076    string final_output;
1077    if (!printer_.is_smart_terminal())
1078      final_output = StripAnsiEscapeCodes(output);
1079    else
1080      final_output = output;
1081
1082#ifdef _WIN32
1083    // Fix extra CR being added on Windows, writing out CR CR LF (#773)
1084    _setmode(_fileno(stdout), _O_BINARY);  // Begin Windows extra CR fix
1085#endif
1086
1087    printer_.PrintOnNewLine(final_output);
1088
1089#ifdef _WIN32
1090    _setmode(_fileno(stdout), _O_TEXT);  // End Windows extra CR fix
1091#endif
1092  }
1093*/
1094        return (start_time, end_time);
1095        unimplemented!();
1096    }
1097
1098    /// Format the progress status string by replacing the placeholders.
1099    /// See the user manual for more information about the available
1100    /// placeholders.
1101    /// @param progress_status_format The format of the progress status.
1102    /// @param status The status of the edge.
1103    pub fn format_progress_status(
1104        progress_status_format: &[u8],
1105        status: BuildStatusEdgeStatus,
1106    ) -> Vec<u8> {
1107        return Vec::new();
1108        unimplemented!()
1109    }
1110
1111    fn print_status(&self, state: &State, edge_idx: EdgeIndex, status: BuildStatusEdgeStatus) {
1112        let force_full_command = match self.config.verbosity {
1113            BuildConfigVerbosity::QUIET => {
1114                return;
1115            }
1116            BuildConfigVerbosity::VERBOSE => true,
1117            BuildConfigVerbosity::NORMAL => false,
1118        };
1119
1120        let edge = state.edge_state.get_edge(edge_idx);
1121        let mut desc_or_cmd = edge.get_binding(&state.node_state, b"description");
1122        if desc_or_cmd.is_empty() || force_full_command {
1123            desc_or_cmd = edge.get_binding(&state.node_state, b"command");
1124        }
1125
1126        let mut to_print = Self::format_progress_status(&self.progress_status_format, status);
1127        to_print.extend_from_slice(&desc_or_cmd);
1128        let ty = if force_full_command {
1129            LinePrinterLineType::Full
1130        } else {
1131            LinePrinterLineType::Elide
1132        };
1133        self.printer.print(&to_print, ty);
1134    }
1135}
1136/*
1137struct BuildStatus {
1138  explicit BuildStatus(const BuildConfig& config);
1139  void PlanHasTotalEdges(int total);
1140  void BuildEdgeStarted(Edge* edge);
1141  void BuildEdgeFinished(Edge* edge, bool success, const string& output,
1142                         int* start_time, int* end_time);
1143  void BuildStarted();
1144  void BuildFinished();
1145
1146
1147
1148 private:
1149  void PrintStatus(Edge* edge, EdgeStatus status);
1150
1151
1152
1153  template<size_t S>
1154  void SnprintfRate(double rate, char(&buf)[S], const char* format) const {
1155    if (rate == -1)
1156      snprintf(buf, S, "?");
1157    else
1158      snprintf(buf, S, format, rate);
1159  }
1160*/
1161
1162struct RateInfo {
1163    rate: f64,
1164    stopwatch: Stopwatch,
1165}
1166
1167impl RateInfo {
1168    pub fn new() -> Self {
1169        RateInfo {
1170            rate: -1f64,
1171            stopwatch: Stopwatch::new(),
1172        }
1173    }
1174
1175    pub fn restart(&mut self) {
1176        self.stopwatch.restart()
1177    }
1178}
1179
1180/*
1181  struct RateInfo {
1182    RateInfo() : rate_(-1) {}
1183
1184    void Restart() { stopwatch_.Restart(); }
1185    double Elapsed() const { return stopwatch_.Elapsed(); }
1186    double rate() { return rate_; }
1187
1188    void UpdateRate(int edges) {
1189      if (edges && stopwatch_.Elapsed())
1190        rate_ = edges / stopwatch_.Elapsed();
1191    }
1192
1193  private:
1194    double rate_;
1195    Stopwatch stopwatch_;
1196  };
1197
1198  */
1199
1200struct SlidingRateInfo {
1201    rate: f64,
1202    stopwatch: Stopwatch,
1203    max_len: usize,
1204    times: VecDeque<f64>,
1205    last_update: isize,
1206}
1207
1208impl SlidingRateInfo {
1209    pub fn new(n: usize) -> Self {
1210        SlidingRateInfo {
1211            rate: -1.0f64,
1212            stopwatch: Stopwatch::new(),
1213            max_len: n,
1214            times: VecDeque::new(),
1215            last_update: -1,
1216        }
1217    }
1218
1219    pub fn restart(&mut self) {
1220        self.stopwatch.restart();
1221    }
1222}
1223
1224/*
1225  struct SlidingRateInfo {
1226    SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {}
1227
1228    void Restart() { stopwatch_.Restart(); }
1229    double rate() { return rate_; }
1230
1231    void UpdateRate(int update_hint) {
1232      if (update_hint == last_update_)
1233        return;
1234      last_update_ = update_hint;
1235
1236      if (times_.size() == N)
1237        times_.pop();
1238      times_.push(stopwatch_.Elapsed());
1239      if (times_.back() != times_.front())
1240        rate_ = times_.size() / (times_.back() - times_.front());
1241    }
1242
1243  private:
1244    double rate_;
1245    Stopwatch stopwatch_;
1246    const size_t N;
1247    queue<double> times_;
1248    int last_update_;
1249  };
1250
1251  mutable RateInfo overall_rate_;
1252  mutable SlidingRateInfo current_rate_;
1253};
1254
1255#endif  // NINJA_BUILD_H_
1256*/
1257
1258/*
1259
1260// Copyright 2011 Google Inc. All Rights Reserved.
1261//
1262// Licensed under the Apache License, Version 2.0 (the "License");
1263// you may not use this file except in compliance with the License.
1264// You may obtain a copy of the License at
1265//
1266//     http://www.apache.org/licenses/LICENSE-2.0
1267//
1268// Unless required by applicable law or agreed to in writing, software
1269// distributed under the License is distributed on an "AS IS" BASIS,
1270// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1271// See the License for the specific language governing permissions and
1272// limitations under the License.
1273
1274#include "build.h"
1275
1276#include <assert.h>
1277#include <errno.h>
1278#include <stdio.h>
1279#include <stdlib.h>
1280#include <functional>
1281
1282#ifdef _WIN32
1283#include <fcntl.h>
1284#include <io.h>
1285#endif
1286
1287#if defined(__SVR4) && defined(__sun)
1288#include <sys/termios.h>
1289#endif
1290
1291#include "build_log.h"
1292#include "clparser.h"
1293#include "debug_flags.h"
1294#include "depfile_parser.h"
1295#include "deps_log.h"
1296#include "disk_interface.h"
1297#include "graph.h"
1298#include "state.h"
1299#include "subprocess.h"
1300#include "util.h"
1301*/
1302
1303use std::collections::VecDeque;
1304
1305struct DryRunCommandRunner {
1306    finished: VecDeque<EdgeIndex>,
1307}
1308
1309impl DryRunCommandRunner {
1310    pub fn new() -> Self {
1311        DryRunCommandRunner { finished: VecDeque::new() }
1312    }
1313}
1314
1315impl CommandRunner for DryRunCommandRunner {
1316    fn can_run_more(&self) -> bool {
1317        true
1318    }
1319
1320    fn start_command(&mut self, _: &State, edge: EdgeIndex) -> bool {
1321        self.finished.push_back(edge);
1322        true
1323    }
1324
1325    fn wait_for_command(&mut self) -> Option<CommandRunnerResult> {
1326        match self.finished.pop_front() {
1327            None => None,
1328            Some(e) => Some(CommandRunnerResult {
1329                edge: e,
1330                status: ExitStatus::ExitSuccess,
1331                output: Vec::new(),
1332            }),
1333        }
1334    }
1335
1336    fn get_active_edges(&self) -> Vec<EdgeIndex> {
1337        Vec::new()
1338    }
1339
1340    fn abort(&mut self) {
1341        //do nothing
1342    }
1343}
1344/*
1345
1346BuildStatus::BuildStatus(const BuildConfig& config)
1347    : config_(config),
1348      start_time_millis_(GetTimeMillis()),
1349      started_edges_(0), finished_edges_(0), total_edges_(0),
1350      progress_status_format_(NULL),
1351      overall_rate_(), current_rate_(config.parallelism) {
1352
1353  // Don't do anything fancy in verbose mode.
1354  if (config_.verbosity != BuildConfig::NORMAL)
1355    printer_.set_smart_terminal(false);
1356
1357  progress_status_format_ = getenv("NINJA_STATUS");
1358  if (!progress_status_format_)
1359    progress_status_format_ = "[%f/%t] ";
1360}
1361
1362void BuildStatus::PlanHasTotalEdges(int total) {
1363  total_edges_ = total;
1364}
1365
1366void BuildStatus::BuildEdgeStarted(Edge* edge) {
1367  int start_time = (int)(GetTimeMillis() - start_time_millis_);
1368  running_edges_.insert(make_pair(edge, start_time));
1369  ++started_edges_;
1370
1371  if (edge->use_console() || printer_.is_smart_terminal())
1372    PrintStatus(edge, kEdgeStarted);
1373
1374  if (edge->use_console())
1375    printer_.SetConsoleLocked(true);
1376}
1377
1378void BuildStatus::BuildEdgeFinished(Edge* edge,
1379                                    bool success,
1380                                    const string& output,
1381                                    int* start_time,
1382                                    int* end_time) {
1383  int64_t now = GetTimeMillis();
1384
1385  ++finished_edges_;
1386
1387  RunningEdgeMap::iterator i = running_edges_.find(edge);
1388  *start_time = i->second;
1389  *end_time = (int)(now - start_time_millis_);
1390  running_edges_.erase(i);
1391
1392  if (edge->use_console())
1393    printer_.SetConsoleLocked(false);
1394
1395  if (config_.verbosity == BuildConfig::QUIET)
1396    return;
1397
1398  if (!edge->use_console())
1399    PrintStatus(edge, kEdgeFinished);
1400
1401  // Print the command that is spewing before printing its output.
1402  if (!success) {
1403    string outputs;
1404    for (vector<Node*>::const_iterator o = edge->outputs_.begin();
1405         o != edge->outputs_.end(); ++o)
1406      outputs += (*o)->path() + " ";
1407
1408    printer_.PrintOnNewLine("FAILED: " + outputs + "\n");
1409    printer_.PrintOnNewLine(edge->EvaluateCommand() + "\n");
1410  }
1411
1412  if (!output.empty()) {
1413    // ninja sets stdout and stderr of subprocesses to a pipe, to be able to
1414    // check if the output is empty. Some compilers, e.g. clang, check
1415    // isatty(stderr) to decide if they should print colored output.
1416    // To make it possible to use colored output with ninja, subprocesses should
1417    // be run with a flag that forces them to always print color escape codes.
1418    // To make sure these escape codes don't show up in a file if ninja's output
1419    // is piped to a file, ninja strips ansi escape codes again if it's not
1420    // writing to a |smart_terminal_|.
1421    // (Launching subprocesses in pseudo ttys doesn't work because there are
1422    // only a few hundred available on some systems, and ninja can launch
1423    // thousands of parallel compile commands.)
1424    // TODO: There should be a flag to disable escape code stripping.
1425    string final_output;
1426    if (!printer_.is_smart_terminal())
1427      final_output = StripAnsiEscapeCodes(output);
1428    else
1429      final_output = output;
1430
1431#ifdef _WIN32
1432    // Fix extra CR being added on Windows, writing out CR CR LF (#773)
1433    _setmode(_fileno(stdout), _O_BINARY);  // Begin Windows extra CR fix
1434#endif
1435
1436    printer_.PrintOnNewLine(final_output);
1437
1438#ifdef _WIN32
1439    _setmode(_fileno(stdout), _O_TEXT);  // End Windows extra CR fix
1440#endif
1441  }
1442}
1443
1444void BuildStatus::BuildStarted() {
1445  overall_rate_.Restart();
1446  current_rate_.Restart();
1447}
1448
1449void BuildStatus::BuildFinished() {
1450  printer_.SetConsoleLocked(false);
1451  printer_.PrintOnNewLine("");
1452}
1453
1454string BuildStatus::FormatProgressStatus(
1455    const char* progress_status_format, EdgeStatus status) const {
1456  string out;
1457  char buf[32];
1458  int percent;
1459  for (const char* s = progress_status_format; *s != '\0'; ++s) {
1460    if (*s == '%') {
1461      ++s;
1462      switch (*s) {
1463      case '%':
1464        out.push_back('%');
1465        break;
1466
1467        // Started edges.
1468      case 's':
1469        snprintf(buf, sizeof(buf), "%d", started_edges_);
1470        out += buf;
1471        break;
1472
1473        // Total edges.
1474      case 't':
1475        snprintf(buf, sizeof(buf), "%d", total_edges_);
1476        out += buf;
1477        break;
1478
1479        // Running edges.
1480      case 'r': {
1481        int running_edges = started_edges_ - finished_edges_;
1482        // count the edge that just finished as a running edge
1483        if (status == kEdgeFinished)
1484          running_edges++;
1485        snprintf(buf, sizeof(buf), "%d", running_edges);
1486        out += buf;
1487        break;
1488      }
1489
1490        // Unstarted edges.
1491      case 'u':
1492        snprintf(buf, sizeof(buf), "%d", total_edges_ - started_edges_);
1493        out += buf;
1494        break;
1495
1496        // Finished edges.
1497      case 'f':
1498        snprintf(buf, sizeof(buf), "%d", finished_edges_);
1499        out += buf;
1500        break;
1501
1502        // Overall finished edges per second.
1503      case 'o':
1504        overall_rate_.UpdateRate(finished_edges_);
1505        SnprintfRate(overall_rate_.rate(), buf, "%.1f");
1506        out += buf;
1507        break;
1508
1509        // Current rate, average over the last '-j' jobs.
1510      case 'c':
1511        current_rate_.UpdateRate(finished_edges_);
1512        SnprintfRate(current_rate_.rate(), buf, "%.1f");
1513        out += buf;
1514        break;
1515
1516        // Percentage
1517      case 'p':
1518        percent = (100 * finished_edges_) / total_edges_;
1519        snprintf(buf, sizeof(buf), "%3i%%", percent);
1520        out += buf;
1521        break;
1522
1523      case 'e': {
1524        double elapsed = overall_rate_.Elapsed();
1525        snprintf(buf, sizeof(buf), "%.3f", elapsed);
1526        out += buf;
1527        break;
1528      }
1529
1530      default:
1531        Fatal("unknown placeholder '%%%c' in $NINJA_STATUS", *s);
1532        return "";
1533      }
1534    } else {
1535      out.push_back(*s);
1536    }
1537  }
1538
1539  return out;
1540}
1541
1542void BuildStatus::PrintStatus(Edge* edge, EdgeStatus status) {
1543  if (config_.verbosity == BuildConfig::QUIET)
1544    return;
1545
1546  bool force_full_command = config_.verbosity == BuildConfig::VERBOSE;
1547
1548  string to_print = edge->GetBinding("description");
1549  if (to_print.empty() || force_full_command)
1550    to_print = edge->GetBinding("command");
1551
1552  to_print = FormatProgressStatus(progress_status_format_, status) + to_print;
1553
1554  printer_.Print(to_print,
1555                 force_full_command ? LinePrinter::FULL : LinePrinter::ELIDE);
1556}
1557
1558Plan::Plan() : command_edges_(0), wanted_edges_(0) {}
1559
1560bool Plan::CleanNode(DependencyScan* scan, Node* node, string* err) {
1561  node->set_dirty(false);
1562
1563  for (vector<Edge*>::const_iterator oe = node->out_edges().begin();
1564       oe != node->out_edges().end(); ++oe) {
1565    // Don't process edges that we don't actually want.
1566    map<Edge*, bool>::iterator want_e = want_.find(*oe);
1567    if (want_e == want_.end() || !want_e->second)
1568      continue;
1569
1570    // Don't attempt to clean an edge if it failed to load deps.
1571    if ((*oe)->deps_missing_)
1572      continue;
1573
1574    // If all non-order-only inputs for this edge are now clean,
1575    // we might have changed the dirty state of the outputs.
1576    vector<Node*>::iterator
1577        begin = (*oe)->inputs_.begin(),
1578        end = (*oe)->inputs_.end() - (*oe)->order_only_deps_;
1579    if (find_if(begin, end, mem_fun(&Node::dirty)) == end) {
1580      // Recompute most_recent_input.
1581      Node* most_recent_input = NULL;
1582      for (vector<Node*>::iterator i = begin; i != end; ++i) {
1583        if (!most_recent_input || (*i)->mtime() > most_recent_input->mtime())
1584          most_recent_input = *i;
1585      }
1586
1587      // Now, this edge is dirty if any of the outputs are dirty.
1588      // If the edge isn't dirty, clean the outputs and mark the edge as not
1589      // wanted.
1590      bool outputs_dirty = false;
1591      if (!scan->RecomputeOutputsDirty(*oe, most_recent_input,
1592                                       &outputs_dirty, err)) {
1593        return false;
1594      }
1595      if (!outputs_dirty) {
1596        for (vector<Node*>::iterator o = (*oe)->outputs_.begin();
1597             o != (*oe)->outputs_.end(); ++o) {
1598          if (!CleanNode(scan, *o, err))
1599            return false;
1600        }
1601
1602        want_e->second = false;
1603        --wanted_edges_;
1604        if (!(*oe)->is_phony())
1605          --command_edges_;
1606      }
1607    }
1608  }
1609  return true;
1610}
1611
1612void Plan::Dump() {
1613  printf("pending: %d\n", (int)want_.size());
1614  for (map<Edge*, bool>::iterator e = want_.begin(); e != want_.end(); ++e) {
1615    if (e->second)
1616      printf("want ");
1617    e->first->Dump();
1618  }
1619  printf("ready: %d\n", (int)ready_.size());
1620}
1621*/
1622
1623struct RealCommandRunner<'a> {
1624    config: &'a BuildConfig,
1625    subprocs: SubprocessSet<EdgeIndex>,
1626}
1627
1628impl<'a> RealCommandRunner<'a> {
1629    pub fn new(config: &'a BuildConfig) -> Self {
1630        RealCommandRunner {
1631            config,
1632            subprocs: SubprocessSet::new(),
1633        }
1634    }
1635}
1636
1637impl<'a> CommandRunner for RealCommandRunner<'a> {
1638    fn can_run_more(&self) -> bool {
1639        let subproc_number = self.subprocs.running().len() + self.subprocs.finished().len();
1640        if subproc_number >= self.config.parallelism {
1641            return false;
1642        }
1643        if self.subprocs.running().is_empty() {
1644            return true;
1645        }
1646        if self.config.max_load_average <= 0.0f64 {
1647            return true;
1648        }
1649        if get_load_average().unwrap_or(-0.0f64) < self.config.max_load_average {
1650            return true;
1651        }
1652        return false;
1653    }
1654
1655    fn start_command(&mut self, state: &State, edge_idx: EdgeIndex) -> bool {
1656        let edge = state.edge_state.get_edge(edge_idx);
1657        let command = edge.evaluate_command(&state.node_state);
1658
1659        return self.subprocs
1660            .add(&command, edge.use_console(), edge_idx)
1661            .is_some();
1662    }
1663
1664    fn wait_for_command(&mut self) -> Option<CommandRunnerResult> {
1665        let (mut subproc, edge_idx) = loop {
1666            if let Some(next_finished) = self.subprocs.next_finished() {
1667                break next_finished;
1668            }
1669            if self.subprocs.do_work().is_err() {
1670                //interrupted
1671                return None;
1672            }
1673        };
1674
1675        let status = subproc.finish();
1676        let output = subproc.output().to_owned();
1677        Some(CommandRunnerResult {
1678            status,
1679            output,
1680            edge: edge_idx,
1681        })
1682    }
1683
1684    fn get_active_edges(&self) -> Vec<EdgeIndex> {
1685        self.subprocs.iter().map(|x| x.1).collect()
1686    }
1687
1688    fn abort(&mut self) {
1689        self.subprocs.clear();
1690    }
1691}
1692
1693/*
1694struct RealCommandRunner : public CommandRunner {
1695  explicit RealCommandRunner(const BuildConfig& config) : config_(config) {}
1696  virtual ~RealCommandRunner() {}
1697  virtual bool CanRunMore();
1698  virtual bool StartCommand(Edge* edge);
1699  virtual bool WaitForCommand(Result* result);
1700  virtual vector<Edge*> GetActiveEdges();
1701  virtual void Abort();
1702
1703  const BuildConfig& config_;
1704  SubprocessSet subprocs_;
1705  map<Subprocess*, Edge*> subproc_to_edge_;
1706};
1707
1708bool RealCommandRunner::CanRunMore() {
1709  size_t subproc_number =
1710      subprocs_.running_.size() + subprocs_.finished_.size();
1711  return (int)subproc_number < config_.parallelism
1712    && ((subprocs_.running_.empty() || config_.max_load_average <= 0.0f)
1713        || GetLoadAverage() < config_.max_load_average);
1714}
1715
1716bool RealCommandRunner::StartCommand(Edge* edge) {
1717  string command = edge->EvaluateCommand();
1718  Subprocess* subproc = subprocs_.Add(command, edge->use_console());
1719  if (!subproc)
1720    return false;
1721  subproc_to_edge_.insert(make_pair(subproc, edge));
1722
1723  return true;
1724}
1725
1726bool RealCommandRunner::WaitForCommand(Result* result) {
1727  Subprocess* subproc;
1728  while ((subproc = subprocs_.NextFinished()) == NULL) {
1729    bool interrupted = subprocs_.DoWork();
1730    if (interrupted)
1731      return false;
1732  }
1733
1734  result->status = subproc->Finish();
1735  result->output = subproc->GetOutput();
1736
1737  map<Subprocess*, Edge*>::iterator e = subproc_to_edge_.find(subproc);
1738  result->edge = e->second;
1739  subproc_to_edge_.erase(e);
1740
1741  delete subproc;
1742  return true;
1743}
1744
1745Builder::Builder(State* state, const BuildConfig& config,
1746                 BuildLog* build_log, DepsLog* deps_log,
1747                 DiskInterface* disk_interface)
1748    : state_(state), config_(config), disk_interface_(disk_interface),
1749      scan_(state, build_log, deps_log, disk_interface) {
1750  status_ = new BuildStatus(config);
1751}
1752
1753Node* Builder::AddTarget(const string& name, string* err) {
1754  Node* node = state_->LookupNode(name);
1755  if (!node) {
1756    *err = "unknown target: '" + name + "'";
1757    return NULL;
1758  }
1759  if (!AddTarget(node, err))
1760    return NULL;
1761  return node;
1762}
1763
1764bool Builder::AddTarget(Node* node, string* err) {
1765  if (!scan_.RecomputeDirty(node, err))
1766    return false;
1767
1768  if (Edge* in_edge = node->in_edge()) {
1769    if (in_edge->outputs_ready())
1770      return true;  // Nothing to do.
1771  }
1772
1773  if (!plan_.AddTarget(node, err))
1774    return false;
1775
1776  return true;
1777}
1778
1779
1780
1781bool Builder::ExtractDeps(CommandRunner::Result* result,
1782                          const string& deps_type,
1783                          const string& deps_prefix,
1784                          vector<Node*>* deps_nodes,
1785                          string* err) {
1786  if (deps_type == "msvc") {
1787    CLParser parser;
1788    string output;
1789    if (!parser.Parse(result->output, deps_prefix, &output, err))
1790      return false;
1791    result->output = output;
1792    for (set<string>::iterator i = parser.includes_.begin();
1793         i != parser.includes_.end(); ++i) {
1794      // ~0 is assuming that with MSVC-parsed headers, it's ok to always make
1795      // all backslashes (as some of the slashes will certainly be backslashes
1796      // anyway). This could be fixed if necessary with some additional
1797      // complexity in IncludesNormalize::Relativize.
1798      deps_nodes->push_back(state_->GetNode(*i, ~0u));
1799    }
1800  } else
1801  if (deps_type == "gcc") {
1802    string depfile = result->edge->GetUnescapedDepfile();
1803    if (depfile.empty()) {
1804      *err = string("edge with deps=gcc but no depfile makes no sense");
1805      return false;
1806    }
1807
1808    // Read depfile content.  Treat a missing depfile as empty.
1809    string content;
1810    switch (disk_interface_->ReadFile(depfile, &content, err)) {
1811    case DiskInterface::Okay:
1812      break;
1813    case DiskInterface::NotFound:
1814      err->clear();
1815      break;
1816    case DiskInterface::OtherError:
1817      return false;
1818    }
1819    if (content.empty())
1820      return true;
1821
1822    DepfileParser deps;
1823    if (!deps.Parse(&content, err))
1824      return false;
1825
1826    // XXX check depfile matches expected output.
1827    deps_nodes->reserve(deps.ins_.size());
1828    for (vector<StringPiece>::iterator i = deps.ins_.begin();
1829         i != deps.ins_.end(); ++i) {
1830      uint64_t slash_bits;
1831      if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, &slash_bits,
1832                            err))
1833        return false;
1834      deps_nodes->push_back(state_->GetNode(*i, slash_bits));
1835    }
1836
1837    if (!g_keep_depfile) {
1838      if (disk_interface_->RemoveFile(depfile) < 0) {
1839        *err = string("deleting depfile: ") + strerror(errno) + string("\n");
1840        return false;
1841      }
1842    }
1843  } else {
1844    Fatal("unknown deps type '%s'", deps_type.c_str());
1845  }
1846
1847  return true;
1848}
1849
1850
1851*/
1852
1853#[cfg(test)]
1854mod tests {
1855    use super::*;
1856    use super::super::test::TestWithStateAndVFS;
1857    use super::super::graph::Node;
1858
1859    /// Fixture for tests involving Plan.
1860    // Though Plan doesn't use State, it's useful to have one around
1861    // to create Nodes and Edges.
1862    struct PlanTestData {
1863        plan: Plan,
1864    }
1865
1866    impl Default for PlanTestData {
1867        fn default() -> Self {
1868            PlanTestData { plan: Plan::new() }
1869        }
1870    }
1871
1872    type PlanTest = TestWithStateAndVFS<PlanTestData>;
1873
1874    impl PlanTest {
1875        pub fn new() -> Self {
1876            Self::new_with_builtin_rule()
1877        }
1878    }
1879
1880    /*
1881
1882/// Fixture for tests involving Plan.
1883// Though Plan doesn't use State, it's useful to have one around
1884// to create Nodes and Edges.
1885struct PlanTest : public StateTestWithBuiltinRules {
1886  Plan plan_;
1887
1888  /// Because FindWork does not return Edges in any sort of predictable order,
1889  // provide a means to get available Edges in order and in a format which is
1890  // easy to write tests around.
1891  void FindWorkSorted(deque<Edge*>* ret, int count) {
1892    struct CompareEdgesByOutput {
1893      static bool cmp(const Edge* a, const Edge* b) {
1894        return a->outputs_[0]->path() < b->outputs_[0]->path();
1895      }
1896    };
1897
1898    for (int i = 0; i < count; ++i) {
1899      ASSERT_TRUE(plan_.more_to_do());
1900      Edge* edge = plan_.FindWork();
1901      ASSERT_TRUE(edge);
1902      ret->push_back(edge);
1903    }
1904    ASSERT_FALSE(plan_.FindWork());
1905    sort(ret->begin(), ret->end(), CompareEdgesByOutput::cmp);
1906  }
1907
1908  void TestPoolWithDepthOne(const char *test_case);
1909};
1910*/
1911    #[test]
1912    fn plantest_basic() {
1913        let mut plantest = PlanTest::new();
1914        plantest.assert_parse(
1915            concat!("build out: cat mid\n", "build mid: cat in\n").as_bytes(),
1916        );
1917        plantest.assert_with_node_mut(b"mid", Node::mark_dirty);
1918        plantest.assert_with_node_mut(b"out", Node::mark_dirty);
1919        let out_node_idx = plantest.assert_node_idx(b"out");
1920
1921        let mut state = plantest.state.borrow_mut();
1922        let state = &mut *state;
1923        let plan = &mut plantest.other.plan;
1924        assert_eq!(Ok(true), plan.add_target(state, out_node_idx));
1925        assert_eq!(true, plan.more_to_do());
1926
1927        let edge_idx = plan.find_work().unwrap();
1928        {
1929            let edge = state.edge_state.get_edge(edge_idx);
1930            let input0 = edge.inputs[0];
1931            assert_eq!(b"in", state.node_state.get_node(input0).path());
1932            let output0 = edge.outputs[0];
1933            assert_eq!(b"mid", state.node_state.get_node(output0).path());
1934        }
1935        assert_eq!(None, plan.find_work());
1936        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
1937        let edge_idx = plan.find_work().unwrap();
1938        {
1939            let edge = state.edge_state.get_edge(edge_idx);
1940            let input0 = edge.inputs[0];
1941            assert_eq!(b"mid", state.node_state.get_node(input0).path());
1942            let output0 = edge.outputs[0];
1943            assert_eq!(b"out", state.node_state.get_node(output0).path());
1944        }
1945        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
1946
1947        assert_eq!(false, plan.more_to_do());
1948        assert_eq!(None, plan.find_work());
1949    }
1950
1951    // Test that two outputs from one rule can be handled as inputs to the next.
1952    #[test]
1953    fn plantest_double_output_direct() {
1954        let mut plantest = PlanTest::new();
1955        plantest.assert_parse(
1956            concat!("build out: cat mid1 mid2\n", "build mid1 mid2: cat in\n").as_bytes(),
1957        );
1958        plantest.assert_with_node_mut(b"mid1", Node::mark_dirty);
1959        plantest.assert_with_node_mut(b"mid2", Node::mark_dirty);
1960        plantest.assert_with_node_mut(b"out", Node::mark_dirty);
1961
1962        let out_node_idx = plantest.assert_node_idx(b"out");
1963        let mut state = plantest.state.borrow_mut();
1964        let state = &mut *state;
1965        let plan = &mut plantest.other.plan;
1966        assert_eq!(Ok(true), plan.add_target(state, out_node_idx));
1967        assert_eq!(true, plan.more_to_do());
1968
1969        let edge_idx = plan.find_work().unwrap(); // cat in
1970        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
1971
1972        let edge_idx = plan.find_work().unwrap(); // cat mid1 mid2
1973        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
1974
1975        assert_eq!(None, plan.find_work()); // done
1976    }
1977
1978    // Test that two outputs from one rule can eventually be routed to another.
1979    #[test]
1980    fn plantest_double_output_indirect() {
1981        let mut plantest = PlanTest::new();
1982        plantest.assert_parse(
1983            concat!(
1984                "build out: cat b1 b2\n",
1985                "build b1: cat a1\n",
1986                "build b2: cat a2\n",
1987                "build a1 a2: cat in\n"
1988            ).as_bytes(),
1989        );
1990        plantest.assert_with_node_mut(b"a1", Node::mark_dirty);
1991        plantest.assert_with_node_mut(b"a2", Node::mark_dirty);
1992        plantest.assert_with_node_mut(b"b1", Node::mark_dirty);
1993        plantest.assert_with_node_mut(b"b2", Node::mark_dirty);
1994        plantest.assert_with_node_mut(b"out", Node::mark_dirty);
1995
1996        let out_node_idx = plantest.assert_node_idx(b"out");
1997        let mut state = plantest.state.borrow_mut();
1998        let state = &mut *state;
1999        let plan = &mut plantest.other.plan;
2000        assert_eq!(Ok(true), plan.add_target(state, out_node_idx));
2001        assert_eq!(true, plan.more_to_do());
2002
2003        let edge_idx = plan.find_work().unwrap(); // cat in
2004        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2005
2006        let edge_idx = plan.find_work().unwrap(); // cat a1
2007        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2008
2009        let edge_idx = plan.find_work().unwrap(); // cat a2
2010        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2011
2012        let edge_idx = plan.find_work().unwrap(); // cat b1 b2
2013        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2014
2015        assert_eq!(None, plan.find_work()); // done
2016    }
2017
2018    // Test that two edges from one output can both execute.
2019    #[test]
2020    fn plantest_double_dependent() {
2021        let mut plantest = PlanTest::new();
2022        plantest.assert_parse(
2023            concat!(
2024                "build out: cat a1 a2\n",
2025                "build a1: cat mid\n",
2026                "build a2: cat mid\n",
2027                "build mid: cat in\n"
2028            ).as_bytes(),
2029        );
2030        plantest.assert_with_node_mut(b"mid", Node::mark_dirty);
2031        plantest.assert_with_node_mut(b"a1", Node::mark_dirty);
2032        plantest.assert_with_node_mut(b"a2", Node::mark_dirty);
2033        plantest.assert_with_node_mut(b"out", Node::mark_dirty);
2034
2035        let out_node_idx = plantest.assert_node_idx(b"out");
2036        let mut state = plantest.state.borrow_mut();
2037        let state = &mut *state;
2038        let plan = &mut plantest.other.plan;
2039        assert_eq!(Ok(true), plan.add_target(state, out_node_idx));
2040        assert_eq!(true, plan.more_to_do());
2041
2042        let edge_idx = plan.find_work().unwrap(); // cat in
2043        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2044
2045        let edge_idx = plan.find_work().unwrap(); // cat mid
2046        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2047
2048        let edge_idx = plan.find_work().unwrap(); // cat mid
2049        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2050
2051        let edge_idx = plan.find_work().unwrap(); // cat a1 a2
2052        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2053
2054        assert_eq!(None, plan.find_work()); // done
2055    }
2056
2057    fn test_pool_with_depth_one_helper(plantest: &mut PlanTest, test_case: &[u8]) {
2058        plantest.assert_parse(test_case);
2059        plantest.assert_with_node_mut(b"out1", Node::mark_dirty);
2060        plantest.assert_with_node_mut(b"out2", Node::mark_dirty);
2061
2062        let out1_node_idx = plantest.assert_node_idx(b"out1");
2063        let out2_node_idx = plantest.assert_node_idx(b"out2");
2064
2065        let mut state = plantest.state.borrow_mut();
2066        let state = &mut *state;
2067        let plan = &mut plantest.other.plan;
2068        assert_eq!(Ok(true), plan.add_target(state, out1_node_idx));
2069        assert_eq!(Ok(true), plan.add_target(state, out2_node_idx));
2070
2071        assert_eq!(true, plan.more_to_do());
2072
2073        let edge_idx = plan.find_work().unwrap();
2074        {
2075            let edge = state.edge_state.get_edge(edge_idx);
2076            let edge_in0_idx = edge.inputs.get(0).cloned().unwrap();
2077            let edge_in0_node = state.node_state.get_node(edge_in0_idx);
2078            assert_eq!(b"in".as_ref(), edge_in0_node.path());
2079            let edge_out0_idx = edge.outputs.get(0).cloned().unwrap();
2080            let edge_out0_node = state.node_state.get_node(edge_out0_idx);
2081            assert_eq!(b"out1".as_ref(), edge_out0_node.path());
2082        }
2083
2084        // This will be false since poolcat is serialized
2085        assert!(plan.find_work().is_none());
2086        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2087
2088        let edge_idx = plan.find_work().unwrap();
2089        {
2090            let edge = state.edge_state.get_edge(edge_idx);
2091            let edge_in0_idx = edge.inputs.get(0).cloned().unwrap();
2092            let edge_in0_node = state.node_state.get_node(edge_in0_idx);
2093            assert_eq!(b"in".as_ref(), edge_in0_node.path());
2094            let edge_out0_idx = edge.outputs.get(0).cloned().unwrap();
2095            let edge_out0_node = state.node_state.get_node(edge_out0_idx);
2096            assert_eq!(b"out2".as_ref(), edge_out0_node.path());
2097        }
2098
2099        // This will be false since poolcat is serialized
2100        assert!(plan.find_work().is_none());
2101        plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2102
2103        assert_eq!(false, plan.more_to_do());
2104        assert_eq!(None, plan.find_work()); // done
2105    }
2106
2107    #[test]
2108    fn plantest_pool_with_depth_one() {
2109        let mut plantest = PlanTest::new();
2110        test_pool_with_depth_one_helper(
2111            &mut plantest,
2112            concat!(
2113                "pool foobar\n",
2114                "  depth = 1\n",
2115                "rule poolcat\n",
2116                "  command = cat $in > $out\n",
2117                "  pool = foobar\n",
2118                "build out1: poolcat in\n",
2119                "build out2: poolcat in\n"
2120            ).as_bytes(),
2121        );
2122    }
2123
2124    #[test]
2125    fn plantest_console_pool() {
2126        let mut plantest = PlanTest::new();
2127        test_pool_with_depth_one_helper(
2128            &mut plantest,
2129            concat!(
2130          "rule poolcat\n",
2131          "  command = cat $in > $out\n",
2132          "  pool = console\n",
2133          "build out1: poolcat in\n",
2134          "build out2: poolcat in\n",
2135        ).as_bytes(),
2136        );
2137    }
2138
2139    /// Because FindWork does not return Edges in any sort of predictable order,
2140    // provide a means to get available Edges in order and in a format which is
2141    // easy to write tests around.
2142    fn find_work_sorted_helper(
2143        plan: &mut Plan,
2144        state: &State,
2145        count: usize,
2146    ) -> VecDeque<EdgeIndex> {
2147        let mut result = (0..count)
2148            .map(|i| {
2149                assert!(plan.more_to_do());
2150                plan.find_work().unwrap()
2151            })
2152            .collect::<Vec<_>>();
2153
2154        assert!(plan.find_work().is_none());
2155        result.sort_by_key(|e| {
2156            state
2157                .node_state
2158                .get_node(state.edge_state.get_edge(*e).outputs[0])
2159                .path()
2160        });
2161        result.into_iter().collect()
2162    }
2163
2164    #[test]
2165    fn plantest_pools_with_depth_two() {
2166        let mut plantest = PlanTest::new();
2167        plantest.assert_parse(
2168            concat!(
2169                "pool foobar\n",
2170                "  depth = 2\n",
2171                "pool bazbin\n",
2172                "  depth = 2\n",
2173                "rule foocat\n",
2174                "  command = cat $in > $out\n",
2175                "  pool = foobar\n",
2176                "rule bazcat\n",
2177                "  command = cat $in > $out\n",
2178                "  pool = bazbin\n",
2179                "build out1: foocat in\n",
2180                "build out2: foocat in\n",
2181                "build out3: foocat in\n",
2182                "build outb1: bazcat in\n",
2183                "build outb2: bazcat in\n",
2184                "build outb3: bazcat in\n",
2185                "  pool =\n",
2186                "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
2187            ).as_bytes(),
2188        );
2189        [
2190            b"out1".as_ref(),
2191            b"out2".as_ref(),
2192            b"out3".as_ref(),
2193            b"outb1".as_ref(),
2194            b"outb2".as_ref(),
2195            b"outb3".as_ref(),
2196            b"allTheThings".as_ref(),
2197        ].as_ref()
2198            .iter()
2199            .for_each(|path| {
2200                plantest.assert_with_node_mut(path, Node::mark_dirty);
2201            });
2202
2203        let mut state = plantest.state.borrow_mut();
2204        let state = &mut *state;
2205        let plan = &mut plantest.other.plan;
2206        let all_the_things_node = state.node_state.lookup_node(b"allTheThings").unwrap();
2207        assert_eq!(Ok(true), plan.add_target(state, all_the_things_node));
2208
2209        let mut edges = find_work_sorted_helper(plan, state, 5);
2210        {
2211            let edge_idx = edges[0];
2212            let edge = state.edge_state.get_edge(edge_idx);
2213            assert_eq!(
2214                b"in".as_ref(),
2215                state.node_state.get_node(edge.inputs[0]).path()
2216            );
2217            assert_eq!(
2218                b"out1".as_ref(),
2219                state.node_state.get_node(edge.outputs[0]).path()
2220            )
2221        }
2222        {
2223            let edge_idx = edges[1];
2224            let edge = state.edge_state.get_edge(edge_idx);
2225            assert_eq!(
2226                b"in".as_ref(),
2227                state.node_state.get_node(edge.inputs[0]).path()
2228            );
2229            assert_eq!(
2230                b"out2".as_ref(),
2231                state.node_state.get_node(edge.outputs[0]).path()
2232            )
2233        }
2234        {
2235            let edge_idx = edges[2];
2236            let edge = state.edge_state.get_edge(edge_idx);
2237            assert_eq!(
2238                b"in".as_ref(),
2239                state.node_state.get_node(edge.inputs[0]).path()
2240            );
2241            assert_eq!(
2242                b"outb1".as_ref(),
2243                state.node_state.get_node(edge.outputs[0]).path()
2244            )
2245        }
2246        {
2247            let edge_idx = edges[3];
2248            let edge = state.edge_state.get_edge(edge_idx);
2249            assert_eq!(
2250                b"in".as_ref(),
2251                state.node_state.get_node(edge.inputs[0]).path()
2252            );
2253            assert_eq!(
2254                b"outb2".as_ref(),
2255                state.node_state.get_node(edge.outputs[0]).path()
2256            )
2257        }
2258        {
2259            let edge_idx = edges[4];
2260            let edge = state.edge_state.get_edge(edge_idx);
2261            assert_eq!(
2262                b"in".as_ref(),
2263                state.node_state.get_node(edge.inputs[0]).path()
2264            );
2265            assert_eq!(
2266                b"outb3".as_ref(),
2267                state.node_state.get_node(edge.outputs[0]).path()
2268            )
2269        }
2270        // finish out1
2271        plan.edge_finished(state, edges.pop_front().unwrap(), EdgeResult::EdgeSucceeded);
2272
2273        let out3_idx = plan.find_work().unwrap();
2274        {
2275            let edge = state.edge_state.get_edge(out3_idx);
2276            assert_eq!(
2277                b"in".as_ref(),
2278                state.node_state.get_node(edge.inputs[0]).path()
2279            );
2280            assert_eq!(
2281                b"out3".as_ref(),
2282                state.node_state.get_node(edge.outputs[0]).path()
2283            )
2284        }
2285        assert!(plan.find_work().is_none());
2286        plan.edge_finished(state, out3_idx, EdgeResult::EdgeSucceeded);
2287        assert!(plan.find_work().is_none());
2288
2289        edges.into_iter().for_each(|edge_idx| {
2290            plan.edge_finished(state, edge_idx, EdgeResult::EdgeSucceeded);
2291        });
2292
2293        let last_idx = plan.find_work().unwrap();
2294        {
2295            let edge = state.edge_state.get_edge(last_idx);
2296            assert_eq!(
2297                b"allTheThings".as_ref(),
2298                state.node_state.get_node(edge.outputs[0]).path()
2299            )
2300        }
2301        plan.edge_finished(state, last_idx, EdgeResult::EdgeSucceeded);
2302
2303        assert_eq!(false, plan.more_to_do());
2304        assert_eq!(None, plan.find_work()); // done
2305    }
2306    /*
2307TEST_F(PlanTest, PoolWithRedundantEdges) {
2308  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2309    "pool compile\n"
2310    "  depth = 1\n"
2311    "rule gen_foo\n"
2312    "  command = touch foo.cpp\n"
2313    "rule gen_bar\n"
2314    "  command = touch bar.cpp\n"
2315    "rule echo\n"
2316    "  command = echo $out > $out\n"
2317    "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
2318    "  pool = compile\n"
2319    "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
2320    "  pool = compile\n"
2321    "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
2322    "build foo.cpp: gen_foo\n"
2323    "build bar.cpp: gen_bar\n"
2324    "build all: phony libfoo.a\n"));
2325  GetNode("foo.cpp")->MarkDirty();
2326  GetNode("foo.cpp.obj")->MarkDirty();
2327  GetNode("bar.cpp")->MarkDirty();
2328  GetNode("bar.cpp.obj")->MarkDirty();
2329  GetNode("libfoo.a")->MarkDirty();
2330  GetNode("all")->MarkDirty();
2331  string err;
2332  EXPECT_TRUE(plan_.AddTarget(GetNode("all"), &err));
2333  ASSERT_EQ("", err);
2334  ASSERT_TRUE(plan_.more_to_do());
2335
2336  Edge* edge = NULL;
2337
2338  deque<Edge*> initial_edges;
2339  FindWorkSorted(&initial_edges, 2);
2340
2341  edge = initial_edges[1];  // Foo first
2342  ASSERT_EQ("foo.cpp", edge->outputs_[0]->path());
2343  plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
2344
2345  edge = plan_.FindWork();
2346  ASSERT_TRUE(edge);
2347  ASSERT_FALSE(plan_.FindWork());
2348  ASSERT_EQ("foo.cpp", edge->inputs_[0]->path());
2349  ASSERT_EQ("foo.cpp", edge->inputs_[1]->path());
2350  ASSERT_EQ("foo.cpp.obj", edge->outputs_[0]->path());
2351  plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
2352
2353  edge = initial_edges[0];  // Now for bar
2354  ASSERT_EQ("bar.cpp", edge->outputs_[0]->path());
2355  plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
2356
2357  edge = plan_.FindWork();
2358  ASSERT_TRUE(edge);
2359  ASSERT_FALSE(plan_.FindWork());
2360  ASSERT_EQ("bar.cpp", edge->inputs_[0]->path());
2361  ASSERT_EQ("bar.cpp", edge->inputs_[1]->path());
2362  ASSERT_EQ("bar.cpp.obj", edge->outputs_[0]->path());
2363  plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
2364
2365  edge = plan_.FindWork();
2366  ASSERT_TRUE(edge);
2367  ASSERT_FALSE(plan_.FindWork());
2368  ASSERT_EQ("foo.cpp.obj", edge->inputs_[0]->path());
2369  ASSERT_EQ("bar.cpp.obj", edge->inputs_[1]->path());
2370  ASSERT_EQ("libfoo.a", edge->outputs_[0]->path());
2371  plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
2372
2373  edge = plan_.FindWork();
2374  ASSERT_TRUE(edge);
2375  ASSERT_FALSE(plan_.FindWork());
2376  ASSERT_EQ("libfoo.a", edge->inputs_[0]->path());
2377  ASSERT_EQ("all", edge->outputs_[0]->path());
2378  plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
2379
2380  edge = plan_.FindWork();
2381  ASSERT_FALSE(edge);
2382  ASSERT_FALSE(plan_.more_to_do());
2383}
2384
2385TEST_F(PlanTest, PoolWithFailingEdge) {
2386  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2387    "pool foobar\n"
2388    "  depth = 1\n"
2389    "rule poolcat\n"
2390    "  command = cat $in > $out\n"
2391    "  pool = foobar\n"
2392    "build out1: poolcat in\n"
2393    "build out2: poolcat in\n"));
2394  GetNode("out1")->MarkDirty();
2395  GetNode("out2")->MarkDirty();
2396  string err;
2397  EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err));
2398  ASSERT_EQ("", err);
2399  EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err));
2400  ASSERT_EQ("", err);
2401  ASSERT_TRUE(plan_.more_to_do());
2402
2403  Edge* edge = plan_.FindWork();
2404  ASSERT_TRUE(edge);
2405  ASSERT_EQ("in",  edge->inputs_[0]->path());
2406  ASSERT_EQ("out1", edge->outputs_[0]->path());
2407
2408  // This will be false since poolcat is serialized
2409  ASSERT_FALSE(plan_.FindWork());
2410
2411  plan_.EdgeFinished(edge, Plan::kEdgeFailed);
2412
2413  edge = plan_.FindWork();
2414  ASSERT_TRUE(edge);
2415  ASSERT_EQ("in", edge->inputs_[0]->path());
2416  ASSERT_EQ("out2", edge->outputs_[0]->path());
2417
2418  ASSERT_FALSE(plan_.FindWork());
2419
2420  plan_.EdgeFinished(edge, Plan::kEdgeFailed);
2421
2422  ASSERT_TRUE(plan_.more_to_do()); // Jobs have failed
2423  edge = plan_.FindWork();
2424  ASSERT_EQ(0, edge);
2425}
2426
2427/// Fake implementation of CommandRunner, useful for tests.
2428struct FakeCommandRunner : public CommandRunner {
2429  explicit FakeCommandRunner(VirtualFileSystem* fs) :
2430      last_command_(NULL), fs_(fs) {}
2431
2432  // CommandRunner impl
2433  virtual bool CanRunMore();
2434  virtual bool StartCommand(Edge* edge);
2435  virtual bool WaitForCommand(Result* result);
2436  virtual vector<Edge*> GetActiveEdges();
2437  virtual void Abort();
2438
2439  vector<string> commands_ran_;
2440  Edge* last_command_;
2441  VirtualFileSystem* fs_;
2442};
2443*/
2444
2445    /*
2446struct BuildTest : public StateTestWithBuiltinRules, public BuildLogUser {
2447  BuildTest() : config_(MakeConfig()), command_runner_(&fs_),
2448                builder_(&state_, config_, NULL, NULL, &fs_),
2449                status_(config_) {
2450  }
2451
2452  virtual void SetUp() {
2453    StateTestWithBuiltinRules::SetUp();
2454
2455    builder_.command_runner_.reset(&command_runner_);
2456    AssertParse(&state_,
2457"build cat1: cat in1\n"
2458"build cat2: cat in1 in2\n"
2459"build cat12: cat cat1 cat2\n");
2460
2461    fs_.Create("in1", "");
2462    fs_.Create("in2", "");
2463  }
2464
2465  ~BuildTest() {
2466    builder_.command_runner_.release();
2467  }
2468
2469  virtual bool IsPathDead(StringPiece s) const { return false; }
2470
2471  /// Rebuild target in the 'working tree' (fs_).
2472  /// State of command_runner_ and logs contents (if specified) ARE MODIFIED.
2473  /// Handy to check for NOOP builds, and higher-level rebuild tests.
2474  void RebuildTarget(const string& target, const char* manifest,
2475                     const char* log_path = NULL, const char* deps_path = NULL,
2476                     State* state = NULL);
2477
2478  // Mark a path dirty.
2479  void Dirty(const string& path);
2480
2481  BuildConfig MakeConfig() {
2482    BuildConfig config;
2483    config.verbosity = BuildConfig::QUIET;
2484    return config;
2485  }
2486
2487  BuildConfig config_;
2488  FakeCommandRunner command_runner_;
2489  VirtualFileSystem fs_;
2490  Builder builder_;
2491
2492  BuildStatus status_;
2493};
2494
2495void BuildTest::RebuildTarget(const string& target, const char* manifest,
2496                              const char* log_path, const char* deps_path,
2497                              State* state) {
2498  State local_state, *pstate = &local_state;
2499  if (state)
2500    pstate = state;
2501  ASSERT_NO_FATAL_FAILURE(AddCatRule(pstate));
2502  AssertParse(pstate, manifest);
2503
2504  string err;
2505  BuildLog build_log, *pbuild_log = NULL;
2506  if (log_path) {
2507    ASSERT_TRUE(build_log.Load(log_path, &err));
2508    ASSERT_TRUE(build_log.OpenForWrite(log_path, *this, &err));
2509    ASSERT_EQ("", err);
2510    pbuild_log = &build_log;
2511  }
2512
2513  DepsLog deps_log, *pdeps_log = NULL;
2514  if (deps_path) {
2515    ASSERT_TRUE(deps_log.Load(deps_path, pstate, &err));
2516    ASSERT_TRUE(deps_log.OpenForWrite(deps_path, &err));
2517    ASSERT_EQ("", err);
2518    pdeps_log = &deps_log;
2519  }
2520
2521  Builder builder(pstate, config_, pbuild_log, pdeps_log, &fs_);
2522  EXPECT_TRUE(builder.AddTarget(target, &err));
2523
2524  command_runner_.commands_ran_.clear();
2525  builder.command_runner_.reset(&command_runner_);
2526  if (!builder.AlreadyUpToDate()) {
2527    bool build_res = builder.Build(&err);
2528    EXPECT_TRUE(build_res);
2529  }
2530  builder.command_runner_.release();
2531}
2532
2533bool FakeCommandRunner::CanRunMore() {
2534  // Only run one at a time.
2535  return last_command_ == NULL;
2536}
2537
2538bool FakeCommandRunner::StartCommand(Edge* edge) {
2539  assert(!last_command_);
2540  commands_ran_.push_back(edge->EvaluateCommand());
2541  if (edge->rule().name() == "cat"  ||
2542      edge->rule().name() == "cat_rsp" ||
2543      edge->rule().name() == "cat_rsp_out" ||
2544      edge->rule().name() == "cc" ||
2545      edge->rule().name() == "touch" ||
2546      edge->rule().name() == "touch-interrupt" ||
2547      edge->rule().name() == "touch-fail-tick2") {
2548    for (vector<Node*>::iterator out = edge->outputs_.begin();
2549         out != edge->outputs_.end(); ++out) {
2550      fs_->Create((*out)->path(), "");
2551    }
2552  } else if (edge->rule().name() == "true" ||
2553             edge->rule().name() == "fail" ||
2554             edge->rule().name() == "interrupt" ||
2555             edge->rule().name() == "console") {
2556    // Don't do anything.
2557  } else {
2558    printf("unknown command\n");
2559    return false;
2560  }
2561
2562  last_command_ = edge;
2563  return true;
2564}
2565
2566bool FakeCommandRunner::WaitForCommand(Result* result) {
2567  if (!last_command_)
2568    return false;
2569
2570  Edge* edge = last_command_;
2571  result->edge = edge;
2572
2573  if (edge->rule().name() == "interrupt" ||
2574      edge->rule().name() == "touch-interrupt") {
2575    result->status = ExitInterrupted;
2576    return true;
2577  }
2578
2579  if (edge->rule().name() == "console") {
2580    if (edge->use_console())
2581      result->status = ExitSuccess;
2582    else
2583      result->status = ExitFailure;
2584    last_command_ = NULL;
2585    return true;
2586  }
2587
2588  if (edge->rule().name() == "fail" ||
2589      (edge->rule().name() == "touch-fail-tick2" && fs_->now_ == 2))
2590    result->status = ExitFailure;
2591  else
2592    result->status = ExitSuccess;
2593  last_command_ = NULL;
2594  return true;
2595}
2596
2597vector<Edge*> FakeCommandRunner::GetActiveEdges() {
2598  vector<Edge*> edges;
2599  if (last_command_)
2600    edges.push_back(last_command_);
2601  return edges;
2602}
2603
2604void FakeCommandRunner::Abort() {
2605  last_command_ = NULL;
2606}
2607
2608void BuildTest::Dirty(const string& path) {
2609  Node* node = GetNode(path);
2610  node->MarkDirty();
2611
2612  // If it's an input file, mark that we've already stat()ed it and
2613  // it's missing.
2614  if (!node->in_edge())
2615    node->MarkMissing();
2616}
2617
2618TEST_F(BuildTest, NoWork) {
2619  string err;
2620  EXPECT_TRUE(builder_.AlreadyUpToDate());
2621}
2622
2623TEST_F(BuildTest, OneStep) {
2624  // Given a dirty target with one ready input,
2625  // we should rebuild the target.
2626  Dirty("cat1");
2627  string err;
2628  EXPECT_TRUE(builder_.AddTarget("cat1", &err));
2629  ASSERT_EQ("", err);
2630  EXPECT_TRUE(builder_.Build(&err));
2631  ASSERT_EQ("", err);
2632
2633  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2634  EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
2635}
2636
2637TEST_F(BuildTest, OneStep2) {
2638  // Given a target with one dirty input,
2639  // we should rebuild the target.
2640  Dirty("cat1");
2641  string err;
2642  EXPECT_TRUE(builder_.AddTarget("cat1", &err));
2643  ASSERT_EQ("", err);
2644  EXPECT_TRUE(builder_.Build(&err));
2645  EXPECT_EQ("", err);
2646
2647  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2648  EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]);
2649}
2650
2651TEST_F(BuildTest, TwoStep) {
2652  string err;
2653  EXPECT_TRUE(builder_.AddTarget("cat12", &err));
2654  ASSERT_EQ("", err);
2655  EXPECT_TRUE(builder_.Build(&err));
2656  EXPECT_EQ("", err);
2657  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2658  // Depending on how the pointers work out, we could've ran
2659  // the first two commands in either order.
2660  EXPECT_TRUE((command_runner_.commands_ran_[0] == "cat in1 > cat1" &&
2661               command_runner_.commands_ran_[1] == "cat in1 in2 > cat2") ||
2662              (command_runner_.commands_ran_[1] == "cat in1 > cat1" &&
2663               command_runner_.commands_ran_[0] == "cat in1 in2 > cat2"));
2664
2665  EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
2666
2667  fs_.Tick();
2668
2669  // Modifying in2 requires rebuilding one intermediate file
2670  // and the final file.
2671  fs_.Create("in2", "");
2672  state_.Reset();
2673  EXPECT_TRUE(builder_.AddTarget("cat12", &err));
2674  ASSERT_EQ("", err);
2675  EXPECT_TRUE(builder_.Build(&err));
2676  ASSERT_EQ("", err);
2677  ASSERT_EQ(5u, command_runner_.commands_ran_.size());
2678  EXPECT_EQ("cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
2679  EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
2680}
2681
2682TEST_F(BuildTest, TwoOutputs) {
2683  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2684"rule touch\n"
2685"  command = touch $out\n"
2686"build out1 out2: touch in.txt\n"));
2687
2688  fs_.Create("in.txt", "");
2689
2690  string err;
2691  EXPECT_TRUE(builder_.AddTarget("out1", &err));
2692  ASSERT_EQ("", err);
2693  EXPECT_TRUE(builder_.Build(&err));
2694  EXPECT_EQ("", err);
2695  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2696  EXPECT_EQ("touch out1 out2", command_runner_.commands_ran_[0]);
2697}
2698
2699TEST_F(BuildTest, ImplicitOutput) {
2700  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2701"rule touch\n"
2702"  command = touch $out $out.imp\n"
2703"build out | out.imp: touch in.txt\n"));
2704  fs_.Create("in.txt", "");
2705
2706  string err;
2707  EXPECT_TRUE(builder_.AddTarget("out.imp", &err));
2708  ASSERT_EQ("", err);
2709  EXPECT_TRUE(builder_.Build(&err));
2710  EXPECT_EQ("", err);
2711  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2712  EXPECT_EQ("touch out out.imp", command_runner_.commands_ran_[0]);
2713}
2714
2715// Test case from
2716//   https://github.com/ninja-build/ninja/issues/148
2717TEST_F(BuildTest, MultiOutIn) {
2718  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2719"rule touch\n"
2720"  command = touch $out\n"
2721"build in1 otherfile: touch in\n"
2722"build out: touch in | in1\n"));
2723
2724  fs_.Create("in", "");
2725  fs_.Tick();
2726  fs_.Create("in1", "");
2727
2728  string err;
2729  EXPECT_TRUE(builder_.AddTarget("out", &err));
2730  ASSERT_EQ("", err);
2731  EXPECT_TRUE(builder_.Build(&err));
2732  EXPECT_EQ("", err);
2733}
2734
2735TEST_F(BuildTest, Chain) {
2736  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2737"build c2: cat c1\n"
2738"build c3: cat c2\n"
2739"build c4: cat c3\n"
2740"build c5: cat c4\n"));
2741
2742  fs_.Create("c1", "");
2743
2744  string err;
2745  EXPECT_TRUE(builder_.AddTarget("c5", &err));
2746  ASSERT_EQ("", err);
2747  EXPECT_TRUE(builder_.Build(&err));
2748  EXPECT_EQ("", err);
2749  ASSERT_EQ(4u, command_runner_.commands_ran_.size());
2750
2751  err.clear();
2752  command_runner_.commands_ran_.clear();
2753  state_.Reset();
2754  EXPECT_TRUE(builder_.AddTarget("c5", &err));
2755  ASSERT_EQ("", err);
2756  EXPECT_TRUE(builder_.AlreadyUpToDate());
2757
2758  fs_.Tick();
2759
2760  fs_.Create("c3", "");
2761  err.clear();
2762  command_runner_.commands_ran_.clear();
2763  state_.Reset();
2764  EXPECT_TRUE(builder_.AddTarget("c5", &err));
2765  ASSERT_EQ("", err);
2766  EXPECT_FALSE(builder_.AlreadyUpToDate());
2767  EXPECT_TRUE(builder_.Build(&err));
2768  ASSERT_EQ(2u, command_runner_.commands_ran_.size());  // 3->4, 4->5
2769}
2770
2771TEST_F(BuildTest, MissingInput) {
2772  // Input is referenced by build file, but no rule for it.
2773  string err;
2774  Dirty("in1");
2775  EXPECT_FALSE(builder_.AddTarget("cat1", &err));
2776  EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it",
2777            err);
2778}
2779
2780TEST_F(BuildTest, MissingTarget) {
2781  // Target is not referenced by build file.
2782  string err;
2783  EXPECT_FALSE(builder_.AddTarget("meow", &err));
2784  EXPECT_EQ("unknown target: 'meow'", err);
2785}
2786
2787TEST_F(BuildTest, MakeDirs) {
2788  string err;
2789
2790#ifdef _WIN32
2791  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2792                                      "build subdir\\dir2\\file: cat in1\n"));
2793#else
2794  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2795                                      "build subdir/dir2/file: cat in1\n"));
2796#endif
2797  EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err));
2798
2799  EXPECT_EQ("", err);
2800  EXPECT_TRUE(builder_.Build(&err));
2801  ASSERT_EQ("", err);
2802  ASSERT_EQ(2u, fs_.directories_made_.size());
2803  EXPECT_EQ("subdir", fs_.directories_made_[0]);
2804  EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]);
2805}
2806
2807TEST_F(BuildTest, DepFileMissing) {
2808  string err;
2809  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2810"rule cc\n  command = cc $in\n  depfile = $out.d\n"
2811"build fo$ o.o: cc foo.c\n"));
2812  fs_.Create("foo.c", "");
2813
2814  EXPECT_TRUE(builder_.AddTarget("fo o.o", &err));
2815  ASSERT_EQ("", err);
2816  ASSERT_EQ(1u, fs_.files_read_.size());
2817  EXPECT_EQ("fo o.o.d", fs_.files_read_[0]);
2818}
2819
2820TEST_F(BuildTest, DepFileOK) {
2821  string err;
2822  int orig_edges = state_.edges_.size();
2823  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2824"rule cc\n  command = cc $in\n  depfile = $out.d\n"
2825"build foo.o: cc foo.c\n"));
2826  Edge* edge = state_.edges_.back();
2827
2828  fs_.Create("foo.c", "");
2829  GetNode("bar.h")->MarkDirty();  // Mark bar.h as missing.
2830  fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
2831  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2832  ASSERT_EQ("", err);
2833  ASSERT_EQ(1u, fs_.files_read_.size());
2834  EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
2835
2836  // Expect three new edges: one generating foo.o, and two more from
2837  // loading the depfile.
2838  ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
2839  // Expect our edge to now have three inputs: foo.c and two headers.
2840  ASSERT_EQ(3u, edge->inputs_.size());
2841
2842  // Expect the command line we generate to only use the original input.
2843  ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
2844}
2845
2846TEST_F(BuildTest, DepFileParseError) {
2847  string err;
2848  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2849"rule cc\n  command = cc $in\n  depfile = $out.d\n"
2850"build foo.o: cc foo.c\n"));
2851  fs_.Create("foo.c", "");
2852  fs_.Create("foo.o.d", "randomtext\n");
2853  EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
2854  EXPECT_EQ("foo.o.d: expected ':' in depfile", err);
2855}
2856
2857TEST_F(BuildTest, EncounterReadyTwice) {
2858  string err;
2859  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2860"rule touch\n"
2861"  command = touch $out\n"
2862"build c: touch\n"
2863"build b: touch || c\n"
2864"build a: touch | b || c\n"));
2865
2866  vector<Edge*> c_out = GetNode("c")->out_edges();
2867  ASSERT_EQ(2u, c_out.size());
2868  EXPECT_EQ("b", c_out[0]->outputs_[0]->path());
2869  EXPECT_EQ("a", c_out[1]->outputs_[0]->path());
2870
2871  fs_.Create("b", "");
2872  EXPECT_TRUE(builder_.AddTarget("a", &err));
2873  ASSERT_EQ("", err);
2874
2875  EXPECT_TRUE(builder_.Build(&err));
2876  ASSERT_EQ("", err);
2877  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2878}
2879
2880TEST_F(BuildTest, OrderOnlyDeps) {
2881  string err;
2882  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2883"rule cc\n  command = cc $in\n  depfile = $out.d\n"
2884"build foo.o: cc foo.c || otherfile\n"));
2885  Edge* edge = state_.edges_.back();
2886
2887  fs_.Create("foo.c", "");
2888  fs_.Create("otherfile", "");
2889  fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
2890  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2891  ASSERT_EQ("", err);
2892
2893  // One explicit, two implicit, one order only.
2894  ASSERT_EQ(4u, edge->inputs_.size());
2895  EXPECT_EQ(2, edge->implicit_deps_);
2896  EXPECT_EQ(1, edge->order_only_deps_);
2897  // Verify the inputs are in the order we expect
2898  // (explicit then implicit then orderonly).
2899  EXPECT_EQ("foo.c", edge->inputs_[0]->path());
2900  EXPECT_EQ("blah.h", edge->inputs_[1]->path());
2901  EXPECT_EQ("bar.h", edge->inputs_[2]->path());
2902  EXPECT_EQ("otherfile", edge->inputs_[3]->path());
2903
2904  // Expect the command line we generate to only use the original input.
2905  ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
2906
2907  // explicit dep dirty, expect a rebuild.
2908  EXPECT_TRUE(builder_.Build(&err));
2909  ASSERT_EQ("", err);
2910  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2911
2912  fs_.Tick();
2913
2914  // Recreate the depfile, as it should have been deleted by the build.
2915  fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
2916
2917  // implicit dep dirty, expect a rebuild.
2918  fs_.Create("blah.h", "");
2919  fs_.Create("bar.h", "");
2920  command_runner_.commands_ran_.clear();
2921  state_.Reset();
2922  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2923  EXPECT_TRUE(builder_.Build(&err));
2924  ASSERT_EQ("", err);
2925  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2926
2927  fs_.Tick();
2928
2929  // Recreate the depfile, as it should have been deleted by the build.
2930  fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
2931
2932  // order only dep dirty, no rebuild.
2933  fs_.Create("otherfile", "");
2934  command_runner_.commands_ran_.clear();
2935  state_.Reset();
2936  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2937  EXPECT_EQ("", err);
2938  EXPECT_TRUE(builder_.AlreadyUpToDate());
2939
2940  // implicit dep missing, expect rebuild.
2941  fs_.RemoveFile("bar.h");
2942  command_runner_.commands_ran_.clear();
2943  state_.Reset();
2944  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2945  EXPECT_TRUE(builder_.Build(&err));
2946  ASSERT_EQ("", err);
2947  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2948}
2949
2950TEST_F(BuildTest, RebuildOrderOnlyDeps) {
2951  string err;
2952  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
2953"rule cc\n  command = cc $in\n"
2954"rule true\n  command = true\n"
2955"build oo.h: cc oo.h.in\n"
2956"build foo.o: cc foo.c || oo.h\n"));
2957
2958  fs_.Create("foo.c", "");
2959  fs_.Create("oo.h.in", "");
2960
2961  // foo.o and order-only dep dirty, build both.
2962  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2963  EXPECT_TRUE(builder_.Build(&err));
2964  ASSERT_EQ("", err);
2965  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
2966
2967  // all clean, no rebuild.
2968  command_runner_.commands_ran_.clear();
2969  state_.Reset();
2970  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2971  EXPECT_EQ("", err);
2972  EXPECT_TRUE(builder_.AlreadyUpToDate());
2973
2974  // order-only dep missing, build it only.
2975  fs_.RemoveFile("oo.h");
2976  command_runner_.commands_ran_.clear();
2977  state_.Reset();
2978  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2979  EXPECT_TRUE(builder_.Build(&err));
2980  ASSERT_EQ("", err);
2981  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2982  ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
2983
2984  fs_.Tick();
2985
2986  // order-only dep dirty, build it only.
2987  fs_.Create("oo.h.in", "");
2988  command_runner_.commands_ran_.clear();
2989  state_.Reset();
2990  EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
2991  EXPECT_TRUE(builder_.Build(&err));
2992  ASSERT_EQ("", err);
2993  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2994  ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
2995}
2996
2997#ifdef _WIN32
2998TEST_F(BuildTest, DepFileCanonicalize) {
2999  string err;
3000  int orig_edges = state_.edges_.size();
3001  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3002"rule cc\n  command = cc $in\n  depfile = $out.d\n"
3003"build gen/stuff\\things/foo.o: cc x\\y/z\\foo.c\n"));
3004  Edge* edge = state_.edges_.back();
3005
3006  fs_.Create("x/y/z/foo.c", "");
3007  GetNode("bar.h")->MarkDirty();  // Mark bar.h as missing.
3008  // Note, different slashes from manifest.
3009  fs_.Create("gen/stuff\\things/foo.o.d",
3010             "gen\\stuff\\things\\foo.o: blah.h bar.h\n");
3011  EXPECT_TRUE(builder_.AddTarget("gen/stuff/things/foo.o", &err));
3012  ASSERT_EQ("", err);
3013  ASSERT_EQ(1u, fs_.files_read_.size());
3014  // The depfile path does not get Canonicalize as it seems unnecessary.
3015  EXPECT_EQ("gen/stuff\\things/foo.o.d", fs_.files_read_[0]);
3016
3017  // Expect three new edges: one generating foo.o, and two more from
3018  // loading the depfile.
3019  ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
3020  // Expect our edge to now have three inputs: foo.c and two headers.
3021  ASSERT_EQ(3u, edge->inputs_.size());
3022
3023  // Expect the command line we generate to only use the original input, and
3024  // using the slashes from the manifest.
3025  ASSERT_EQ("cc x\\y/z\\foo.c", edge->EvaluateCommand());
3026}
3027#endif
3028
3029TEST_F(BuildTest, Phony) {
3030  string err;
3031  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3032"build out: cat bar.cc\n"
3033"build all: phony out\n"));
3034  fs_.Create("bar.cc", "");
3035
3036  EXPECT_TRUE(builder_.AddTarget("all", &err));
3037  ASSERT_EQ("", err);
3038
3039  // Only one command to run, because phony runs no command.
3040  EXPECT_FALSE(builder_.AlreadyUpToDate());
3041  EXPECT_TRUE(builder_.Build(&err));
3042  ASSERT_EQ("", err);
3043  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3044}
3045
3046TEST_F(BuildTest, PhonyNoWork) {
3047  string err;
3048  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3049"build out: cat bar.cc\n"
3050"build all: phony out\n"));
3051  fs_.Create("bar.cc", "");
3052  fs_.Create("out", "");
3053
3054  EXPECT_TRUE(builder_.AddTarget("all", &err));
3055  ASSERT_EQ("", err);
3056  EXPECT_TRUE(builder_.AlreadyUpToDate());
3057}
3058
3059// Test a self-referencing phony.  Ideally this should not work, but
3060// ninja 1.7 and below tolerated and CMake 2.8.12.x and 3.0.x both
3061// incorrectly produce it.  We tolerate it for compatibility.
3062TEST_F(BuildTest, PhonySelfReference) {
3063  string err;
3064  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3065"build a: phony a\n"));
3066
3067  EXPECT_TRUE(builder_.AddTarget("a", &err));
3068  ASSERT_EQ("", err);
3069  EXPECT_TRUE(builder_.AlreadyUpToDate());
3070}
3071
3072TEST_F(BuildTest, Fail) {
3073  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3074"rule fail\n"
3075"  command = fail\n"
3076"build out1: fail\n"));
3077
3078  string err;
3079  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3080  ASSERT_EQ("", err);
3081
3082  EXPECT_FALSE(builder_.Build(&err));
3083  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3084  ASSERT_EQ("subcommand failed", err);
3085}
3086
3087TEST_F(BuildTest, SwallowFailures) {
3088  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3089"rule fail\n"
3090"  command = fail\n"
3091"build out1: fail\n"
3092"build out2: fail\n"
3093"build out3: fail\n"
3094"build all: phony out1 out2 out3\n"));
3095
3096  // Swallow two failures, die on the third.
3097  config_.failures_allowed = 3;
3098
3099  string err;
3100  EXPECT_TRUE(builder_.AddTarget("all", &err));
3101  ASSERT_EQ("", err);
3102
3103  EXPECT_FALSE(builder_.Build(&err));
3104  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3105  ASSERT_EQ("subcommands failed", err);
3106}
3107
3108TEST_F(BuildTest, SwallowFailuresLimit) {
3109  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3110"rule fail\n"
3111"  command = fail\n"
3112"build out1: fail\n"
3113"build out2: fail\n"
3114"build out3: fail\n"
3115"build final: cat out1 out2 out3\n"));
3116
3117  // Swallow ten failures; we should stop before building final.
3118  config_.failures_allowed = 11;
3119
3120  string err;
3121  EXPECT_TRUE(builder_.AddTarget("final", &err));
3122  ASSERT_EQ("", err);
3123
3124  EXPECT_FALSE(builder_.Build(&err));
3125  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3126  ASSERT_EQ("cannot make progress due to previous errors", err);
3127}
3128
3129TEST_F(BuildTest, SwallowFailuresPool) {
3130  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3131"pool failpool\n"
3132"  depth = 1\n"
3133"rule fail\n"
3134"  command = fail\n"
3135"  pool = failpool\n"
3136"build out1: fail\n"
3137"build out2: fail\n"
3138"build out3: fail\n"
3139"build final: cat out1 out2 out3\n"));
3140
3141  // Swallow ten failures; we should stop before building final.
3142  config_.failures_allowed = 11;
3143
3144  string err;
3145  EXPECT_TRUE(builder_.AddTarget("final", &err));
3146  ASSERT_EQ("", err);
3147
3148  EXPECT_FALSE(builder_.Build(&err));
3149  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3150  ASSERT_EQ("cannot make progress due to previous errors", err);
3151}
3152
3153TEST_F(BuildTest, PoolEdgesReadyButNotWanted) {
3154  fs_.Create("x", "");
3155
3156  const char* manifest =
3157    "pool some_pool\n"
3158    "  depth = 4\n"
3159    "rule touch\n"
3160    "  command = touch $out\n"
3161    "  pool = some_pool\n"
3162    "rule cc\n"
3163    "  command = touch grit\n"
3164    "\n"
3165    "build B.d.stamp: cc | x\n"
3166    "build C.stamp: touch B.d.stamp\n"
3167    "build final.stamp: touch || C.stamp\n";
3168
3169  RebuildTarget("final.stamp", manifest);
3170
3171  fs_.RemoveFile("B.d.stamp");
3172
3173  State save_state;
3174  RebuildTarget("final.stamp", manifest, NULL, NULL, &save_state);
3175  EXPECT_GE(save_state.LookupPool("some_pool")->current_use(), 0);
3176}
3177
3178struct BuildWithLogTest : public BuildTest {
3179  BuildWithLogTest() {
3180    builder_.SetBuildLog(&build_log_);
3181  }
3182
3183  BuildLog build_log_;
3184};
3185
3186TEST_F(BuildWithLogTest, NotInLogButOnDisk) {
3187  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3188"rule cc\n"
3189"  command = cc\n"
3190"build out1: cc in\n"));
3191
3192  // Create input/output that would be considered up to date when
3193  // not considering the command line hash.
3194  fs_.Create("in", "");
3195  fs_.Create("out1", "");
3196  string err;
3197
3198  // Because it's not in the log, it should not be up-to-date until
3199  // we build again.
3200  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3201  EXPECT_FALSE(builder_.AlreadyUpToDate());
3202
3203  command_runner_.commands_ran_.clear();
3204  state_.Reset();
3205
3206  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3207  EXPECT_TRUE(builder_.Build(&err));
3208  EXPECT_TRUE(builder_.AlreadyUpToDate());
3209}
3210
3211TEST_F(BuildWithLogTest, RebuildAfterFailure) {
3212  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3213"rule touch-fail-tick2\n"
3214"  command = touch-fail-tick2\n"
3215"build out1: touch-fail-tick2 in\n"));
3216
3217  string err;
3218
3219  fs_.Create("in", "");
3220
3221  // Run once successfully to get out1 in the log
3222  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3223  EXPECT_TRUE(builder_.Build(&err));
3224  EXPECT_EQ("", err);
3225  EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3226
3227  command_runner_.commands_ran_.clear();
3228  state_.Reset();
3229  builder_.Cleanup();
3230  builder_.plan_.Reset();
3231
3232  fs_.Tick();
3233  fs_.Create("in", "");
3234
3235  // Run again with a failure that updates the output file timestamp
3236  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3237  EXPECT_FALSE(builder_.Build(&err));
3238  EXPECT_EQ("subcommand failed", err);
3239  EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3240
3241  command_runner_.commands_ran_.clear();
3242  state_.Reset();
3243  builder_.Cleanup();
3244  builder_.plan_.Reset();
3245
3246  fs_.Tick();
3247
3248  // Run again, should rerun even though the output file is up to date on disk
3249  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3250  EXPECT_FALSE(builder_.AlreadyUpToDate());
3251  EXPECT_TRUE(builder_.Build(&err));
3252  EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3253  EXPECT_EQ("", err);
3254}
3255
3256TEST_F(BuildWithLogTest, RebuildWithNoInputs) {
3257  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3258"rule touch\n"
3259"  command = touch\n"
3260"build out1: touch\n"
3261"build out2: touch in\n"));
3262
3263  string err;
3264
3265  fs_.Create("in", "");
3266
3267  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3268  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3269  EXPECT_TRUE(builder_.Build(&err));
3270  EXPECT_EQ("", err);
3271  EXPECT_EQ(2u, command_runner_.commands_ran_.size());
3272
3273  command_runner_.commands_ran_.clear();
3274  state_.Reset();
3275
3276  fs_.Tick();
3277
3278  fs_.Create("in", "");
3279
3280  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3281  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3282  EXPECT_TRUE(builder_.Build(&err));
3283  EXPECT_EQ("", err);
3284  EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3285}
3286
3287TEST_F(BuildWithLogTest, RestatTest) {
3288  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3289"rule true\n"
3290"  command = true\n"
3291"  restat = 1\n"
3292"rule cc\n"
3293"  command = cc\n"
3294"  restat = 1\n"
3295"build out1: cc in\n"
3296"build out2: true out1\n"
3297"build out3: cat out2\n"));
3298
3299  fs_.Create("out1", "");
3300  fs_.Create("out2", "");
3301  fs_.Create("out3", "");
3302
3303  fs_.Tick();
3304
3305  fs_.Create("in", "");
3306
3307  // Do a pre-build so that there's commands in the log for the outputs,
3308  // otherwise, the lack of an entry in the build log will cause out3 to rebuild
3309  // regardless of restat.
3310  string err;
3311  EXPECT_TRUE(builder_.AddTarget("out3", &err));
3312  ASSERT_EQ("", err);
3313  EXPECT_TRUE(builder_.Build(&err));
3314  ASSERT_EQ("", err);
3315  EXPECT_EQ("[3/3]", builder_.status_->FormatProgressStatus("[%s/%t]",
3316      BuildStatus::kEdgeStarted));
3317  command_runner_.commands_ran_.clear();
3318  state_.Reset();
3319
3320  fs_.Tick();
3321
3322  fs_.Create("in", "");
3323  // "cc" touches out1, so we should build out2.  But because "true" does not
3324  // touch out2, we should cancel the build of out3.
3325  EXPECT_TRUE(builder_.AddTarget("out3", &err));
3326  ASSERT_EQ("", err);
3327  EXPECT_TRUE(builder_.Build(&err));
3328  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3329
3330  // If we run again, it should be a no-op, because the build log has recorded
3331  // that we've already built out2 with an input timestamp of 2 (from out1).
3332  command_runner_.commands_ran_.clear();
3333  state_.Reset();
3334  EXPECT_TRUE(builder_.AddTarget("out3", &err));
3335  ASSERT_EQ("", err);
3336  EXPECT_TRUE(builder_.AlreadyUpToDate());
3337
3338  fs_.Tick();
3339
3340  fs_.Create("in", "");
3341
3342  // The build log entry should not, however, prevent us from rebuilding out2
3343  // if out1 changes.
3344  command_runner_.commands_ran_.clear();
3345  state_.Reset();
3346  EXPECT_TRUE(builder_.AddTarget("out3", &err));
3347  ASSERT_EQ("", err);
3348  EXPECT_TRUE(builder_.Build(&err));
3349  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3350}
3351
3352TEST_F(BuildWithLogTest, RestatMissingFile) {
3353  // If a restat rule doesn't create its output, and the output didn't
3354  // exist before the rule was run, consider that behavior equivalent
3355  // to a rule that doesn't modify its existent output file.
3356
3357  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3358"rule true\n"
3359"  command = true\n"
3360"  restat = 1\n"
3361"rule cc\n"
3362"  command = cc\n"
3363"build out1: true in\n"
3364"build out2: cc out1\n"));
3365
3366  fs_.Create("in", "");
3367  fs_.Create("out2", "");
3368
3369  // Do a pre-build so that there's commands in the log for the outputs,
3370  // otherwise, the lack of an entry in the build log will cause out2 to rebuild
3371  // regardless of restat.
3372  string err;
3373  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3374  ASSERT_EQ("", err);
3375  EXPECT_TRUE(builder_.Build(&err));
3376  ASSERT_EQ("", err);
3377  command_runner_.commands_ran_.clear();
3378  state_.Reset();
3379
3380  fs_.Tick();
3381  fs_.Create("in", "");
3382  fs_.Create("out2", "");
3383
3384  // Run a build, expect only the first command to run.
3385  // It doesn't touch its output (due to being the "true" command), so
3386  // we shouldn't run the dependent build.
3387  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3388  ASSERT_EQ("", err);
3389  EXPECT_TRUE(builder_.Build(&err));
3390  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3391}
3392
3393TEST_F(BuildWithLogTest, RestatSingleDependentOutputDirty) {
3394  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3395    "rule true\n"
3396    "  command = true\n"
3397    "  restat = 1\n"
3398    "rule touch\n"
3399    "  command = touch\n"
3400    "build out1: true in\n"
3401    "build out2 out3: touch out1\n"
3402    "build out4: touch out2\n"
3403    ));
3404
3405  // Create the necessary files
3406  fs_.Create("in", "");
3407
3408  string err;
3409  EXPECT_TRUE(builder_.AddTarget("out4", &err));
3410  ASSERT_EQ("", err);
3411  EXPECT_TRUE(builder_.Build(&err));
3412  ASSERT_EQ("", err);
3413  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3414
3415  fs_.Tick();
3416  fs_.Create("in", "");
3417  fs_.RemoveFile("out3");
3418
3419  // Since "in" is missing, out1 will be built. Since "out3" is missing,
3420  // out2 and out3 will be built even though "in" is not touched when built.
3421  // Then, since out2 is rebuilt, out4 should be rebuilt -- the restat on the
3422  // "true" rule should not lead to the "touch" edge writing out2 and out3 being
3423  // cleard.
3424  command_runner_.commands_ran_.clear();
3425  state_.Reset();
3426  EXPECT_TRUE(builder_.AddTarget("out4", &err));
3427  ASSERT_EQ("", err);
3428  EXPECT_TRUE(builder_.Build(&err));
3429  ASSERT_EQ("", err);
3430  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3431}
3432
3433// Test scenario, in which an input file is removed, but output isn't changed
3434// https://github.com/ninja-build/ninja/issues/295
3435TEST_F(BuildWithLogTest, RestatMissingInput) {
3436  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3437    "rule true\n"
3438    "  command = true\n"
3439    "  depfile = $out.d\n"
3440    "  restat = 1\n"
3441    "rule cc\n"
3442    "  command = cc\n"
3443    "build out1: true in\n"
3444    "build out2: cc out1\n"));
3445
3446  // Create all necessary files
3447  fs_.Create("in", "");
3448
3449  // The implicit dependencies and the depfile itself
3450  // are newer than the output
3451  TimeStamp restat_mtime = fs_.Tick();
3452  fs_.Create("out1.d", "out1: will.be.deleted restat.file\n");
3453  fs_.Create("will.be.deleted", "");
3454  fs_.Create("restat.file", "");
3455
3456  // Run the build, out1 and out2 get built
3457  string err;
3458  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3459  ASSERT_EQ("", err);
3460  EXPECT_TRUE(builder_.Build(&err));
3461  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3462
3463  // See that an entry in the logfile is created, capturing
3464  // the right mtime
3465  BuildLog::LogEntry* log_entry = build_log_.LookupByOutput("out1");
3466  ASSERT_TRUE(NULL != log_entry);
3467  ASSERT_EQ(restat_mtime, log_entry->mtime);
3468
3469  // Now remove a file, referenced from depfile, so that target becomes
3470  // dirty, but the output does not change
3471  fs_.RemoveFile("will.be.deleted");
3472
3473  // Trigger the build again - only out1 gets built
3474  command_runner_.commands_ran_.clear();
3475  state_.Reset();
3476  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3477  ASSERT_EQ("", err);
3478  EXPECT_TRUE(builder_.Build(&err));
3479  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3480
3481  // Check that the logfile entry remains correctly set
3482  log_entry = build_log_.LookupByOutput("out1");
3483  ASSERT_TRUE(NULL != log_entry);
3484  ASSERT_EQ(restat_mtime, log_entry->mtime);
3485}
3486
3487struct BuildDryRun : public BuildWithLogTest {
3488  BuildDryRun() {
3489    config_.dry_run = true;
3490  }
3491};
3492
3493TEST_F(BuildDryRun, AllCommandsShown) {
3494  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3495"rule true\n"
3496"  command = true\n"
3497"  restat = 1\n"
3498"rule cc\n"
3499"  command = cc\n"
3500"  restat = 1\n"
3501"build out1: cc in\n"
3502"build out2: true out1\n"
3503"build out3: cat out2\n"));
3504
3505  fs_.Create("out1", "");
3506  fs_.Create("out2", "");
3507  fs_.Create("out3", "");
3508
3509  fs_.Tick();
3510
3511  fs_.Create("in", "");
3512
3513  // "cc" touches out1, so we should build out2.  But because "true" does not
3514  // touch out2, we should cancel the build of out3.
3515  string err;
3516  EXPECT_TRUE(builder_.AddTarget("out3", &err));
3517  ASSERT_EQ("", err);
3518  EXPECT_TRUE(builder_.Build(&err));
3519  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3520}
3521
3522// Test that RSP files are created when & where appropriate and deleted after
3523// successful execution.
3524TEST_F(BuildTest, RspFileSuccess)
3525{
3526  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3527    "rule cat_rsp\n"
3528    "  command = cat $rspfile > $out\n"
3529    "  rspfile = $rspfile\n"
3530    "  rspfile_content = $long_command\n"
3531    "rule cat_rsp_out\n"
3532    "  command = cat $rspfile > $out\n"
3533    "  rspfile = $out.rsp\n"
3534    "  rspfile_content = $long_command\n"
3535    "build out1: cat in\n"
3536    "build out2: cat_rsp in\n"
3537    "  rspfile = out 2.rsp\n"
3538    "  long_command = Some very long command\n"
3539    "build out$ 3: cat_rsp_out in\n"
3540    "  long_command = Some very long command\n"));
3541
3542  fs_.Create("out1", "");
3543  fs_.Create("out2", "");
3544  fs_.Create("out 3", "");
3545
3546  fs_.Tick();
3547
3548  fs_.Create("in", "");
3549
3550  string err;
3551  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3552  ASSERT_EQ("", err);
3553  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3554  ASSERT_EQ("", err);
3555  EXPECT_TRUE(builder_.AddTarget("out 3", &err));
3556  ASSERT_EQ("", err);
3557
3558  size_t files_created = fs_.files_created_.size();
3559  size_t files_removed = fs_.files_removed_.size();
3560
3561  EXPECT_TRUE(builder_.Build(&err));
3562  ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3563
3564  // The RSP files were created
3565  ASSERT_EQ(files_created + 2, fs_.files_created_.size());
3566  ASSERT_EQ(1u, fs_.files_created_.count("out 2.rsp"));
3567  ASSERT_EQ(1u, fs_.files_created_.count("out 3.rsp"));
3568
3569  // The RSP files were removed
3570  ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
3571  ASSERT_EQ(1u, fs_.files_removed_.count("out 2.rsp"));
3572  ASSERT_EQ(1u, fs_.files_removed_.count("out 3.rsp"));
3573}
3574
3575// Test that RSP file is created but not removed for commands, which fail
3576TEST_F(BuildTest, RspFileFailure) {
3577  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3578    "rule fail\n"
3579    "  command = fail\n"
3580    "  rspfile = $rspfile\n"
3581    "  rspfile_content = $long_command\n"
3582    "build out: fail in\n"
3583    "  rspfile = out.rsp\n"
3584    "  long_command = Another very long command\n"));
3585
3586  fs_.Create("out", "");
3587  fs_.Tick();
3588  fs_.Create("in", "");
3589
3590  string err;
3591  EXPECT_TRUE(builder_.AddTarget("out", &err));
3592  ASSERT_EQ("", err);
3593
3594  size_t files_created = fs_.files_created_.size();
3595  size_t files_removed = fs_.files_removed_.size();
3596
3597  EXPECT_FALSE(builder_.Build(&err));
3598  ASSERT_EQ("subcommand failed", err);
3599  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3600
3601  // The RSP file was created
3602  ASSERT_EQ(files_created + 1, fs_.files_created_.size());
3603  ASSERT_EQ(1u, fs_.files_created_.count("out.rsp"));
3604
3605  // The RSP file was NOT removed
3606  ASSERT_EQ(files_removed, fs_.files_removed_.size());
3607  ASSERT_EQ(0u, fs_.files_removed_.count("out.rsp"));
3608
3609  // The RSP file contains what it should
3610  ASSERT_EQ("Another very long command", fs_.files_["out.rsp"].contents);
3611}
3612
3613// Test that contents of the RSP file behaves like a regular part of
3614// command line, i.e. triggers a rebuild if changed
3615TEST_F(BuildWithLogTest, RspFileCmdLineChange) {
3616  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3617    "rule cat_rsp\n"
3618    "  command = cat $rspfile > $out\n"
3619    "  rspfile = $rspfile\n"
3620    "  rspfile_content = $long_command\n"
3621    "build out: cat_rsp in\n"
3622    "  rspfile = out.rsp\n"
3623    "  long_command = Original very long command\n"));
3624
3625  fs_.Create("out", "");
3626  fs_.Tick();
3627  fs_.Create("in", "");
3628
3629  string err;
3630  EXPECT_TRUE(builder_.AddTarget("out", &err));
3631  ASSERT_EQ("", err);
3632
3633  // 1. Build for the 1st time (-> populate log)
3634  EXPECT_TRUE(builder_.Build(&err));
3635  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3636
3637  // 2. Build again (no change)
3638  command_runner_.commands_ran_.clear();
3639  state_.Reset();
3640  EXPECT_TRUE(builder_.AddTarget("out", &err));
3641  EXPECT_EQ("", err);
3642  ASSERT_TRUE(builder_.AlreadyUpToDate());
3643
3644  // 3. Alter the entry in the logfile
3645  // (to simulate a change in the command line between 2 builds)
3646  BuildLog::LogEntry* log_entry = build_log_.LookupByOutput("out");
3647  ASSERT_TRUE(NULL != log_entry);
3648  ASSERT_NO_FATAL_FAILURE(AssertHash(
3649        "cat out.rsp > out;rspfile=Original very long command",
3650        log_entry->command_hash));
3651  log_entry->command_hash++;  // Change the command hash to something else.
3652  // Now expect the target to be rebuilt
3653  command_runner_.commands_ran_.clear();
3654  state_.Reset();
3655  EXPECT_TRUE(builder_.AddTarget("out", &err));
3656  EXPECT_EQ("", err);
3657  EXPECT_TRUE(builder_.Build(&err));
3658  EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3659}
3660
3661TEST_F(BuildTest, InterruptCleanup) {
3662  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3663"rule interrupt\n"
3664"  command = interrupt\n"
3665"rule touch-interrupt\n"
3666"  command = touch-interrupt\n"
3667"build out1: interrupt in1\n"
3668"build out2: touch-interrupt in2\n"));
3669
3670  fs_.Create("out1", "");
3671  fs_.Create("out2", "");
3672  fs_.Tick();
3673  fs_.Create("in1", "");
3674  fs_.Create("in2", "");
3675
3676  // An untouched output of an interrupted command should be retained.
3677  string err;
3678  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3679  EXPECT_EQ("", err);
3680  EXPECT_FALSE(builder_.Build(&err));
3681  EXPECT_EQ("interrupted by user", err);
3682  builder_.Cleanup();
3683  EXPECT_GT(fs_.Stat("out1", &err), 0);
3684  err = "";
3685
3686  // A touched output of an interrupted command should be deleted.
3687  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3688  EXPECT_EQ("", err);
3689  EXPECT_FALSE(builder_.Build(&err));
3690  EXPECT_EQ("interrupted by user", err);
3691  builder_.Cleanup();
3692  EXPECT_EQ(0, fs_.Stat("out2", &err));
3693}
3694
3695TEST_F(BuildTest, StatFailureAbortsBuild) {
3696  const string kTooLongToStat(400, 'i');
3697  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3698("build " + kTooLongToStat + ": cat in\n").c_str()));
3699  fs_.Create("in", "");
3700
3701  // This simulates a stat failure:
3702  fs_.files_[kTooLongToStat].mtime = -1;
3703  fs_.files_[kTooLongToStat].stat_error = "stat failed";
3704
3705  string err;
3706  EXPECT_FALSE(builder_.AddTarget(kTooLongToStat, &err));
3707  EXPECT_EQ("stat failed", err);
3708}
3709
3710TEST_F(BuildTest, PhonyWithNoInputs) {
3711  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3712"build nonexistent: phony\n"
3713"build out1: cat || nonexistent\n"
3714"build out2: cat nonexistent\n"));
3715  fs_.Create("out1", "");
3716  fs_.Create("out2", "");
3717
3718  // out1 should be up to date even though its input is dirty, because its
3719  // order-only dependency has nothing to do.
3720  string err;
3721  EXPECT_TRUE(builder_.AddTarget("out1", &err));
3722  ASSERT_EQ("", err);
3723  EXPECT_TRUE(builder_.AlreadyUpToDate());
3724
3725  // out2 should still be out of date though, because its input is dirty.
3726  err.clear();
3727  command_runner_.commands_ran_.clear();
3728  state_.Reset();
3729  EXPECT_TRUE(builder_.AddTarget("out2", &err));
3730  ASSERT_EQ("", err);
3731  EXPECT_TRUE(builder_.Build(&err));
3732  EXPECT_EQ("", err);
3733  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3734}
3735
3736TEST_F(BuildTest, DepsGccWithEmptyDepfileErrorsOut) {
3737  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3738"rule cc\n"
3739"  command = cc\n"
3740"  deps = gcc\n"
3741"build out: cc\n"));
3742  Dirty("out");
3743
3744  string err;
3745  EXPECT_TRUE(builder_.AddTarget("out", &err));
3746  ASSERT_EQ("", err);
3747  EXPECT_FALSE(builder_.AlreadyUpToDate());
3748
3749  EXPECT_FALSE(builder_.Build(&err));
3750  ASSERT_EQ("subcommand failed", err);
3751  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3752}
3753
3754TEST_F(BuildTest, StatusFormatElapsed) {
3755  status_.BuildStarted();
3756  // Before any task is done, the elapsed time must be zero.
3757  EXPECT_EQ("[%/e0.000]",
3758            status_.FormatProgressStatus("[%%/e%e]",
3759                BuildStatus::kEdgeStarted));
3760}
3761
3762TEST_F(BuildTest, StatusFormatReplacePlaceholder) {
3763  EXPECT_EQ("[%/s0/t0/r0/u0/f0]",
3764            status_.FormatProgressStatus("[%%/s%s/t%t/r%r/u%u/f%f]",
3765                BuildStatus::kEdgeStarted));
3766}
3767
3768TEST_F(BuildTest, FailedDepsParse) {
3769  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3770"build bad_deps.o: cat in1\n"
3771"  deps = gcc\n"
3772"  depfile = in1.d\n"));
3773
3774  string err;
3775  EXPECT_TRUE(builder_.AddTarget("bad_deps.o", &err));
3776  ASSERT_EQ("", err);
3777
3778  // These deps will fail to parse, as they should only have one
3779  // path to the left of the colon.
3780  fs_.Create("in1.d", "AAA BBB");
3781
3782  EXPECT_FALSE(builder_.Build(&err));
3783  EXPECT_EQ("subcommand failed", err);
3784}
3785
3786/// Tests of builds involving deps logs necessarily must span
3787/// multiple builds.  We reuse methods on BuildTest but not the
3788/// builder_ it sets up, because we want pristine objects for
3789/// each build.
3790struct BuildWithDepsLogTest : public BuildTest {
3791  BuildWithDepsLogTest() {}
3792
3793  virtual void SetUp() {
3794    BuildTest::SetUp();
3795
3796    temp_dir_.CreateAndEnter("BuildWithDepsLogTest");
3797  }
3798
3799  virtual void TearDown() {
3800    temp_dir_.Cleanup();
3801  }
3802
3803  ScopedTempDir temp_dir_;
3804
3805  /// Shadow parent class builder_ so we don't accidentally use it.
3806  void* builder_;
3807};
3808
3809/// Run a straightforwad build where the deps log is used.
3810TEST_F(BuildWithDepsLogTest, Straightforward) {
3811  string err;
3812  // Note: in1 was created by the superclass SetUp().
3813  const char* manifest =
3814      "build out: cat in1\n"
3815      "  deps = gcc\n"
3816      "  depfile = in1.d\n";
3817  {
3818    State state;
3819    ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3820    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3821
3822    // Run the build once, everything should be ok.
3823    DepsLog deps_log;
3824    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
3825    ASSERT_EQ("", err);
3826
3827    Builder builder(&state, config_, NULL, &deps_log, &fs_);
3828    builder.command_runner_.reset(&command_runner_);
3829    EXPECT_TRUE(builder.AddTarget("out", &err));
3830    ASSERT_EQ("", err);
3831    fs_.Create("in1.d", "out: in2");
3832    EXPECT_TRUE(builder.Build(&err));
3833    EXPECT_EQ("", err);
3834
3835    // The deps file should have been removed.
3836    EXPECT_EQ(0, fs_.Stat("in1.d", &err));
3837    // Recreate it for the next step.
3838    fs_.Create("in1.d", "out: in2");
3839    deps_log.Close();
3840    builder.command_runner_.release();
3841  }
3842
3843  {
3844    State state;
3845    ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3846    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3847
3848    // Touch the file only mentioned in the deps.
3849    fs_.Tick();
3850    fs_.Create("in2", "");
3851
3852    // Run the build again.
3853    DepsLog deps_log;
3854    ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
3855    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
3856
3857    Builder builder(&state, config_, NULL, &deps_log, &fs_);
3858    builder.command_runner_.reset(&command_runner_);
3859    command_runner_.commands_ran_.clear();
3860    EXPECT_TRUE(builder.AddTarget("out", &err));
3861    ASSERT_EQ("", err);
3862    EXPECT_TRUE(builder.Build(&err));
3863    EXPECT_EQ("", err);
3864
3865    // We should have rebuilt the output due to in2 being
3866    // out of date.
3867    EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3868
3869    builder.command_runner_.release();
3870  }
3871}
3872
3873/// Verify that obsolete dependency info causes a rebuild.
3874/// 1) Run a successful build where everything has time t, record deps.
3875/// 2) Move input/output to time t+1 -- despite files in alignment,
3876///    should still need to rebuild due to deps at older time.
3877TEST_F(BuildWithDepsLogTest, ObsoleteDeps) {
3878  string err;
3879  // Note: in1 was created by the superclass SetUp().
3880  const char* manifest =
3881      "build out: cat in1\n"
3882      "  deps = gcc\n"
3883      "  depfile = in1.d\n";
3884  {
3885    // Run an ordinary build that gathers dependencies.
3886    fs_.Create("in1", "");
3887    fs_.Create("in1.d", "out: ");
3888
3889    State state;
3890    ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3891    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3892
3893    // Run the build once, everything should be ok.
3894    DepsLog deps_log;
3895    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
3896    ASSERT_EQ("", err);
3897
3898    Builder builder(&state, config_, NULL, &deps_log, &fs_);
3899    builder.command_runner_.reset(&command_runner_);
3900    EXPECT_TRUE(builder.AddTarget("out", &err));
3901    ASSERT_EQ("", err);
3902    EXPECT_TRUE(builder.Build(&err));
3903    EXPECT_EQ("", err);
3904
3905    deps_log.Close();
3906    builder.command_runner_.release();
3907  }
3908
3909  // Push all files one tick forward so that only the deps are out
3910  // of date.
3911  fs_.Tick();
3912  fs_.Create("in1", "");
3913  fs_.Create("out", "");
3914
3915  // The deps file should have been removed, so no need to timestamp it.
3916  EXPECT_EQ(0, fs_.Stat("in1.d", &err));
3917
3918  {
3919    State state;
3920    ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3921    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3922
3923    DepsLog deps_log;
3924    ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
3925    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
3926
3927    Builder builder(&state, config_, NULL, &deps_log, &fs_);
3928    builder.command_runner_.reset(&command_runner_);
3929    command_runner_.commands_ran_.clear();
3930    EXPECT_TRUE(builder.AddTarget("out", &err));
3931    ASSERT_EQ("", err);
3932
3933    // Recreate the deps file here because the build expects them to exist.
3934    fs_.Create("in1.d", "out: ");
3935
3936    EXPECT_TRUE(builder.Build(&err));
3937    EXPECT_EQ("", err);
3938
3939    // We should have rebuilt the output due to the deps being
3940    // out of date.
3941    EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3942
3943    builder.command_runner_.release();
3944  }
3945}
3946
3947TEST_F(BuildWithDepsLogTest, DepsIgnoredInDryRun) {
3948  const char* manifest =
3949      "build out: cat in1\n"
3950      "  deps = gcc\n"
3951      "  depfile = in1.d\n";
3952
3953  fs_.Create("out", "");
3954  fs_.Tick();
3955  fs_.Create("in1", "");
3956
3957  State state;
3958  ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
3959  ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
3960
3961  // The deps log is NULL in dry runs.
3962  config_.dry_run = true;
3963  Builder builder(&state, config_, NULL, NULL, &fs_);
3964  builder.command_runner_.reset(&command_runner_);
3965  command_runner_.commands_ran_.clear();
3966
3967  string err;
3968  EXPECT_TRUE(builder.AddTarget("out", &err));
3969  ASSERT_EQ("", err);
3970  EXPECT_TRUE(builder.Build(&err));
3971  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3972
3973  builder.command_runner_.release();
3974}
3975
3976/// Check that a restat rule generating a header cancels compilations correctly.
3977TEST_F(BuildTest, RestatDepfileDependency) {
3978  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
3979"rule true\n"
3980"  command = true\n"  // Would be "write if out-of-date" in reality.
3981"  restat = 1\n"
3982"build header.h: true header.in\n"
3983"build out: cat in1\n"
3984"  depfile = in1.d\n"));
3985
3986  fs_.Create("header.h", "");
3987  fs_.Create("in1.d", "out: header.h");
3988  fs_.Tick();
3989  fs_.Create("header.in", "");
3990
3991  string err;
3992  EXPECT_TRUE(builder_.AddTarget("out", &err));
3993  ASSERT_EQ("", err);
3994  EXPECT_TRUE(builder_.Build(&err));
3995  EXPECT_EQ("", err);
3996}
3997
3998/// Check that a restat rule generating a header cancels compilations correctly,
3999/// depslog case.
4000TEST_F(BuildWithDepsLogTest, RestatDepfileDependencyDepsLog) {
4001  string err;
4002  // Note: in1 was created by the superclass SetUp().
4003  const char* manifest =
4004      "rule true\n"
4005      "  command = true\n"  // Would be "write if out-of-date" in reality.
4006      "  restat = 1\n"
4007      "build header.h: true header.in\n"
4008      "build out: cat in1\n"
4009      "  deps = gcc\n"
4010      "  depfile = in1.d\n";
4011  {
4012    State state;
4013    ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
4014    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
4015
4016    // Run the build once, everything should be ok.
4017    DepsLog deps_log;
4018    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
4019    ASSERT_EQ("", err);
4020
4021    Builder builder(&state, config_, NULL, &deps_log, &fs_);
4022    builder.command_runner_.reset(&command_runner_);
4023    EXPECT_TRUE(builder.AddTarget("out", &err));
4024    ASSERT_EQ("", err);
4025    fs_.Create("in1.d", "out: header.h");
4026    EXPECT_TRUE(builder.Build(&err));
4027    EXPECT_EQ("", err);
4028
4029    deps_log.Close();
4030    builder.command_runner_.release();
4031  }
4032
4033  {
4034    State state;
4035    ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
4036    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
4037
4038    // Touch the input of the restat rule.
4039    fs_.Tick();
4040    fs_.Create("header.in", "");
4041
4042    // Run the build again.
4043    DepsLog deps_log;
4044    ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
4045    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
4046
4047    Builder builder(&state, config_, NULL, &deps_log, &fs_);
4048    builder.command_runner_.reset(&command_runner_);
4049    command_runner_.commands_ran_.clear();
4050    EXPECT_TRUE(builder.AddTarget("out", &err));
4051    ASSERT_EQ("", err);
4052    EXPECT_TRUE(builder.Build(&err));
4053    EXPECT_EQ("", err);
4054
4055    // Rule "true" should have run again, but the build of "out" should have
4056    // been cancelled due to restat propagating through the depfile header.
4057    EXPECT_EQ(1u, command_runner_.commands_ran_.size());
4058
4059    builder.command_runner_.release();
4060  }
4061}
4062
4063TEST_F(BuildWithDepsLogTest, DepFileOKDepsLog) {
4064  string err;
4065  const char* manifest =
4066      "rule cc\n  command = cc $in\n  depfile = $out.d\n  deps = gcc\n"
4067      "build fo$ o.o: cc foo.c\n";
4068
4069  fs_.Create("foo.c", "");
4070
4071  {
4072    State state;
4073    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
4074
4075    // Run the build once, everything should be ok.
4076    DepsLog deps_log;
4077    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
4078    ASSERT_EQ("", err);
4079
4080    Builder builder(&state, config_, NULL, &deps_log, &fs_);
4081    builder.command_runner_.reset(&command_runner_);
4082    EXPECT_TRUE(builder.AddTarget("fo o.o", &err));
4083    ASSERT_EQ("", err);
4084    fs_.Create("fo o.o.d", "fo\\ o.o: blah.h bar.h\n");
4085    EXPECT_TRUE(builder.Build(&err));
4086    EXPECT_EQ("", err);
4087
4088    deps_log.Close();
4089    builder.command_runner_.release();
4090  }
4091
4092  {
4093    State state;
4094    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
4095
4096    DepsLog deps_log;
4097    ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
4098    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
4099    ASSERT_EQ("", err);
4100
4101    Builder builder(&state, config_, NULL, &deps_log, &fs_);
4102    builder.command_runner_.reset(&command_runner_);
4103
4104    Edge* edge = state.edges_.back();
4105
4106    state.GetNode("bar.h", 0)->MarkDirty();  // Mark bar.h as missing.
4107    EXPECT_TRUE(builder.AddTarget("fo o.o", &err));
4108    ASSERT_EQ("", err);
4109
4110    // Expect three new edges: one generating fo o.o, and two more from
4111    // loading the depfile.
4112    ASSERT_EQ(3u, state.edges_.size());
4113    // Expect our edge to now have three inputs: foo.c and two headers.
4114    ASSERT_EQ(3u, edge->inputs_.size());
4115
4116    // Expect the command line we generate to only use the original input.
4117    ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
4118
4119    deps_log.Close();
4120    builder.command_runner_.release();
4121  }
4122}
4123
4124#ifdef _WIN32
4125TEST_F(BuildWithDepsLogTest, DepFileDepsLogCanonicalize) {
4126  string err;
4127  const char* manifest =
4128      "rule cc\n  command = cc $in\n  depfile = $out.d\n  deps = gcc\n"
4129      "build a/b\\c\\d/e/fo$ o.o: cc x\\y/z\\foo.c\n";
4130
4131  fs_.Create("x/y/z/foo.c", "");
4132
4133  {
4134    State state;
4135    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
4136
4137    // Run the build once, everything should be ok.
4138    DepsLog deps_log;
4139    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
4140    ASSERT_EQ("", err);
4141
4142    Builder builder(&state, config_, NULL, &deps_log, &fs_);
4143    builder.command_runner_.reset(&command_runner_);
4144    EXPECT_TRUE(builder.AddTarget("a/b/c/d/e/fo o.o", &err));
4145    ASSERT_EQ("", err);
4146    // Note, different slashes from manifest.
4147    fs_.Create("a/b\\c\\d/e/fo o.o.d",
4148               "a\\b\\c\\d\\e\\fo\\ o.o: blah.h bar.h\n");
4149    EXPECT_TRUE(builder.Build(&err));
4150    EXPECT_EQ("", err);
4151
4152    deps_log.Close();
4153    builder.command_runner_.release();
4154  }
4155
4156  {
4157    State state;
4158    ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest));
4159
4160    DepsLog deps_log;
4161    ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err));
4162    ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err));
4163    ASSERT_EQ("", err);
4164
4165    Builder builder(&state, config_, NULL, &deps_log, &fs_);
4166    builder.command_runner_.reset(&command_runner_);
4167
4168    Edge* edge = state.edges_.back();
4169
4170    state.GetNode("bar.h", 0)->MarkDirty();  // Mark bar.h as missing.
4171    EXPECT_TRUE(builder.AddTarget("a/b/c/d/e/fo o.o", &err));
4172    ASSERT_EQ("", err);
4173
4174    // Expect three new edges: one generating fo o.o, and two more from
4175    // loading the depfile.
4176    ASSERT_EQ(3u, state.edges_.size());
4177    // Expect our edge to now have three inputs: foo.c and two headers.
4178    ASSERT_EQ(3u, edge->inputs_.size());
4179
4180    // Expect the command line we generate to only use the original input.
4181    // Note, slashes from manifest, not .d.
4182    ASSERT_EQ("cc x\\y/z\\foo.c", edge->EvaluateCommand());
4183
4184    deps_log.Close();
4185    builder.command_runner_.release();
4186  }
4187}
4188#endif
4189
4190/// Check that a restat rule doesn't clear an edge if the depfile is missing.
4191/// Follows from: https://github.com/ninja-build/ninja/issues/603
4192TEST_F(BuildTest, RestatMissingDepfile) {
4193const char* manifest =
4194"rule true\n"
4195"  command = true\n"  // Would be "write if out-of-date" in reality.
4196"  restat = 1\n"
4197"build header.h: true header.in\n"
4198"build out: cat header.h\n"
4199"  depfile = out.d\n";
4200
4201  fs_.Create("header.h", "");
4202  fs_.Tick();
4203  fs_.Create("out", "");
4204  fs_.Create("header.in", "");
4205
4206  // Normally, only 'header.h' would be rebuilt, as
4207  // its rule doesn't touch the output and has 'restat=1' set.
4208  // But we are also missing the depfile for 'out',
4209  // which should force its command to run anyway!
4210  RebuildTarget("out", manifest);
4211  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
4212}
4213
4214/// Check that a restat rule doesn't clear an edge if the deps are missing.
4215/// https://github.com/ninja-build/ninja/issues/603
4216TEST_F(BuildWithDepsLogTest, RestatMissingDepfileDepslog) {
4217  string err;
4218  const char* manifest =
4219"rule true\n"
4220"  command = true\n"  // Would be "write if out-of-date" in reality.
4221"  restat = 1\n"
4222"build header.h: true header.in\n"
4223"build out: cat header.h\n"
4224"  deps = gcc\n"
4225"  depfile = out.d\n";
4226
4227  // Build once to populate ninja deps logs from out.d
4228  fs_.Create("header.in", "");
4229  fs_.Create("out.d", "out: header.h");
4230  fs_.Create("header.h", "");
4231
4232  RebuildTarget("out", manifest, "build_log", "ninja_deps");
4233  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
4234
4235  // Sanity: this rebuild should be NOOP
4236  RebuildTarget("out", manifest, "build_log", "ninja_deps");
4237  ASSERT_EQ(0u, command_runner_.commands_ran_.size());
4238
4239  // Touch 'header.in', blank dependencies log (create a different one).
4240  // Building header.h triggers 'restat' outputs cleanup.
4241  // Validate that out is rebuilt netherless, as deps are missing.
4242  fs_.Tick();
4243  fs_.Create("header.in", "");
4244
4245  // (switch to a new blank deps_log "ninja_deps2")
4246  RebuildTarget("out", manifest, "build_log", "ninja_deps2");
4247  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
4248
4249  // Sanity: this build should be NOOP
4250  RebuildTarget("out", manifest, "build_log", "ninja_deps2");
4251  ASSERT_EQ(0u, command_runner_.commands_ran_.size());
4252
4253  // Check that invalidating deps by target timestamp also works here
4254  // Repeat the test but touch target instead of blanking the log.
4255  fs_.Tick();
4256  fs_.Create("header.in", "");
4257  fs_.Create("out", "");
4258  RebuildTarget("out", manifest, "build_log", "ninja_deps2");
4259  ASSERT_EQ(2u, command_runner_.commands_ran_.size());
4260
4261  // And this build should be NOOP again
4262  RebuildTarget("out", manifest, "build_log", "ninja_deps2");
4263  ASSERT_EQ(0u, command_runner_.commands_ran_.size());
4264}
4265
4266TEST_F(BuildTest, WrongOutputInDepfileCausesRebuild) {
4267  string err;
4268  const char* manifest =
4269"rule cc\n"
4270"  command = cc $in\n"
4271"  depfile = $out.d\n"
4272"build foo.o: cc foo.c\n";
4273
4274  fs_.Create("foo.c", "");
4275  fs_.Create("foo.o", "");
4276  fs_.Create("header.h", "");
4277  fs_.Create("foo.o.d", "bar.o.d: header.h\n");
4278
4279  RebuildTarget("foo.o", manifest, "build_log", "ninja_deps");
4280  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4281}
4282
4283TEST_F(BuildTest, Console) {
4284  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
4285"rule console\n"
4286"  command = console\n"
4287"  pool = console\n"
4288"build cons: console in.txt\n"));
4289
4290  fs_.Create("in.txt", "");
4291
4292  string err;
4293  EXPECT_TRUE(builder_.AddTarget("cons", &err));
4294  ASSERT_EQ("", err);
4295  EXPECT_TRUE(builder_.Build(&err));
4296  EXPECT_EQ("", err);
4297  ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4298}
4299
4300*/
4301
4302
4303}