From e98ac4ece6730427156c93668c4eaf921753ba22 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Sat, 5 Mar 2005 07:59:14 +0000 Subject: [PATCH] Initial Python integration support. Disabled by default, find and change the setting of HAVE_PYTHON in build.jam to enable it. [SVN r27559] --- historic/jam/src/build.jam | 15 +++ historic/jam/src/builtins.c | 186 +++++++++++++++++++++++++++++++++++- historic/jam/src/builtins.h | 1 + historic/jam/src/compile.c | 107 +++++++++++++++++++++ historic/jam/src/jam.c | 30 ++++++ historic/jam/src/jam.h | 5 + historic/jam/src/rules.c | 3 + historic/jam/src/rules.h | 3 + jam_src/build.jam | 15 +++ jam_src/builtins.c | 186 +++++++++++++++++++++++++++++++++++- jam_src/builtins.h | 1 + jam_src/compile.c | 107 +++++++++++++++++++++ jam_src/jam.c | 30 ++++++ jam_src/jam.h | 5 + jam_src/rules.c | 3 + jam_src/rules.h | 3 + 16 files changed, 696 insertions(+), 4 deletions(-) diff --git a/historic/jam/src/build.jam b/historic/jam/src/build.jam index 94d7e63a2..bde19a823 100644 --- a/historic/jam/src/build.jam +++ b/historic/jam/src/build.jam @@ -17,6 +17,11 @@ VERSION = 3$(.)1$(.)10 ; RELEASE = 1 ; LICENSE = 1_0 ; +HAVE_PYTHON = 0 ; +PYTHON_INCUDES = /usr/include/python2.3 ; +PYTHON_LIB = -lpython2.3 ; + + # Generate development debug binaries? if --debug in $(ARGV) { @@ -326,6 +331,16 @@ if $(VMS) } --defs += YYSTACKSIZE=5000 ; +if $(HAVE_PYTHON) = 1 +{ + --defs += HAVE_PYTHON ; + --flags += -I$(PYTHON_INCUDES) ; + --flags += -Wno-long-long ; + --libs += $(PYTHON_LIB) ; +} + + + # The basic symbolic targets... NOTFILE all clean dist ; ALWAYS clean ; diff --git a/historic/jam/src/builtins.c b/historic/jam/src/builtins.c index 8049c2f45..899c7ccce 100644 --- a/historic/jam/src/builtins.c +++ b/historic/jam/src/builtins.c @@ -22,6 +22,7 @@ # include "hdrmacro.h" # include "compile.h" # include "native.h" +# include "variable.h" # include /* @@ -287,8 +288,14 @@ load_builtins() builtin_check_if_file, 0, args ); } - - +#ifdef HAVE_PYTHON + { + char * args[] = { "python-module", ":", "function", ":", + "jam-module", ":", "rule-name", 0 }; + bind_builtin( "PYTHON_IMPORT_RULE", + builtin_python_import_rule, 0, args ); + } +#endif # ifdef OS_NT { @@ -1238,6 +1245,92 @@ LIST *builtin_check_if_file( PARSE *parse, FRAME *frame ) } +#ifdef HAVE_PYTHON + +LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame ) +{ + static int first_time = 1; + char* python_module = lol_get( frame->args, 0 )->string; + char* python_function = lol_get( frame->args, 1 )->string; + char* jam_module = lol_get( frame->args, 2 )->string; + char* jam_rule = lol_get( frame->args, 3 )->string; + + PyObject *pName, *pModule, *pDict, *pFunc; + + if (first_time) + { + /* At the first invocation, we add the value of the + global EXTRA_PYTHONPATH to the sys.path Python + variable. + */ + LIST* extra = 0; + module_t* outer_module = frame->module; + + first_time = 0; + + if ( outer_module != root_module()) + { + exit_module( outer_module ); + enter_module( root_module()); + } + + extra = var_get("EXTRA_PYTHONPATH"); + + if ( outer_module != root_module()) + { + exit_module( root_module()); + enter_module( outer_module ); + } + + for(; extra; extra = extra->next) + { + string buf[1]; + string_new(buf); + string_append(buf, "import sys\nsys.path.append(\""); + string_append(buf, extra->string); + string_append(buf, "\")\n"); + PyRun_SimpleString(buf->value); + string_free(buf); + } + } + + + pName = PyString_FromString(python_module); + + pModule = PyImport_Import(pName); + Py_DECREF(pName); + + if (pModule != NULL) { + pDict = PyModule_GetDict(pModule); + pFunc = PyDict_GetItemString(pDict, python_function); + + if (pFunc && PyCallable_Check(pFunc)) { + + module_t* m = bindmodule(jam_module); + RULE* r = bindrule( jam_rule, m ); + + /* Make pFunc owned */ + Py_INCREF(pFunc); + + r->python_function = pFunc; + } + else { + if (PyErr_Occurred()) + PyErr_Print(); + fprintf(stderr, "Cannot find function \"%s\"\n", python_function); + } + Py_DECREF(pModule); + } + else { + PyErr_Print(); + fprintf(stderr, "Failed to load \"%s\"\n", python_module); + } + return L0; + +} + +#endif + void lol_build( LOL* lol, char** elements ) { LIST* l = L0; @@ -1261,3 +1354,92 @@ void lol_build( LOL* lol, char** elements ) lol_add( lol, l ); } +#ifdef HAVE_PYTHON + +/** Calls the bjam rule specified by name passed in 'args'. + The name is looked up in context of bjam's 'python_interface' + module. Returns the list of string retured by the rule. +*/ +PyObject* +bjam_call(PyObject* self, PyObject* args) +{ + FRAME inner[1]; + LIST *result; + PARSE *p; + char* rulename; + + /* Build up the list of arg lists */ + + frame_init( inner ); + inner->prev = 0; + inner->prev_user = 0; + inner->module = bindmodule("python_interface"); + inner->procedure = 0; + + /* Extract the rule name and arguments from 'args' */ + + /* PyTuple_GetItem returns borrowed reference */ + rulename = PyString_AsString(PyTuple_GetItem(args, 0)); + { + int i = 1; + int size = PyTuple_Size(args); + for( ; i < size; ++i) { + PyObject* a = PyTuple_GetItem(args, i); + if (PyString_Check(a)) + { + lol_add(inner->args, + list_new(0, newstr(PyString_AsString(a)))); + } + else if (PySequence_Check(a)) + { + LIST* l = 0; + int s = PySequence_Size(a); + int i = 0; + for(; i < s; ++i) + { + /* PySequence_GetItem returns new reference. */ + PyObject* e = PySequence_GetItem(a, i); + l = list_new(l, newstr(PyString_AsString(e))); + Py_DECREF(e); + } + lol_add(inner->args, l); + } + } + } + + result = evaluate_rule( rulename, inner ); + + frame_free( inner ); +} + +/** Accepts three arguments: module name, rule name and Python callable. + + Creates bjam rule with the specified name in the specified module, + which will invoke the Python callable. +*/ +PyObject* +bjam_import_rule(PyObject* self, PyObject* args) +{ + char* module; + char* rule; + PyObject* func; + module_t* m; + RULE* r; + + if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func)) + return NULL; + + if (!PyCallable_Check(func)) + return NULL; + + m = bindmodule(module); + r = bindrule(rule, m); + + /* Make pFunc owned */ + Py_INCREF(func); + + r->python_function = func; + return Py_None; +} + +#endif diff --git a/historic/jam/src/builtins.h b/historic/jam/src/builtins.h index c94b00a1e..781a21943 100644 --- a/historic/jam/src/builtins.h +++ b/historic/jam/src/builtins.h @@ -44,6 +44,7 @@ LIST *builtin_native_rule( PARSE *parse, FRAME *frame ); LIST *builtin_user_module( PARSE *parse, FRAME *frame ); LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame ); LIST *builtin_check_if_file( PARSE *parse, FRAME *frame ); +LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame ); void backtrace( FRAME *frame ); diff --git a/historic/jam/src/compile.c b/historic/jam/src/compile.c index 87d6b1344..8bea9b5c7 100644 --- a/historic/jam/src/compile.c +++ b/historic/jam/src/compile.c @@ -889,6 +889,106 @@ void profile_dump() } } +static int python_instance_number = 0; + +RULE * +enter_rule( char *rulename, module_t *target_module ); + +#ifdef HAVE_PYTHON +static LIST* +call_python_function(RULE* r, FRAME* frame) +{ + LIST* result = 0; + PyObject* arguments = PyTuple_New(frame->args->count); + int i ; + PyObject* py_result; + + for(i = 0; i < frame->args->count; ++i) + { + PyObject* arg = PyList_New(0); + LIST* l = lol_get( frame->args, i); + + for(; l; l = l->next) + { + PyObject* v = PyString_FromString(l->string); + /* Steals reference to 'v' */ + PyList_Append(arg, v); + } + /* Steals reference to 'arg' */ + PyTuple_SetItem(arguments, i, arg); + } + + py_result = PyObject_CallObject(r->python_function, arguments); + Py_DECREF(arguments); + if (py_result != NULL) { + + if (PyList_Check(py_result)) { + int size = PyList_Size(py_result); + int i; + for(i = 0; i < size; ++i) + { + PyObject* item = PyList_GetItem(py_result, i); + if (PyString_Check(item)) + { + result = list_new(result, + newstr(PyString_AsString(item))); + } + else + { + fprintf(stderr, "Non-string object returned by Python call\n"); + } + } + } + else if (PyInstance_Check(py_result)) + { + static char instance_name[1000]; + static char imported_method_name[1000]; + module_t* m; + PyObject* method; + PyObject* method_name = PyString_FromString("foo"); + RULE* r; + + fprintf(stderr, "Got instance!\n"); + + snprintf(instance_name, 1000, + "pyinstance%d", python_instance_number); + snprintf(imported_method_name, 1000, + "pyinstance%d.foo", python_instance_number); + ++python_instance_number; + + m = bindmodule(instance_name); + + /* This is expected to get bound method. */ + method = PyObject_GetAttr(py_result, method_name); + + r = bindrule( imported_method_name, root_module() ); + + r->python_function = method; + + result = list_new(0, newstr(instance_name)); + + Py_DECREF(method_name); + } + else if (py_result == Py_None) + { + result = L0; + } + else + { + fprintf(stderr, "Non-list object returned by Python call\n"); + } + + Py_DECREF(py_result); + } + else { + PyErr_Print(); + fprintf(stderr,"Call failed\n"); + } + + return result; +} +#endif + /* * evaluate_rule() - execute a rule invocation */ @@ -925,6 +1025,13 @@ evaluate_rule( rulename = l->string; rule = bindrule( l->string, frame->module ); +#ifdef HAVE_PYTHON + if (rule->python_function) + { + return call_python_function(rule, frame); + } +#endif + /* drop the rule name */ l = list_pop_front( l ); diff --git a/historic/jam/src/jam.c b/historic/jam/src/jam.c index c3f8c763f..7774d5543 100644 --- a/historic/jam/src/jam.c +++ b/historic/jam/src/jam.c @@ -196,6 +196,14 @@ static void run_unit_tests() } #endif +#ifdef HAVE_PYTHON + extern PyObject* + bjam_call(PyObject *self, PyObject *args); + + extern PyObject* + bjam_import_rule(PyObject* self, PyObject* args); +#endif + int main( int argc, char **argv, char **arg_environ ) { int n; @@ -211,6 +219,23 @@ int main( int argc, char **argv, char **arg_environ ) InitGraf(&qd.thePort); # endif +#ifdef HAVE_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."}, + {NULL, NULL, 0, NULL} + }; + + Py_InitModule("bjam", BjamMethods); + } + +#endif + argc--, argv++; if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 ) @@ -463,5 +488,10 @@ int main( int argc, char **argv, char **arg_environ ) if( globs.cmdout ) fclose( globs.cmdout ); +#ifdef HAVE_PYTHON + Py_Finalize(); +#endif + + return status ? EXITBAD : EXITOK; } diff --git a/historic/jam/src/jam.h b/historic/jam/src/jam.h index b6c45c72a..9cd74f781 100644 --- a/historic/jam/src/jam.h +++ b/historic/jam/src/jam.h @@ -37,6 +37,11 @@ #ifndef JAM_H_VP_2003_08_01 #define JAM_H_VP_2003_08_01 + +#ifdef HAVE_PYTHON +#include +#endif + /* * VMS, OPENVMS */ diff --git a/historic/jam/src/rules.c b/historic/jam/src/rules.c index c98751f2f..0d0cb2fd8 100644 --- a/historic/jam/src/rules.c +++ b/historic/jam/src/rules.c @@ -82,6 +82,9 @@ enter_rule( char *rulename, module_t *target_module ) r->arguments = 0; r->exported = 0; r->module = target_module; +#ifdef HAVE_PYTHON + r->python_function = 0; +#endif } return r; } diff --git a/historic/jam/src/rules.h b/historic/jam/src/rules.h index 3dc21a3f1..91a9c4aaf 100644 --- a/historic/jam/src/rules.h +++ b/historic/jam/src/rules.h @@ -87,6 +87,9 @@ struct _rule { * appear in the global module and be * automatically imported into other modules */ +#ifdef HAVE_PYTHON + PyObject* python_function; +#endif }; /* ACTIONS - a chain of ACTIONs */ diff --git a/jam_src/build.jam b/jam_src/build.jam index 94d7e63a2..bde19a823 100644 --- a/jam_src/build.jam +++ b/jam_src/build.jam @@ -17,6 +17,11 @@ VERSION = 3$(.)1$(.)10 ; RELEASE = 1 ; LICENSE = 1_0 ; +HAVE_PYTHON = 0 ; +PYTHON_INCUDES = /usr/include/python2.3 ; +PYTHON_LIB = -lpython2.3 ; + + # Generate development debug binaries? if --debug in $(ARGV) { @@ -326,6 +331,16 @@ if $(VMS) } --defs += YYSTACKSIZE=5000 ; +if $(HAVE_PYTHON) = 1 +{ + --defs += HAVE_PYTHON ; + --flags += -I$(PYTHON_INCUDES) ; + --flags += -Wno-long-long ; + --libs += $(PYTHON_LIB) ; +} + + + # The basic symbolic targets... NOTFILE all clean dist ; ALWAYS clean ; diff --git a/jam_src/builtins.c b/jam_src/builtins.c index 8049c2f45..899c7ccce 100644 --- a/jam_src/builtins.c +++ b/jam_src/builtins.c @@ -22,6 +22,7 @@ # include "hdrmacro.h" # include "compile.h" # include "native.h" +# include "variable.h" # include /* @@ -287,8 +288,14 @@ load_builtins() builtin_check_if_file, 0, args ); } - - +#ifdef HAVE_PYTHON + { + char * args[] = { "python-module", ":", "function", ":", + "jam-module", ":", "rule-name", 0 }; + bind_builtin( "PYTHON_IMPORT_RULE", + builtin_python_import_rule, 0, args ); + } +#endif # ifdef OS_NT { @@ -1238,6 +1245,92 @@ LIST *builtin_check_if_file( PARSE *parse, FRAME *frame ) } +#ifdef HAVE_PYTHON + +LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame ) +{ + static int first_time = 1; + char* python_module = lol_get( frame->args, 0 )->string; + char* python_function = lol_get( frame->args, 1 )->string; + char* jam_module = lol_get( frame->args, 2 )->string; + char* jam_rule = lol_get( frame->args, 3 )->string; + + PyObject *pName, *pModule, *pDict, *pFunc; + + if (first_time) + { + /* At the first invocation, we add the value of the + global EXTRA_PYTHONPATH to the sys.path Python + variable. + */ + LIST* extra = 0; + module_t* outer_module = frame->module; + + first_time = 0; + + if ( outer_module != root_module()) + { + exit_module( outer_module ); + enter_module( root_module()); + } + + extra = var_get("EXTRA_PYTHONPATH"); + + if ( outer_module != root_module()) + { + exit_module( root_module()); + enter_module( outer_module ); + } + + for(; extra; extra = extra->next) + { + string buf[1]; + string_new(buf); + string_append(buf, "import sys\nsys.path.append(\""); + string_append(buf, extra->string); + string_append(buf, "\")\n"); + PyRun_SimpleString(buf->value); + string_free(buf); + } + } + + + pName = PyString_FromString(python_module); + + pModule = PyImport_Import(pName); + Py_DECREF(pName); + + if (pModule != NULL) { + pDict = PyModule_GetDict(pModule); + pFunc = PyDict_GetItemString(pDict, python_function); + + if (pFunc && PyCallable_Check(pFunc)) { + + module_t* m = bindmodule(jam_module); + RULE* r = bindrule( jam_rule, m ); + + /* Make pFunc owned */ + Py_INCREF(pFunc); + + r->python_function = pFunc; + } + else { + if (PyErr_Occurred()) + PyErr_Print(); + fprintf(stderr, "Cannot find function \"%s\"\n", python_function); + } + Py_DECREF(pModule); + } + else { + PyErr_Print(); + fprintf(stderr, "Failed to load \"%s\"\n", python_module); + } + return L0; + +} + +#endif + void lol_build( LOL* lol, char** elements ) { LIST* l = L0; @@ -1261,3 +1354,92 @@ void lol_build( LOL* lol, char** elements ) lol_add( lol, l ); } +#ifdef HAVE_PYTHON + +/** Calls the bjam rule specified by name passed in 'args'. + The name is looked up in context of bjam's 'python_interface' + module. Returns the list of string retured by the rule. +*/ +PyObject* +bjam_call(PyObject* self, PyObject* args) +{ + FRAME inner[1]; + LIST *result; + PARSE *p; + char* rulename; + + /* Build up the list of arg lists */ + + frame_init( inner ); + inner->prev = 0; + inner->prev_user = 0; + inner->module = bindmodule("python_interface"); + inner->procedure = 0; + + /* Extract the rule name and arguments from 'args' */ + + /* PyTuple_GetItem returns borrowed reference */ + rulename = PyString_AsString(PyTuple_GetItem(args, 0)); + { + int i = 1; + int size = PyTuple_Size(args); + for( ; i < size; ++i) { + PyObject* a = PyTuple_GetItem(args, i); + if (PyString_Check(a)) + { + lol_add(inner->args, + list_new(0, newstr(PyString_AsString(a)))); + } + else if (PySequence_Check(a)) + { + LIST* l = 0; + int s = PySequence_Size(a); + int i = 0; + for(; i < s; ++i) + { + /* PySequence_GetItem returns new reference. */ + PyObject* e = PySequence_GetItem(a, i); + l = list_new(l, newstr(PyString_AsString(e))); + Py_DECREF(e); + } + lol_add(inner->args, l); + } + } + } + + result = evaluate_rule( rulename, inner ); + + frame_free( inner ); +} + +/** Accepts three arguments: module name, rule name and Python callable. + + Creates bjam rule with the specified name in the specified module, + which will invoke the Python callable. +*/ +PyObject* +bjam_import_rule(PyObject* self, PyObject* args) +{ + char* module; + char* rule; + PyObject* func; + module_t* m; + RULE* r; + + if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func)) + return NULL; + + if (!PyCallable_Check(func)) + return NULL; + + m = bindmodule(module); + r = bindrule(rule, m); + + /* Make pFunc owned */ + Py_INCREF(func); + + r->python_function = func; + return Py_None; +} + +#endif diff --git a/jam_src/builtins.h b/jam_src/builtins.h index c94b00a1e..781a21943 100644 --- a/jam_src/builtins.h +++ b/jam_src/builtins.h @@ -44,6 +44,7 @@ LIST *builtin_native_rule( PARSE *parse, FRAME *frame ); LIST *builtin_user_module( PARSE *parse, FRAME *frame ); LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame ); LIST *builtin_check_if_file( PARSE *parse, FRAME *frame ); +LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame ); void backtrace( FRAME *frame ); diff --git a/jam_src/compile.c b/jam_src/compile.c index 87d6b1344..8bea9b5c7 100644 --- a/jam_src/compile.c +++ b/jam_src/compile.c @@ -889,6 +889,106 @@ void profile_dump() } } +static int python_instance_number = 0; + +RULE * +enter_rule( char *rulename, module_t *target_module ); + +#ifdef HAVE_PYTHON +static LIST* +call_python_function(RULE* r, FRAME* frame) +{ + LIST* result = 0; + PyObject* arguments = PyTuple_New(frame->args->count); + int i ; + PyObject* py_result; + + for(i = 0; i < frame->args->count; ++i) + { + PyObject* arg = PyList_New(0); + LIST* l = lol_get( frame->args, i); + + for(; l; l = l->next) + { + PyObject* v = PyString_FromString(l->string); + /* Steals reference to 'v' */ + PyList_Append(arg, v); + } + /* Steals reference to 'arg' */ + PyTuple_SetItem(arguments, i, arg); + } + + py_result = PyObject_CallObject(r->python_function, arguments); + Py_DECREF(arguments); + if (py_result != NULL) { + + if (PyList_Check(py_result)) { + int size = PyList_Size(py_result); + int i; + for(i = 0; i < size; ++i) + { + PyObject* item = PyList_GetItem(py_result, i); + if (PyString_Check(item)) + { + result = list_new(result, + newstr(PyString_AsString(item))); + } + else + { + fprintf(stderr, "Non-string object returned by Python call\n"); + } + } + } + else if (PyInstance_Check(py_result)) + { + static char instance_name[1000]; + static char imported_method_name[1000]; + module_t* m; + PyObject* method; + PyObject* method_name = PyString_FromString("foo"); + RULE* r; + + fprintf(stderr, "Got instance!\n"); + + snprintf(instance_name, 1000, + "pyinstance%d", python_instance_number); + snprintf(imported_method_name, 1000, + "pyinstance%d.foo", python_instance_number); + ++python_instance_number; + + m = bindmodule(instance_name); + + /* This is expected to get bound method. */ + method = PyObject_GetAttr(py_result, method_name); + + r = bindrule( imported_method_name, root_module() ); + + r->python_function = method; + + result = list_new(0, newstr(instance_name)); + + Py_DECREF(method_name); + } + else if (py_result == Py_None) + { + result = L0; + } + else + { + fprintf(stderr, "Non-list object returned by Python call\n"); + } + + Py_DECREF(py_result); + } + else { + PyErr_Print(); + fprintf(stderr,"Call failed\n"); + } + + return result; +} +#endif + /* * evaluate_rule() - execute a rule invocation */ @@ -925,6 +1025,13 @@ evaluate_rule( rulename = l->string; rule = bindrule( l->string, frame->module ); +#ifdef HAVE_PYTHON + if (rule->python_function) + { + return call_python_function(rule, frame); + } +#endif + /* drop the rule name */ l = list_pop_front( l ); diff --git a/jam_src/jam.c b/jam_src/jam.c index c3f8c763f..7774d5543 100644 --- a/jam_src/jam.c +++ b/jam_src/jam.c @@ -196,6 +196,14 @@ static void run_unit_tests() } #endif +#ifdef HAVE_PYTHON + extern PyObject* + bjam_call(PyObject *self, PyObject *args); + + extern PyObject* + bjam_import_rule(PyObject* self, PyObject* args); +#endif + int main( int argc, char **argv, char **arg_environ ) { int n; @@ -211,6 +219,23 @@ int main( int argc, char **argv, char **arg_environ ) InitGraf(&qd.thePort); # endif +#ifdef HAVE_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."}, + {NULL, NULL, 0, NULL} + }; + + Py_InitModule("bjam", BjamMethods); + } + +#endif + argc--, argv++; if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 ) @@ -463,5 +488,10 @@ int main( int argc, char **argv, char **arg_environ ) if( globs.cmdout ) fclose( globs.cmdout ); +#ifdef HAVE_PYTHON + Py_Finalize(); +#endif + + return status ? EXITBAD : EXITOK; } diff --git a/jam_src/jam.h b/jam_src/jam.h index b6c45c72a..9cd74f781 100644 --- a/jam_src/jam.h +++ b/jam_src/jam.h @@ -37,6 +37,11 @@ #ifndef JAM_H_VP_2003_08_01 #define JAM_H_VP_2003_08_01 + +#ifdef HAVE_PYTHON +#include +#endif + /* * VMS, OPENVMS */ diff --git a/jam_src/rules.c b/jam_src/rules.c index c98751f2f..0d0cb2fd8 100644 --- a/jam_src/rules.c +++ b/jam_src/rules.c @@ -82,6 +82,9 @@ enter_rule( char *rulename, module_t *target_module ) r->arguments = 0; r->exported = 0; r->module = target_module; +#ifdef HAVE_PYTHON + r->python_function = 0; +#endif } return r; } diff --git a/jam_src/rules.h b/jam_src/rules.h index 3dc21a3f1..91a9c4aaf 100644 --- a/jam_src/rules.h +++ b/jam_src/rules.h @@ -87,6 +87,9 @@ struct _rule { * appear in the global module and be * automatically imported into other modules */ +#ifdef HAVE_PYTHON + PyObject* python_function; +#endif }; /* ACTIONS - a chain of ACTIONs */