if ! $(gPYTHON_INCLUDED) { gPYTHON_INCLUDED = true ; # Do some OS-specific setup if $(NT) { PYTHON_VERSION ?= 2.1 ; } else if $(UNIX) { PYTHON_VERSION ?= 1.5 ; } # Strip the dot from the Python version in order to be able to name # libraries PYTHON_VERSION_NODOT = [ SUBST $(PYTHON_VERSION) ([0-9]*)\.([0-9]*) $1$2 ] ; local RUN_PATH = $(RUN_PATH) ; if $(NT) { PYTHON_ROOT ?= c:/tools/python ; PYTHON_LIB_PATH ?= $(PYTHON_ROOT)/libs $(PYTHON_ROOT)/PCBuild ; # Locate Python libraries. In the case of MSVC the libraries are # found implicitly, and GCC/MINGW will use -lpython to # find it, but other compilers may need an explicit pointer on the # command line. PYTHON_LIB ?= python$(PYTHON_VERSION_NODOT).lib ; SEARCH on $(PYTHON_LIB) = $(PYTHON_LIB_PATH) ; PYTHON_D_LIB ?= python$(PYTHON_VERSION_NODOT)_d.lib ; SEARCH on $(PYTHON_D_LIB) = $(PYTHON_LIB_PATH) ; # common properties required for compiling any Python module. PYTHON_PROPERTIES ?= select-python-includes dynamic $(BOOST_ROOT) <*>SIZEOF_LONG=4 <*>USE_DL_IMPORT <*>python$(PYTHON_VERSION).dll ; GCC_PYTHON_ROOT ?= $(CYGWIN_ROOT)/usr/local ; GCC_PYTHON_ROOT ?= /usr/local ; GCC_PYTHON_DEBUG_ROOT ?= $(CYGWIN_ROOT)/usr/local/pydebug ; GCC_PYTHON_DEBUG_ROOT ?= /usr/local/pydebug ; } else if $(UNIX) { PYTHON_VERSION ?= 1.5 ; PYTHON_ROOT ?= /usr/local ; PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include/python$(PYTHON_VERSION) ; PYTHON_LIB_PATH ?= $(PYTHON_ROOT)/lib/python$(PYTHON_VERSION)/config ; PYTHON_PROPERTIES ?= $(PYTHON_INCLUDES) $(PYTHON_LIB_PATH) <*>"-expect_unresolved 'Py*' -expect_unresolved '_Py*'" ; } # Locate the python executable PYTHON ?= python$(SUFEXE) ; SEARCH on $(PYTHON) = $(PYTHON_ROOT)/bin $(RUN_PATH) ; # And the debugging version PYTHON_D ?= $(PYTHON:S=)_d$(PYTHON:S) ; SEARCH on $(PYTHON_D) = $(RUN_PATH) ; # select-python-library # # Ungristed elements of a requirements list are treated as the rule # names to be called to transform the property set. This is used when # the requirements are too complicated to express otherwise. This # rule selects the right python library when building on Windows. rule select-python-library ( toolset variant : properties * ) { if $(NT) { if $(toolset) = mingw { local lib = python$(PYTHON_VERSION_NODOT) ; if BOOST_DEBUG_PYTHON in $(properties) { lib = python$(PYTHON_VERSION_NODOT)_d ; } properties += $(lib) ; } else if $(toolset) = gcc { local python-root = $(GCC_PYTHON_ROOT) ; if BOOST_DEBUG_PYTHON in $(properties) { python-root = $(GCC_PYTHON_DEBUG_ROOT) ; } properties += $(python-root)/lib/python$(PYTHON_VERSION)/config ; } else if ! ( $(toolset) = msvc ) { local lib = $(PYTHON_LIB) ; if BOOST_DEBUG_PYTHON in $(properties) { lib = $(PYTHON_D_LIB) ; } properties += $(lib) ; } } return $(properties) ; } rule select-python-includes ( toolset variant : properties * ) { if $(toolset) = gcc { local python-root = $(GCC_PYTHON_ROOT) ; if BOOST_DEBUG_PYTHON in $(properties) { python-root = $(GCC_PYTHON_DEBUG_ROOT) ; } properties += $(python-root)/include/python$(PYTHON_VERSION) ; } else { properties += $(PYTHON_ROOT)/include $(PYTHON_ROOT)/PC # in case the user is using a source installation _DEBUG ; } return $(properties) ; } PYTHON_PROPERTIES += <*>util $(BOOST_ROOT) select-python-library # These two compilers pick up implicit directions from #pragmas # to look for those libraries. <*>$(PYTHON_LIB_PATH) <*>$(PYTHON_LIB_PATH) <*>$(PYTHON_LIB_PATH) ; # Extends the RUN_PATH assignment for targets built under Cygwin so # that the Python DLL can be found. rule add-cygwin-python-run-path ( module ) { local d = $(GCC_ROOT_DIRECTORY) ; while $(d:D) != $(d) { local python-root = $(GCC_PYTHON_ROOT) ; if BOOST_DEBUG_PYTHON in $(gBUILD_PROPERTIES) { python-root = $(GCC_PYTHON_DEBUG_ROOT) ; } gRUN_PATH($(module)) += $(python-root)/lib/python$(PYTHON_VERSION)/config ; d = $(d:D) ; } } # This is the generator function for Python modules. It deals with the # need to change the name of modules compiled with debugging on. This # is just a wrapper around the generator for shared libraries, # dll-files. rule python-files ( module implib ? : sources * ) { dll-files $(module) $(implib) : $(sources) : PYD ; if ( $(gCURRENT_TOOLSET) = gcc ) { if $(NT) { add-cygwin-python-run-path $(<[-1]) ; } else { gRUN_PATH($(module)) += $(GCC_ROOT_DIRECTORY)/lib ; } } } if $(NT) { # Adjust the name of Python modules so that they have the _d # suffix when compiled with python debugging enabled. gNAME_ADJUST(PYD) = name-adjust-PYD ; rule name-adjust-PYD ( pyd implib ? : properties * : toolset variant ) { # Cygwin python is only happy if compiled modules have a .dll # extension if $(toolset) = gcc { pyd = $(pyd:S=.dll) ; } else if BOOST_DEBUG_PYTHON in $(properties) { pyd = $(pyd:S=)_d$(pyd:S) ; } return $(pyd) $(implib) ; } } rule Link-PYD { if $(<[2]) { MODE on $(<[2]) = $(IMPMODE) ; Chmod $(<[2]) ; } gRUN_PATH($(<)) += $(gLOCATE($(<[1]))) ; if $(UNIX) { gRUN_LD_LIBRARY_PATH($(<)) += $(gLOCATE($(<[1]))) ; } Link-action $(<) : $(>) : PYD ; } declare-target-type PYD : true ; gGENERATOR_FUNCTION(PYD) = python-files ; if $(NT) { SUFPYD = .pyd $(SUFDLL[2-]) ; } else { SUFPYD = $(SUFDLL) ; } PYDMODE = $(DLLMODE) ; SHARED_TYPES += PYD ; # Declare a python extension. rule extension ( name : sources + : requirements * : default-BUILD * ) { requirements += $(PYTHON_PROPERTIES) ; declare-local-target $(name) : $(sources) : $(requirements) : $(default-BUILD) : PYD ; } # boost-python-runtest target : python-script sources : requirements : local-build : args # # declare two python module tests: $(<).test which builds when out-of-date, and # $(<).run which builds unconditionally. rule boost-python-runtest ( target : python-script sources + : requirements * : local-build * : args * ) { # tell Jam that the python script is relative to this directory SEARCH on $(python-script) = $(SEARCH_SOURCE) ; # The user can add additional arguments in PYTHON_TEST_ARGS. local gPYTHON_TEST_ARGS = $(args) $(PYTHON_TEST_ARGS) ; # declare the two subsidiary tests. declare-local-target $(<:S=.test) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_TEST ; declare-local-target $(<:S=.run) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_RUNTEST ; } rule boost-python-test ( name : sources + : requirements * : default-BUILD * ) { type-DEPENDS test : $(name) ; local gSUPPRESS_FAKE_TARGETS = true ; extension $(name) : $(sources) : $(requirements) : $(4) ; } # special rules for two new target types: PYTHON_TEST and PYTHON_RUNTEST. # These are identical except that PYTHON_TEST runs the test when out-of-date, and # PYTHON_RUNTEST runs the test unconditionally. These are used by boost-python-runtest. SUFPYTHON_TEST = .test ; gGENERATOR_FUNCTION(PYTHON_TEST) = python-test-target ; rule python-test-target ( test-target : sources + ) { python-runtest-aux $(test-target) : $(sources) ; Clean clean : $(test-target) ; # remove the test-target as part of any clean operation type-DEPENDS test : $(test-target) ; MakeLocate $(test-target) : $(LOCATE_TARGET) ; } actions python-test-target bind PYTHON { $(SHELL_SET)PATH=$(PATH) $(SHELL_EXPORT)PATH $(SHELL_SET)LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(SHELL_EXPORT)LD_LIBRARY_PATH $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) $(SHELL_EXPORT)PYTHONPATH $(PYTHON_LAUNCH) $(PYTHON) $(PYTHON_ARGS) "$(>)" $(ARGS) > "$(<)" } SUFPYTHON_RUNTEST = .run ; gGENERATOR_FUNCTION(PYTHON_RUNTEST) = python-runtest-target ; rule python-runtest-target ( test-target : sources + ) { type-DEPENDS runtest : $(test-target) ; python-runtest-aux $(test-target) : $(sources) ; NOTFILE $(test-target) ; ALWAYS $(test-target) ; } actions python-runtest-target bind PYTHON { $(SHELL_SET)PATH=$(PATH) $(SHELL_EXPORT)PATH $(SHELL_SET)LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(SHELL_EXPORT)LD_LIBRARY_PATH $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) $(SHELL_EXPORT)PYTHONPATH $(PYTHON_LAUNCH) $(PYTHON) $(PYTHON_ARGS) "$(>)" $(ARGS) } # This is the rule that actually causes the test to run. It is used by # bothe python-test-target and python-runtest-target. rule python-runtest-aux ( target : sources + ) { DEPENDS $(target) : $(>) ; ARGS on $(target) += $(gPYTHON_TEST_ARGS) ; # Some tests need an extra command-line arg if built with # msvc. Checking the target grist is a cheap way to # find out. switch $(target) { case <*\\\\msvc\\\\*>* : ARGS on $(target) += --broken-auto-ptr ; case <*\\\\intel-win32\\\\*>* : ARGS on $(target) += --broken-auto-ptr ; } # choose the right python executable local python = $(PYTHON) ; local splitpath = $(SPLITPATH) ; # compute the PYTHONPATH environment variable that will allow the test to # find all of the modules on which it depends. local pythonpath = $(gLOCATE($(>[1]))) # location of python test file $(gRUN_PATH($(target))) # location of module dependencies [ join-path $(TOP) libs python test ] # location of doctest $(>:D) # directory of python driver file(s) $(PYTHONPATH) # base PYTHONPATH from environment ; if $(NT) && ( $(gCURRENT_TOOLSET) = gcc ) { python = python$(PYTHON_VERSION)$(SUFEXE) ; local python-root = $(GCC_PYTHON_ROOT) ; if BOOST_DEBUG_PYTHON in $(gBUILD_PROPERTIES) { python-root = $(GCC_PYTHON_DEBUG_ROOT) ; } SEARCH on $(python) = [ join-path [ split-path $(python-root)/bin ] ] $(RUN_PATH) ; splitpath = ":" ; local pp ; for local p in $(pythonpath) { # if already rooted... if $(p:R=xx) = $(p) { p = [ split-path $(p) ] ; p = [ join-path /cygdrive [ SUBST $(p[1]) ^(.).* $1 ] $(p[2-]) ] ; } pp += $(p) ; } pythonpath = $(pp:T) ; } else if BOOST_DEBUG_PYTHON in $(gBUILD_PROPERTIES) && $(NT) { python = $(PYTHON_D) ; } PYTHONPATH on $(target) = [ join $(pythonpath) : $(splitpath) ] ; # set the path so that DLLs linked into extension modules will be # found PATH on $(target) = [ join $(gRUN_PATH($(target))) # location of module dependencies $(>:D) # directory of python driver file(s) $(PATH) # base PATH from environment : $(SPLITPATH) ] ; # platform path separator LD_LIBRARY_PATH on $(target) = [ join $(gRUN_LD_LIBRARY_PATH($(target))) # location of module dependencies : $(SPLITPATH) ] ; # platform path separator PYTHON on $(target) = $(python) ; DEPENDS $(target) : $(python) ; } }