1 |
|
|
/* $OpenBSD: main.c,v 1.122 2017/04/20 03:04:11 dlg Exp $ */ |
2 |
|
|
/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 1988, 1989, 1990, 1993 |
6 |
|
|
* The Regents of the University of California. All rights reserved. |
7 |
|
|
* Copyright (c) 1989 by Berkeley Softworks |
8 |
|
|
* All rights reserved. |
9 |
|
|
* |
10 |
|
|
* This code is derived from software contributed to Berkeley by |
11 |
|
|
* Adam de Boor. |
12 |
|
|
* |
13 |
|
|
* Redistribution and use in source and binary forms, with or without |
14 |
|
|
* modification, are permitted provided that the following conditions |
15 |
|
|
* are met: |
16 |
|
|
* 1. Redistributions of source code must retain the above copyright |
17 |
|
|
* notice, this list of conditions and the following disclaimer. |
18 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
19 |
|
|
* notice, this list of conditions and the following disclaimer in the |
20 |
|
|
* documentation and/or other materials provided with the distribution. |
21 |
|
|
* 3. Neither the name of the University nor the names of its contributors |
22 |
|
|
* may be used to endorse or promote products derived from this software |
23 |
|
|
* without specific prior written permission. |
24 |
|
|
* |
25 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
26 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
29 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
30 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
31 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
32 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
33 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
34 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
35 |
|
|
* SUCH DAMAGE. |
36 |
|
|
*/ |
37 |
|
|
|
38 |
|
|
#include <sys/param.h> /* MACHINE MACHINE_ARCH */ |
39 |
|
|
#include <sys/types.h> |
40 |
|
|
#include <sys/stat.h> |
41 |
|
|
#include <sys/utsname.h> |
42 |
|
|
#include <err.h> |
43 |
|
|
#include <errno.h> |
44 |
|
|
#include <stdio.h> |
45 |
|
|
#include <stdlib.h> |
46 |
|
|
#include <string.h> |
47 |
|
|
#include <unistd.h> |
48 |
|
|
#include "config.h" |
49 |
|
|
#include "defines.h" |
50 |
|
|
#include "var.h" |
51 |
|
|
#include "lowparse.h" |
52 |
|
|
#include "parse.h" |
53 |
|
|
#include "parsevar.h" |
54 |
|
|
#include "dir.h" |
55 |
|
|
#include "direxpand.h" |
56 |
|
|
#include "error.h" |
57 |
|
|
#include "pathnames.h" |
58 |
|
|
#include "init.h" |
59 |
|
|
#include "job.h" |
60 |
|
|
#include "compat.h" |
61 |
|
|
#include "targ.h" |
62 |
|
|
#include "suff.h" |
63 |
|
|
#include "str.h" |
64 |
|
|
#include "main.h" |
65 |
|
|
#include "lst.h" |
66 |
|
|
#include "memory.h" |
67 |
|
|
#include "make.h" |
68 |
|
|
#include "dump.h" |
69 |
|
|
|
70 |
|
|
#define MAKEFLAGS ".MAKEFLAGS" |
71 |
|
|
|
72 |
|
|
static LIST to_create; /* Targets to be made */ |
73 |
|
|
Lst create = &to_create; |
74 |
|
|
bool allPrecious; /* .PRECIOUS given on line by itself */ |
75 |
|
|
|
76 |
|
|
static bool noBuiltins; /* -r flag */ |
77 |
|
|
static LIST makefiles; /* ordered list of makefiles to read */ |
78 |
|
|
static LIST varstoprint; /* list of variables to print */ |
79 |
|
|
int maxJobs; /* -j argument */ |
80 |
|
|
bool compatMake; /* -B argument */ |
81 |
|
|
static bool forceJobs = false; |
82 |
|
|
int debug; /* -d flag */ |
83 |
|
|
bool noExecute; /* -n flag */ |
84 |
|
|
bool keepgoing; /* -k flag */ |
85 |
|
|
bool queryFlag; /* -q flag */ |
86 |
|
|
bool touchFlag; /* -t flag */ |
87 |
|
|
bool ignoreErrors; /* -i flag */ |
88 |
|
|
bool beSilent; /* -s flag */ |
89 |
|
|
bool dumpData; /* -p flag */ |
90 |
|
|
|
91 |
|
|
struct dirs { |
92 |
|
|
char *current; |
93 |
|
|
char *object; |
94 |
|
|
}; |
95 |
|
|
|
96 |
|
|
static void MainParseArgs(int, char **); |
97 |
|
|
static void add_dirpath(Lst, const char *); |
98 |
|
|
static void usage(void); |
99 |
|
|
static void posixParseOptLetter(int); |
100 |
|
|
static void record_option(int, const char *); |
101 |
|
|
|
102 |
|
|
static char *figure_out_MACHINE(void); |
103 |
|
|
static char *figure_out_MACHINE_ARCH(void); |
104 |
|
|
static char *figure_out_MACHINE_CPU(void); |
105 |
|
|
|
106 |
|
|
static char *chdir_verify_path(const char *, struct dirs *); |
107 |
|
|
static char *figure_out_CURDIR(void); |
108 |
|
|
static void setup_CURDIR_OBJDIR(struct dirs *); |
109 |
|
|
|
110 |
|
|
static void setup_VPATH(void); |
111 |
|
|
|
112 |
|
|
static void read_all_make_rules(bool, bool, Lst, struct dirs *); |
113 |
|
|
static void read_makefile_list(Lst, struct dirs *); |
114 |
|
|
static bool ReadMakefile(void *, void *); |
115 |
|
|
|
116 |
|
|
static void |
117 |
|
|
record_option(int c, const char *arg) |
118 |
|
|
{ |
119 |
|
30 |
char opt[3]; |
120 |
|
|
|
121 |
|
15 |
opt[0] = '-'; |
122 |
|
15 |
opt[1] = c; |
123 |
|
15 |
opt[2] = '\0'; |
124 |
|
15 |
Var_Append(MAKEFLAGS, opt); |
125 |
✓✗ |
15 |
if (arg != NULL) |
126 |
|
15 |
Var_Append(MAKEFLAGS, arg); |
127 |
|
15 |
} |
128 |
|
|
|
129 |
|
|
static void |
130 |
|
|
posixParseOptLetter(int c) |
131 |
|
|
{ |
132 |
|
|
switch(c) { |
133 |
|
|
case 'B': |
134 |
|
|
compatMake = true; |
135 |
|
|
return; /* XXX don't pass to submakes. */ |
136 |
|
|
case 'S': |
137 |
|
|
keepgoing = false; |
138 |
|
|
break; |
139 |
|
|
case 'e': |
140 |
|
|
Var_setCheckEnvFirst(true); |
141 |
|
|
break; |
142 |
|
|
case 'i': |
143 |
|
|
ignoreErrors = true; |
144 |
|
|
break; |
145 |
|
|
case 'k': |
146 |
|
|
keepgoing = true; |
147 |
|
|
break; |
148 |
|
|
case 'n': |
149 |
|
|
noExecute = true; |
150 |
|
|
break; |
151 |
|
|
case 'p': |
152 |
|
|
dumpData = true; |
153 |
|
|
break; |
154 |
|
|
case 'q': |
155 |
|
|
queryFlag = true; |
156 |
|
|
/* Kind of nonsensical, wot? */ |
157 |
|
|
break; |
158 |
|
|
case 'r': |
159 |
|
|
noBuiltins = true; |
160 |
|
|
break; |
161 |
|
|
case 's': |
162 |
|
|
beSilent = true; |
163 |
|
|
break; |
164 |
|
|
case 't': |
165 |
|
|
touchFlag = true; |
166 |
|
|
break; |
167 |
|
|
default: |
168 |
|
|
case '?': |
169 |
|
|
usage(); |
170 |
|
|
} |
171 |
|
|
record_option(c, NULL); |
172 |
|
|
} |
173 |
|
|
|
174 |
|
|
/*- |
175 |
|
|
* MainParseArgs -- |
176 |
|
|
* Parse a given argument vector. Called from main() and from |
177 |
|
|
* Main_ParseArgLine() when the .MAKEFLAGS target is used. |
178 |
|
|
* |
179 |
|
|
* XXX: Deal with command line overriding .MAKEFLAGS in makefile |
180 |
|
|
* |
181 |
|
|
* Side Effects: |
182 |
|
|
* Various global and local flags will be set depending on the flags |
183 |
|
|
* given |
184 |
|
|
*/ |
185 |
|
|
static void |
186 |
|
|
MainParseArgs(int argc, char **argv) |
187 |
|
|
{ |
188 |
|
|
int c, optend; |
189 |
|
|
|
190 |
|
|
#define OPTFLAGS "BC:D:I:SV:d:ef:ij:km:npqrst" |
191 |
|
|
#define OPTLETTERS "BSiknpqrst" |
192 |
|
|
|
193 |
✗✓ |
66242 |
if (pledge("stdio rpath wpath cpath fattr proc exec flock", NULL) == -1) |
194 |
|
|
err(2, "pledge"); |
195 |
|
|
|
196 |
|
33121 |
optind = 1; /* since we're called more than once */ |
197 |
|
33121 |
optreset = 1; |
198 |
|
|
optend = 0; |
199 |
✓✓ |
227444 |
while (optind < argc) { |
200 |
✓✗✓✓
|
161202 |
if (!optend && argv[optind][0] == '-') { |
201 |
✗✓ |
6003 |
if (argv[optind][1] == '\0') |
202 |
|
|
optind++; /* ignore "-" */ |
203 |
✗✓✗✗
|
6003 |
else if (argv[optind][1] == '-' && |
204 |
|
|
argv[optind][2] == '\0') { |
205 |
|
|
optind++; /* ignore "--" */ |
206 |
|
|
optend++; /* "--" denotes end of flags */ |
207 |
|
|
} |
208 |
|
|
} |
209 |
✓✗ |
316435 |
c = optend ? -1 : getopt(argc, argv, OPTFLAGS); |
210 |
✗✗✓✗ ✓✗✗✓ ✗✓ |
155233 |
switch (c) { |
211 |
|
|
case 'C': |
212 |
|
|
break; |
213 |
|
|
case 'D': |
214 |
|
|
Var_Set(optarg, "1"); |
215 |
|
|
record_option(c, optarg); |
216 |
|
|
break; |
217 |
|
|
case 'I': |
218 |
|
|
Parse_AddIncludeDir(optarg); |
219 |
|
|
record_option(c, optarg); |
220 |
|
|
break; |
221 |
|
|
case 'V': |
222 |
|
15 |
Lst_AtEnd(&varstoprint, optarg); |
223 |
|
15 |
record_option(c, optarg); |
224 |
|
15 |
break; |
225 |
|
|
case 'd': { |
226 |
|
|
char *modules = optarg; |
227 |
|
|
|
228 |
|
|
for (; *modules; ++modules) |
229 |
|
|
switch (*modules) { |
230 |
|
|
case 'A': |
231 |
|
|
debug = ~0; |
232 |
|
|
break; |
233 |
|
|
case 'a': |
234 |
|
|
debug |= DEBUG_ARCH; |
235 |
|
|
break; |
236 |
|
|
case 'c': |
237 |
|
|
debug |= DEBUG_COND; |
238 |
|
|
break; |
239 |
|
|
case 'd': |
240 |
|
|
debug |= DEBUG_DIR; |
241 |
|
|
break; |
242 |
|
|
case 'D': |
243 |
|
|
debug |= DEBUG_DOUBLE; |
244 |
|
|
break; |
245 |
|
|
case 'e': |
246 |
|
|
debug |= DEBUG_EXPENSIVE; |
247 |
|
|
break; |
248 |
|
|
case 'f': |
249 |
|
|
debug |= DEBUG_FOR; |
250 |
|
|
break; |
251 |
|
|
case 'g': |
252 |
|
|
if (modules[1] == '1') { |
253 |
|
|
debug |= DEBUG_GRAPH1; |
254 |
|
|
++modules; |
255 |
|
|
} |
256 |
|
|
else if (modules[1] == '2') { |
257 |
|
|
debug |= DEBUG_GRAPH2; |
258 |
|
|
++modules; |
259 |
|
|
} |
260 |
|
|
break; |
261 |
|
|
case 'h': |
262 |
|
|
debug |= DEBUG_HELDJOBS; |
263 |
|
|
break; |
264 |
|
|
case 'j': |
265 |
|
|
debug |= DEBUG_JOB | DEBUG_KILL; |
266 |
|
|
break; |
267 |
|
|
case 'J': |
268 |
|
|
/* ignore */ |
269 |
|
|
break; |
270 |
|
|
case 'k': |
271 |
|
|
debug |= DEBUG_KILL; |
272 |
|
|
break; |
273 |
|
|
case 'l': |
274 |
|
|
debug |= DEBUG_LOUD; |
275 |
|
|
break; |
276 |
|
|
case 'm': |
277 |
|
|
debug |= DEBUG_MAKE; |
278 |
|
|
break; |
279 |
|
|
case 'n': |
280 |
|
|
debug |= DEBUG_NAME_MATCHING; |
281 |
|
|
break; |
282 |
|
|
case 'p': |
283 |
|
|
debug |= DEBUG_PARALLEL; |
284 |
|
|
break; |
285 |
|
|
case 'q': |
286 |
|
|
debug |= DEBUG_QUICKDEATH; |
287 |
|
|
break; |
288 |
|
|
case 's': |
289 |
|
|
debug |= DEBUG_SUFF; |
290 |
|
|
break; |
291 |
|
|
case 't': |
292 |
|
|
debug |= DEBUG_TARG; |
293 |
|
|
break; |
294 |
|
|
case 'T': |
295 |
|
|
debug |= DEBUG_TARGGROUP; |
296 |
|
|
break; |
297 |
|
|
case 'v': |
298 |
|
|
debug |= DEBUG_VAR; |
299 |
|
|
break; |
300 |
|
|
default: |
301 |
|
|
(void)fprintf(stderr, |
302 |
|
|
"make: illegal argument to -d option -- %c\n", |
303 |
|
|
*modules); |
304 |
|
|
usage(); |
305 |
|
|
} |
306 |
|
|
record_option(c, optarg); |
307 |
|
|
break; |
308 |
|
|
} |
309 |
|
|
case 'f': |
310 |
|
19 |
Lst_AtEnd(&makefiles, optarg); |
311 |
|
19 |
break; |
312 |
|
|
case 'j': { |
313 |
|
|
const char *errstr; |
314 |
|
|
|
315 |
|
|
forceJobs = true; |
316 |
|
|
maxJobs = strtonum(optarg, 1, INT_MAX, &errstr); |
317 |
|
|
if (errstr != NULL) { |
318 |
|
|
fprintf(stderr, |
319 |
|
|
"make: illegal argument to -j option" |
320 |
|
|
" -- %s -- %s\n", optarg, errstr); |
321 |
|
|
usage(); |
322 |
|
|
} |
323 |
|
|
record_option(c, optarg); |
324 |
|
|
break; |
325 |
|
|
} |
326 |
|
|
case 'm': |
327 |
|
|
Dir_AddDir(systemIncludePath, optarg); |
328 |
|
|
record_option(c, optarg); |
329 |
|
|
break; |
330 |
|
|
case -1: |
331 |
|
|
/* Check for variable assignments and targets. */ |
332 |
✓✗✓✓
|
149196 |
if (argv[optind] != NULL && |
333 |
|
74598 |
!Parse_CmdlineVar(argv[optind])) { |
334 |
✗✓ |
16773 |
if (!*argv[optind]) |
335 |
|
|
Punt("illegal (null) argument."); |
336 |
|
16773 |
Lst_AtEnd(create, estrdup(argv[optind])); |
337 |
|
16773 |
} |
338 |
|
74598 |
optind++; /* skip over non-option */ |
339 |
|
74598 |
break; |
340 |
|
|
default: |
341 |
|
|
posixParseOptLetter(c); |
342 |
|
|
} |
343 |
|
|
} |
344 |
|
33121 |
} |
345 |
|
|
|
346 |
|
|
static void |
347 |
|
|
MainParseChdir(int argc, char **argv) |
348 |
|
|
{ |
349 |
|
|
int c, optend, oldopterr; |
350 |
|
|
|
351 |
|
33706 |
optind = 1; /* since we're called more than once */ |
352 |
|
16853 |
optreset = 1; |
353 |
|
|
optend = 0; |
354 |
|
16853 |
oldopterr = opterr; |
355 |
|
16853 |
opterr = 0; |
356 |
✓✓ |
102972 |
while (optind < argc) { |
357 |
✓✗✓✓
|
69266 |
if (!optend && argv[optind][0] == '-') { |
358 |
✗✓ |
6003 |
if (argv[optind][1] == '\0') |
359 |
|
|
optind++; /* ignore "-" */ |
360 |
✗✓✗✗
|
6003 |
else if (argv[optind][1] == '-' && |
361 |
|
|
argv[optind][2] == '\0') { |
362 |
|
|
optind++; /* ignore "--" */ |
363 |
|
|
optend++; /* "--" denotes end of flags */ |
364 |
|
|
} |
365 |
|
|
} |
366 |
✓✗ |
138498 |
c = optend ? -1 : getopt(argc, argv, OPTFLAGS); |
367 |
✓✓✓ |
69232 |
switch (c) { |
368 |
|
|
case 'C': |
369 |
✗✓ |
5969 |
if (chdir(optarg) == -1) |
370 |
|
|
err(2, "chdir(%s)", optarg); |
371 |
|
|
break; |
372 |
|
|
case -1: |
373 |
|
28630 |
optind++; /* skip over non-option */ |
374 |
|
28630 |
break; |
375 |
|
|
default: |
376 |
|
|
break; |
377 |
|
|
} |
378 |
|
|
} |
379 |
|
16853 |
opterr = oldopterr; |
380 |
|
16853 |
} |
381 |
|
|
|
382 |
|
|
/*- |
383 |
|
|
* Main_ParseArgLine -- |
384 |
|
|
* Used by the parse module when a .MFLAGS or .MAKEFLAGS target |
385 |
|
|
* is encountered and by main() when reading the .MAKEFLAGS envariable. |
386 |
|
|
* Takes a line of arguments and breaks it into its |
387 |
|
|
* component words and passes those words and the number of them to the |
388 |
|
|
* MainParseArgs function. |
389 |
|
|
* The line should have all its leading whitespace removed. |
390 |
|
|
* |
391 |
|
|
* Side Effects: |
392 |
|
|
* Only those that come from the various arguments. |
393 |
|
|
*/ |
394 |
|
|
void |
395 |
|
|
Main_ParseArgLine(const char *line) /* Line to fracture */ |
396 |
|
|
{ |
397 |
|
|
char **argv; /* Manufactured argument vector */ |
398 |
|
33706 |
int argc; /* Number of arguments in argv */ |
399 |
|
16853 |
char *args; /* Space used by the args */ |
400 |
|
|
char *buf; |
401 |
|
|
char *argv0; |
402 |
|
|
const char *s; |
403 |
|
|
size_t len; |
404 |
|
|
|
405 |
|
|
|
406 |
✓✓ |
16853 |
if (line == NULL) |
407 |
|
50 |
return; |
408 |
✓✓ |
67212 |
for (; *line == ' '; ++line) |
409 |
|
|
continue; |
410 |
✓✓ |
16803 |
if (!*line) |
411 |
|
535 |
return; |
412 |
|
|
|
413 |
|
|
/* POSIX rule: MAKEFLAGS can hold a set of option letters without |
414 |
|
|
* any blanks or dashes. */ |
415 |
|
32536 |
for (s = line;; s++) { |
416 |
✗✓ |
32536 |
if (*s == '\0') { |
417 |
|
|
while (line != s) |
418 |
|
|
posixParseOptLetter(*line++); |
419 |
|
|
return; |
420 |
|
|
} |
421 |
✓✓ |
32536 |
if (strchr(OPTLETTERS, *s) == NULL) |
422 |
|
|
break; |
423 |
|
|
} |
424 |
|
16268 |
argv0 = Var_Value(".MAKE"); |
425 |
|
16268 |
len = strlen(line) + strlen(argv0) + 2; |
426 |
|
16268 |
buf = emalloc(len); |
427 |
|
16268 |
(void)snprintf(buf, len, "%s %s", argv0, line); |
428 |
|
|
|
429 |
|
16268 |
argv = brk_string(buf, &argc, &args); |
430 |
|
16268 |
free(buf); |
431 |
|
16268 |
MainParseArgs(argc, argv); |
432 |
|
|
|
433 |
|
16268 |
free(args); |
434 |
|
16268 |
free(argv); |
435 |
|
33121 |
} |
436 |
|
|
|
437 |
|
|
/* Add a :-separated path to a Lst of directories. */ |
438 |
|
|
static void |
439 |
|
|
add_dirpath(Lst l, const char *n) |
440 |
|
|
{ |
441 |
|
|
const char *start; |
442 |
|
|
const char *cp; |
443 |
|
|
|
444 |
|
33734 |
for (start = n;;) { |
445 |
✓✓✓✗
|
692849 |
for (cp = start; *cp != '\0' && *cp != ':';) |
446 |
|
219705 |
cp++; |
447 |
|
16867 |
Dir_AddDiri(l, start, cp); |
448 |
✗✓ |
16867 |
if (*cp == '\0') |
449 |
|
|
break; |
450 |
|
|
else |
451 |
|
|
start= cp+1; |
452 |
|
|
} |
453 |
|
16867 |
} |
454 |
|
|
|
455 |
|
|
/* |
456 |
|
|
* Get the name of this type of MACHINE from utsname so we can share an |
457 |
|
|
* executable for similar machines. (i.e. m68k: amiga hp300, mac68k, sun3, ...) |
458 |
|
|
* |
459 |
|
|
* Note that MACHINE, MACHINE_ARCH and MACHINE_CPU are decided at |
460 |
|
|
* run-time. |
461 |
|
|
*/ |
462 |
|
|
static char * |
463 |
|
|
figure_out_MACHINE() |
464 |
|
|
{ |
465 |
|
33706 |
char *r = getenv("MACHINE"); |
466 |
✓✗ |
16853 |
if (r == NULL) { |
467 |
|
|
static struct utsname utsname; |
468 |
|
|
|
469 |
✗✓ |
16853 |
if (uname(&utsname) == -1) |
470 |
|
|
err(2, "uname"); |
471 |
|
|
r = utsname.machine; |
472 |
|
16853 |
} |
473 |
|
16853 |
return r; |
474 |
|
|
} |
475 |
|
|
|
476 |
|
|
static char * |
477 |
|
|
figure_out_MACHINE_ARCH() |
478 |
|
|
{ |
479 |
|
33706 |
char *r = getenv("MACHINE_ARCH"); |
480 |
|
16853 |
if (r == NULL) { |
481 |
|
|
#ifndef MACHINE_ARCH |
482 |
|
|
r = "unknown"; /* XXX: no uname -p yet */ |
483 |
|
|
#else |
484 |
|
|
r = MACHINE_ARCH; |
485 |
|
|
#endif |
486 |
|
|
} |
487 |
|
16853 |
return r; |
488 |
|
|
} |
489 |
|
|
static char * |
490 |
|
|
figure_out_MACHINE_CPU() |
491 |
|
|
{ |
492 |
|
33706 |
char *r = getenv("MACHINE_CPU"); |
493 |
|
16853 |
if (r == NULL) { |
494 |
|
|
#if !defined(MACHINE_CPU) && ! defined(MACHINE_ARCH) |
495 |
|
|
r = "unknown"; /* XXX: no uname -p yet */ |
496 |
|
|
#else |
497 |
|
|
#if defined(MACHINE_CPU) |
498 |
|
|
r = MACHINE_CPU; |
499 |
|
|
#else |
500 |
|
|
r = MACHINE_ARCH; |
501 |
|
|
#endif |
502 |
|
|
#endif |
503 |
|
|
} |
504 |
|
16853 |
return r; |
505 |
|
|
} |
506 |
|
|
|
507 |
|
|
static char * |
508 |
|
|
figure_out_CURDIR() |
509 |
|
|
{ |
510 |
|
|
char *dir, *cwd; |
511 |
|
33706 |
struct stat sa, sb; |
512 |
|
|
|
513 |
|
|
/* curdir is cwd... */ |
514 |
|
16853 |
cwd = dogetcwd(); |
515 |
✗✓ |
16853 |
if (cwd == NULL) |
516 |
|
|
err(2, "%s", strerror(errno)); |
517 |
|
|
|
518 |
✗✓ |
16853 |
if (stat(cwd, &sa) == -1) |
519 |
|
|
err(2, "%s: %s", cwd, strerror(errno)); |
520 |
|
|
|
521 |
|
|
/* ...but we can use the alias $PWD if we can prove it is the same |
522 |
|
|
* directory */ |
523 |
✓✗ |
16853 |
if ((dir = getenv("PWD")) != NULL) { |
524 |
✓✗✓✓ ✓✗ |
44598 |
if (stat(dir, &sb) == 0 && sa.st_ino == sb.st_ino && |
525 |
|
10892 |
sa.st_dev == sb.st_dev) { |
526 |
|
10892 |
free(cwd); |
527 |
|
10892 |
return estrdup(dir); |
528 |
|
|
} |
529 |
|
|
} |
530 |
|
|
|
531 |
|
5961 |
return cwd; |
532 |
|
16853 |
} |
533 |
|
|
|
534 |
|
|
static char * |
535 |
|
|
chdir_verify_path(const char *path, struct dirs *d) |
536 |
|
|
{ |
537 |
✗✓ |
33706 |
if (chdir(path) == 0) { |
538 |
|
|
if (path[0] != '/') |
539 |
|
|
return Str_concat(d->current, path, '/'); |
540 |
|
|
else |
541 |
|
|
return estrdup(path); |
542 |
|
|
} |
543 |
|
16853 |
return NULL; |
544 |
|
16853 |
} |
545 |
|
|
|
546 |
|
|
static void |
547 |
|
|
setup_CURDIR_OBJDIR(struct dirs *d) |
548 |
|
|
{ |
549 |
|
|
char *path; |
550 |
|
|
|
551 |
|
33706 |
d->current = figure_out_CURDIR(); |
552 |
|
|
/* |
553 |
|
|
* If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory |
554 |
|
|
* exists, change into it and build there. |
555 |
|
|
* |
556 |
|
|
* Once things are initted, |
557 |
|
|
* have to add the original directory to the search path, |
558 |
|
|
* and modify the paths for the Makefiles appropriately. The |
559 |
|
|
* current directory is also placed as a variable for make scripts. |
560 |
|
|
*/ |
561 |
|
16853 |
if ((path = getenv("MAKEOBJDIR")) == NULL) { |
562 |
|
|
path = _PATH_OBJDIR; |
563 |
|
|
} |
564 |
|
16853 |
d->object = chdir_verify_path(path, d); |
565 |
✓✗ |
16853 |
if (d->object == NULL) |
566 |
|
16853 |
d->object = d->current; |
567 |
|
16853 |
} |
568 |
|
|
|
569 |
|
|
/* |
570 |
|
|
* if the VPATH variable is defined, add its contents to the search path. |
571 |
|
|
* Uses the same format as the PATH env variable, i.e., |
572 |
|
|
* <directory>:<directory>:<directory>... |
573 |
|
|
*/ |
574 |
|
|
static void |
575 |
|
|
setup_VPATH() |
576 |
|
|
{ |
577 |
✓✓ |
33706 |
if (Var_Value("VPATH") != NULL) { |
578 |
|
|
char *vpath; |
579 |
|
|
|
580 |
|
14 |
vpath = Var_Subst("${VPATH}", NULL, false); |
581 |
|
14 |
add_dirpath(defaultPath, vpath); |
582 |
|
14 |
(void)free(vpath); |
583 |
|
14 |
} |
584 |
|
16853 |
} |
585 |
|
|
|
586 |
|
|
static void |
587 |
|
|
read_makefile_list(Lst mk, struct dirs *d) |
588 |
|
|
{ |
589 |
|
|
LstNode ln; |
590 |
|
33744 |
ln = Lst_Find(mk, ReadMakefile, d); |
591 |
✗✓ |
16872 |
if (ln != NULL) |
592 |
|
|
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); |
593 |
|
16872 |
} |
594 |
|
|
|
595 |
|
|
static void |
596 |
|
|
read_all_make_rules(bool noBuiltins, bool read_depend, |
597 |
|
|
Lst makefiles, struct dirs *d) |
598 |
|
|
{ |
599 |
|
|
/* |
600 |
|
|
* Read in the built-in rules first, followed by the specified |
601 |
|
|
* makefile(s), or the default Makefile or makefile, in that order. |
602 |
|
|
*/ |
603 |
✓✗ |
16853 |
if (!noBuiltins) { |
604 |
|
16853 |
LIST sysMkPath; /* Path of sys.mk */ |
605 |
|
|
|
606 |
|
16853 |
Lst_Init(&sysMkPath); |
607 |
|
16853 |
Dir_Expand(_PATH_DEFSYSMK, systemIncludePath, &sysMkPath); |
608 |
✗✓ |
16853 |
if (Lst_IsEmpty(&sysMkPath)) |
609 |
|
|
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); |
610 |
|
|
|
611 |
|
16853 |
read_makefile_list(&sysMkPath, d); |
612 |
|
16853 |
} |
613 |
|
|
|
614 |
✓✓ |
16853 |
if (!Lst_IsEmpty(makefiles)) { |
615 |
|
19 |
read_makefile_list(makefiles, d); |
616 |
✓✗ |
16853 |
} else if (!ReadMakefile("makefile", d)) |
617 |
|
16834 |
(void)ReadMakefile("Makefile", d); |
618 |
|
|
|
619 |
|
|
/* read a .depend file, if it exists, and we're not building depend */ |
620 |
|
|
|
621 |
✓✓ |
16853 |
if (read_depend) |
622 |
|
15609 |
(void)ReadMakefile(".depend", d); |
623 |
|
16853 |
Parse_End(); |
624 |
|
16853 |
} |
625 |
|
|
|
626 |
|
|
|
627 |
|
|
int main(int, char **); |
628 |
|
|
/*- |
629 |
|
|
* main -- |
630 |
|
|
* The main function, for obvious reasons. Initializes variables |
631 |
|
|
* and a few modules, then parses the arguments give it in the |
632 |
|
|
* environment and on the command line. Reads the system makefile |
633 |
|
|
* followed by either Makefile, makefile or the file given by the |
634 |
|
|
* -f argument. Sets the .MAKEFLAGS PMake variable based on all the |
635 |
|
|
* flags it has received by then uses either the Make or the Compat |
636 |
|
|
* module to create the initial list of targets. |
637 |
|
|
* |
638 |
|
|
* Results: |
639 |
|
|
* If -q was given, exits -1 if anything was out-of-date. Else it exits |
640 |
|
|
* 0. |
641 |
|
|
* |
642 |
|
|
* Side Effects: |
643 |
|
|
* The program exits when done. Targets are created. etc. etc. etc. |
644 |
|
|
*/ |
645 |
|
|
int |
646 |
|
|
main(int argc, char **argv) |
647 |
|
|
{ |
648 |
|
|
static LIST targs; /* target nodes to create */ |
649 |
|
|
bool outOfDate = true; /* false if all targets up to date */ |
650 |
|
33706 |
char *machine = figure_out_MACHINE(); |
651 |
|
16853 |
char *machine_arch = figure_out_MACHINE_ARCH(); |
652 |
|
16853 |
char *machine_cpu = figure_out_MACHINE_CPU(); |
653 |
|
|
const char *syspath = _PATH_DEFSYSPATH; |
654 |
|
|
char *p; |
655 |
|
|
static struct dirs d; |
656 |
|
|
bool read_depend = true;/* false if we don't want to read .depend */ |
657 |
|
|
|
658 |
|
16853 |
MainParseChdir(argc, argv); |
659 |
|
16853 |
setup_CURDIR_OBJDIR(&d); |
660 |
|
|
|
661 |
|
16853 |
esetenv("PWD", d.object); |
662 |
|
16853 |
unsetenv("CDPATH"); |
663 |
|
|
|
664 |
|
|
Static_Lst_Init(create); |
665 |
|
|
Static_Lst_Init(&makefiles); |
666 |
|
|
Static_Lst_Init(&varstoprint); |
667 |
|
|
Static_Lst_Init(&targs); |
668 |
|
|
|
669 |
|
16853 |
beSilent = false; /* Print commands as executed */ |
670 |
|
16853 |
ignoreErrors = false; /* Pay attention to non-zero returns */ |
671 |
|
16853 |
noExecute = false; /* Execute all commands */ |
672 |
|
16853 |
keepgoing = false; /* Stop on error */ |
673 |
|
16853 |
allPrecious = false; /* Remove targets when interrupted */ |
674 |
|
16853 |
queryFlag = false; /* This is not just a check-run */ |
675 |
|
16853 |
noBuiltins = false; /* Read the built-in rules */ |
676 |
|
16853 |
touchFlag = false; /* Actually update targets */ |
677 |
|
16853 |
debug = 0; /* No debug verbosity, please. */ |
678 |
|
|
|
679 |
|
16853 |
maxJobs = DEFMAXJOBS; |
680 |
|
16853 |
compatMake = false; /* No compat mode */ |
681 |
|
|
|
682 |
|
|
|
683 |
|
|
/* |
684 |
|
|
* Initialize all external modules. |
685 |
|
|
*/ |
686 |
|
16853 |
Init(); |
687 |
|
|
|
688 |
✗✓ |
16853 |
if (d.object != d.current) |
689 |
|
|
Dir_AddDir(defaultPath, d.current); |
690 |
|
16853 |
Var_Set(".CURDIR", d.current); |
691 |
|
16853 |
Var_Set(".OBJDIR", d.object); |
692 |
|
16853 |
Parse_setcurdir(d.current); |
693 |
|
16853 |
Targ_setdirs(d.current, d.object); |
694 |
|
|
|
695 |
|
|
/* |
696 |
|
|
* Initialize various variables. |
697 |
|
|
* MAKE also gets this name, for compatibility |
698 |
|
|
* .MAKEFLAGS gets set to the empty string just in case. |
699 |
|
|
* MFLAGS also gets initialized empty, for compatibility. |
700 |
|
|
*/ |
701 |
|
16853 |
Var_Set("MAKE", argv[0]); |
702 |
|
16853 |
Var_Set(".MAKE", argv[0]); |
703 |
|
16853 |
Var_Set(MAKEFLAGS, ""); |
704 |
|
16853 |
Var_Set("MFLAGS", ""); |
705 |
|
16853 |
Var_Set("MACHINE", machine); |
706 |
|
16853 |
Var_Set("MACHINE_ARCH", machine_arch); |
707 |
|
16853 |
Var_Set("MACHINE_CPU", machine_cpu); |
708 |
|
|
|
709 |
|
|
/* |
710 |
|
|
* First snag any flags out of the MAKEFLAGS environment variable. |
711 |
|
|
*/ |
712 |
|
16853 |
Main_ParseArgLine(getenv("MAKEFLAGS")); |
713 |
|
|
|
714 |
|
16853 |
basedirectory = getenv("MAKEBASEDIRECTORY"); |
715 |
✓✓ |
16853 |
if (basedirectory == NULL) |
716 |
|
50 |
setenv("MAKEBASEDIRECTORY", d.current, 0); |
717 |
|
|
|
718 |
|
16853 |
MainParseArgs(argc, argv); |
719 |
|
|
|
720 |
|
|
/* |
721 |
|
|
* Be compatible if user did not specify -j |
722 |
|
|
*/ |
723 |
✓✗ |
16853 |
if (!forceJobs) |
724 |
|
16853 |
compatMake = true; |
725 |
|
|
|
726 |
|
|
/* And set up everything for sub-makes */ |
727 |
|
16853 |
Var_AddCmdline(MAKEFLAGS); |
728 |
|
|
|
729 |
|
|
|
730 |
|
|
/* |
731 |
|
|
* Set up the .TARGETS variable to contain the list of targets to be |
732 |
|
|
* created. If none specified, make the variable empty -- the parser |
733 |
|
|
* will fill the thing in with the default or .MAIN target. |
734 |
|
|
*/ |
735 |
✓✓ |
16853 |
if (!Lst_IsEmpty(create)) { |
736 |
|
|
LstNode ln; |
737 |
|
|
|
738 |
✓✓ |
67092 |
for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) { |
739 |
|
16773 |
char *name = Lst_Datum(ln); |
740 |
|
|
|
741 |
✓✓ |
16773 |
if (strcmp(name, "depend") == 0) |
742 |
|
1244 |
read_depend = false; |
743 |
|
|
|
744 |
|
16773 |
Var_Append(".TARGETS", name); |
745 |
|
|
} |
746 |
|
16773 |
} else |
747 |
|
80 |
Var_Set(".TARGETS", ""); |
748 |
|
|
|
749 |
|
|
|
750 |
|
|
/* |
751 |
|
|
* If no user-supplied system path was given (through the -m option) |
752 |
|
|
* add the directories from the DEFSYSPATH (more than one may be given |
753 |
|
|
* as dir1:...:dirn) to the system include path. |
754 |
|
|
*/ |
755 |
✓✗ |
16853 |
if (Lst_IsEmpty(systemIncludePath)) |
756 |
|
16853 |
add_dirpath(systemIncludePath, syspath); |
757 |
|
|
|
758 |
|
16853 |
read_all_make_rules(noBuiltins, read_depend, &makefiles, &d); |
759 |
|
|
|
760 |
|
16853 |
Var_Append("MFLAGS", Var_Value(MAKEFLAGS)); |
761 |
|
|
|
762 |
|
|
/* Install all the flags into the MAKEFLAGS env variable. */ |
763 |
✓✗✓✗
|
33706 |
if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) |
764 |
|
16853 |
esetenv("MAKEFLAGS", p); |
765 |
|
|
|
766 |
|
16853 |
setup_VPATH(); |
767 |
|
|
|
768 |
|
16853 |
process_suffixes_after_makefile_is_read(); |
769 |
|
|
|
770 |
✗✓ |
16853 |
if (dumpData) { |
771 |
|
|
dump_data(); |
772 |
|
|
exit(0); |
773 |
|
|
} |
774 |
|
|
|
775 |
|
|
/* Print the initial graph, if the user requested it. */ |
776 |
✗✓ |
16853 |
if (DEBUG(GRAPH1)) |
777 |
|
|
dump_data(); |
778 |
|
|
|
779 |
|
|
/* Print the values of any variables requested by the user. */ |
780 |
✓✓ |
16853 |
if (!Lst_IsEmpty(&varstoprint)) { |
781 |
|
|
LstNode ln; |
782 |
|
|
|
783 |
✓✓ |
60 |
for (ln = Lst_First(&varstoprint); ln != NULL; |
784 |
|
15 |
ln = Lst_Adv(ln)) { |
785 |
|
15 |
char *value = Var_Value(Lst_Datum(ln)); |
786 |
|
|
|
787 |
|
15 |
printf("%s\n", value ? value : ""); |
788 |
|
|
} |
789 |
|
15 |
} else { |
790 |
|
|
/* Have now read the entire graph and need to make a list |
791 |
|
|
* of targets to create. If none was given on the command |
792 |
|
|
* line, we consult the parsing module to find the main |
793 |
|
|
* target(s) to create. */ |
794 |
✓✓ |
16838 |
if (Lst_IsEmpty(create)) |
795 |
|
19 |
Parse_MainName(&targs); |
796 |
|
|
else |
797 |
|
16819 |
Targ_FindList(&targs, create); |
798 |
|
|
|
799 |
|
16838 |
Job_Init(maxJobs); |
800 |
|
|
/* If the user has defined a .BEGIN target, execute the commands |
801 |
|
|
* attached to it. */ |
802 |
✓✗ |
16838 |
if (!queryFlag) |
803 |
|
16838 |
Job_Begin(); |
804 |
✓✗ |
16838 |
if (compatMake) |
805 |
|
|
/* Compat_Init will take care of creating all the |
806 |
|
|
* targets as well as initializing the module. */ |
807 |
|
16838 |
Compat_Run(&targs); |
808 |
|
|
else { |
809 |
|
|
/* Traverse the graph, checking on all the targets. */ |
810 |
|
|
outOfDate = Make_Run(&targs); |
811 |
|
|
} |
812 |
|
|
} |
813 |
|
|
|
814 |
|
|
/* print the graph now it's been processed if the user requested it */ |
815 |
✗✓ |
16713 |
if (DEBUG(GRAPH2)) |
816 |
|
|
post_mortem(); |
817 |
|
|
|
818 |
✗✓✗✗
|
16713 |
if (queryFlag && outOfDate) |
819 |
|
|
return 1; |
820 |
|
|
else |
821 |
|
16713 |
return 0; |
822 |
|
16713 |
} |
823 |
|
|
|
824 |
|
|
/*- |
825 |
|
|
* ReadMakefile -- |
826 |
|
|
* Open and parse the given makefile. |
827 |
|
|
* |
828 |
|
|
* Results: |
829 |
|
|
* true if ok. false if couldn't open file. |
830 |
|
|
* |
831 |
|
|
* Side Effects: |
832 |
|
|
* lots |
833 |
|
|
*/ |
834 |
|
|
static bool |
835 |
|
|
ReadMakefile(void *p, void *q) |
836 |
|
|
{ |
837 |
|
|
const char *fname = p; /* makefile to read */ |
838 |
|
132302 |
struct dirs *d = q; |
839 |
|
|
FILE *stream; |
840 |
|
|
char *name; |
841 |
|
|
|
842 |
✓✓ |
66151 |
if (!strcmp(fname, "-")) { |
843 |
|
19 |
Var_Set("MAKEFILE", ""); |
844 |
|
19 |
Parse_File(estrdup("(stdin)"), stdin); |
845 |
|
19 |
} else { |
846 |
✓✓ |
66132 |
if ((stream = fopen(fname, "r")) != NULL) |
847 |
|
|
goto found; |
848 |
|
|
/* if we've chdir'd, rebuild the path name */ |
849 |
✗✓✗✗
|
32443 |
if (d->current != d->object && *fname != '/') { |
850 |
|
|
char *path; |
851 |
|
|
|
852 |
|
|
path = Str_concat(d->current, fname, '/'); |
853 |
|
|
if ((stream = fopen(path, "r")) == NULL) |
854 |
|
|
free(path); |
855 |
|
|
else { |
856 |
|
|
fname = path; |
857 |
|
|
goto found; |
858 |
|
|
} |
859 |
|
|
} |
860 |
|
|
/* look in -I and system include directories. */ |
861 |
|
32443 |
name = Dir_FindFile(fname, userIncludePath); |
862 |
✓✗ |
32443 |
if (!name) |
863 |
|
32443 |
name = Dir_FindFile(fname, systemIncludePath); |
864 |
✗✓✗✗
|
32443 |
if (!name || !(stream = fopen(name, "r"))) |
865 |
|
32443 |
return false; |
866 |
|
|
fname = name; |
867 |
|
|
/* |
868 |
|
|
* set the MAKEFILE variable desired by System V fans -- the |
869 |
|
|
* placement of the setting here means it gets set to the last |
870 |
|
|
* makefile specified, as it is set by SysV make. |
871 |
|
|
*/ |
872 |
|
33689 |
found: Var_Set("MAKEFILE", fname); |
873 |
|
33689 |
Parse_File(fname, stream); |
874 |
|
|
} |
875 |
|
33708 |
return true; |
876 |
|
66151 |
} |
877 |
|
|
|
878 |
|
|
|
879 |
|
|
/* |
880 |
|
|
* usage -- |
881 |
|
|
* exit with usage message |
882 |
|
|
*/ |
883 |
|
|
static void |
884 |
|
|
usage() |
885 |
|
|
{ |
886 |
|
|
(void)fprintf(stderr, |
887 |
|
|
"usage: make [-BeiknpqrSst] [-C directory] [-D variable] [-d flags] [-f mk]\n\ |
888 |
|
|
[-I directory] [-j max_processes] [-m directory] [-V variable]\n\ |
889 |
|
|
[NAME=value] [target ...]\n"); |
890 |
|
|
exit(2); |
891 |
|
|
} |
892 |
|
|
|
893 |
|
|
|