aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinichiro Hamaji <hamaji@google.com>2016-02-28 04:40:46 +0000
committerShinichiro Hamaji <hamaji@google.com>2016-02-28 04:40:46 +0000
commit086b17663573f0d2742c534885a787c6d98216b9 (patch)
tree5618f6c181f4685b721fb141b59dfbbd691ce12b
parent59ce30d7b247cfc41950e2cc5438a1bff66bdc1f (diff)
downloadkati-086b17663573f0d2742c534885a787c6d98216b9.tar.gz
Revert "Merge remote-tracking branch 'aosp/upstream'"
This reverts commit 59ce30d7b247cfc41950e2cc5438a1bff66bdc1f. This looks the culprit of b/27381403. As I haven't figured out the cause yet, let's just revert this for now. Bug: 27381403 Change-Id: Ifd25a24b4bd7f2922ce76d6a05f85723074848ea
-rw-r--r--Android.bp1
-rw-r--r--Makefile.ckati1
-rw-r--r--affinity.cc50
-rw-r--r--affinity.h21
-rw-r--r--condvar.cc4
-rw-r--r--condvar.h2
-rw-r--r--dep.cc40
-rw-r--r--dep.h3
-rw-r--r--eval.cc25
-rw-r--r--eval.h15
-rw-r--r--expr.cc5
-rw-r--r--expr.h2
-rw-r--r--file_cache.cc2
-rw-r--r--fileutil.cc11
-rw-r--r--find.cc10
-rw-r--r--flags.cc2
-rw-r--r--flags.h1
-rw-r--r--func.cc25
-rw-r--r--main.cc14
-rw-r--r--mutex.cc8
-rw-r--r--mutex.h14
-rw-r--r--ninja.cc234
-rw-r--r--regen.cc6
-rwxr-xr-xrun_integration_test.rb182
-rwxr-xr-xruntest.rb1
-rw-r--r--stats.cc26
-rw-r--r--stats.h2
-rw-r--r--stmt.cc13
-rw-r--r--stmt.h9
-rw-r--r--string_piece.cc12
-rw-r--r--string_piece_test.cc4
-rw-r--r--strutil.cc61
-rw-r--r--strutil.h2
-rw-r--r--symtab.cc17
-rw-r--r--testcase/ninja_mkdir.sh42
-rw-r--r--testcase/shell_var_with_args.mk9
-rw-r--r--testcase/sort.mk7
-rw-r--r--thread_local.h11
-rw-r--r--thread_pool.cc12
-rw-r--r--var.cc8
-rw-r--r--var.h31
41 files changed, 405 insertions, 540 deletions
diff --git a/Android.bp b/Android.bp
index fea1241..432505e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,7 +15,6 @@
cc_library_host_static {
name: "libckati",
srcs: [
- "affinity.cc",
"command.cc",
"condvar.cc",
"dep.cc",
diff --git a/Makefile.ckati b/Makefile.ckati
index 38e1feb..cf5bab8 100644
--- a/Makefile.ckati
+++ b/Makefile.ckati
@@ -22,7 +22,6 @@ KATI_INTERMEDIATES_PATH ?= .
KATI_BIN_PATH ?= .
KATI_CXX_SRCS := \
- affinity.cc \
command.cc \
condvar.cc \
dep.cc \
diff --git a/affinity.cc b/affinity.cc
deleted file mode 100644
index 0743f94..0000000
--- a/affinity.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 Google Inc. All rights reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "affinity.h"
-
-#include "flags.h"
-#include "log.h"
-
-#ifdef __linux__
-
-#include <sched.h>
-
-void SetAffinityForSingleThread() {
- cpu_set_t cs;
- CPU_ZERO(&cs);
- int n = g_flags.num_cpus / 2;
- CPU_SET(n, &cs);
- if (n > 1)
- CPU_SET(n + 1, &cs);
- if (sched_setaffinity(0, sizeof(cs), &cs) < 0)
- WARN("sched_setaffinity: %s", strerror(errno));
-}
-
-void SetAffinityForMultiThread() {
- cpu_set_t cs;
- CPU_ZERO(&cs);
- for (int i = 0; i < g_flags.num_cpus; i++) {
- CPU_SET(i, &cs);
- }
- if (sched_setaffinity(0, sizeof(cs), &cs) < 0)
- WARN("sched_setaffinity: %s", strerror(errno));
-}
-
-#else
-
-void SetAffinityForSingleThread() {}
-void SetAffinityForMultiThread() {}
-
-#endif
diff --git a/affinity.h b/affinity.h
deleted file mode 100644
index e6f6adc..0000000
--- a/affinity.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 Google Inc. All rights reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef AFFINITY_H_
-#define AFFINITY_H_
-
-void SetAffinityForSingleThread();
-void SetAffinityForMultiThread();
-
-#endif
diff --git a/condvar.cc b/condvar.cc
index f8b488b..d7d4e39 100644
--- a/condvar.cc
+++ b/condvar.cc
@@ -26,8 +26,8 @@ condition_variable::~condition_variable() {
PERROR("pthread_cond_destroy");
}
-void condition_variable::wait(const UniqueLock<Mutex>& mu) {
- if (pthread_cond_wait(&cond_, &mu.Mutex()->mu_) != 0)
+void condition_variable::wait(const unique_lock<mutex>& mu) {
+ if (pthread_cond_wait(&cond_, &mu.mutex()->mu_) != 0)
PERROR("pthread_cond_wait");
}
diff --git a/condvar.h b/condvar.h
index b75b9a4..2f9ab3a 100644
--- a/condvar.h
+++ b/condvar.h
@@ -24,7 +24,7 @@ class condition_variable {
condition_variable();
~condition_variable();
- void wait(const UniqueLock<Mutex>& mu);
+ void wait(const unique_lock<mutex>& mu);
void notify_one();
void notify_all();
diff --git a/dep.cc b/dep.cc
index 434d9ad..45f9584 100644
--- a/dep.cc
+++ b/dep.cc
@@ -27,10 +27,8 @@
#include "fileutil.h"
#include "log.h"
#include "rule.h"
-#include "stats.h"
#include "strutil.h"
#include "symtab.h"
-#include "timeutil.h"
#include "var.h"
namespace {
@@ -118,14 +116,13 @@ DepNode::DepNode(Symbol o, bool p, bool r)
class DepBuilder {
public:
DepBuilder(Evaluator* ev,
- const vector<const Rule*>& rules,
+ const vector<shared_ptr<Rule>>& rules,
const unordered_map<Symbol, Vars*>& rule_vars)
: ev_(ev),
rule_vars_(rule_vars),
implicit_rules_(new RuleTrie()),
first_rule_(NULL),
depfile_var_name_(Intern(".KATI_DEPFILE")) {
- ScopedTimeReporter tr("make dep (populate)");
PopulateRules(rules);
LOG_STAT("%zu variables", ev->mutable_vars()->size());
LOG_STAT("%zu explicit rules", rules_.size());
@@ -229,8 +226,8 @@ class DepBuilder {
return ::Exists(target.str());
}
- void PopulateRules(const vector<const Rule*>& rules) {
- for (const Rule* rule : rules) {
+ void PopulateRules(const vector<shared_ptr<Rule>>& rules) {
+ for (shared_ptr<Rule> rule : rules) {
if (rule->outputs.empty()) {
PopulateImplicitRule(rule);
} else {
@@ -242,7 +239,7 @@ class DepBuilder {
}
}
- bool PopulateSuffixRule(const Rule* rule, Symbol output) {
+ bool PopulateSuffixRule(shared_ptr<Rule> rule, Symbol output) {
if (output.empty() || output.str()[0] != '.')
return false;
@@ -294,7 +291,6 @@ class DepBuilder {
const Rule& rule,
Symbol output,
bool is_suffix_rule) {
- COLLECT_STATS("make dep (merge rule)");
if (old_rule.is_double_colon != rule.is_double_colon) {
ERROR("%s:%d: *** target file `%s' has both : and :: entries.",
LOCF(rule.loc), output.str().c_str());
@@ -341,7 +337,7 @@ class DepBuilder {
return r;
}
- void PopulateExplicitRule(const Rule* orig_rule) {
+ void PopulateExplicitRule(shared_ptr<Rule> orig_rule) {
for (Symbol output : orig_rule->outputs) {
const bool is_suffix_rule = PopulateSuffixRule(orig_rule, output);
@@ -349,7 +345,7 @@ class DepBuilder {
rule->outputs.clear();
rule->outputs.push_back(output);
- auto p = rules_.emplace(output, rule);
+ auto p = rules_.insert(make_pair(output, rule));
if (p.second) {
if (!first_rule_ && output.get(0) != '.') {
rule->is_default_target = true;
@@ -362,24 +358,9 @@ class DepBuilder {
}
}
- static bool IsIgnorableImplicitRule(const Rule* rule) {
- // As kati doesn't have RCS/SCCS related default rules, we can
- // safely ignore suppression for them.
- if (rule->inputs.size() != 1)
- return false;
- if (!rule->order_only_inputs.empty())
- return false;
- if (!rule->cmds.empty())
- return false;
- const string& i = rule->inputs[0].str();
- return (i == "RCS/%,v" || i == "RCS/%" || i == "%,v" ||
- i == "s.%" || i == "SCCS/s.%");
- }
-
- void PopulateImplicitRule(const Rule* rule) {
+ void PopulateImplicitRule(shared_ptr<Rule> rule) {
for (Symbol output_pattern : rule->output_patterns) {
- if (output_pattern.str() != "%" || !IsIgnorableImplicitRule(rule))
- implicit_rules_->Add(output_pattern.str(), rule);
+ implicit_rules_->Add(output_pattern.str(), rule.get());
}
}
@@ -456,7 +437,6 @@ class DepBuilder {
bool PickRule(Symbol output, DepNode* n,
shared_ptr<Rule>* out_rule, Vars** out_var) {
- COLLECT_STATS("make dep (pick rule)");
shared_ptr<Rule> rule = LookupRule(output);
Vars* vars = LookupRuleVars(output);
*out_rule = rule;
@@ -559,7 +539,6 @@ class DepBuilder {
vector<unique_ptr<ScopedVar>> sv;
if (vars) {
- COLLECT_STATS("make dep (create scope)");
for (const auto& p : *vars) {
Symbol name = p.first;
RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
@@ -640,12 +619,11 @@ class DepBuilder {
};
void MakeDep(Evaluator* ev,
- const vector<const Rule*>& rules,
+ const vector<shared_ptr<Rule>>& rules,
const unordered_map<Symbol, Vars*>& rule_vars,
const vector<Symbol>& targets,
vector<DepNode*>* nodes) {
DepBuilder db(ev, rules, rule_vars);
- ScopedTimeReporter tr("make dep (build)");
db.Build(targets, nodes);
}
diff --git a/dep.h b/dep.h
index 05d10d0..bb70eb3 100644
--- a/dep.h
+++ b/dep.h
@@ -15,6 +15,7 @@
#ifndef DEP_H_
#define DEP_H_
+#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
@@ -52,7 +53,7 @@ void InitDepNodePool();
void QuitDepNodePool();
void MakeDep(Evaluator* ev,
- const vector<const Rule*>& rules,
+ const vector<shared_ptr<Rule>>& rules,
const unordered_map<Symbol, Vars*>& rule_vars,
const vector<Symbol>& targets,
vector<DepNode*>* nodes);
diff --git a/eval.cc b/eval.cc
index be4bb34..ae41567 100644
--- a/eval.cc
+++ b/eval.cc
@@ -30,8 +30,15 @@
#include "symtab.h"
#include "var.h"
+EvalResult::~EvalResult() {
+ for (auto p : rule_vars)
+ delete p.second;
+ delete vars;
+}
+
Evaluator::Evaluator(const Vars* vars)
- : vars_(new Vars(*vars)),
+ : in_vars_(vars),
+ vars_(new Vars()),
last_rule_(NULL),
current_scope_(NULL),
avoid_io_(false),
@@ -54,12 +61,9 @@ Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
Var* rhs = NULL;
bool needs_assign = true;
switch (op) {
- case AssignOp::COLON_EQ: {
- SimpleVar* sv = new SimpleVar(origin);
- rhs_v->Eval(this, sv->mutable_value());
- rhs = sv;
+ case AssignOp::COLON_EQ:
+ rhs = new SimpleVar(rhs_v->Eval(this), origin);
break;
- }
case AssignOp::EQ:
rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
break;
@@ -96,7 +100,7 @@ Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
void Evaluator::EvalAssign(const AssignStmt* stmt) {
loc_ = stmt->loc();
last_rule_ = NULL;
- Symbol lhs = stmt->GetLhsSymbol(this);
+ Symbol lhs = Intern(stmt->lhs->Eval(this));
if (lhs.empty())
Error("*** empty variable name.");
Var* rhs = EvalRHS(lhs, stmt->rhs, stmt->orig_rhs, stmt->op,
@@ -127,12 +131,11 @@ void Evaluator::EvalRule(const RuleStmt* stmt) {
}
LOG("Rule: %s", rule->DebugString().c_str());
- rules_.push_back(rule);
+ rules_.push_back(shared_ptr<Rule>(rule));
last_rule_ = rule;
return;
}
- Symbol lhs = Intern(rule_var.lhs);
for (Symbol output : rule_var.outputs) {
auto p = rule_vars_.emplace(output, nullptr);
if (p.second) {
@@ -156,6 +159,7 @@ void Evaluator::EvalRule(const RuleStmt* stmt) {
}
current_scope_ = p.first->second;
+ Symbol lhs = Intern(rule_var.lhs);
Var* rhs_var = EvalRHS(lhs, rhs, StringPiece("*TODO*"), rule_var.op);
if (rhs_var)
current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
@@ -287,6 +291,9 @@ Var* Evaluator::LookupVarGlobal(Symbol name) {
Var* v = vars_->Lookup(name);
if (v->IsDefined())
return v;
+ v = in_vars_->Lookup(name);
+ if (v->IsDefined())
+ return v;
used_undefined_vars_.insert(name);
return v;
}
diff --git a/eval.h b/eval.h
index cb03d5d..6bc21b9 100644
--- a/eval.h
+++ b/eval.h
@@ -15,6 +15,7 @@
#ifndef EVAL_H_
#define EVAL_H_
+#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -31,6 +32,15 @@ class Rule;
class Var;
class Vars;
+struct EvalResult {
+ ~EvalResult();
+ vector<shared_ptr<Rule>> rules;
+ Vars* vars;
+ unordered_map<StringPiece, Vars*> rule_vars;
+ // TODO: read_mks
+ unordered_map<StringPiece, bool> exports;
+};
+
class Evaluator {
public:
Evaluator(const Vars* vars);
@@ -52,7 +62,7 @@ class Evaluator {
const Loc& loc() const { return loc_; }
void set_loc(const Loc& loc) { loc_ = loc; }
- const vector<const Rule*>& rules() const { return rules_; }
+ const vector<shared_ptr<Rule>>& rules() const { return rules_; }
const unordered_map<Symbol, Vars*>& rule_vars() const {
return rule_vars_;
}
@@ -97,9 +107,10 @@ class Evaluator {
Var* LookupVarGlobal(Symbol name);
+ const Vars* in_vars_;
Vars* vars_;
unordered_map<Symbol, Vars*> rule_vars_;
- vector<const Rule*> rules_;
+ vector<shared_ptr<Rule>> rules_;
unordered_map<Symbol, bool> exports_;
Rule* last_rule_;
diff --git a/expr.cc b/expr.cc
index a629352..a8f306c 100644
--- a/expr.cc
+++ b/expr.cc
@@ -62,8 +62,7 @@ class Literal : public Value {
s->append(s_.begin(), s_.end());
}
- virtual bool IsLiteral() const override { return true; }
- virtual StringPiece GetLiteralValueUnsafe() const { return s_; }
+ virtual bool IsLiteral() const { return true; }
virtual string DebugString_() const override {
return s_.as_string();
@@ -110,7 +109,7 @@ class Expr : public Value {
return r;
}
- virtual Value* Compact() override {
+ virtual Value* Compact() {
if (vals_.size() != 1) {
return this;
}
diff --git a/expr.h b/expr.h
index fdd6d36..e479ed8 100644
--- a/expr.h
+++ b/expr.h
@@ -42,8 +42,6 @@ class Value : public Evaluable {
virtual Value* Compact() { return this; }
virtual bool IsLiteral() const { return false; }
- // Only safe after IsLiteral() returns true.
- virtual StringPiece GetLiteralValueUnsafe() const { return ""; }
string DebugString() const;
diff --git a/file_cache.cc b/file_cache.cc
index afdb3bd..6a05550 100644
--- a/file_cache.cc
+++ b/file_cache.cc
@@ -44,7 +44,7 @@ class MakefileCacheManagerImpl : public MakefileCacheManager {
virtual Makefile* ReadMakefile(const string& filename) override {
Makefile* result = NULL;
- auto p = cache_.emplace(filename, result);
+ auto p = cache_.insert(make_pair(filename, result));
if (p.second) {
p.first->second = result = new Makefile(filename);
} else {
diff --git a/fileutil.cc b/fileutil.cc
index a2a0d09..42e81a2 100644
--- a/fileutil.cc
+++ b/fileutil.cc
@@ -32,7 +32,6 @@
#include <unordered_map>
#include "log.h"
-#include "strutil.h"
bool Exists(StringPiece filename) {
CHECK(filename.size() < PATH_MAX);
@@ -63,13 +62,6 @@ double GetTimestamp(StringPiece filename) {
int RunCommand(const string& shell, const string& cmd,
RedirectStderr redirect_stderr,
string* s) {
- string cmd_escaped = cmd;
- EscapeShell(&cmd_escaped);
- string cmd_with_shell = shell + " -c \"" + cmd_escaped + "\"";
- const char* argv[] = {
- "/bin/sh", "-c", cmd_with_shell.c_str(), NULL
- };
-
int pipefd[2];
if (pipe(pipefd) != 0)
PERROR("pipe failed");
@@ -114,6 +106,9 @@ int RunCommand(const string& shell, const string& cmd,
PERROR("dup2 failed");
close(pipefd[1]);
+ const char* argv[] = {
+ shell.c_str(), "-c", cmd.c_str(), NULL
+ };
execvp(argv[0], const_cast<char**>(argv));
PLOG("execvp for %s failed", argv[0]);
kill(getppid(), SIGTERM);
diff --git a/find.cc b/find.cc
index b783acb..4c7cd8f 100644
--- a/find.cc
+++ b/find.cc
@@ -154,7 +154,7 @@ class DirentFileNode : public DirentNode {
virtual bool RunFind(const FindCommand& fc, int d,
string* path,
unordered_map<const DirentNode*, string>*,
- string* out) const override {
+ string* out) const {
PrintIfNecessary(fc, *path, type_, d, out);
return true;
}
@@ -205,7 +205,7 @@ class DirentDirNode : public DirentNode {
}
}
- virtual const DirentNode* FindDir(StringPiece d) const override {
+ virtual const DirentNode* FindDir(StringPiece d) const {
if (d.empty() || d == ".")
return this;
size_t index = d.find('/');
@@ -224,7 +224,7 @@ class DirentDirNode : public DirentNode {
virtual bool RunFind(const FindCommand& fc, int d,
string* path,
unordered_map<const DirentNode*, string>* cur_read_dirs,
- string* out) const override {
+ string* out) const {
ScopedReadDirTracker srdt(this, *path, cur_read_dirs);
if (!srdt.ok()) {
fprintf(stderr, "FindEmulator: find: File system loop detected; `%s' is "
@@ -308,7 +308,7 @@ class DirentSymlinkNode : public DirentNode {
: DirentNode(name), to_(NULL), errno_(0) {
}
- virtual const DirentNode* FindDir(StringPiece d) const override {
+ virtual const DirentNode* FindDir(StringPiece d) const {
if (errno_ == 0 && to_)
return to_->FindDir(d);
return NULL;
@@ -317,7 +317,7 @@ class DirentSymlinkNode : public DirentNode {
virtual bool RunFind(const FindCommand& fc, int d,
string* path,
unordered_map<const DirentNode*, string>* cur_read_dirs,
- string* out) const override {
+ string* out) const {
unsigned char type = DT_LNK;
if (fc.follows_symlinks && errno_ != ENOENT) {
if (errno_) {
diff --git a/flags.cc b/flags.cc
index 73c7105..06772f0 100644
--- a/flags.cc
+++ b/flags.cc
@@ -49,7 +49,7 @@ static bool ParseCommandLineOptionWithArg(StringPiece option,
void Flags::Parse(int argc, char** argv) {
subkati_args.push_back(argv[0]);
- num_jobs = num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ num_jobs = sysconf(_SC_NPROCESSORS_ONLN);
const char* num_jobs_str;
for (int i = 1; i < argc; i++) {
diff --git a/flags.h b/flags.h
index 275a3ee..d2fe923 100644
--- a/flags.h
+++ b/flags.h
@@ -44,7 +44,6 @@ struct Flags {
const char* makefile;
const char* ninja_dir;
const char* ninja_suffix;
- int num_cpus;
int num_jobs;
int remote_num_jobs;
vector<const char*> subkati_args;
diff --git a/func.cc b/func.cc
index 2ea8afa..39af0e9 100644
--- a/func.cc
+++ b/func.cc
@@ -182,14 +182,10 @@ void FilterOutFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
}
void SortFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
- string list;
- args[0]->Eval(ev, &list);
- COLLECT_STATS("func sort time");
- // TODO(hamaji): Probably we could use a faster string-specific sort
- // algorithm.
+ const string&& list = args[0]->Eval(ev);
vector<StringPiece> toks;
WordScanner(list).Split(&toks);
- stable_sort(toks.begin(), toks.end());
+ sort(toks.begin(), toks.end());
WordWriter ww(s);
StringPiece prev;
for (StringPiece tok : toks) {
@@ -578,9 +574,8 @@ void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
}
void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
- static const Symbol tmpvar_names[] = {
- Intern("0"), Intern("1"), Intern("2"), Intern("3"), Intern("4"),
- Intern("5"), Intern("6"), Intern("7"), Intern("8"), Intern("9")
+ static const string tmpvar_names[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
};
const string&& func_name = args[0]->Eval(ev);
@@ -598,25 +593,25 @@ void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
vector<unique_ptr<ScopedVar>> sv;
for (size_t i = 1; ; i++) {
string s;
- Symbol tmpvar_name_sym(Symbol::IsUninitialized{});
+ StringPiece tmpvar_name;
if (i < sizeof(tmpvar_names)/sizeof(tmpvar_names[0])) {
- tmpvar_name_sym = tmpvar_names[i];
+ tmpvar_name = tmpvar_names[i];
} else {
s = StringPrintf("%d", i);
- tmpvar_name_sym = Intern(s);
+ tmpvar_name = s;
}
if (i < args.size()) {
sv.emplace_back(new ScopedVar(ev->mutable_vars(),
- tmpvar_name_sym, av[i-1].get()));
+ Intern(tmpvar_name), av[i-1].get()));
} else {
// We need to blank further automatic vars
- Var *v = ev->LookupVar(tmpvar_name_sym);
+ Var *v = ev->LookupVar(Intern(tmpvar_name));
if (!v->IsDefined()) break;
if (v->Origin() != VarOrigin::AUTOMATIC) break;
av.emplace_back(new SimpleVar("", VarOrigin::AUTOMATIC));
sv.emplace_back(new ScopedVar(ev->mutable_vars(),
- tmpvar_name_sym, av[i-1].get()));
+ Intern(tmpvar_name), av[i-1].get()));
}
}
diff --git a/main.cc b/main.cc
index c732dda..a64a37e 100644
--- a/main.cc
+++ b/main.cc
@@ -21,7 +21,6 @@
#include <time.h>
#include <unistd.h>
-#include "affinity.h"
#include "dep.h"
#include "eval.h"
#include "exec.h"
@@ -124,7 +123,7 @@ static int Run(const vector<Symbol>& targets,
if (g_flags.generate_ninja && (g_flags.regen || g_flags.dump_kati_stamp)) {
ScopedTimeReporter tr("regen check time");
if (!NeedsRegen(start_time, orig_args)) {
- fprintf(stderr, "No need to regenerate ninja file\n");
+ printf("No need to regenerate ninja file\n");
return 0;
}
if (g_flags.dump_kati_stamp) {
@@ -134,14 +133,9 @@ static int Run(const vector<Symbol>& targets,
ClearGlobCache();
}
- SetAffinityForSingleThread();
-
MakefileCacheManager* cache_mgr = NewMakefileCacheManager();
Vars* vars = new Vars();
- vars->Assign(Intern("MAKEFILE_LIST"),
- new SimpleVar(StringPrintf(" %s", g_flags.makefile),
- VarOrigin::FILE));
for (char** p = environ; *p; p++) {
SetVar(*p, VarOrigin::ENVIRONMENT, vars);
}
@@ -160,6 +154,10 @@ static int Run(const vector<Symbol>& targets,
SetVar(l, VarOrigin::COMMAND_LINE, ev->mutable_vars());
}
+ vars->Assign(Intern("MAKEFILE_LIST"),
+ new SimpleVar(StringPrintf(" %s", g_flags.makefile),
+ VarOrigin::FILE));
+
{
ScopedTimeReporter tr("eval time");
Makefile* mk = cache_mgr->ReadMakefile(g_flags.makefile);
@@ -210,8 +208,6 @@ static int Run(const vector<Symbol>& targets,
for (Stmt* stmt : bootstrap_asts)
delete stmt;
delete ev;
- // Each Var will be deleted by |ev|.
- vars->clear();
delete vars;
delete cache_mgr;
diff --git a/mutex.cc b/mutex.cc
index 986366b..ae4bd3b 100644
--- a/mutex.cc
+++ b/mutex.cc
@@ -16,22 +16,22 @@
#include "log.h"
-Mutex::Mutex() {
+mutex::mutex() {
if (pthread_mutex_init(&mu_, NULL) != 0)
PERROR("pthread_mutex_init");
}
-Mutex::~Mutex() {
+mutex::~mutex() {
if (pthread_mutex_destroy(&mu_) != 0)
PERROR("pthread_mutex_destroy");
}
-void Mutex::lock() {
+void mutex::lock() {
if (pthread_mutex_lock(&mu_) != 0)
PERROR("pthread_mutex_lock");
}
-void Mutex::unlock() {
+void mutex::unlock() {
if (pthread_mutex_unlock(&mu_) != 0)
PERROR("pthread_mutex_unlock");
}
diff --git a/mutex.h b/mutex.h
index e730294..d6f1f5a 100644
--- a/mutex.h
+++ b/mutex.h
@@ -17,10 +17,10 @@
#include <pthread.h>
-class Mutex {
+class mutex {
public:
- explicit Mutex();
- ~Mutex();
+ explicit mutex();
+ ~mutex();
void lock();
void unlock();
@@ -31,17 +31,17 @@ class Mutex {
friend class condition_variable;
};
-template<class T> class UniqueLock {
+template<class T> class unique_lock {
public:
- explicit UniqueLock(T& mu)
+ explicit unique_lock(T& mu)
: mu_(mu) {
mu_.lock();
}
- ~UniqueLock() {
+ ~unique_lock() {
mu_.unlock();
}
- T* Mutex() const { return &mu_; }
+ T* mutex() const { return &mu_; }
private:
T& mu_;
diff --git a/ninja.cc b/ninja.cc
index eeefce0..f14610f 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -22,7 +22,6 @@
#include <unistd.h>
#include <map>
-#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
@@ -41,8 +40,6 @@
#include "string_piece.h"
#include "stringprintf.h"
#include "strutil.h"
-#include "thread_pool.h"
-#include "timeutil.h"
#include "var.h"
#include "version.h"
@@ -168,12 +165,6 @@ bool GetDepfileFromCommand(string* cmd, string* out) {
return true;
}
-struct NinjaNode {
- const DepNode* node;
- vector<Command*> commands;
- int rule_id;
-};
-
class NinjaGenerator {
public:
NinjaGenerator(Evaluator* ev, double start_time)
@@ -184,7 +175,7 @@ class NinjaGenerator {
start_time_(start_time),
default_target_(NULL) {
ev_->set_avoid_io(true);
- shell_ = EscapeNinja(ev->EvalVar(kShellSym));
+ shell_ = ev->EvalVar(kShellSym);
if (g_flags.goma_dir)
gomacc_ = StringPrintf("%s/gomacc ", g_flags.goma_dir);
@@ -193,15 +184,12 @@ class NinjaGenerator {
~NinjaGenerator() {
ev_->set_avoid_io(false);
- for (NinjaNode* nn : nodes_)
- delete nn;
}
void Generate(const vector<DepNode*>& nodes,
const string& orig_args) {
unlink(GetNinjaStampFilename().c_str());
- PopulateNinjaNodes(nodes);
- GenerateNinja(orig_args);
+ GenerateNinja(nodes, orig_args);
GenerateShell();
GenerateStamp(orig_args);
}
@@ -218,40 +206,8 @@ class NinjaGenerator {
}
private:
- void PopulateNinjaNodes(const vector<DepNode*>& nodes) {
- ScopedTimeReporter tr("ninja gen (eval)");
- for (DepNode* node : nodes) {
- PopulateNinjaNode(node);
- }
- }
-
- void PopulateNinjaNode(DepNode* node) {
- auto p = done_.insert(node->output);
- if (!p.second)
- return;
-
- // A hack to exclude out phony target in Android. If this exists,
- // "ninja -t clean" tries to remove this directory and fails.
- if (g_flags.detect_android_echo && node->output.str() == "out")
- return;
-
- // This node is a leaf node
- if (!node->has_rule && !node->is_phony) {
- return;
- }
-
- NinjaNode* nn = new NinjaNode;
- nn->node = node;
- ce_.Eval(node, &nn->commands);
- nn->rule_id = nn->commands.empty() ? -1 : rule_id_++;
- nodes_.push_back(nn);
-
- for (DepNode* d : node->deps) {
- PopulateNinjaNode(d);
- }
- for (DepNode* d : node->order_onlys) {
- PopulateNinjaNode(d);
- }
+ string GenRuleName() {
+ return StringPrintf("rule%d", rule_id_++);
}
StringPiece TranslateCommand(const char* in, string* cmd_buf) {
@@ -328,22 +284,6 @@ class NinjaGenerator {
cmd_buf->size() - orig_size);
}
- bool IsOutputMkdir(const char *name, StringPiece cmd) {
- if (!HasPrefix(cmd, "mkdir -p ")) {
- return false;
- }
- cmd = cmd.substr(9, cmd.size());
- if (cmd.get(cmd.size() - 1) == '/') {
- cmd = cmd.substr(0, cmd.size() - 1);
- }
-
- StringPiece dir = Dirname(name);
- if (cmd == dir) {
- return true;
- }
- return false;
- }
-
bool GetDescriptionFromCommand(StringPiece cmd, string *out) {
if (!HasPrefix(cmd, "echo ")) {
return false;
@@ -393,8 +333,7 @@ class NinjaGenerator {
return true;
}
- bool GenShellScript(const char *name,
- const vector<Command*>& commands,
+ bool GenShellScript(const vector<Command*>& commands,
string* cmd_buf,
string* description) {
// TODO: This is a dirty hack to set local_pool even without
@@ -408,10 +347,7 @@ class NinjaGenerator {
bool got_descritpion = false;
bool use_gomacc = false;
bool should_ignore_error = false;
- auto command_count = commands.size();
for (const Command* c : commands) {
- size_t cmd_begin = cmd_buf->size();
-
if (!cmd_buf->empty()) {
if (should_ignore_error) {
*cmd_buf += " ; ";
@@ -425,7 +361,7 @@ class NinjaGenerator {
while (isspace(*in))
in++;
- bool needs_subshell = command_count > 1;
+ bool needs_subshell = commands.size() > 1;
if (*in == '(') {
needs_subshell = false;
}
@@ -438,15 +374,11 @@ class NinjaGenerator {
if (g_flags.detect_android_echo && !got_descritpion && !c->echo &&
GetDescriptionFromCommand(translated, description)) {
got_descritpion = true;
- translated.clear();
- } else if (IsOutputMkdir(name, translated) && !c->echo &&
- cmd_begin == 0) {
+ cmd_buf->resize(cmd_start);
translated.clear();
}
if (translated.empty()) {
- cmd_buf->resize(cmd_begin);
- command_count -= 1;
- continue;
+ *cmd_buf += "true";
} else if (g_flags.goma_dir) {
size_t pos = GetGomaccPosForAndroidCompileCommand(translated);
if (pos != string::npos) {
@@ -469,7 +401,7 @@ class NinjaGenerator {
g_flags.goma_dir) && !use_gomacc;
}
- bool GetDepfile(const DepNode* node, string* cmd_buf, string* depfile) {
+ bool GetDepfile(DepNode* node, string* cmd_buf, string* depfile) {
if (node->depfile_var) {
node->depfile_var->Eval(ev_, depfile);
return true;
@@ -481,55 +413,75 @@ class NinjaGenerator {
return result;
}
- void EmitDepfile(NinjaNode* nn, string* cmd_buf, ostringstream* o) {
- const DepNode* node = nn->node;
+ void EmitDepfile(DepNode* node, string* cmd_buf) {
string depfile;
if (!GetDepfile(node, cmd_buf, &depfile))
return;
- *o << " depfile = " << depfile << "\n";
- *o << " deps = gcc\n";
+ fprintf(fp_, " depfile = %s\n", depfile.c_str());
+ fprintf(fp_, " deps = gcc\n");
}
- void EmitNode(NinjaNode* nn, ostringstream* o) {
- const DepNode* node = nn->node;
- const vector<Command*>& commands = nn->commands;
+ void EmitNode(DepNode* node) {
+ auto p = done_.insert(node->output);
+ if (!p.second)
+ return;
+
+ // A hack to exclude out phony target in Android. If this exists,
+ // "ninja -t clean" tries to remove this directory and fails.
+ if (g_flags.detect_android_echo && node->output.str() == "out")
+ return;
+
+ // This node is a leaf node
+ if (!node->has_rule && !node->is_phony) {
+ return;
+ }
+
+ vector<Command*> commands;
+ ce_.Eval(node, &commands);
string rule_name = "phony";
bool use_local_pool = false;
if (!commands.empty()) {
- rule_name = StringPrintf("rule%d", nn->rule_id);
- *o << "rule " << rule_name << "\n";
+ rule_name = GenRuleName();
+ fprintf(fp_, "rule %s\n", rule_name.c_str());
string description = "build $out";
string cmd_buf;
- use_local_pool |= GenShellScript(node->output.c_str(), commands,
- &cmd_buf, &description);
- *o << " description = " << description << "\n";
- EmitDepfile(nn, &cmd_buf, o);
+ use_local_pool |= GenShellScript(commands, &cmd_buf, &description);
+ fprintf(fp_, " description = %s\n", description.c_str());
+ EmitDepfile(node, &cmd_buf);
// It seems Linux is OK with ~130kB and Mac's limit is ~250kB.
// TODO: Find this number automatically.
if (cmd_buf.size() > 100 * 1000) {
- *o << " rspfile = $out.rsp\n";
- *o << " rspfile_content = " << cmd_buf << "\n";
- *o << " command = " << shell_ << " $out.rsp\n";
+ fprintf(fp_, " rspfile = $out.rsp\n");
+ fprintf(fp_, " rspfile_content = %s\n", cmd_buf.c_str());
+ fprintf(fp_, " command = %s $out.rsp\n", shell_.c_str());
} else {
EscapeShell(&cmd_buf);
- *o << " command = " << shell_ << " -c \"" << cmd_buf << "\"\n";
+ fprintf(fp_, " command = %s -c \"%s\"\n",
+ shell_.c_str(), cmd_buf.c_str());
}
if (node->is_restat) {
- *o << " restat = 1\n";
+ fprintf(fp_, " restat = 1\n");
}
}
- EmitBuild(nn, rule_name, use_local_pool, o);
+ EmitBuild(node, rule_name, use_local_pool);
+
+ for (DepNode* d : node->deps) {
+ EmitNode(d);
+ }
+ for (DepNode* d : node->order_onlys) {
+ EmitNode(d);
+ }
}
- string EscapeNinja(const string& s) const {
- if (s.find_first_of("$: ") == string::npos)
- return s;
+ string EscapeBuildTarget(Symbol s) const {
+ if (s.str().find_first_of("$: ") == string::npos)
+ return s.str();
string r;
- for (char c : s) {
+ for (char c : s.str()) {
switch (c) {
case '$':
case ':':
@@ -543,33 +495,58 @@ class NinjaGenerator {
return r;
}
- string EscapeBuildTarget(Symbol s) const {
- return EscapeNinja(s.str());
+ void EscapeShell(string* s) const {
+ if (s->find_first_of("$`\\\"") == string::npos)
+ return;
+ string r;
+ bool last_dollar = false;
+ for (char c : *s) {
+ switch (c) {
+ case '$':
+ if (last_dollar) {
+ r += c;
+ last_dollar = false;
+ } else {
+ r += '\\';
+ r += c;
+ last_dollar = true;
+ }
+ break;
+ case '`':
+ case '"':
+ case '\\':
+ r += '\\';
+ // fall through.
+ default:
+ r += c;
+ last_dollar = false;
+ }
+ }
+ s->swap(r);
}
- void EmitBuild(NinjaNode* nn, const string& rule_name,
- bool use_local_pool, ostringstream* o) {
- const DepNode* node = nn->node;
+ void EmitBuild(DepNode* node, const string& rule_name, bool use_local_pool) {
string target = EscapeBuildTarget(node->output);
- *o << "build " << target << ": " << rule_name;
+ fprintf(fp_, "build %s: %s",
+ target.c_str(),
+ rule_name.c_str());
vector<Symbol> order_onlys;
if (node->is_phony) {
- *o << " _kati_always_build_";
+ fprintf(fp_, " _kati_always_build_");
}
for (DepNode* d : node->deps) {
- *o << " " << EscapeBuildTarget(d->output).c_str();
+ fprintf(fp_, " %s", EscapeBuildTarget(d->output).c_str());
}
if (!node->order_onlys.empty()) {
- *o << " ||";
+ fprintf(fp_, " ||");
for (DepNode* d : node->order_onlys) {
- *o << " " << EscapeBuildTarget(d->output).c_str();
+ fprintf(fp_, " %s", EscapeBuildTarget(d->output).c_str());
}
}
- *o << "\n";
+ fprintf(fp_, "\n");
if (use_local_pool)
- *o << " pool = local_pool\n";
+ fprintf(fp_, " pool = local_pool\n");
if (node->is_default_target) {
- UniqueLock<Mutex> lock(mu_);
default_target_ = node;
}
}
@@ -596,8 +573,8 @@ class NinjaGenerator {
return GetFilename("env%s.sh");
}
- void GenerateNinja(const string& orig_args) {
- ScopedTimeReporter tr("ninja gen (emit)");
+ void GenerateNinja(const vector<DepNode*>& nodes,
+ const string& orig_args) {
fp_ = fopen(GetNinjaFilename().c_str(), "wb");
if (fp_ == NULL)
PERROR("fopen(build.ninja) failed");
@@ -624,24 +601,8 @@ class NinjaGenerator {
EmitRegenRules(orig_args);
- unique_ptr<ThreadPool> tp(NewThreadPool(g_flags.num_jobs));
- CHECK(g_flags.num_jobs);
- int num_nodes_per_task = nodes_.size() / (g_flags.num_jobs * 10) + 1;
- int num_tasks = nodes_.size() / num_nodes_per_task + 1;
- vector<ostringstream> bufs(num_tasks);
- for (int i = 0; i < num_tasks; i++) {
- tp->Submit([this, i, num_nodes_per_task, &bufs]() {
- int l = min(num_nodes_per_task * (i + 1),
- static_cast<int>(nodes_.size()));
- for (int j = num_nodes_per_task * i; j < l; j++) {
- EmitNode(nodes_[j], &bufs[i]);
- }
- });
- }
- tp->Wait();
-
- for (const ostringstream& buf : bufs) {
- fprintf(fp_, "%s", buf.str().c_str());
+ for (DepNode* node : nodes) {
+ EmitNode(node);
}
unordered_set<Symbol> used_env_vars(Vars::used_env_vars());
@@ -804,11 +765,8 @@ class NinjaGenerator {
string shell_;
map<string, string> used_envs_;
string kati_binary_;
- const double start_time_;
- vector<NinjaNode*> nodes_;
-
- Mutex mu_;
- const DepNode* default_target_;
+ double start_time_;
+ DepNode* default_target_;
};
string GetNinjaFilename() {
diff --git a/regen.cc b/regen.cc
index a448612..a40ebf3 100644
--- a/regen.cc
+++ b/regen.cc
@@ -364,7 +364,7 @@ class StampChecker {
// TODO: Make glob cache thread safe and create a task for each glob.
for (GlobResult* gr : globs_) {
if (CheckGlobResult(gr, &err)) {
- UniqueLock<Mutex> lock(mu_);
+ unique_lock<mutex> lock(mu_);
if (!needs_regen_) {
needs_regen_ = true;
msg_ = err;
@@ -378,7 +378,7 @@ class StampChecker {
tp->Submit([this, sr]() {
string err;
if (CheckShellResult(sr, &err)) {
- UniqueLock<Mutex> lock(mu_);
+ unique_lock<mutex> lock(mu_);
if (!needs_regen_) {
needs_regen_ = true;
msg_ = err;
@@ -398,7 +398,7 @@ class StampChecker {
double gen_time_;
vector<GlobResult*> globs_;
vector<ShellResult*> commands_;
- Mutex mu_;
+ mutex mu_;
bool needs_regen_;
string msg_;
};
diff --git a/run_integration_test.rb b/run_integration_test.rb
new file mode 100755
index 0000000..3a5b7d0
--- /dev/null
+++ b/run_integration_test.rb
@@ -0,0 +1,182 @@
+#!/usr/bin/env ruby
+#
+# Copyright 2015 Google Inc. All rights reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'fileutils'
+
+FileUtils.mkdir_p('repo')
+Dir.chdir('repo')
+
+def check_command(cmd)
+ puts cmd
+ if !system(cmd)
+ puts "#{cmd} failed"
+ exit 1
+ end
+end
+
+class TestCase
+ attr_reader :name
+
+ def initialize(name, checkout, prepare, clean, target)
+ @name = name
+ @checkout = checkout
+ @prepare = prepare
+ @clean = clean
+ @target = target
+ end
+
+ def normalize_log(log, out)
+ # TODO: Fix.
+ if @name == 'android'
+ log = log.gsub(/[ \t]+/, ' ')
+ log = log.split("\n").sort.join("\n").sub(/ Stop\.$/, '')
+ # This is a completely sane warning from kati for Android.
+ log.sub!(%r(build/core/product_config.mk:152: warning: Unmatched parens: .*\n), '')
+ # Not sure why the order can be inconsistent, but this would be OK.
+ # TODO: Inevestigate.
+ log.gsub!(/(\.mk\.PRODUCT_COPY_FILES := )(.*)/){$1 + $2.split.sort * ' '}
+ end
+ File.open(out, 'w') do |of|
+ of.print log
+ end
+ log
+ end
+
+ def run
+ @checkout.call(self)
+
+ Dir.chdir(@name) do
+ @prepare.call(self)
+
+ [['make', 'make'], ['kati', '../../kati']].each do |n, cmd|
+ @clean.call(self)
+ print "Running #{n} for #{@name}..."
+ STDOUT.flush
+ started = Time.now
+ system("#{cmd} #{@target} > #{n}.log 2>&1")
+ elapsed = Time.now - started
+ puts " %.2f secs" % elapsed
+ end
+
+ make_log = File.read('make.log')
+ kati_log = File.read('kati.log')
+ kati_log.gsub!(/^\*kati\*.*\n/, '')
+
+ make_log = normalize_log(make_log, 'make-normalized.log')
+ kati_log = normalize_log(kati_log, 'kati-normalized.log')
+ if make_log == kati_log
+ puts "#{@name}: OK"
+ return true
+ else
+ puts "#{@name}: FAIL"
+ return false
+ end
+ end
+ end
+end
+
+class GitTestCase < TestCase
+ def initialize(name, repo, rev, prepare, clean, target)
+ checkout = Proc.new{|tc|
+ if !File.exist?(@name)
+ check_command("git clone #{repo}")
+ end
+ Dir.chdir(@name) {
+ check_command("git checkout #{rev}")
+ }
+ }
+
+ super(name, checkout, prepare, clean, target)
+ end
+end
+
+class AndroidTestCase < TestCase
+ def initialize
+ name = 'android'
+ checkout = Proc.new{|tc|
+ FileUtils.mkdir_p(@name)
+ md5 = `md5sum android.tgz`
+ need_update = true
+ if File.exist?("#{@name}/STAMP")
+ stamp = File.read("#{@name}/STAMP")
+ if md5 == stamp
+ need_update = false
+ end
+ end
+
+ if need_update
+ check_command("tar -xzf android.tgz")
+ File.open("#{@name}/STAMP.tmp", 'w') do |ofile|
+ ofile.print(md5)
+ end
+ File.rename("#{@name}/STAMP.tmp", "#{@name}/STAMP")
+ end
+ }
+
+ super(name, checkout, DO_NOTHING, DO_NOTHING, 'dump-products')
+ end
+end
+
+DO_NOTHING = Proc.new{|tc|}
+MAKE_CLEAN = Proc.new{|tc|
+ check_command("make clean > /dev/null")
+}
+CONFIGURE = Proc.new{|tc|
+ check_command("./configure > /dev/null")
+}
+
+TESTS = [
+ GitTestCase.new('maloader',
+ 'https://github.com/shinh/maloader.git',
+ '5d125933bc6c141bed05c309c2dc0e14ada6f5c7',
+ DO_NOTHING,
+ MAKE_CLEAN,
+ ''),
+ GitTestCase.new('glog',
+ 'https://github.com/google/glog',
+ '1b0b08c8dda1659027677966b03a3ff3c488e549',
+ CONFIGURE,
+ MAKE_CLEAN,
+ ''),
+ AndroidTestCase.new(),
+]
+
+fails = []
+TESTS.each do |tc|
+ if !ARGV.empty?
+ if !ARGV.include?(tc.name)
+ next
+ end
+ end
+
+ if !tc.run
+ fails << tc.name
+ end
+end
+
+puts
+
+if fails.empty?
+ puts "PASS!"
+else
+ puts "=== Failures ==="
+ fails.each do |n|
+ puts n
+ end
+ puts
+
+ puts "FAIL!"
+end
diff --git a/runtest.rb b/runtest.rb
index bf42bfe..7123113 100755
--- a/runtest.rb
+++ b/runtest.rb
@@ -341,6 +341,7 @@ run_shell_test = proc do |sh|
output = normalize_kati_log(output)
if is_ninja_test
output = normalize_ninja_log(output, sh)
+ output.gsub!(/No need to regenerate ninja file\n/, '')
end
File.open('out.make', 'w'){|ofile|ofile.print(expected)}
File.open('out.kati', 'w'){|ofile|ofile.print(output)}
diff --git a/stats.cc b/stats.cc
index 60b3285..9d4a160 100644
--- a/stats.cc
+++ b/stats.cc
@@ -27,37 +27,43 @@
namespace {
-Mutex g_mu;
+mutex g_mu;
vector<Stats*>* g_stats;
+#ifdef __linux__
+thread_local double g_start_time;
+#define REF(x) x
+#else
DEFINE_THREAD_LOCAL(double, g_start_time);
+#define REF(x) x.Ref()
+#endif
} // namespace
Stats::Stats(const char* name)
: name_(name), elapsed_(0), cnt_(0) {
- UniqueLock<Mutex> lock(g_mu);
+ unique_lock<mutex> lock(g_mu);
if (g_stats == NULL)
g_stats = new vector<Stats*>;
g_stats->push_back(this);
}
string Stats::String() const {
- UniqueLock<Mutex> lock(mu_);
+ unique_lock<mutex> lock(mu_);
return StringPrintf("%s: %f / %d", name_, elapsed_, cnt_);
}
void Stats::Start() {
- CHECK(!TLS_REF(g_start_time));
- TLS_REF(g_start_time) = GetTime();
- UniqueLock<Mutex> lock(mu_);
+ CHECK(!REF(g_start_time));
+ REF(g_start_time) = GetTime();
+ unique_lock<mutex> lock(mu_);
cnt_++;
}
double Stats::End() {
- CHECK(TLS_REF(g_start_time));
- double e = GetTime() - TLS_REF(g_start_time);
- TLS_REF(g_start_time) = 0;
- UniqueLock<Mutex> lock(mu_);
+ CHECK(REF(g_start_time));
+ double e = GetTime() - REF(g_start_time);
+ REF(g_start_time) = 0;
+ unique_lock<mutex> lock(mu_);
elapsed_ += e;
return e;
}
diff --git a/stats.h b/stats.h
index 190fa57..6244b54 100644
--- a/stats.h
+++ b/stats.h
@@ -36,7 +36,7 @@ class Stats {
const char* name_;
double elapsed_;
int cnt_;
- mutable Mutex mu_;
+ mutable mutex mu_;
};
class ScopedStatsRecorder {
diff --git a/stmt.cc b/stmt.cc
index 155e0cd..1abab32 100644
--- a/stmt.cc
+++ b/stmt.cc
@@ -55,19 +55,6 @@ string AssignStmt::DebugString() const {
opstr, dirstr, LOCF(loc()));
}
-Symbol AssignStmt::GetLhsSymbol(Evaluator* ev) const {
- if (!lhs->IsLiteral()) {
- string buf;
- lhs->Eval(ev, &buf);
- return Intern(buf);
- }
-
- if (!lhs_sym_cache_.IsValid()) {
- lhs_sym_cache_ = Intern(lhs->GetLiteralValueUnsafe());
- }
- return lhs_sym_cache_;
-}
-
string CommandStmt::DebugString() const {
return StringPrintf("CommandStmt(%s, loc=%s:%d)",
expr->DebugString().c_str(), LOCF(loc()));
diff --git a/stmt.h b/stmt.h
index 3b6feeb..4d4c5eb 100644
--- a/stmt.h
+++ b/stmt.h
@@ -20,7 +20,6 @@
#include "loc.h"
#include "string_piece.h"
-#include "symtab.h"
using namespace std;
@@ -86,19 +85,11 @@ struct AssignStmt : public Stmt {
AssignOp op;
AssignDirective directive;
- AssignStmt()
- : lhs_sym_cache_(Symbol::IsUninitialized{}) {
- }
virtual ~AssignStmt();
virtual void Eval(Evaluator* ev) const;
virtual string DebugString() const;
-
- Symbol GetLhsSymbol(Evaluator* ev) const;
-
- private:
- mutable Symbol lhs_sym_cache_;
};
struct CommandStmt : public Stmt {
diff --git a/string_piece.cc b/string_piece.cc
index d287616..78de4ed 100644
--- a/string_piece.cc
+++ b/string_piece.cc
@@ -21,7 +21,6 @@
#include <ctype.h>
#include <limits.h>
-#include <stdint.h>
#include <algorithm>
#include <ostream>
@@ -33,15 +32,8 @@ typedef StringPiece::size_type size_type;
bool operator==(const StringPiece& x, const StringPiece& y) {
if (x.size() != y.size())
return false;
- size_t len = x.size();
- if (len >= sizeof(uint64_t)) {
- len -= sizeof(uint64_t);
- uint64_t xt = *reinterpret_cast<const uint64_t*>(x.data() + len);
- uint64_t yt = *reinterpret_cast<const uint64_t*>(y.data() + len);
- if (xt != yt)
- return false;
- }
- return StringPiece::wordmemcmp(x.data(), y.data(), len) == 0;
+
+ return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
}
void StringPiece::CopyToString(std::string* target) const {
diff --git a/string_piece_test.cc b/string_piece_test.cc
index 0434cbe..7b253a0 100644
--- a/string_piece_test.cc
+++ b/string_piece_test.cc
@@ -30,8 +30,4 @@ int main() {
assert(sps.size() == 2);
assert(sps.count(StringPiece("foo")) == 1);
assert(sps.count(StringPiece("bar")) == 1);
-
- assert(StringPiece("hogefugahige") == StringPiece("hogefugahige"));
- assert(StringPiece("hogefugahoge") != StringPiece("hogefugahige"));
- assert(StringPiece("hogefugahige") != StringPiece("higefugahige"));
}
diff --git a/strutil.cc b/strutil.cc
index 80a4b5b..0e5e766 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -55,11 +55,11 @@ static int SkipUntilSSE42(const char* s, int len,
WordScanner::Iterator& WordScanner::Iterator::operator++() {
int len = static_cast<int>(in->size());
- for (s = i + 1; s < len; s++) {
+ for (s = i; s < len; s++) {
if (!isSpace((*in)[s]))
break;
}
- if (s >= len) {
+ if (s == len) {
in = NULL;
s = 0;
i = 0;
@@ -92,7 +92,7 @@ WordScanner::Iterator WordScanner::begin() const {
Iterator iter;
iter.in = &in_;
iter.s = 0;
- iter.i = -1;
+ iter.i = 0;
++iter;
return iter;
}
@@ -423,30 +423,6 @@ size_t FindThreeOutsideParen(StringPiece s, char c1, char c2, char c3) {
}
size_t FindEndOfLine(StringPiece s, size_t e, size_t* lf_cnt) {
-#ifdef __SSE4_2__
- static const char ranges[] = "\n\n\\\\";
- while (e < s.size()) {
- e += SkipUntilSSE42(s.data() + e, s.size() - e, ranges, 4);
- char c = s[e];
- if (c == '\\') {
- if (s[e+1] == '\n') {
- e += 2;
- ++*lf_cnt;
- } else if (s[e+1] == '\r' && s[e+2] == '\n') {
- e += 3;
- ++*lf_cnt;
- } else if (s[e+1] == '\\') {
- e += 2;
- } else {
- e++;
- }
- } else if (c == '\n') {
- ++*lf_cnt;
- return e;
- }
- }
- return e;
-#else
bool prev_backslash = false;
for (; e < s.size(); e++) {
char c = s[e];
@@ -463,7 +439,6 @@ size_t FindEndOfLine(StringPiece s, size_t e, size_t* lf_cnt) {
}
}
return e;
-#endif
}
StringPiece TrimLeadingCurdir(StringPiece s) {
@@ -521,33 +496,3 @@ string EchoEscape(const string str) {
}
return buf;
}
-
-void EscapeShell(string* s) {
- if (s->find_first_of("$`\\\"") == string::npos)
- return;
- string r;
- bool last_dollar = false;
- for (char c : *s) {
- switch (c) {
- case '$':
- if (last_dollar) {
- r += c;
- last_dollar = false;
- } else {
- r += '\\';
- r += c;
- last_dollar = true;
- }
- break;
- case '`':
- case '"':
- case '\\':
- r += '\\';
- // fall through.
- default:
- r += c;
- last_dollar = false;
- }
- }
- s->swap(r);
-}
diff --git a/strutil.h b/strutil.h
index 12e46a5..5938efb 100644
--- a/strutil.h
+++ b/strutil.h
@@ -142,6 +142,4 @@ string ConcatDir(StringPiece b, StringPiece n);
string EchoEscape(const string str);
-void EscapeShell(string* s);
-
#endif // STRUTIL_H_
diff --git a/symtab.cc b/symtab.cc
index af0b620..d8d7e93 100644
--- a/symtab.cc
+++ b/symtab.cc
@@ -14,13 +14,8 @@
// +build ignore
-//#define ENABLE_TID_CHECK
-
#include "symtab.h"
-#ifdef ENABLE_TID_CHECK
-#include <pthread.h>
-#endif
#include <string.h>
#include <unordered_map>
@@ -40,10 +35,6 @@ Symbol::Symbol(int v)
class Symtab {
public:
Symtab() {
-#ifdef ENABLE_TID_CHECK
- tid_ = pthread_self();
-#endif
-
CHECK(g_symbols == NULL);
g_symbols = &symbols_;
@@ -81,11 +72,6 @@ class Symtab {
}
Symbol Intern(StringPiece s) {
-#ifdef ENABLE_TID_CHECK
- if (tid_ != pthread_self())
- abort();
-#endif
-
if (s.size() <= 1) {
return Symbol(s.empty() ? 0 : (unsigned char)s[0]);
}
@@ -95,9 +81,6 @@ class Symtab {
private:
unordered_map<StringPiece, Symbol> symtab_;
vector<string*> symbols_;
-#ifdef ENABLE_TID_CHECK
- pthread_t tid_;
-#endif
};
static Symtab* g_symtab;
diff --git a/testcase/ninja_mkdir.sh b/testcase/ninja_mkdir.sh
deleted file mode 100644
index e54298d..0000000
--- a/testcase/ninja_mkdir.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2016 Google Inc. All rights reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http:#www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -e
-
-log=/tmp/log
-mk="$@"
-
-cat <<EOF > Makefile
-test: a/b
-
-a/b:
- @mkdir -p \$(dir \$@)
- touch \$@
-EOF
-
-${mk} 2> ${log}
-if [ -e ninja.sh ]; then
- ./ninja.sh
-fi
-if [[ ! -d a ]]; then
- echo "Created 'a'"
-fi
-if [ -e ninja.sh ]; then
- if grep -q "mkdir -p" build.ninja; then
- echo "Should not include 'mkdir -p' in build.ninja"
- echo "Ninja will automatically create this directory"
- fi
-fi
diff --git a/testcase/shell_var_with_args.mk b/testcase/shell_var_with_args.mk
deleted file mode 100644
index ca7b54a..0000000
--- a/testcase/shell_var_with_args.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-# TODO(go): Fix
-
-export FOO=-x
-
-SHELL := PS4="cmd: " /bin/bash $${FOO}
-$(info $(shell echo foo))
-
-test:
- @echo baz
diff --git a/testcase/sort.mk b/testcase/sort.mk
index bf67a14..c521289 100644
--- a/testcase/sort.mk
+++ b/testcase/sort.mk
@@ -1,12 +1,5 @@
-sp := $(subst S, ,S)
-
test:
echo $(sort foo bar lose)
echo $(sort foo bar aaaa)
echo $(sort foo bar lose lose foo bar bar)
- echo $(sort baz bar)
- echo $(sort single)
- echo $(sort $(sp)foo$(sp))
echo $(sort )
- echo $(sort device/sample/products/AndroidProducts.mk device/moto/shamu/AndroidProducts.mk device/asus/fugu/AndroidProducts.mk device/asus/deb/AndroidProducts.mk device/asus/flo/AndroidProducts.mk device/generic/arm64/AndroidProducts.mk device/generic/qemu/AndroidProducts.mk device/generic/mini-emulator-x86_64/AndroidProducts.mk device/generic/x86/AndroidProducts.mk device/generic/mips/AndroidProducts.mk device/generic/mini-emulator-x86/AndroidProducts.mk device/generic/mini-emulator-mips/AndroidProducts.mk device/generic/mini-emulator-arm64/AndroidProducts.mk device/generic/mini-emulator-armv7-a-neon/AndroidProducts.mk device/generic/x86_64/AndroidProducts.mk device/generic/armv7-a-neon/AndroidProducts.mk device/htc/flounder/AndroidProducts.mk device/lge/bullhead/AndroidProducts.mk device/lge/hammerhead/AndroidProducts.mk device/huawei/angler/AndroidProducts.mk)
- echo $(sort cpplint-art-phony libart libartd libgabi++ libopenjdkjvm libopenjdkjvmd libart)
diff --git a/thread_local.h b/thread_local.h
index 28b146a..3bbf663 100644
--- a/thread_local.h
+++ b/thread_local.h
@@ -39,13 +39,6 @@
#include "log.h"
-#ifdef __linux__
-
-#define DEFINE_THREAD_LOCAL(Type, name) thread_local Type name
-#define TLS_REF(x) x
-
-#else
-
// Thread local storage implementation which uses pthread.
// Note that DEFINE_THREAD_LOCAL creates a global variable just like
// thread local storage based on __thread keyword. So we should not use
@@ -95,8 +88,4 @@ class ThreadLocal {
} \
ThreadLocal<Type, &name##_key, &name##_once> name;
-#define TLS_REF(x) x.Ref()
-
-#endif
-
#endif // THREAD_LOCAL_H_
diff --git a/thread_pool.cc b/thread_pool.cc
index c504ef5..ba7ee00 100644
--- a/thread_pool.cc
+++ b/thread_pool.cc
@@ -17,7 +17,6 @@
#include <stack>
#include <vector>
-#include "affinity.h"
#include "condvar.h"
#include "mutex.h"
#include "thread.h"
@@ -26,7 +25,6 @@ class ThreadPoolImpl : public ThreadPool {
public:
explicit ThreadPoolImpl(int num_threads)
: is_waiting_(false) {
- SetAffinityForMultiThread();
threads_.reserve(num_threads);
for (int i = 0; i < num_threads; i++) {
threads_.push_back(thread([this]() { Loop(); }));
@@ -37,14 +35,14 @@ class ThreadPoolImpl : public ThreadPool {
}
virtual void Submit(function<void(void)> task) override {
- UniqueLock<Mutex> lock(mu_);
+ unique_lock<mutex> lock(mu_);
tasks_.push(task);
cond_.notify_one();
}
virtual void Wait() override {
{
- UniqueLock<Mutex> lock(mu_);
+ unique_lock<mutex> lock(mu_);
is_waiting_ = true;
cond_.notify_all();
}
@@ -52,8 +50,6 @@ class ThreadPoolImpl : public ThreadPool {
for (thread& th : threads_) {
th.join();
}
-
- SetAffinityForSingleThread();
}
private:
@@ -61,7 +57,7 @@ class ThreadPoolImpl : public ThreadPool {
while (true) {
function<void(void)> task;
{
- UniqueLock<Mutex> lock(mu_);
+ unique_lock<mutex> lock(mu_);
if (tasks_.empty()) {
if (is_waiting_)
return;
@@ -79,7 +75,7 @@ class ThreadPoolImpl : public ThreadPool {
}
vector<thread> threads_;
- Mutex mu_;
+ mutex mu_;
condition_variable cond_;
stack<function<void(void)>> tasks_;
bool is_waiting_;
diff --git a/var.cc b/var.cc
index a5cde3e..d21dc4f 100644
--- a/var.cc
+++ b/var.cc
@@ -47,10 +47,6 @@ void Var::AppendVar(Evaluator*, Value*) {
CHECK(false);
}
-SimpleVar::SimpleVar(VarOrigin origin)
- : origin_(origin) {
-}
-
SimpleVar::SimpleVar(const string& v, VarOrigin origin)
: v_(v), origin_(origin) {
}
@@ -125,7 +121,7 @@ Var* Vars::Lookup(Symbol name) const {
}
void Vars::Assign(Symbol name, Var* v) {
- auto p = emplace(name, v);
+ auto p = insert(make_pair(name, v));
if (!p.second) {
Var* orig = p.first->second;
if (orig->Origin() == VarOrigin::OVERRIDE ||
@@ -145,7 +141,7 @@ unordered_set<Symbol> Vars::used_env_vars_;
ScopedVar::ScopedVar(Vars* vars, Symbol name, Var* var)
: vars_(vars), orig_(NULL) {
- auto p = vars->emplace(name, var);
+ auto p = vars->insert(make_pair(name, var));
iter_ = p.first;
if (!p.second) {
orig_ = iter_->second;
diff --git a/var.h b/var.h
index 5ba5fcb..3bae262 100644
--- a/var.h
+++ b/var.h
@@ -62,26 +62,23 @@ class Var : public Evaluable {
class SimpleVar : public Var {
public:
- explicit SimpleVar(VarOrigin origin);
SimpleVar(const string& v, VarOrigin origin);
- virtual const char* Flavor() const override {
+ virtual const char* Flavor() const {
return "simple";
}
- virtual VarOrigin Origin() const override {
+ virtual VarOrigin Origin() const {
return origin_;
}
virtual void Eval(Evaluator* ev, string* s) const override;
- virtual void AppendVar(Evaluator* ev, Value* v) override;
+ virtual void AppendVar(Evaluator* ev, Value* v);
virtual StringPiece String() const override;
virtual string DebugString() const override;
- string* mutable_value() { return &v_; }
-
private:
string v_;
VarOrigin origin_;
@@ -91,16 +88,16 @@ class RecursiveVar : public Var {
public:
RecursiveVar(Value* v, VarOrigin origin, StringPiece orig);
- virtual const char* Flavor() const override {
+ virtual const char* Flavor() const {
return "recursive";
}
- virtual VarOrigin Origin() const override {
+ virtual VarOrigin Origin() const {
return origin_;
}
virtual void Eval(Evaluator* ev, string* s) const override;
- virtual void AppendVar(Evaluator* ev, Value* v) override;
+ virtual void AppendVar(Evaluator* ev, Value* v);
virtual StringPiece String() const override;
@@ -116,13 +113,13 @@ class UndefinedVar : public Var {
public:
UndefinedVar();
- virtual const char* Flavor() const override {
+ virtual const char* Flavor() const {
return "undefined";
}
- virtual VarOrigin Origin() const override {
+ virtual VarOrigin Origin() const {
return VarOrigin::UNDEFINED;
}
- virtual bool IsDefined() const override { return false; }
+ virtual bool IsDefined() const { return false; }
virtual void Eval(Evaluator* ev, string* s) const override;
@@ -141,19 +138,19 @@ class RuleVar : public Var {
delete v_;
}
- virtual const char* Flavor() const override {
+ virtual const char* Flavor() const {
return v_->Flavor();
}
- virtual VarOrigin Origin() const override {
+ virtual VarOrigin Origin() const {
return v_->Origin();
}
- virtual bool IsDefined() const override {
+ virtual bool IsDefined() const {
return v_->IsDefined();
}
- virtual void Eval(Evaluator* ev, string* s) const override {
+ virtual void Eval(Evaluator* ev, string* s) const {
v_->Eval(ev, s);
}
- virtual void AppendVar(Evaluator* ev, Value* v) override {
+ virtual void AppendVar(Evaluator* ev, Value* v) {
v_->AppendVar(ev, v);
}
virtual StringPiece String() const override {