blob: c293b552c2bf5cf9845c51d6b0ec120c6fb40283 [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>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090018#include <stdio.h>
19#include <string.h>
Shinichiro Hamaji087cecd2015-07-06 19:51:58 +090020#include <stdlib.h>
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +090021#include <unistd.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090022
23#include "ast.h"
24#include "dep.h"
25#include "eval.h"
26#include "exec.h"
27#include "file.h"
28#include "file_cache.h"
29#include "fileutil.h"
Shinichiro Hamaji5f57a992015-06-30 19:39:39 +090030#include "find.h"
Shinichiro Hamaji08808d32015-06-26 08:02:45 +090031#include "flags.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090032#include "func.h"
33#include "log.h"
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090034#include "ninja.h"
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +090035#include "parser.h"
Shinichiro Hamaji0d8e79b2015-06-30 03:29:35 +090036#include "stats.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090037#include "string_piece.h"
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +090038#include "stringprintf.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090039#include "strutil.h"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090040#include "symtab.h"
Shinichiro Hamajicbd34cd2015-07-05 02:53:04 +090041#include "timeutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090042#include "var.h"
43
44static const char* g_makefile;
Shinichiro Hamaji64cd8062015-06-27 16:58:36 +090045static bool g_is_syntax_check_only;
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090046static bool g_generate_ninja;
Shinichiro Hamaji8bddb462015-07-06 18:55:47 +090047static const char* g_ninja_suffix;
Shinichiro Hamaji4e950e62015-07-02 02:59:55 +090048static bool g_use_find_emulator;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090049
Shinichiro Hamaji94d7a612015-06-29 18:16:11 +090050static bool ParseCommandLineOptionWithArg(StringPiece option,
51 char* argv[],
52 int* index,
53 const char** out_arg) {
54 const char* arg = argv[*index];
55 if (!HasPrefix(arg, option))
56 return false;
57 if (arg[option.size()] == '\0') {
58 ++*index;
59 *out_arg = argv[*index];
60 return true;
61 }
62 if (arg[option.size()] == '=') {
63 *out_arg = arg + option.size() + 1;
64 return true;
65 }
Shinichiro Hamaji087cecd2015-07-06 19:51:58 +090066 // E.g, -j999
67 if (option.size() == 2) {
68 *out_arg = arg + option.size();
69 return true;
70 }
Shinichiro Hamaji94d7a612015-06-29 18:16:11 +090071 return false;
72}
73
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090074static void ParseCommandLine(int argc, char* argv[],
Shinichiro Hamajie7992752015-06-29 18:38:35 +090075 vector<Symbol>* targets,
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +090076 vector<StringPiece>* cl_vars) {
Shinichiro Hamaji087cecd2015-07-06 19:51:58 +090077 // TODO: Decide the appropriate number based on the number of cores.
78 g_num_jobs = 32;
79 const char* num_jobs_str;
80
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090081 for (int i = 1; i < argc; i++) {
82 const char* arg = argv[i];
83 if (!strcmp(arg, "-f")) {
84 g_makefile = argv[++i];
Shinichiro Hamaji08808d32015-06-26 08:02:45 +090085 } else if (!strcmp(arg, "-c")) {
86 g_is_syntax_check_only = true;
Shinichiro Hamaji64cd8062015-06-27 16:58:36 +090087 } else if (!strcmp(arg, "-i")) {
88 g_is_dry_run = true;
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +090089 } else if (!strcmp(arg, "--kati_stats")) {
90 g_enable_stat_logs = true;
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +090091 } else if (!strcmp(arg, "--ninja")) {
92 g_generate_ninja = true;
Shinichiro Hamaji8bddb462015-07-06 18:55:47 +090093 } else if (ParseCommandLineOptionWithArg(
Shinichiro Hamaji087cecd2015-07-06 19:51:58 +090094 "-j", argv, &i, &num_jobs_str)) {
95 g_num_jobs = strtol(num_jobs_str, NULL, 10);
96 if (g_num_jobs <= 0) {
97 ERROR("Invalid -j flag: %s", num_jobs_str);
98 }
99 } else if (ParseCommandLineOptionWithArg(
Shinichiro Hamaji8bddb462015-07-06 18:55:47 +0900100 "--ninja_suffix", argv, &i, &g_ninja_suffix)) {
Shinichiro Hamaji4e950e62015-07-02 02:59:55 +0900101 } else if (!strcmp(arg, "--use_find_emulator")) {
102 g_use_find_emulator = true;
Shinichiro Hamaji94d7a612015-06-29 18:16:11 +0900103 } else if (ParseCommandLineOptionWithArg(
Shinichiro Hamaji9facae22015-07-03 17:16:36 +0900104 "--goma_dir", argv, &i, &g_goma_dir)) {
105 } else if (ParseCommandLineOptionWithArg(
Shinichiro Hamaji94d7a612015-06-29 18:16:11 +0900106 "--ignore_optional_include",
107 argv, &i, &g_ignore_optional_include_pattern)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900108 } else if (arg[0] == '-') {
109 ERROR("Unknown flag: %s", arg);
110 } else {
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900111 if (strchr(arg, '=')) {
112 cl_vars->push_back(arg);
113 } else {
114 targets->push_back(Intern(arg));
115 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900116 }
117 }
118}
119
120static void Init() {
121 InitSymtab();
122 InitFuncTable();
123 InitDepNodePool();
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900124 InitParser();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900125
126 if (g_makefile == NULL) {
127 if (Exists("GNUmakefile")) {
128 g_makefile = "GNUmakefile";
129 } else if (Exists("makefile")) {
130 g_makefile = "makefile";
131 } else if (Exists("Makefile")) {
132 g_makefile = "Makefile";
133 } else {
134 ERROR("*** No targets specified and no makefile found.");
135 }
136 }
137}
138
139static void Quit() {
Shinichiro Hamaji0d8e79b2015-06-30 03:29:35 +0900140 ReportAllStats();
141
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900142 QuitParser();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900143 QuitDepNodePool();
144 QuitFuncTable();
145 QuitSymtab();
146}
147
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900148static void ReadBootstrapMakefile(const vector<Symbol>& targets,
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900149 vector<AST*>* asts) {
150 string bootstrap = (
151 "CC:=cc\n"
152 "CXX:=g++\n"
153 "AR:=ar\n"
154 "MAKE:=kati\n"
155 // Pretend to be GNU make 3.81, for compatibility.
156 "MAKE_VERSION:=3.81\n"
157 "SHELL:=/bin/sh\n"
158 // TODO: Add more builtin vars.
159
160 // http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
161 // The document above is actually not correct. See default.c:
162 // http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
163 ".c.o:\n"
164 "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
165 ".cc.o:\n"
166 "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
167 // TODO: Add more builtin rules.
168 );
169 bootstrap += StringPrintf("MAKECMDGOALS:=%s\n",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900170 JoinSymbols(targets, " ").c_str());
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900171
172 char cwd[PATH_MAX];
173 if (!getcwd(cwd, PATH_MAX)) {
174 fprintf(stderr, "getcwd failed\n");
175 CHECK(false);
176 }
177 bootstrap += StringPrintf("CURDIR:=%s\n", cwd);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900178 Parse(Intern(bootstrap).str(), Loc("*bootstrap*", 0), asts);
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900179}
180
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900181static void SetVar(StringPiece l, VarOrigin origin, Vars* vars) {
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900182 size_t found = l.find('=');
183 CHECK(found != string::npos);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900184 Symbol lhs = Intern(l.substr(0, found));
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900185 StringPiece rhs = l.substr(found + 1);
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900186 vars->Assign(lhs,
187 new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900188}
189
190extern "C" char** environ;
191static void FillDefaultVars(const vector<StringPiece>& cl_vars, Vars* vars) {
192 for (char** p = environ; *p; p++) {
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900193 SetVar(*p, VarOrigin::ENVIRONMENT, vars);
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900194 }
195 for (StringPiece l : cl_vars) {
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900196 SetVar(l, VarOrigin::COMMAND_LINE, vars);
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900197 }
198}
199
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900200static int Run(const vector<Symbol>& targets,
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900201 const vector<StringPiece>& cl_vars) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900202 MakefileCacheManager* cache_mgr = NewMakefileCacheManager();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900203
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900204 Vars* vars = new Vars();
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900205 FillDefaultVars(cl_vars, vars);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900206 Evaluator* ev = new Evaluator(vars);
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900207
208 vector<AST*> bootstrap_asts;
209 ReadBootstrapMakefile(targets, &bootstrap_asts);
210 ev->set_is_bootstrap(true);
211 for (AST* ast : bootstrap_asts) {
212 LOG("%s", ast->DebugString().c_str());
213 ast->Eval(ev);
214 }
215 ev->set_is_bootstrap(false);
216
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900217 vars->Assign(Intern("MAKEFILE_LIST"),
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900218 new SimpleVar(make_shared<string>(
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900219 StringPrintf(" %s", g_makefile)), VarOrigin::FILE));
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900220
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900221 {
222 ScopedTimeReporter tr("eval time");
223 Makefile* mk = cache_mgr->ReadMakefile(g_makefile);
224 for (AST* ast : mk->asts()) {
225 LOG("%s", ast->DebugString().c_str());
226 ast->Eval(ev);
227 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900228 }
229
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900230 vector<DepNode*> nodes;
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900231 {
232 ScopedTimeReporter tr("make dep time");
233 MakeDep(ev, ev->rules(), ev->rule_vars(), targets, &nodes);
234 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900235
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900236 for (const auto& p : ev->exports()) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900237 const Symbol name = p.first;
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900238 if (p.second) {
239 Var* v = ev->LookupVar(name);
240 shared_ptr<string> value = v->Eval(ev);
241 LOG("setenv(%s, %s)", name.c_str(), value->c_str());
242 setenv(name.c_str(), value->c_str(), 1);
243 } else {
244 LOG("unsetenv(%s)", name.c_str());
245 unsetenv(name.c_str());
246 }
247 }
248
Shinichiro Hamaji64cd8062015-06-27 16:58:36 +0900249 if (g_is_syntax_check_only)
250 return 0;
251
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900252 if (g_generate_ninja) {
253 ScopedTimeReporter tr("generate ninja time");
Shinichiro Hamaji8bddb462015-07-06 18:55:47 +0900254 GenerateNinja(g_ninja_suffix, nodes, ev);
Shinichiro Hamaji5f86e1a2015-06-29 14:25:39 +0900255 return 0;
256 }
257
Shinichiro Hamaji54e52dd2015-06-27 17:14:06 +0900258 {
259 ScopedTimeReporter tr("exec time");
260 Exec(nodes, ev);
261 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900262
Shinichiro Hamaji0e74c542015-06-22 16:17:08 +0900263 for (AST* ast : bootstrap_asts)
264 delete ast;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900265 delete ev;
266 delete vars;
267 delete cache_mgr;
268
Shinichiro Hamaji64cd8062015-06-27 16:58:36 +0900269 return 0;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900270}
271
272int main(int argc, char* argv[]) {
273 Init();
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900274 vector<Symbol> targets;
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900275 vector<StringPiece> cl_vars;
276 ParseCommandLine(argc, argv, &targets, &cl_vars);
Shinichiro Hamaji5f57a992015-06-30 19:39:39 +0900277 // This depends on command line flags.
Shinichiro Hamaji4e950e62015-07-02 02:59:55 +0900278 if (g_use_find_emulator)
279 InitFindEmulator();
Shinichiro Hamaji9db4cb82015-06-22 16:51:04 +0900280 int r = Run(targets, cl_vars);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900281 Quit();
282 return r;
283}