struct State;
-// Run in "browse" mode, which execs a Python webserver.
-// |command| is the command used to invoke ninja.
-// This function does not return if it runs successfully.
+/// Run in "browse" mode, which execs a Python webserver.
+/// |command| is the command used to invoke ninja.
+/// This function does not return if it runs successfully.
void RunBrowsePython(State* state, const char* ninja_command);
#endif // NINJA_BROWSE_H_
#include "ninja.h"
#include "subprocess.h"
+/// Tracks the status of a build: completion fraction, printing updates.
struct BuildStatus {
BuildStatus();
void PlanHasTotalEdges(int total);
void BuildEdgeStarted(Edge* edge);
- // Returns the time the edge took, in ms.
+ /// Returns the time the edge took, in ms.
int BuildEdgeFinished(Edge* edge);
void PrintStatus(Edge* edge);
RunningEdgeMap running_edges_;
BuildConfig::Verbosity verbosity_;
- // Whether we can do fancy terminal control codes.
+ /// Whether we can do fancy terminal control codes.
bool smart_terminal_;
};
return edge;
}
+/// A CommandRunner that doesn't actually run the commands.
struct DryRunCommandRunner : public CommandRunner {
virtual ~DryRunCommandRunner() {}
virtual bool CanRunMore() {
struct Node;
struct State;
-// Plan stores the state of a build plan: what we intend to build,
-// which steps we're ready to execute.
+/// Plan stores the state of a build plan: what we intend to build,
+/// which steps we're ready to execute.
struct Plan {
Plan();
- // Add a target to our plan (including all its dependencies).
- // Returns false if we don't need to build this target; may
- // fill in |err| with an error message if there's a problem.
+ /// Add a target to our plan (including all its dependencies).
+ /// Returns false if we don't need to build this target; may
+ /// fill in |err| with an error message if there's a problem.
bool AddTarget(Node* node, string* err);
// Pop a ready edge off the queue of edges to build.
// Returns NULL if there's no work to do.
Edge* FindWork();
- // Returns true if there's more work to be done.
+ /// Returns true if there's more work to be done.
bool more_to_do() const { return !want_.empty(); }
- // Dumps the current state of the plan.
+ /// Dumps the current state of the plan.
void Dump();
- // Mark an edge as done building. Used internally and by
- // tests.
+ /// Mark an edge as done building. Used internally and by
+ /// tests.
void EdgeFinished(Edge* edge);
- // Number of edges with commands to run.
+ /// Number of edges with commands to run.
int command_edge_count() const { return command_edges_; }
private:
set<Edge*> want_;
set<Edge*> ready_;
- // Total number of edges that have commands (not phony).
+ /// Total number of edges that have commands (not phony).
int command_edges_;
};
-// CommandRunner is an interface that wraps running the build
-// subcommands. This allows tests to abstract out running commands.
-// RealCommandRunner is an implementation that actually runs commands.
+/// CommandRunner is an interface that wraps running the build
+/// subcommands. This allows tests to abstract out running commands.
+/// RealCommandRunner is an implementation that actually runs commands.
struct CommandRunner {
virtual ~CommandRunner() {}
virtual bool CanRunMore() = 0;
virtual bool StartCommand(Edge* edge) = 0;
- // Wait for commands to make progress; return false if there is no
- // progress to be made.
+ /// Wait for commands to make progress; return false if there is no
+ /// progress to be made.
virtual bool WaitForCommands() = 0;
virtual Edge* NextFinishedCommand(bool* success) = 0;
};
+/// Options (e.g. verbosity, parallelism) passed to a build.
struct BuildConfig {
BuildConfig() : verbosity(NORMAL), dry_run(false), parallelism(1) {}
int parallelism;
};
+/// Builder wraps the build process: starting commands, updating status.
struct Builder {
Builder(State* state, const BuildConfig& config);
struct BuildConfig;
struct Edge;
-// Store a log of every command ran for every build.
-// It has a few uses:
-// 1) historical command lines for output files, so we know
-// when we need to rebuild due to the command changing
-// 2) historical timing information
-// 3) maybe we can generate some sort of build overview output
-// from it
+/// Store a log of every command ran for every build.
+/// It has a few uses:
+///
+/// 1) historical command lines for output files, so we know
+/// when we need to rebuild due to the command changing
+/// 2) historical timing information
+/// 3) maybe we can generate some sort of build overview output
+/// from it
struct BuildLog {
BuildLog();
void RecordCommand(Edge* edge, int time_ms);
void Close();
- // Load the on-disk log.
+ /// Load the on-disk log.
bool Load(const string& path, string* err);
struct LogEntry {
}
};
- // Lookup a previously-run command by its output path.
+ /// Lookup a previously-run command by its output path.
LogEntry* LookupByOutput(const string& path);
- // Serialize an entry into a log file.
+ /// Serialize an entry into a log file.
void WriteEntry(FILE* f, const LogEntry& entry);
- // Rewrite the known log entries, throwing away old data.
+ /// Rewrite the known log entries, throwing away old data.
bool Recompact(const string& path, string* err);
typedef map<string, LogEntry*> Log;
#include "graph.h"
#include "test.h"
+/// Fixture for tests involving Plan.
// Though Plan doesn't use State, it's useful to have one around
// to create Nodes and Edges.
struct PlanTest : public StateTestWithBuiltinRules {
#include <vector>
using namespace std;
-// A scope for variable lookups.
+/// An interface for a scope for variable (e.g. "$foo") lookups.
struct Env {
virtual string LookupVariable(const string& var) = 0;
};
-// A standard scope, which contains a mapping of variables to values
-// as well as a pointer to a parent scope.
+/// An Env which contains a mapping of variables to values
+/// as well as a pointer to a parent scope.
struct BindingEnv : public Env {
BindingEnv() : parent_(NULL) {}
virtual string LookupVariable(const string& var);
Env* parent_;
};
-// A tokenized string that contains variable references.
-// Can be evaluated relative to an Env.
+/// A tokenized string that contains variable references.
+/// Can be evaluated relative to an Env.
struct EvalString {
bool Parse(const string& input, string* err, size_t* err_index=NULL);
string Evaluate(Env* env) const;
return true;
}
+/// An Env for an Edge, providing $in and $out.
struct EdgeEnv : public Env {
EdgeEnv(Edge* edge) : edge_(edge) {}
virtual string LookupVariable(const string& var) {
struct DiskInterface;
struct Node;
+
+/// Information about a single on-disk file: path, mtime.
struct FileStat {
FileStat(const string& path) : path_(path), mtime_(-1), node_(NULL) {}
- // Return true if the file exists (mtime_ got a value).
+ /// Return true if the file exists (mtime_ got a value).
bool Stat(DiskInterface* disk_interface);
- // Return true if we needed to stat.
+ /// Return true if we needed to stat.
bool StatIfNecessary(DiskInterface* disk_interface) {
if (status_known())
return false;
};
struct Edge;
+
+/// Information about a node in the dependency graph: the file, whether
+/// it's dirty, etc.
struct Node {
Node(FileStat* file) : file_(file), dirty_(false), in_edge_(NULL) {}
vector<Edge*> out_edges_;
};
+/// An invokable build command and associated metadata (description, etc.).
struct Rule {
Rule(const string& name) : name_(name) { }
};
struct State;
+
+/// An edge in the dependency graph; links between Nodes using Rules.
struct Edge {
Edge() : rule_(NULL), env_(NULL), implicit_deps_(0), order_only_deps_(0) {}
// the output to be dirty).
EXPECT_TRUE(GetNode("out.o")->dirty_);
}
+
+TEST_F(GraphTest, PathWithCurrentDirectory) {
+ ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
+"rule catdep\n"
+" depfile = $out.d\n"
+" command = cat $in > $out\n"
+"build ./out.o: catdep ./foo.cc\n"));
+ fs_.Create("./foo.cc", 1, "");
+ fs_.Create("./out.o.d", 1, "out.o: foo.cc\n");
+ fs_.Create("./out.o", 1, "");
+
+ Edge* edge = GetNode("./out.o")->in_edge_;
+ string err;
+ EXPECT_TRUE(edge->RecomputeDirty(&state_, &fs_, &err));
+ ASSERT_EQ("", err);
+
+ EXPECT_FALSE(GetNode("./out.o")->dirty_);
+}
struct Node;
+/// Runs the process of creating GraphViz .dot file output.
struct GraphViz {
void Start();
void AddTarget(Node* node);
}
}
+/// An implementation of ManifestParser::FileReader that actually reads
+/// the file.
struct RealFileReader : public ManifestParser::FileReader {
bool ReadFile(const string& path, string* content, string* err) {
return ::ReadFile(path, content, err) == 0;
int ReadFile(const string& path, string* contents, string* err);
+/// Interface for accessing the disk.
+///
+/// Abstract so it can be mocked out for tests. The real implementation
+/// is RealDiskInterface.
struct DiskInterface {
- // stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
+ /// stat() a file, returning the mtime, or 0 if missing and -1 on
+ /// other errors.
virtual int Stat(const string& path) = 0;
- // Create a directory, returning false on failure.
+ /// Create a directory, returning false on failure.
virtual bool MakeDir(const string& path) = 0;
- // Read a file to a string. Fill in |err| on error.
+ /// Read a file to a string. Fill in |err| on error.
virtual string ReadFile(const string& path, string* err) = 0;
- // Create all the parent directories for path; like mkdir -p `basename path`.
+ /// Create all the parent directories for path; like mkdir -p
+ /// `basename path`.
bool MakeDirs(const string& path);
};
+/// Implementation of DiskInterface that actually hits the disk.
struct RealDiskInterface : public DiskInterface {
virtual int Stat(const string& path);
virtual bool MakeDir(const string& path);
virtual string ReadFile(const string& path, string* err);
};
+/// Mapping of path -> FileStat.
struct StatCache {
typedef hash_map<string, FileStat*> Paths;
Paths paths_;
+
FileStat* GetFile(const string& path);
+
+ /// Dump the mapping to stdout (useful for debugging).
void Dump();
void Reload();
};
+/// Global state (file status, loaded rules) for a single run.
struct State {
State();
struct BindingEnv;
+/// A single parsed token in an input stream.
struct Token {
enum Type {
NONE,
const char* end_;
};
+/// Processes an input stream into Tokens.
struct Tokenizer {
Tokenizer(bool whitespace_significant)
: whitespace_significant_(whitespace_significant),
int last_indent_, cur_indent_;
};
+/// Parses simple Makefiles as generated by gcc.
struct MakefileParser {
MakefileParser();
bool Parse(const string& input, string* err);
struct State;
+/// Parses .ninja files.
struct ManifestParser {
struct FileReader {
virtual bool ReadFile(const string& path, string* content, string* err) = 0;
bool Parse(const string& input, string* err);
bool ParseRule(string* err);
- // Parse a key=val statement. If expand is true, evaluate variables
- // within the value immediately.
+ /// Parse a key=val statement. If expand is true, evaluate variables
+ /// within the value immediately.
bool ParseLet(string* key, string* val, bool expand, string* err);
bool ParseEdge(string* err);
- // Parse either a 'subninja' or 'include' line.
+ /// Parse either a 'subninja' or 'include' line.
bool ParseFileInclude(Token::Type type, string* err);
State* state_;
#include <queue>
using namespace std;
-// Subprocess wraps a single async subprocess. It is entirely
-// passive: it expects the caller to notify it when its fds are ready
-// for reading, as well as call Finish() to reap the child once done()
-// is true.
+/// Subprocess wraps a single async subprocess. It is entirely
+/// passive: it expects the caller to notify it when its fds are ready
+/// for reading, as well as call Finish() to reap the child once done()
+/// is true.
struct Subprocess {
Subprocess();
~Subprocess();
bool Start(const string& command);
void OnFDReady(int fd);
- // Returns true on successful process exit.
+ /// Returns true on successful process exit.
bool Finish();
bool done() const {
pid_t pid_;
};
-// SubprocessSet runs a poll() loop around a set of Subprocesses.
-// DoWork() waits for any state change in subprocesses; finished_
-// is a queue of subprocesses as they finish.
+/// SubprocessSet runs a poll() loop around a set of Subprocesses.
+/// DoWork() waits for any state change in subprocesses; finished_
+/// is a queue of subprocesses as they finish.
struct SubprocessSet {
void Add(Subprocess* subprocess);
void DoWork();
struct Node;
-// A base test fixture that includes a State object with a
-// builtin "cat" rule.
+/// A base test fixture that includes a State object with a
+/// builtin "cat" rule.
struct StateTestWithBuiltinRules : public testing::Test {
StateTestWithBuiltinRules();
Node* GetNode(const string& path);
void AssertParse(State* state, const char* input);
-// An implementation of DiskInterface that uses an in-memory representation
-// of disk state. It also logs file accesses and directory creations
-// so it can be used by tests to verify disk access patterns.
+/// An implementation of DiskInterface that uses an in-memory representation
+/// of disk state. It also logs file accesses and directory creations
+/// so it can be used by tests to verify disk access patterns.
struct VirtualFileSystem : public DiskInterface {
- // "Create" a file with a given mtime and contents.
+ /// "Create" a file with a given mtime and contents.
void Create(const string& path, int time, const string& contents);
// DiskInterface
virtual bool MakeDir(const string& path);
virtual string ReadFile(const string& path, string* err);
+ /// An entry for a single in-memory file.
struct Entry {
int mtime;
string contents;
#include <string>
using namespace std;
-// Log a fatal message, dump a backtrace, and exit.
+/// Log a fatal message and exit.
void Fatal(const char* msg, ...);
-// Log an error message.
+/// Log an error message.
void Error(const char* msg, ...);
-// Canonicalize a path like "foo/../bar.h" into just "bar.h".
+/// Canonicalize a path like "foo/../bar.h" into just "bar.h".
bool CanonicalizePath(string* path, string* err);
#endif // NINJA_UTIL_H_