]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * /+\ | |
3 | * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. | |
4 | * \+/ | |
5 | * | |
6 | * This file is part of jam. | |
7 | * | |
8 | * License is hereby granted to use this software and distribute it freely, as | |
9 | * long as this copyright notice is retained and modifications are clearly | |
10 | * marked. | |
11 | * | |
12 | * ALL WARRANTIES ARE HEREBY DISCLAIMED. | |
13 | */ | |
14 | ||
15 | /* This file is ALSO: | |
16 | * Copyright 2001-2004 David Abrahams. | |
17 | * Distributed under the Boost Software License, Version 1.0. | |
18 | * (See accompanying file LICENSE_1_0.txt or copy at | |
19 | * http://www.boost.org/LICENSE_1_0.txt) | |
20 | */ | |
21 | ||
22 | /* | |
23 | * jam.c - make redux | |
24 | * | |
25 | * See Jam.html for usage information. | |
26 | * | |
27 | * These comments document the code. | |
28 | * | |
29 | * The top half of the code is structured such: | |
30 | * | |
31 | * jam | |
32 | * / | \ | |
33 | * +---+ | \ | |
34 | * / | \ | |
35 | * jamgram option \ | |
36 | * / | \ \ | |
37 | * / | \ \ | |
38 | * / | \ | | |
39 | * scan | compile make | |
40 | * | | / | \ / | \ | |
41 | * | | / | \ / | \ | |
42 | * | | / | \ / | \ | |
43 | * jambase parse | rules search make1 | |
44 | * | | | \ | |
45 | * | | | \ | |
46 | * | | | \ | |
47 | * builtins timestamp command execute | |
48 | * | | |
49 | * | | |
50 | * | | |
51 | * filesys | |
52 | * | |
53 | * | |
54 | * The support routines are called by all of the above, but themselves are | |
55 | * layered thus: | |
56 | * | |
57 | * variable|expand | |
58 | * / | | | |
59 | * / | | | |
60 | * / | | | |
61 | * lists | pathsys | |
62 | * \ | | |
63 | * \ hash | |
64 | * \ | | |
65 | * \ | | |
66 | * \ | | |
67 | * \ | | |
68 | * \ | | |
69 | * object | |
70 | * | |
71 | * Roughly, the modules are: | |
72 | * | |
73 | * builtins.c - jam's built-in rules | |
74 | * command.c - maintain lists of commands | |
75 | * compile.c - compile parsed jam statements | |
76 | * exec*.c - execute a shell script on a specific OS | |
77 | * file*.c - scan directories and archives on a specific OS | |
78 | * hash.c - simple in-memory hashing routines | |
79 | * hdrmacro.c - handle header file parsing for filename macro definitions | |
80 | * headers.c - handle #includes in source files | |
81 | * jambase.c - compilable copy of Jambase | |
82 | * jamgram.y - jam grammar | |
83 | * lists.c - maintain lists of strings | |
84 | * make.c - bring a target up to date, once rules are in place | |
85 | * make1.c - execute command to bring targets up to date | |
86 | * object.c - string manipulation routines | |
87 | * option.c - command line option processing | |
88 | * parse.c - make and destroy parse trees as driven by the parser | |
89 | * path*.c - manipulate file names on a specific OS | |
90 | * hash.c - simple in-memory hashing routines | |
91 | * regexp.c - Henry Spencer's regexp | |
92 | * rules.c - access to RULEs, TARGETs, and ACTIONs | |
93 | * scan.c - the jam yacc scanner | |
94 | * search.c - find a target along $(SEARCH) or $(LOCATE) | |
95 | * timestamp.c - get the timestamp of a file or archive member | |
96 | * variable.c - handle jam multi-element variables | |
97 | */ | |
98 | ||
99 | ||
100 | #include "jam.h" | |
101 | #include "patchlevel.h" | |
102 | ||
103 | #include "builtins.h" | |
104 | #include "class.h" | |
105 | #include "compile.h" | |
106 | #include "constants.h" | |
b32b8144 | 107 | #include "debugger.h" |
7c673cae FG |
108 | #include "filesys.h" |
109 | #include "function.h" | |
110 | #include "hcache.h" | |
111 | #include "lists.h" | |
112 | #include "make.h" | |
113 | #include "object.h" | |
114 | #include "option.h" | |
115 | #include "output.h" | |
116 | #include "parse.h" | |
117 | #include "cwd.h" | |
118 | #include "rules.h" | |
119 | #include "scan.h" | |
120 | #include "search.h" | |
121 | #include "strings.h" | |
122 | #include "timestamp.h" | |
123 | #include "variable.h" | |
b32b8144 | 124 | #include "execcmd.h" |
7c673cae FG |
125 | |
126 | /* Macintosh is "special" */ | |
127 | #ifdef OS_MAC | |
128 | # include <QuickDraw.h> | |
129 | #endif | |
130 | ||
131 | /* And UNIX for this. */ | |
132 | #ifdef unix | |
133 | # include <sys/utsname.h> | |
134 | # include <signal.h> | |
135 | #endif | |
136 | ||
137 | struct globs globs = | |
138 | { | |
139 | 0, /* noexec */ | |
140 | 1, /* jobs */ | |
141 | 0, /* quitquick */ | |
142 | 0, /* newestfirst */ | |
143 | 0, /* pipes action stdout and stderr merged to action output */ | |
144 | #ifdef OS_MAC | |
145 | { 0, 0 }, /* debug - suppress tracing output */ | |
146 | #else | |
147 | { 0, 1 }, /* debug ... */ | |
148 | #endif | |
149 | 0, /* output commands, not run them */ | |
150 | 0, /* action timeout */ | |
151 | 0 /* maximum buffer size zero is all output */ | |
152 | }; | |
153 | ||
154 | /* Symbols to be defined as true for use in Jambase. */ | |
155 | static char * othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 }; | |
156 | ||
157 | ||
158 | /* Known for sure: | |
159 | * mac needs arg_enviro | |
160 | * OS2 needs extern environ | |
161 | */ | |
162 | ||
163 | #ifdef OS_MAC | |
164 | # define use_environ arg_environ | |
165 | # ifdef MPW | |
166 | QDGlobals qd; | |
167 | # endif | |
168 | #endif | |
169 | ||
170 | ||
171 | #ifdef OS_VMS | |
172 | # define use_environ arg_environ | |
173 | #endif | |
174 | ||
175 | ||
176 | /* on Win32-LCC */ | |
177 | #if defined( OS_NT ) && defined( __LCC__ ) | |
178 | # define use_environ _environ | |
179 | #endif | |
180 | ||
181 | #if defined( __MWERKS__) | |
182 | # define use_environ _environ | |
183 | extern char * * _environ; | |
184 | #endif | |
185 | ||
186 | #ifndef use_environ | |
187 | # define use_environ environ | |
188 | # if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT ) | |
189 | extern char **environ; | |
190 | # endif | |
191 | #endif | |
192 | ||
193 | #if YYDEBUG != 0 | |
194 | extern int yydebug; | |
195 | #endif | |
196 | ||
197 | #ifndef NDEBUG | |
198 | static void run_unit_tests() | |
199 | { | |
200 | # if defined( USE_EXECNT ) | |
201 | extern void execnt_unit_test(); | |
202 | execnt_unit_test(); | |
203 | # endif | |
204 | string_unit_test(); | |
205 | } | |
206 | #endif | |
207 | ||
208 | int anyhow = 0; | |
209 | ||
210 | #ifdef HAVE_PYTHON | |
211 | extern PyObject * bjam_call ( PyObject * self, PyObject * args ); | |
212 | extern PyObject * bjam_import_rule ( PyObject * self, PyObject * args ); | |
213 | extern PyObject * bjam_define_action( PyObject * self, PyObject * args ); | |
214 | extern PyObject * bjam_variable ( PyObject * self, PyObject * args ); | |
215 | extern PyObject * bjam_backtrace ( PyObject * self, PyObject * args ); | |
216 | extern PyObject * bjam_caller ( PyObject * self, PyObject * args ); | |
217 | int python_optimize = 1; /* Set Python optimzation on by default */ | |
218 | #endif | |
219 | ||
220 | void regex_done(); | |
221 | ||
222 | char const * saved_argv0; | |
223 | ||
b32b8144 FG |
224 | static void usage( const char * progname ) |
225 | { | |
226 | err_printf("\nusage: %s [ options ] targets...\n\n", progname); | |
227 | ||
228 | err_printf("-a Build all targets, even if they are current.\n"); | |
229 | err_printf("-dx Set the debug level to x (0-13,console,mi).\n"); | |
230 | err_printf("-fx Read x instead of Jambase.\n"); | |
231 | /* err_printf( "-g Build from newest sources first.\n" ); */ | |
232 | err_printf("-jx Run up to x shell commands concurrently.\n"); | |
233 | err_printf("-lx Limit actions to x number of seconds after which they are stopped.\n"); | |
234 | err_printf("-mx Maximum target output saved (kb), default is to save all output.\n"); | |
235 | err_printf("-n Don't actually execute the updating actions.\n"); | |
236 | err_printf("-ox Mirror all output to file x.\n"); | |
237 | err_printf("-px x=0, pipes action stdout and stderr merged into action output.\n"); | |
238 | err_printf("-q Quit quickly as soon as a target fails.\n"); | |
239 | err_printf("-sx=y Set variable x=y, overriding environment.\n"); | |
240 | err_printf("-tx Rebuild x, even if it is up-to-date.\n"); | |
241 | err_printf("-v Print the version of jam and exit.\n"); | |
242 | #ifdef HAVE_PYTHON | |
243 | err_printf("-z Disable Python Optimization and enable asserts\n"); | |
244 | #endif | |
245 | err_printf("--x Option is ignored.\n\n"); | |
246 | ||
247 | exit( EXITBAD ); | |
248 | } | |
249 | ||
7c673cae FG |
250 | int main( int argc, char * * argv, char * * arg_environ ) |
251 | { | |
252 | int n; | |
253 | char * s; | |
254 | struct bjam_option optv[ N_OPTS ]; | |
255 | char const * all = "all"; | |
256 | int status; | |
257 | int arg_c = argc; | |
258 | char * * arg_v = argv; | |
259 | char const * progname = argv[ 0 ]; | |
260 | module_t * environ_module; | |
b32b8144 | 261 | int is_debugger; |
7c673cae FG |
262 | |
263 | saved_argv0 = argv[ 0 ]; | |
264 | ||
265 | BJAM_MEM_INIT(); | |
266 | ||
267 | #ifdef OS_MAC | |
268 | InitGraf( &qd.thePort ); | |
b32b8144 FG |
269 | #endif |
270 | ||
271 | cwd_init(); | |
272 | ||
273 | #ifdef JAM_DEBUGGER | |
274 | ||
275 | is_debugger = 0; | |
276 | ||
277 | if ( getoptions( argc - 1, argv + 1, "-:l:m:d:j:p:f:gs:t:ano:qv", optv ) < 0 ) | |
278 | usage( progname ); | |
279 | ||
280 | if ( ( s = getoptval( optv, 'd', 0 ) ) ) | |
281 | { | |
282 | if ( strcmp( s, "mi" ) == 0 ) | |
283 | { | |
284 | debug_interface = DEBUG_INTERFACE_MI; | |
285 | is_debugger = 1; | |
286 | } | |
287 | else if ( strcmp( s, "console" ) == 0 ) | |
288 | { | |
289 | debug_interface = DEBUG_INTERFACE_CONSOLE; | |
290 | is_debugger = 1; | |
291 | } | |
292 | } | |
293 | ||
294 | #if NT | |
295 | ||
296 | if ( argc >= 3 ) | |
297 | { | |
298 | /* Check whether this instance is being run by the debugger. */ | |
299 | size_t opt_len = strlen( debugger_opt ); | |
300 | if ( strncmp( argv[ 1 ], debugger_opt, opt_len ) == 0 && | |
301 | strncmp( argv[ 2 ], debugger_opt, opt_len ) == 0 ) | |
302 | { | |
303 | debug_init_handles( argv[ 1 ] + opt_len, argv[ 2 ] + opt_len ); | |
304 | /* Fix up argc/argv to hide the internal options */ | |
305 | arg_c = argc = (argc - 2); | |
306 | argv[ 2 ] = argv[ 0 ]; | |
307 | arg_v = argv = (argv + 2); | |
308 | debug_interface = DEBUG_INTERFACE_CHILD; | |
309 | } | |
310 | } | |
311 | ||
312 | if ( is_debugger ) | |
313 | { | |
314 | return debugger(); | |
315 | } | |
316 | ||
317 | #else | |
318 | ||
319 | if ( is_debugger ) | |
320 | { | |
321 | if ( setjmp( debug_child_data.jmp ) != 0 ) | |
322 | { | |
323 | arg_c = argc = debug_child_data.argc; | |
324 | arg_v = argv = (char * *)debug_child_data.argv; | |
325 | debug_interface = DEBUG_INTERFACE_CHILD; | |
326 | } | |
327 | else | |
328 | { | |
329 | return debugger(); | |
330 | } | |
331 | } | |
332 | ||
333 | #endif | |
334 | ||
7c673cae FG |
335 | #endif |
336 | ||
337 | --argc; | |
338 | ++argv; | |
339 | ||
340 | #ifdef HAVE_PYTHON | |
341 | #define OPTSTRING "-:l:m:d:j:p:f:gs:t:ano:qvz" | |
342 | #else | |
343 | #define OPTSTRING "-:l:m:d:j:p:f:gs:t:ano:qv" | |
344 | #endif | |
345 | ||
346 | if ( getoptions( argc, argv, OPTSTRING, optv ) < 0 ) | |
347 | { | |
b32b8144 | 348 | usage( progname ); |
7c673cae FG |
349 | } |
350 | ||
351 | /* Version info. */ | |
352 | if ( ( s = getoptval( optv, 'v', 0 ) ) ) | |
353 | { | |
354 | out_printf( "Boost.Jam Version %s. %s.\n", VERSION, OSMINOR ); | |
355 | out_printf( " Copyright 1993-2002 Christopher Seiwald and Perforce " | |
356 | "Software, Inc.\n" ); | |
357 | out_printf( " Copyright 2001 David Turner.\n" ); | |
358 | out_printf( " Copyright 2001-2004 David Abrahams.\n" ); | |
359 | out_printf( " Copyright 2002-2015 Rene Rivera.\n" ); | |
360 | out_printf( " Copyright 2003-2015 Vladimir Prus.\n" ); | |
361 | return EXITOK; | |
362 | } | |
363 | ||
364 | /* Pick up interesting options. */ | |
365 | if ( ( s = getoptval( optv, 'n', 0 ) ) ) | |
366 | { | |
367 | ++globs.noexec; | |
368 | globs.debug[ 2 ] = 1; | |
369 | } | |
370 | ||
371 | if ( ( s = getoptval( optv, 'p', 0 ) ) ) | |
372 | { | |
373 | /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action | |
374 | * stdout and stderr. | |
375 | */ | |
376 | globs.pipe_action = atoi( s ); | |
377 | if ( globs.pipe_action < 0 || 3 < globs.pipe_action ) | |
378 | { | |
379 | err_printf( "Invalid pipe descriptor '%d', valid values are -p[0..3]." | |
380 | "\n", globs.pipe_action ); | |
381 | exit( EXITBAD ); | |
382 | } | |
383 | } | |
384 | ||
385 | if ( ( s = getoptval( optv, 'q', 0 ) ) ) | |
386 | globs.quitquick = 1; | |
387 | ||
388 | if ( ( s = getoptval( optv, 'a', 0 ) ) ) | |
389 | anyhow++; | |
390 | ||
391 | if ( ( s = getoptval( optv, 'j', 0 ) ) ) | |
392 | { | |
393 | globs.jobs = atoi( s ); | |
b32b8144 | 394 | if ( globs.jobs < 1 ) |
7c673cae | 395 | { |
b32b8144 | 396 | err_printf( "Invalid value for the '-j' option.\n" ); |
7c673cae FG |
397 | exit( EXITBAD ); |
398 | } | |
399 | } | |
400 | ||
401 | if ( ( s = getoptval( optv, 'g', 0 ) ) ) | |
402 | globs.newestfirst = 1; | |
403 | ||
404 | if ( ( s = getoptval( optv, 'l', 0 ) ) ) | |
405 | globs.timeout = atoi( s ); | |
406 | ||
407 | if ( ( s = getoptval( optv, 'm', 0 ) ) ) | |
408 | globs.max_buf = atoi( s ) * 1024; /* convert to kb */ | |
409 | ||
410 | #ifdef HAVE_PYTHON | |
411 | if ( ( s = getoptval( optv, 'z', 0 ) ) ) | |
412 | python_optimize = 0; /* disable python optimization */ | |
413 | #endif | |
414 | ||
415 | /* Turn on/off debugging */ | |
416 | for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n ) | |
417 | { | |
418 | int i; | |
419 | ||
420 | /* First -d, turn off defaults. */ | |
421 | if ( !n ) | |
422 | for ( i = 0; i < DEBUG_MAX; ++i ) | |
423 | globs.debug[i] = 0; | |
424 | ||
425 | i = atoi( s ); | |
426 | ||
427 | if ( ( i < 0 ) || ( i >= DEBUG_MAX ) ) | |
428 | { | |
429 | out_printf( "Invalid debug level '%s'.\n", s ); | |
430 | continue; | |
431 | } | |
432 | ||
433 | /* n turns on levels 1-n. */ | |
434 | /* +n turns on level n. */ | |
435 | if ( *s == '+' ) | |
436 | globs.debug[ i ] = 1; | |
437 | else while ( i ) | |
438 | globs.debug[ i-- ] = 1; | |
439 | } | |
440 | ||
441 | /* If an output file is specified, set globs.out to that. */ | |
442 | if ( ( s = getoptval( optv, 'o', 0 ) ) ) | |
443 | { | |
444 | if ( !( globs.out = fopen( s, "w" ) ) ) | |
445 | { | |
446 | err_printf( "Failed to write to '%s'\n", s ); | |
447 | exit( EXITBAD ); | |
448 | } | |
449 | /* ++globs.noexec; */ | |
450 | } | |
451 | ||
452 | constants_init(); | |
7c673cae FG |
453 | |
454 | { | |
455 | PROFILE_ENTER( MAIN ); | |
456 | ||
457 | #ifdef HAVE_PYTHON | |
458 | { | |
459 | PROFILE_ENTER( MAIN_PYTHON ); | |
460 | Py_OptimizeFlag = python_optimize; | |
461 | Py_Initialize(); | |
462 | { | |
463 | static PyMethodDef BjamMethods[] = { | |
464 | {"call", bjam_call, METH_VARARGS, | |
465 | "Call the specified bjam rule."}, | |
466 | {"import_rule", bjam_import_rule, METH_VARARGS, | |
467 | "Imports Python callable to bjam."}, | |
468 | {"define_action", bjam_define_action, METH_VARARGS, | |
469 | "Defines a command line action."}, | |
470 | {"variable", bjam_variable, METH_VARARGS, | |
471 | "Obtains a variable from bjam's global module."}, | |
472 | {"backtrace", bjam_backtrace, METH_VARARGS, | |
473 | "Returns bjam backtrace from the last call into Python."}, | |
474 | {"caller", bjam_caller, METH_VARARGS, | |
475 | "Returns the module from which the last call into Python is made."}, | |
476 | {NULL, NULL, 0, NULL} | |
477 | }; | |
478 | ||
479 | Py_InitModule( "bjam", BjamMethods ); | |
480 | } | |
481 | PROFILE_EXIT( MAIN_PYTHON ); | |
482 | } | |
483 | #endif | |
484 | ||
485 | #ifndef NDEBUG | |
486 | run_unit_tests(); | |
487 | #endif | |
488 | #if YYDEBUG != 0 | |
489 | if ( DEBUG_PARSE ) | |
490 | yydebug = 1; | |
491 | #endif | |
492 | ||
493 | /* Set JAMDATE. */ | |
494 | { | |
495 | timestamp current; | |
496 | timestamp_current( ¤t ); | |
497 | var_set( root_module(), constant_JAMDATE, list_new( outf_time( | |
498 | ¤t ) ), VAR_SET ); | |
499 | } | |
500 | ||
501 | /* Set JAM_VERSION. */ | |
502 | var_set( root_module(), constant_JAM_VERSION, | |
503 | list_push_back( list_push_back( list_new( | |
504 | object_new( VERSION_MAJOR_SYM ) ), | |
505 | object_new( VERSION_MINOR_SYM ) ), | |
506 | object_new( VERSION_PATCH_SYM ) ), | |
507 | VAR_SET ); | |
508 | ||
509 | /* Set JAMUNAME. */ | |
510 | #ifdef unix | |
511 | { | |
512 | struct utsname u; | |
513 | ||
514 | if ( uname( &u ) >= 0 ) | |
515 | { | |
516 | var_set( root_module(), constant_JAMUNAME, | |
517 | list_push_back( | |
518 | list_push_back( | |
519 | list_push_back( | |
520 | list_push_back( | |
521 | list_new( | |
522 | object_new( u.sysname ) ), | |
523 | object_new( u.nodename ) ), | |
524 | object_new( u.release ) ), | |
525 | object_new( u.version ) ), | |
526 | object_new( u.machine ) ), VAR_SET ); | |
527 | } | |
528 | } | |
529 | #endif /* unix */ | |
530 | ||
531 | /* Set JAM_TIMESTAMP_RESOLUTION. */ | |
532 | { | |
533 | timestamp fmt_resolution[ 1 ]; | |
534 | file_supported_fmt_resolution( fmt_resolution ); | |
535 | var_set( root_module(), constant_JAM_TIMESTAMP_RESOLUTION, list_new( | |
536 | object_new( timestamp_timestr( fmt_resolution ) ) ), VAR_SET ); | |
537 | } | |
538 | ||
539 | /* Load up environment variables. */ | |
540 | ||
541 | /* First into the global module, with splitting, for backward | |
542 | * compatibility. | |
543 | */ | |
544 | var_defines( root_module(), use_environ, 1 ); | |
545 | ||
546 | environ_module = bindmodule( constant_ENVIRON ); | |
547 | /* Then into .ENVIRON, without splitting. */ | |
548 | var_defines( environ_module, use_environ, 0 ); | |
549 | ||
550 | /* | |
551 | * Jam defined variables OS & OSPLAT. We load them after environment, so | |
552 | * that setting OS in environment does not change Jam's notion of the | |
553 | * current platform. | |
554 | */ | |
555 | var_defines( root_module(), othersyms, 1 ); | |
556 | ||
557 | /* Load up variables set on command line. */ | |
558 | for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n ) | |
559 | { | |
560 | char * symv[ 2 ]; | |
561 | symv[ 0 ] = s; | |
562 | symv[ 1 ] = 0; | |
563 | var_defines( root_module(), symv, 1 ); | |
564 | var_defines( environ_module, symv, 0 ); | |
565 | } | |
566 | ||
567 | /* Set the ARGV to reflect the complete list of arguments of invocation. | |
568 | */ | |
569 | for ( n = 0; n < arg_c; ++n ) | |
570 | var_set( root_module(), constant_ARGV, list_new( object_new( | |
571 | arg_v[ n ] ) ), VAR_APPEND ); | |
572 | ||
573 | /* Initialize built-in rules. */ | |
574 | load_builtins(); | |
575 | ||
576 | /* Add the targets in the command line to the update list. */ | |
577 | for ( n = 1; n < arg_c; ++n ) | |
578 | { | |
579 | if ( arg_v[ n ][ 0 ] == '-' ) | |
580 | { | |
581 | char * f = "-:l:d:j:f:gs:t:ano:qv"; | |
582 | for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break; | |
583 | if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n; | |
584 | } | |
585 | else | |
586 | { | |
587 | OBJECT * const target = object_new( arg_v[ n ] ); | |
588 | mark_target_for_updating( target ); | |
589 | object_free( target ); | |
590 | } | |
591 | } | |
592 | ||
593 | if ( list_empty( targets_to_update() ) ) | |
594 | mark_target_for_updating( constant_all ); | |
595 | ||
596 | /* Parse ruleset. */ | |
597 | { | |
598 | FRAME frame[ 1 ]; | |
599 | frame_init( frame ); | |
600 | for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n ) | |
601 | { | |
602 | OBJECT * const filename = object_new( s ); | |
603 | parse_file( filename, frame ); | |
604 | object_free( filename ); | |
605 | } | |
606 | ||
607 | if ( !n ) | |
608 | parse_file( constant_plus, frame ); | |
609 | } | |
610 | ||
611 | status = yyanyerrors(); | |
612 | ||
613 | /* Manually touch -t targets. */ | |
614 | for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n ) | |
615 | { | |
616 | OBJECT * const target = object_new( s ); | |
617 | touch_target( target ); | |
618 | object_free( target ); | |
619 | } | |
620 | ||
621 | /* The build system may set the PARALLELISM variable to override -j | |
622 | * options. | |
623 | */ | |
624 | { | |
625 | LIST * const p = var_get( root_module(), constant_PARALLELISM ); | |
626 | if ( !list_empty( p ) ) | |
627 | { | |
628 | int const j = atoi( object_str( list_front( p ) ) ); | |
b32b8144 FG |
629 | if ( j < 1 ) |
630 | out_printf( "Invalid value of PARALLELISM: %s.\n", | |
631 | object_str( list_front( p ) ) ); | |
7c673cae FG |
632 | else |
633 | globs.jobs = j; | |
634 | } | |
635 | } | |
636 | ||
637 | /* KEEP_GOING overrides -q option. */ | |
638 | { | |
639 | LIST * const p = var_get( root_module(), constant_KEEP_GOING ); | |
640 | if ( !list_empty( p ) ) | |
641 | globs.quitquick = atoi( object_str( list_front( p ) ) ) ? 0 : 1; | |
642 | } | |
643 | ||
644 | /* Now make target. */ | |
645 | { | |
646 | PROFILE_ENTER( MAIN_MAKE ); | |
647 | LIST * const targets = targets_to_update(); | |
648 | if ( !list_empty( targets ) ) | |
649 | status |= make( targets, anyhow ); | |
650 | else | |
651 | status = last_update_now_status; | |
652 | PROFILE_EXIT( MAIN_MAKE ); | |
653 | } | |
654 | ||
655 | PROFILE_EXIT( MAIN ); | |
656 | } | |
657 | ||
658 | if ( DEBUG_PROFILE ) | |
659 | profile_dump(); | |
660 | ||
661 | ||
662 | #ifdef OPT_HEADER_CACHE_EXT | |
663 | hcache_done(); | |
664 | #endif | |
665 | ||
666 | clear_targets_to_update(); | |
667 | ||
668 | /* Widely scattered cleanup. */ | |
669 | property_set_done(); | |
b32b8144 | 670 | exec_done(); |
7c673cae FG |
671 | file_done(); |
672 | rules_done(); | |
673 | timestamp_done(); | |
674 | search_done(); | |
675 | class_done(); | |
676 | modules_done(); | |
677 | regex_done(); | |
678 | cwd_done(); | |
679 | path_done(); | |
680 | function_done(); | |
681 | list_done(); | |
682 | constants_done(); | |
683 | object_done(); | |
684 | ||
685 | /* Close log out. */ | |
686 | if ( globs.out ) | |
687 | fclose( globs.out ); | |
688 | ||
689 | #ifdef HAVE_PYTHON | |
690 | Py_Finalize(); | |
691 | #endif | |
692 | ||
693 | BJAM_MEM_CLOSE(); | |
694 | ||
695 | return status ? EXITBAD : EXITOK; | |
696 | } | |
697 | ||
698 | ||
699 | /* | |
700 | * executable_path() | |
701 | */ | |
702 | ||
703 | #if defined(_WIN32) | |
704 | # define WIN32_LEAN_AND_MEAN | |
705 | # include <windows.h> | |
706 | char * executable_path( char const * argv0 ) | |
707 | { | |
708 | char buf[ 1024 ]; | |
709 | DWORD const ret = GetModuleFileName( NULL, buf, sizeof( buf ) ); | |
710 | return ( !ret || ret == sizeof( buf ) ) ? NULL : strdup( buf ); | |
711 | } | |
712 | #elif defined(__APPLE__) /* Not tested */ | |
713 | # include <mach-o/dyld.h> | |
714 | char *executable_path( char const * argv0 ) | |
715 | { | |
716 | char buf[ 1024 ]; | |
717 | uint32_t size = sizeof( buf ); | |
718 | return _NSGetExecutablePath( buf, &size ) ? NULL : strdup( buf ); | |
719 | } | |
720 | #elif defined(sun) || defined(__sun) /* Not tested */ | |
721 | # include <stdlib.h> | |
722 | char * executable_path( char const * argv0 ) | |
723 | { | |
724 | const char * execname = getexecname(); | |
725 | return execname ? strdup( execname ) : NULL; | |
726 | } | |
727 | #elif defined(__FreeBSD__) | |
728 | # include <sys/sysctl.h> | |
729 | char * executable_path( char const * argv0 ) | |
730 | { | |
731 | int mib[ 4 ] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; | |
732 | char buf[ 1024 ]; | |
733 | size_t size = sizeof( buf ); | |
734 | sysctl( mib, 4, buf, &size, NULL, 0 ); | |
735 | return ( !size || size == sizeof( buf ) ) ? NULL : strndup( buf, size ); | |
736 | } | |
737 | #elif defined(__linux__) | |
738 | # include <unistd.h> | |
739 | char * executable_path( char const * argv0 ) | |
740 | { | |
741 | char buf[ 1024 ]; | |
742 | ssize_t const ret = readlink( "/proc/self/exe", buf, sizeof( buf ) ); | |
743 | return ( !ret || ret == sizeof( buf ) ) ? NULL : strndup( buf, ret ); | |
744 | } | |
745 | #elif defined(OS_VMS) | |
746 | # include <unixlib.h> | |
747 | char * executable_path( char const * argv0 ) | |
748 | { | |
749 | char * vms_path = NULL; | |
750 | char * posix_path = NULL; | |
751 | char * p; | |
752 | ||
753 | /* On VMS argv[0] shows absolute path to the image file. | |
754 | * So, just remove VMS file version and translate path to POSIX-style. | |
755 | */ | |
756 | vms_path = strdup( argv0 ); | |
757 | if ( vms_path && ( p = strchr( vms_path, ';') ) ) *p = '\0'; | |
758 | posix_path = decc$translate_vms( vms_path ); | |
759 | if ( vms_path ) free( vms_path ); | |
760 | ||
761 | return posix_path > 0 ? strdup( posix_path ) : NULL; | |
762 | } | |
763 | #else | |
764 | char * executable_path( char const * argv0 ) | |
765 | { | |
766 | /* If argv0 is an absolute path, assume it is the right absolute path. */ | |
767 | return argv0[ 0 ] == '/' ? strdup( argv0 ) : NULL; | |
768 | } | |
769 | #endif |