blob: e89e17bfd39e79575885bc92cce43d9318ca7f67 [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +090017#include <limits.h>
Dan Willemsenfcc71f82017-10-11 18:35:09 -070018#include <signal.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090019#include <stdio.h>
Shinichiro Hamaji087cecd2015-07-06 19:51:58 +090020#include <stdlib.h>
Dan Willemsen3ce083f2017-10-11 22:17:48 -070021#include <string.h>
Shinichiro Hamajia4bb7742015-07-31 11:27:30 +090022#include <time.h>
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +090023#include <unistd.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090024
Shinichiro Hamaji1a444a82016-02-16 13:49:49 +090025#include "affinity.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090026#include "dep.h"
27#include "eval.h"
28#include "exec.h"
29#include "file.h"
30#include "file_cache.h"
31#include "fileutil.h"
Shinichiro Hamaji5f57a992015-06-30 19:39:39 +090032#include "find.h"
Shinichiro Hamaji08808d32015-06-26 08:02:45 +090033#include "flags.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090034#include "func.h"
35#include "log.h"
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090036#include "ninja.h"
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090037#include "parser.h"
Shinichiro Hamaji8ef0ce52016-01-19 18:07:43 +090038#include "regen.h"
Shinichiro Hamaji0d8e79b2015-06-30 03:29:35 +090039#include "stats.h"
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090040#include "stmt.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090041#include "string_piece.h"
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +090042#include "stringprintf.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090043#include "strutil.h"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090044#include "symtab.h"
Shinichiro Hamajicbd34cd2015-07-05 02:53:04 +090045#include "timeutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090046#include "var.h"
47
Dan Willemsen834c6db2017-08-15 14:44:32 -070048// We know that there are leaks in Kati. Turn off LeakSanitizer by default.
49extern "C" const char* __asan_default_options() {
Dan Willemsenfcc71f82017-10-11 18:35:09 -070050 return "detect_leaks=0:allow_user_segv_handler=1";
Dan Willemsen834c6db2017-08-15 14:44:32 -070051}
52
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090053static void Init() {
54 InitSymtab();
55 InitFuncTable();
56 InitDepNodePool();
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090057 InitParser();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090058}
59
60static void Quit() {
Shinichiro Hamaji0d8e79b2015-06-30 03:29:35 +090061 ReportAllStats();
62
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090063 QuitParser();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090064 QuitDepNodePool();
65 QuitFuncTable();
66 QuitSymtab();
67}
68
Shinichiro Hamajie7992752015-06-29 18:38:35 +090069static void ReadBootstrapMakefile(const vector<Symbol>& targets,
Shinichiro Hamaji645cca72015-09-24 17:04:21 +090070 vector<Stmt*>* stmts) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -070071 string bootstrap =
72 ("CC?=cc\n"
Shinichiro Hamajid749b932015-07-13 20:51:15 -070073#if defined(__APPLE__)
Dan Willemsen3ce083f2017-10-11 22:17:48 -070074 "CXX?=c++\n"
Shinichiro Hamajid749b932015-07-13 20:51:15 -070075#else
Dan Willemsen3ce083f2017-10-11 22:17:48 -070076 "CXX?=g++\n"
Shinichiro Hamajid749b932015-07-13 20:51:15 -070077#endif
Dan Willemsen3ce083f2017-10-11 22:17:48 -070078 "AR?=ar\n"
79 // Pretend to be GNU make 3.81, for compatibility.
80 "MAKE_VERSION?=3.81\n"
81 "KATI?=ckati\n"
82 // Overwrite $SHELL environment variable.
83 "SHELL=/bin/sh\n"
84 // TODO: Add more builtin vars.
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +090085
Dan Willemsen3ce083f2017-10-11 22:17:48 -070086 // http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
87 // The document above is actually not correct. See default.c:
88 // http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
89 ".c.o:\n"
90 "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
91 ".cc.o:\n"
92 "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
93 // TODO: Add more builtin rules.
94 );
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +090095 if (g_flags.generate_ninja) {
Shinichiro Hamajib6a04542015-09-09 17:37:41 +090096 bootstrap += StringPrintf("MAKE?=make -j%d\n",
Shinichiro Hamaji9dce4442015-12-05 11:05:00 +090097 g_flags.num_jobs <= 1 ? 1 : g_flags.num_jobs / 2);
Shinichiro Hamajib6a04542015-09-09 17:37:41 +090098 } else {
99 bootstrap += StringPrintf("MAKE?=%s\n",
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900100 JoinStrings(g_flags.subkati_args, " ").c_str());
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900101 }
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700102 bootstrap +=
103 StringPrintf("MAKECMDGOALS?=%s\n", JoinSymbols(targets, " ").c_str());
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900104
105 char cwd[PATH_MAX];
106 if (!getcwd(cwd, PATH_MAX)) {
107 fprintf(stderr, "getcwd failed\n");
108 CHECK(false);
109 }
110 bootstrap += StringPrintf("CURDIR:=%s\n", cwd);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900111 Parse(Intern(bootstrap).str(), Loc("*bootstrap*", 0), stmts);
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900112}
113
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900114static void SetVar(StringPiece l, VarOrigin origin) {
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900115 size_t found = l.find('=');
116 CHECK(found != string::npos);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900117 Symbol lhs = Intern(l.substr(0, found));
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900118 StringPiece rhs = l.substr(found + 1);
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900119 lhs.SetGlobalVar(
120 new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900121}
122
123extern "C" char** environ;
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900124
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700125class SegfaultHandler {
126 public:
127 explicit SegfaultHandler(Evaluator* ev);
128 ~SegfaultHandler();
129
130 void handle(int, siginfo_t*, void*);
131
132 private:
133 static SegfaultHandler* global_handler;
134
135 void dumpstr(const char* s) const {
136 (void)write(STDERR_FILENO, s, strlen(s));
137 }
138 void dumpint(int i) const {
139 char buf[11];
140 char* ptr = buf + sizeof(buf) - 1;
141
142 if (i < 0) {
143 i = -i;
144 dumpstr("-");
145 } else if (i == 0) {
146 dumpstr("0");
147 return;
148 }
149
150 *ptr = '\0';
151 while (ptr > buf && i > 0) {
152 *--ptr = '0' + (i % 10);
153 i = i / 10;
154 }
155
156 dumpstr(ptr);
157 }
158
159 Evaluator* ev_;
160
161 struct sigaction orig_action_;
162 struct sigaction new_action_;
163};
164
165SegfaultHandler* SegfaultHandler::global_handler = nullptr;
166
167SegfaultHandler::SegfaultHandler(Evaluator* ev) : ev_(ev) {
168 CHECK(global_handler == nullptr);
169 global_handler = this;
170
171 // Construct an alternate stack, so that we can handle stack overflows.
172 stack_t ss;
173 ss.ss_sp = malloc(SIGSTKSZ * 2);
174 CHECK(ss.ss_sp != nullptr);
175 ss.ss_size = SIGSTKSZ * 2;
176 ss.ss_flags = 0;
177 if (sigaltstack(&ss, nullptr) == -1) {
178 PERROR("sigaltstack");
179 }
180
181 // Register our segfault handler using the alternate stack, falling
182 // back to the default handler.
183 sigemptyset(&new_action_.sa_mask);
184 new_action_.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESETHAND;
185 new_action_.sa_sigaction = [](int sig, siginfo_t* info, void* context) {
186 if (global_handler != nullptr) {
187 global_handler->handle(sig, info, context);
188 }
189
190 raise(SIGSEGV);
191 };
192 sigaction(SIGSEGV, &new_action_, &orig_action_);
193}
194
195void SegfaultHandler::handle(int sig, siginfo_t* info, void* context) {
196 // Avoid fprintf in case it allocates or tries to do anything else that may
197 // hang.
198 dumpstr("*kati*: Segmentation fault, last evaluated line was ");
199 dumpstr(ev_->loc().filename);
200 dumpstr(":");
201 dumpint(ev_->loc().lineno);
202 dumpstr("\n");
203
204 // Run the original handler, in case we've been preloaded with libSegFault
205 // or similar.
206 if (orig_action_.sa_sigaction != nullptr) {
207 orig_action_.sa_sigaction(sig, info, context);
208 }
209}
210
211SegfaultHandler::~SegfaultHandler() {
212 sigaction(SIGSEGV, &orig_action_, nullptr);
213 global_handler = nullptr;
214}
215
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900216static int Run(const vector<Symbol>& targets,
Shinichiro Hamaji998ccf72015-07-18 12:37:02 +0900217 const vector<StringPiece>& cl_vars,
218 const string& orig_args) {
Shinichiro Hamaji90db5412015-08-13 15:03:52 +0900219 double start_time = GetTime();
220
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900221 if (g_flags.generate_ninja && (g_flags.regen || g_flags.dump_kati_stamp)) {
Shinichiro Hamajif9e15242015-07-31 12:50:06 +0900222 ScopedTimeReporter tr("regen check time");
Shinichiro Hamajif9869fc2015-09-28 17:18:59 +0900223 if (!NeedsRegen(start_time, orig_args)) {
Shinichiro Hamajiac50ff42016-02-09 16:23:28 +0900224 fprintf(stderr, "No need to regenerate ninja file\n");
Shinichiro Hamajif6df3342015-08-11 14:59:36 +0900225 return 0;
226 }
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900227 if (g_flags.dump_kati_stamp) {
Shinichiro Hamajif6df3342015-08-11 14:59:36 +0900228 printf("Need to regenerate ninja file\n");
Shinichiro Hamajia4bb7742015-07-31 11:27:30 +0900229 return 0;
230 }
Shinichiro Hamajia09ed282015-07-31 12:21:54 +0900231 ClearGlobCache();
Shinichiro Hamajia4bb7742015-07-31 11:27:30 +0900232 }
233
Shinichiro Hamaji1a444a82016-02-16 13:49:49 +0900234 SetAffinityForSingleThread();
235
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900236 MakefileCacheManager* cache_mgr = NewMakefileCacheManager();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900237
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700238 Intern("MAKEFILE_LIST")
239 .SetGlobalVar(new SimpleVar(StringPrintf(" %s", g_flags.makefile),
240 VarOrigin::FILE));
Shinichiro Hamaji91d12492015-09-04 09:54:48 +0900241 for (char** p = environ; *p; p++) {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900242 SetVar(*p, VarOrigin::ENVIRONMENT);
Shinichiro Hamaji91d12492015-09-04 09:54:48 +0900243 }
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700244 unique_ptr<Evaluator> ev(new Evaluator());
245 SegfaultHandler segfault(ev.get());
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900246
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900247 vector<Stmt*> bootstrap_asts;
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900248 ReadBootstrapMakefile(targets, &bootstrap_asts);
249 ev->set_is_bootstrap(true);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900250 for (Stmt* stmt : bootstrap_asts) {
251 LOG("%s", stmt->DebugString().c_str());
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700252 stmt->Eval(ev.get());
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900253 }
254 ev->set_is_bootstrap(false);
255
Shinichiro Hamaji1c3a6952016-05-20 16:35:35 +0900256 ev->set_is_commandline(true);
Shinichiro Hamaji91d12492015-09-04 09:54:48 +0900257 for (StringPiece l : cl_vars) {
Shinichiro Hamaji1c3a6952016-05-20 16:35:35 +0900258 vector<Stmt*> asts;
259 Parse(Intern(l).str(), Loc("*bootstrap*", 0), &asts);
260 CHECK(asts.size() == 1);
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700261 asts[0]->Eval(ev.get());
Shinichiro Hamaji91d12492015-09-04 09:54:48 +0900262 }
Shinichiro Hamaji1c3a6952016-05-20 16:35:35 +0900263 ev->set_is_commandline(false);
Shinichiro Hamaji91d12492015-09-04 09:54:48 +0900264
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900265 {
266 ScopedTimeReporter tr("eval time");
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900267 Makefile* mk = cache_mgr->ReadMakefile(g_flags.makefile);
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900268 for (Stmt* stmt : mk->stmts()) {
269 LOG("%s", stmt->DebugString().c_str());
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700270 stmt->Eval(ev.get());
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900271 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900272 }
273
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900274 for (ParseErrorStmt* err : GetParseErrors()) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800275 WARN_LOC(err->loc(), "warning for parse error in an unevaluated line: %s",
276 err->msg.c_str());
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900277 }
278
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900279 vector<DepNode*> nodes;
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900280 {
281 ScopedTimeReporter tr("make dep time");
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700282 MakeDep(ev.get(), ev->rules(), ev->rule_vars(), targets, &nodes);
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900283 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900284
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900285 if (g_flags.is_syntax_check_only)
Shinichiro Hamajied883ef2015-07-31 13:15:04 +0900286 return 0;
287
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900288 if (g_flags.generate_ninja) {
Shinichiro Hamajied883ef2015-07-31 13:15:04 +0900289 ScopedTimeReporter tr("generate ninja time");
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700290 GenerateNinja(nodes, ev.get(), orig_args, start_time);
Dan Willemsen36e57292017-10-09 11:23:32 -0700291 ev->DumpStackStats();
Shinichiro Hamajied883ef2015-07-31 13:15:04 +0900292 return 0;
293 }
294
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900295 for (const auto& p : ev->exports()) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900296 const Symbol name = p.first;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900297 if (p.second) {
298 Var* v = ev->LookupVar(name);
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700299 const string&& value = v->Eval(ev.get());
Shinichiro Hamajifb415ad2015-08-14 17:19:34 +0900300 LOG("setenv(%s, %s)", name.c_str(), value.c_str());
301 setenv(name.c_str(), value.c_str(), 1);
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900302 } else {
303 LOG("unsetenv(%s)", name.c_str());
304 unsetenv(name.c_str());
305 }
306 }
307
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900308 {
309 ScopedTimeReporter tr("exec time");
Dan Willemsenfcc71f82017-10-11 18:35:09 -0700310 Exec(nodes, ev.get());
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900311 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900312
Dan Willemsen36e57292017-10-09 11:23:32 -0700313 ev->DumpStackStats();
314
Shinichiro Hamaji645cca72015-09-24 17:04:21 +0900315 for (Stmt* stmt : bootstrap_asts)
316 delete stmt;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900317 delete cache_mgr;
318
Shinichiro Hamaji64cd8062015-06-27 16:58:36 +0900319 return 0;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900320}
321
Shinichiro Hamaji34556cc2015-10-05 15:01:46 +0900322static void FindFirstMakefie() {
323 if (g_flags.makefile != NULL)
324 return;
325 if (Exists("GNUmakefile")) {
326 g_flags.makefile = "GNUmakefile";
327#if !defined(__APPLE__)
328 } else if (Exists("makefile")) {
329 g_flags.makefile = "makefile";
330#endif
331 } else if (Exists("Makefile")) {
332 g_flags.makefile = "Makefile";
333 }
334}
335
Shinichiro Hamaji71cf60b2015-10-08 18:00:07 +0900336static void HandleRealpath(int argc, char** argv) {
337 char buf[PATH_MAX];
338 for (int i = 0; i < argc; i++) {
339 if (realpath(argv[i], buf))
340 printf("%s\n", buf);
341 }
342}
343
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900344int main(int argc, char* argv[]) {
Shinichiro Hamaji71cf60b2015-10-08 18:00:07 +0900345 if (argc >= 2 && !strcmp(argv[1], "--realpath")) {
346 HandleRealpath(argc - 2, argv + 2);
347 return 0;
348 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900349 Init();
Shinichiro Hamaji998ccf72015-07-18 12:37:02 +0900350 string orig_args;
351 for (int i = 0; i < argc; i++) {
352 if (i)
353 orig_args += ' ';
354 orig_args += argv[i];
355 }
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900356 g_flags.Parse(argc, argv);
Shinichiro Hamaji34556cc2015-10-05 15:01:46 +0900357 FindFirstMakefie();
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900358 if (g_flags.makefile == NULL)
Shinichiro Hamajie4ee8ea2015-08-15 01:22:23 +0900359 ERROR("*** No targets specified and no makefile found.");
Shinichiro Hamaji5f57a992015-06-30 19:39:39 +0900360 // This depends on command line flags.
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900361 if (g_flags.use_find_emulator)
Shinichiro Hamaji4e950e62015-07-02 02:59:55 +0900362 InitFindEmulator();
Shinichiro Hamaji003d06e2015-09-09 18:22:04 +0900363 int r = Run(g_flags.targets, g_flags.cl_vars, orig_args);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900364 Quit();
365 return r;
366}