|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "jam.h" |
|
#include "patchlevel.h" |
|
|
|
#include "builtins.h" |
|
#include "class.h" |
|
#include "compile.h" |
|
#include "constants.h" |
|
#include "filesys.h" |
|
#include "function.h" |
|
#include "hcache.h" |
|
#include "lists.h" |
|
#include "make.h" |
|
#include "object.h" |
|
#include "option.h" |
|
#include "output.h" |
|
#include "parse.h" |
|
#include "cwd.h" |
|
#include "rules.h" |
|
#include "scan.h" |
|
#include "search.h" |
|
#include "strings.h" |
|
#include "timestamp.h" |
|
#include "variable.h" |
|
|
|
|
|
#ifdef OS_MAC |
|
# include <QuickDraw.h> |
|
#endif |
|
|
|
|
|
#ifdef unix |
|
# include <sys/utsname.h> |
|
# include <signal.h> |
|
#endif |
|
|
|
struct globs globs = |
|
{ |
|
0, |
|
1, |
|
0, |
|
0, |
|
0, |
|
#ifdef OS_MAC |
|
{ 0, 0 }, |
|
#else |
|
{ 0, 1 }, |
|
#endif |
|
0, |
|
0, |
|
0 |
|
}; |
|
|
|
|
|
static char * othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef OS_MAC |
|
# define use_environ arg_environ |
|
# ifdef MPW |
|
QDGlobals qd; |
|
# endif |
|
#endif |
|
|
|
|
|
#if defined( OS_NT ) && defined( __LCC__ ) |
|
# define use_environ _environ |
|
#endif |
|
|
|
#if defined( __MWERKS__) |
|
# define use_environ _environ |
|
extern char * * _environ; |
|
#endif |
|
|
|
#ifndef use_environ |
|
# define use_environ environ |
|
# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT ) |
|
extern char **environ; |
|
# endif |
|
#endif |
|
|
|
#if YYDEBUG != 0 |
|
extern int yydebug; |
|
#endif |
|
|
|
#ifndef NDEBUG |
|
static void run_unit_tests() |
|
{ |
|
# if defined( USE_EXECNT ) |
|
extern void execnt_unit_test(); |
|
execnt_unit_test(); |
|
# endif |
|
string_unit_test(); |
|
} |
|
#endif |
|
|
|
int anyhow = 0; |
|
|
|
#ifdef HAVE_PYTHON |
|
extern PyObject * bjam_call ( PyObject * self, PyObject * args ); |
|
extern PyObject * bjam_import_rule ( PyObject * self, PyObject * args ); |
|
extern PyObject * bjam_define_action( PyObject * self, PyObject * args ); |
|
extern PyObject * bjam_variable ( PyObject * self, PyObject * args ); |
|
extern PyObject * bjam_backtrace ( PyObject * self, PyObject * args ); |
|
extern PyObject * bjam_caller ( PyObject * self, PyObject * args ); |
|
#endif |
|
|
|
void regex_done(); |
|
|
|
char const * saved_argv0; |
|
|
|
int main( int argc, char * * argv, char * * arg_environ ) |
|
{ |
|
int n; |
|
char * s; |
|
struct bjam_option optv[ N_OPTS ]; |
|
char const * all = "all"; |
|
int status; |
|
int arg_c = argc; |
|
char * * arg_v = argv; |
|
char const * progname = argv[ 0 ]; |
|
module_t * environ_module; |
|
|
|
saved_argv0 = argv[ 0 ]; |
|
|
|
BJAM_MEM_INIT(); |
|
|
|
#ifdef OS_MAC |
|
InitGraf( &qd.thePort ); |
|
#endif |
|
|
|
--argc; |
|
++argv; |
|
|
|
if ( getoptions( argc, argv, "-:l:m:d:j:p:f:gs:t:ano:qv", optv ) < 0 ) |
|
{ |
|
printf( "\nusage: %s [ options ] targets...\n\n", progname ); |
|
|
|
printf( "-a Build all targets, even if they are current.\n" ); |
|
printf( "-dx Set the debug level to x (0-9).\n" ); |
|
printf( "-fx Read x instead of Jambase.\n" ); |
|
|
|
printf( "-jx Run up to x shell commands concurrently.\n" ); |
|
printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" ); |
|
printf( "-mx Maximum target output saved (kb), default is to save all output.\n" ); |
|
printf( "-n Don't actually execute the updating actions.\n" ); |
|
printf( "-ox Write the updating actions to file x.\n" ); |
|
printf( "-px x=0, pipes action stdout and stderr merged into action output.\n" ); |
|
printf( "-q Quit quickly as soon as a target fails.\n" ); |
|
printf( "-sx=y Set variable x=y, overriding environment.\n" ); |
|
printf( "-tx Rebuild x, even if it is up-to-date.\n" ); |
|
printf( "-v Print the version of jam and exit.\n" ); |
|
printf( "--x Option is ignored.\n\n" ); |
|
|
|
exit( EXITBAD ); |
|
} |
|
|
|
|
|
if ( ( s = getoptval( optv, 'v', 0 ) ) ) |
|
{ |
|
printf( "Boost.Jam Version %s. %s.\n", VERSION, OSMINOR ); |
|
printf( " Copyright 1993-2002 Christopher Seiwald and Perforce " |
|
"Software, Inc.\n" ); |
|
printf( " Copyright 2001 David Turner.\n" ); |
|
printf( " Copyright 2001-2004 David Abrahams.\n" ); |
|
printf( " Copyright 2002-2008 Rene Rivera.\n" ); |
|
printf( " Copyright 2003-2008 Vladimir Prus.\n" ); |
|
return EXITOK; |
|
} |
|
|
|
|
|
if ( ( s = getoptval( optv, 'n', 0 ) ) ) |
|
{ |
|
++globs.noexec; |
|
globs.debug[ 2 ] = 1; |
|
} |
|
|
|
if ( ( s = getoptval( optv, 'p', 0 ) ) ) |
|
{ |
|
|
|
|
|
|
|
globs.pipe_action = atoi( s ); |
|
if ( globs.pipe_action < 0 || 3 < globs.pipe_action ) |
|
{ |
|
printf( "Invalid pipe descriptor '%d', valid values are -p[0..3]." |
|
"\n", globs.pipe_action ); |
|
exit( EXITBAD ); |
|
} |
|
} |
|
|
|
if ( ( s = getoptval( optv, 'q', 0 ) ) ) |
|
globs.quitquick = 1; |
|
|
|
if ( ( s = getoptval( optv, 'a', 0 ) ) ) |
|
anyhow++; |
|
|
|
if ( ( s = getoptval( optv, 'j', 0 ) ) ) |
|
{ |
|
globs.jobs = atoi( s ); |
|
if ( globs.jobs < 1 || globs.jobs > MAXJOBS ) |
|
{ |
|
printf( "Invalid value for the '-j' option, valid values are 1 " |
|
"through %d.\n", MAXJOBS ); |
|
exit( EXITBAD ); |
|
} |
|
} |
|
|
|
if ( ( s = getoptval( optv, 'g', 0 ) ) ) |
|
globs.newestfirst = 1; |
|
|
|
if ( ( s = getoptval( optv, 'l', 0 ) ) ) |
|
globs.timeout = atoi( s ); |
|
|
|
if ( ( s = getoptval( optv, 'm', 0 ) ) ) |
|
globs.max_buf = atoi( s ) * 1024; |
|
|
|
|
|
for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n ) |
|
{ |
|
int i; |
|
|
|
|
|
if ( !n ) |
|
for ( i = 0; i < DEBUG_MAX; ++i ) |
|
globs.debug[i] = 0; |
|
|
|
i = atoi( s ); |
|
|
|
if ( ( i < 0 ) || ( i >= DEBUG_MAX ) ) |
|
{ |
|
printf( "Invalid debug level '%s'.\n", s ); |
|
continue; |
|
} |
|
|
|
|
|
|
|
if ( *s == '+' ) |
|
globs.debug[ i ] = 1; |
|
else while ( i ) |
|
globs.debug[ i-- ] = 1; |
|
} |
|
|
|
constants_init(); |
|
cwd_init(); |
|
|
|
{ |
|
PROFILE_ENTER( MAIN ); |
|
|
|
#ifdef HAVE_PYTHON |
|
{ |
|
PROFILE_ENTER( MAIN_PYTHON ); |
|
Py_Initialize(); |
|
{ |
|
static PyMethodDef BjamMethods[] = { |
|
{"call", bjam_call, METH_VARARGS, |
|
"Call the specified bjam rule."}, |
|
{"import_rule", bjam_import_rule, METH_VARARGS, |
|
"Imports Python callable to bjam."}, |
|
{"define_action", bjam_define_action, METH_VARARGS, |
|
"Defines a command line action."}, |
|
{"variable", bjam_variable, METH_VARARGS, |
|
"Obtains a variable from bjam's global module."}, |
|
{"backtrace", bjam_backtrace, METH_VARARGS, |
|
"Returns bjam backtrace from the last call into Python."}, |
|
{"caller", bjam_caller, METH_VARARGS, |
|
"Returns the module from which the last call into Python is made."}, |
|
{NULL, NULL, 0, NULL} |
|
}; |
|
|
|
Py_InitModule( "bjam", BjamMethods ); |
|
} |
|
PROFILE_EXIT( MAIN_PYTHON ); |
|
} |
|
#endif |
|
|
|
#ifndef NDEBUG |
|
run_unit_tests(); |
|
#endif |
|
#if YYDEBUG != 0 |
|
if ( DEBUG_PARSE ) |
|
yydebug = 1; |
|
#endif |
|
|
|
|
|
{ |
|
timestamp current; |
|
timestamp_current( ¤t ); |
|
var_set( root_module(), constant_JAMDATE, list_new( outf_time( |
|
¤t ) ), VAR_SET ); |
|
} |
|
|
|
|
|
var_set( root_module(), constant_JAM_VERSION, |
|
list_push_back( list_push_back( list_new( |
|
object_new( VERSION_MAJOR_SYM ) ), |
|
object_new( VERSION_MINOR_SYM ) ), |
|
object_new( VERSION_PATCH_SYM ) ), |
|
VAR_SET ); |
|
|
|
|
|
#ifdef unix |
|
{ |
|
struct utsname u; |
|
|
|
if ( uname( &u ) >= 0 ) |
|
{ |
|
var_set( root_module(), constant_JAMUNAME, |
|
list_push_back( |
|
list_push_back( |
|
list_push_back( |
|
list_push_back( |
|
list_new( |
|
object_new( u.sysname ) ), |
|
object_new( u.nodename ) ), |
|
object_new( u.release ) ), |
|
object_new( u.version ) ), |
|
object_new( u.machine ) ), VAR_SET ); |
|
} |
|
} |
|
#endif |
|
|
|
|
|
{ |
|
timestamp fmt_resolution[ 1 ]; |
|
file_supported_fmt_resolution( fmt_resolution ); |
|
var_set( root_module(), constant_JAM_TIMESTAMP_RESOLUTION, list_new( |
|
object_new( timestamp_timestr( fmt_resolution ) ) ), VAR_SET ); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
var_defines( root_module(), use_environ, 1 ); |
|
|
|
environ_module = bindmodule( constant_ENVIRON ); |
|
|
|
var_defines( environ_module, use_environ, 0 ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
var_defines( root_module(), othersyms, 1 ); |
|
|
|
|
|
for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n ) |
|
{ |
|
char * symv[ 2 ]; |
|
symv[ 0 ] = s; |
|
symv[ 1 ] = 0; |
|
var_defines( root_module(), symv, 1 ); |
|
var_defines( environ_module, symv, 0 ); |
|
} |
|
|
|
|
|
|
|
for ( n = 0; n < arg_c; ++n ) |
|
var_set( root_module(), constant_ARGV, list_new( object_new( |
|
arg_v[ n ] ) ), VAR_APPEND ); |
|
|
|
|
|
load_builtins(); |
|
|
|
|
|
for ( n = 1; n < arg_c; ++n ) |
|
{ |
|
if ( arg_v[ n ][ 0 ] == '-' ) |
|
{ |
|
char * f = "-:l:d:j:f:gs:t:ano:qv"; |
|
for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break; |
|
if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n; |
|
} |
|
else |
|
{ |
|
OBJECT * const target = object_new( arg_v[ n ] ); |
|
mark_target_for_updating( target ); |
|
object_free( target ); |
|
} |
|
} |
|
|
|
if ( list_empty( targets_to_update() ) ) |
|
mark_target_for_updating( constant_all ); |
|
|
|
|
|
{ |
|
FRAME frame[ 1 ]; |
|
frame_init( frame ); |
|
for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n ) |
|
{ |
|
OBJECT * const filename = object_new( s ); |
|
parse_file( filename, frame ); |
|
object_free( filename ); |
|
} |
|
|
|
if ( !n ) |
|
parse_file( constant_plus, frame ); |
|
} |
|
|
|
status = yyanyerrors(); |
|
|
|
|
|
for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n ) |
|
{ |
|
OBJECT * const target = object_new( s ); |
|
touch_target( target ); |
|
object_free( target ); |
|
} |
|
|
|
|
|
if ( ( s = getoptval( optv, 'o', 0 ) ) ) |
|
{ |
|
if ( !( globs.cmdout = fopen( s, "w" ) ) ) |
|
{ |
|
printf( "Failed to write to '%s'\n", s ); |
|
exit( EXITBAD ); |
|
} |
|
++globs.noexec; |
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
LIST * const p = var_get( root_module(), constant_PARALLELISM ); |
|
if ( !list_empty( p ) ) |
|
{ |
|
int const j = atoi( object_str( list_front( p ) ) ); |
|
if ( j < 1 || j > MAXJOBS ) |
|
printf( "Invalid value of PARALLELISM: %s. Valid values " |
|
"are 1 through %d.\n", object_str( list_front( p ) ), |
|
MAXJOBS ); |
|
else |
|
globs.jobs = j; |
|
} |
|
} |
|
|
|
|
|
{ |
|
LIST * const p = var_get( root_module(), constant_KEEP_GOING ); |
|
if ( !list_empty( p ) ) |
|
globs.quitquick = atoi( object_str( list_front( p ) ) ) ? 0 : 1; |
|
} |
|
|
|
|
|
{ |
|
PROFILE_ENTER( MAIN_MAKE ); |
|
LIST * const targets = targets_to_update(); |
|
if ( !list_empty( targets ) ) |
|
status |= make( targets, anyhow ); |
|
else |
|
status = last_update_now_status; |
|
PROFILE_EXIT( MAIN_MAKE ); |
|
} |
|
|
|
PROFILE_EXIT( MAIN ); |
|
} |
|
|
|
if ( DEBUG_PROFILE ) |
|
profile_dump(); |
|
|
|
|
|
#ifdef OPT_HEADER_CACHE_EXT |
|
hcache_done(); |
|
#endif |
|
|
|
clear_targets_to_update(); |
|
|
|
|
|
property_set_done(); |
|
file_done(); |
|
rules_done(); |
|
timestamp_done(); |
|
search_done(); |
|
class_done(); |
|
modules_done(); |
|
regex_done(); |
|
cwd_done(); |
|
path_done(); |
|
function_done(); |
|
list_done(); |
|
constants_done(); |
|
object_done(); |
|
|
|
|
|
if ( globs.cmdout ) |
|
fclose( globs.cmdout ); |
|
|
|
#ifdef HAVE_PYTHON |
|
Py_Finalize(); |
|
#endif |
|
|
|
BJAM_MEM_CLOSE(); |
|
|
|
return status ? EXITBAD : EXITOK; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32) |
|
# define WIN32_LEAN_AND_MEAN |
|
# include <windows.h> |
|
char * executable_path( char const * argv0 ) |
|
{ |
|
char buf[ 1024 ]; |
|
DWORD const ret = GetModuleFileName( NULL, buf, sizeof( buf ) ); |
|
return ( !ret || ret == sizeof( buf ) ) ? NULL : strdup( buf ); |
|
} |
|
#elif defined(__APPLE__) |
|
# include <mach-o/dyld.h> |
|
char *executable_path( char const * argv0 ) |
|
{ |
|
char buf[ 1024 ]; |
|
uint32_t size = sizeof( buf ); |
|
return _NSGetExecutablePath( buf, &size ) ? NULL : strdup( buf ); |
|
} |
|
#elif defined(sun) || defined(__sun) |
|
# include <stdlib.h> |
|
char * executable_path( char const * argv0 ) |
|
{ |
|
return strdup( getexecname() ); |
|
} |
|
#elif defined(__FreeBSD__) |
|
# include <sys/sysctl.h> |
|
char * executable_path( char const * argv0 ) |
|
{ |
|
int mib[ 4 ] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; |
|
char buf[ 1024 ]; |
|
size_t size = sizeof( buf ); |
|
sysctl( mib, 4, buf, &size, NULL, 0 ); |
|
return ( !size || size == sizeof( buf ) ) ? NULL : strndup( buf, size ); |
|
} |
|
#elif defined(__linux__) |
|
# include <unistd.h> |
|
char * executable_path( char const * argv0 ) |
|
{ |
|
char buf[ 1024 ]; |
|
ssize_t const ret = readlink( "/proc/self/exe", buf, sizeof( buf ) ); |
|
return ( !ret || ret == sizeof( buf ) ) ? NULL : strndup( buf, ret ); |
|
} |
|
#else |
|
char * executable_path( char const * argv0 ) |
|
{ |
|
|
|
return argv0[ 0 ] == '/' ? strdup( argv0 ) : NULL; |
|
} |
|
#endif |
|
|