aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2018-02-27 00:25:01 -0800
committerDan Willemsen <dwillemsen@google.com>2018-02-27 03:14:23 -0800
commitc3f6a9791d9b747a49dfd02602bb5662ba6e2783 (patch)
treee78b0345bfc5a080fb757ba5406cfd0cded2a600
parent575ebd04c5a3c305233b6ad8d8952a6295160f25 (diff)
downloadkati-c3f6a9791d9b747a49dfd02602bb5662ba6e2783.tar.gz
Add KATI_(deprecate|obsolete)_export
Allow makefiles to mark the `export` and `unexport` keywords as deprecated or obsolete. In large builds like Android, we've got our own ways to set global environment variables, it's very unlikely that individual makefiles need to set an environment variable for every single rule. We expect to eventually add environment variables to the list of inputs that ninja checks to see if a command needs to run again (currently it just checks the timestamps and commandline). Reducing the ability for makefiles to export global variables per-configuration means that we're more likely to share compile steps between configurations. Change-Id: I8df0630ef264e39fd077b08dcac57e571ebe214f
-rw-r--r--eval.cc24
-rw-r--r--eval.h14
-rw-r--r--func.cc32
-rw-r--r--testcase/deprecated_export.mk21
-rw-r--r--testcase/err_obsolete_export.mk7
5 files changed, 95 insertions, 3 deletions
diff --git a/eval.cc b/eval.cc
index cf3f859..fa7bebb 100644
--- a/eval.cc
+++ b/eval.cc
@@ -38,6 +38,7 @@ Evaluator::Evaluator()
eval_depth_(0),
posix_sym_(Intern(".POSIX")),
is_posix_(false),
+ export_error_(false),
kati_readonly_(Intern(".KATI_READONLY")) {
#if defined(__APPLE__)
stack_size_ = pthread_get_stacksize_np(pthread_self());
@@ -358,18 +359,35 @@ void Evaluator::EvalExport(const ExportStmt* stmt) {
const string&& exports = stmt->expr->Eval(this);
for (StringPiece tok : WordScanner(exports)) {
size_t equal_index = tok.find('=');
+ StringPiece lhs;
if (equal_index == string::npos) {
- exports_[Intern(tok)] = stmt->is_export;
+ lhs = tok;
} else if (equal_index == 0 ||
(equal_index == 1 &&
(tok[0] == ':' || tok[0] == '?' || tok[0] == '+'))) {
// Do not export tokens after an assignment.
break;
} else {
- StringPiece lhs, rhs;
+ StringPiece rhs;
AssignOp op;
ParseAssignStatement(tok, equal_index, &lhs, &rhs, &op);
- exports_[Intern(lhs)] = stmt->is_export;
+ }
+ Symbol sym = Intern(lhs);
+ exports_[sym] = stmt->is_export;
+
+ if (export_message_) {
+ const char* prefix = "";
+ if (!stmt->is_export) {
+ prefix = "un";
+ }
+
+ if (export_error_) {
+ Error(StringPrintf("*** %s: %sexport is obsolete%s.", sym.c_str(),
+ prefix, export_message_->c_str()));
+ } else {
+ WARN_LOC(loc(), "%s: %sexport has been deprecated%s.", sym.c_str(),
+ prefix, export_message_->c_str());
+ }
}
}
}
diff --git a/eval.h b/eval.h
index e588f7e..4fb5f05 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>
@@ -98,6 +99,16 @@ class Evaluator {
}
void DumpStackStats() const;
+ bool ExportDeprecated() const { return export_message_ && !export_error_; };
+ bool ExportObsolete() const { return export_error_; };
+ void SetExportDeprecated(StringPiece msg) {
+ export_message_.reset(new string(msg.as_string()));
+ }
+ void SetExportObsolete(StringPiece msg) {
+ export_message_.reset(new string(msg.as_string()));
+ export_error_ = true;
+ }
+
private:
Var* EvalRHS(Symbol lhs,
Value* rhs,
@@ -139,6 +150,9 @@ class Evaluator {
void* lowest_stack_;
Loc lowest_loc_;
+ unique_ptr<string> export_message_;
+ bool export_error_;
+
static unordered_set<Symbol> used_undefined_vars_;
Symbol kati_readonly_;
diff --git a/func.cc b/func.cc
index 1dea7bb..c033d3b 100644
--- a/func.cc
+++ b/func.cc
@@ -892,6 +892,36 @@ void ObsoleteVarFunc(const vector<Value*>& args, Evaluator* ev, string*) {
}
}
+void DeprecateExportFunc(const vector<Value*>& args, Evaluator* ev, string*) {
+ string msg = ". " + args[0]->Eval(ev);
+
+ if (ev->avoid_io()) {
+ ev->Error("*** $(KATI_deprecate_export) is not supported in rules.");
+ }
+
+ if (ev->ExportObsolete()) {
+ ev->Error("*** Export is already obsolete.");
+ } else if (ev->ExportDeprecated()) {
+ ev->Error("*** Export is already deprecated.");
+ }
+
+ ev->SetExportDeprecated(msg);
+}
+
+void ObsoleteExportFunc(const vector<Value*>& args, Evaluator* ev, string*) {
+ string msg = ". " + args[0]->Eval(ev);
+
+ if (ev->avoid_io()) {
+ ev->Error("*** $(KATI_obsolete_export) is not supported in rules.");
+ }
+
+ if (ev->ExportObsolete()) {
+ ev->Error("*** Export is already obsolete.");
+ }
+
+ ev->SetExportObsolete(msg);
+}
+
FuncInfo g_func_infos[] = {
{"patsubst", &PatsubstFunc, 3, 3, false, false},
{"strip", &StripFunc, 1, 1, false, false},
@@ -939,6 +969,8 @@ FuncInfo g_func_infos[] = {
/* Kati custom extension functions */
{"KATI_deprecated_var", &DeprecatedVarFunc, 2, 1, false, false},
{"KATI_obsolete_var", &ObsoleteVarFunc, 2, 1, false, false},
+ {"KATI_deprecate_export", &DeprecateExportFunc, 1, 1, false, false},
+ {"KATI_obsolete_export", &ObsoleteExportFunc, 1, 1, false, false},
};
unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
diff --git a/testcase/deprecated_export.mk b/testcase/deprecated_export.mk
new file mode 100644
index 0000000..3744f70
--- /dev/null
+++ b/testcase/deprecated_export.mk
@@ -0,0 +1,21 @@
+# TODO(go): not implemented
+
+A := 1
+B := 2
+export A B
+
+$(KATI_deprecate_export Message)
+
+export C := ok
+unexport B
+
+ifndef KATI
+$(info Makefile:9: C: export has been deprecated. Message.)
+$(info Makefile:10: B: unexport has been deprecated. Message.)
+endif
+
+test:
+ echo $$(A)
+ echo $$(B)
+ echo $$(C)
+ echo Done
diff --git a/testcase/err_obsolete_export.mk b/testcase/err_obsolete_export.mk
new file mode 100644
index 0000000..bf78dc3
--- /dev/null
+++ b/testcase/err_obsolete_export.mk
@@ -0,0 +1,7 @@
+# TODO(go): not implemented
+
+export A := ok
+
+$(KATI_obsolete_export Message)
+
+export B := fail $(or $(KATI),$(error B: export is obsolete. Message))